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

/// Use this library to open a path or URL using the program
/// configured on the system.
///
/// # Usage
///
/// ```ignore
/// if utils::open::item("https://google.com").is_ok() {
///     println!("Look at your browser!");
/// }
/// ```
///
/// # Notes
/// As an operating system program is used, the open can fail.
/// Therfore, you are advised to at least check the result with
/// .is_err() and behave accordingly, e.g. by letting the user know
/// what you tried to open, and failed.
///
/// The following programs are used to attempt to open the item by
/// operating system:
///
/// * Linux: xdg-open, gnome-open, kde-open
/// * OS X: open
/// * Windows: start
///
use std::process::{Command, Output};
use errors::{DeliveryError, Kind};

// The MIT License (MIT)
// =====================

// Copyright © `2015` `Sebastian Thiel`

// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the “Software”), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:

// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.

#[cfg(target_os = "macos")]
pub fn item(path: &str) -> Result<(), DeliveryError> {
    item_for_cmds(path, &["open"])
}

#[cfg(not(any(target_os = "windows", target_os = "macos")))]
pub fn item(path: &str) -> Result<(), DeliveryError> {
    item_for_cmds(path, &["xdg-open", "gnome-open", "kde-open"])
}

#[cfg(target_os = "windows")]
pub fn item(path: &str) -> Result<(), DeliveryError> {
    item_for_cmds(path, &["start"])
}

fn item_for_cmds(path: &str, cmds: &[&str]) -> Result<(), DeliveryError> {
    let mut res = Err(DeliveryError { kind: Kind::OpenFailed,
                                      detail: None});
    for cmd in cmds {
        res = item_for_cmd(path, cmd);
        match res {
            Ok(_) => break,
            Err(_) => continue,
        }
    }
    res
}

fn item_for_cmd(path: &str, cmd: &str) -> Result<(), DeliveryError> {
    process_response(cmd, try!(Command::new(cmd).arg(path).output()))
}

fn process_response(cmd: &str, res: Output) -> Result<(), DeliveryError> {
    if res.status.success() {
        Ok(())
    } else {
        let code = match res.status.code() {
            Some(c) => format!("{}", c),
            None => format!("{}", "terminated by signal")
        };
        let msg = format!("Command '{}' failed with code {}",
                          cmd, code);
        Err(DeliveryError { kind: Kind::OpenFailed,
                            detail: Some(msg) })
    }
}
<commit_msg>Hack to make open::item work on windows<commit_after>//
// Copyright:: Copyright (c) 2015 Chef Software, Inc.
// License:: Apache License, Version 2.0
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

/// Use this library to open a path or URL using the program
/// configured on the system.
///
/// # Usage
///
/// ```ignore
/// if utils::open::item("https://google.com").is_ok() {
///     println!("Look at your browser!");
/// }
/// ```
///
/// # Notes
/// As an operating system program is used, the open can fail.
/// Therfore, you are advised to at least check the result with
/// .is_err() and behave accordingly, e.g. by letting the user know
/// what you tried to open, and failed.
///
/// The following programs are used to attempt to open the item by
/// operating system:
///
/// * Linux: xdg-open, gnome-open, kde-open
/// * OS X: open
/// * Windows: start
///
use std::process::{Command, Output};
use errors::{DeliveryError, Kind};

// The MIT License (MIT)
// =====================

// Copyright © `2015` `Sebastian Thiel`

// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the “Software”), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:

// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.

#[cfg(target_os = "macos")]
pub fn item(path: &str) -> Result<(), DeliveryError> {
    item_for_cmds(path, &["open"])
}

#[cfg(not(any(target_os = "windows", target_os = "macos")))]
pub fn item(path: &str) -> Result<(), DeliveryError> {
    item_for_cmds(path, &["xdg-open", "gnome-open", "kde-open"])
}

#[cfg(target_os = "windows")]
pub fn item(path: &str) -> Result<(), DeliveryError> {
    process_response("start", try!(Command::new("cmd.exe")
                                    .arg("/c")
                                    .arg("start")
                                    .arg(path)
                                    .output()))
}

#[cfg(not(target_os = "windows"))]
fn item_for_cmds(path: &str, cmds: &[&str]) -> Result<(), DeliveryError> {
    let mut res = Err(DeliveryError { kind: Kind::OpenFailed,
                                      detail: None});
    for cmd in cmds {
        res = item_for_cmd(path, cmd);
        match res {
            Ok(_) => break,
            Err(_) => continue,
        }
    }
    res
}

#[cfg(not(target_os = "windows"))]
fn item_for_cmd(path: &str, cmd: &str) -> Result<(), DeliveryError> {
    process_response(cmd, try!(Command::new(cmd).arg(path).output()))
}

fn process_response(cmd: &str, res: Output) -> Result<(), DeliveryError> {
    if res.status.success() {
        Ok(())
    } else {
        let code = match res.status.code() {
            Some(c) => format!("{}", c),
            None => format!("{}", "terminated by signal")
        };
        let msg = format!("Command '{}' failed with code {}",
                          cmd, code);
        Err(DeliveryError { kind: Kind::OpenFailed,
                            detail: Some(msg) })
    }
}
<|endoftext|>


<commit_before>// Create a task that is supervised by another task,
// join the supervised task from the supervising task,
// then fail the supervised task. The supervised task
// will kill the supervising task, waking it up. The
// supervising task no longer needs to be wakened when
// the supervised task exits.

use std;
import std::task;

fn supervised() {
    // Yield to make sure the supervisor joins before we
    // fail. This is currently not needed because the supervisor
    // runs first, but I can imagine that changing.
    task::yield();
    fail;
}

fn supervisor() {
    // Unsupervise this task so the process doesn't return a failure status as
    // a result of the main task being killed.
    task::unsupervise();
    let t = task::_spawn(bind supervised());
    task::join_id(t);
}

fn main() {
    let dom2 = task::_spawn(bind supervisor());
    task::join_id(dom2);
}

// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
<commit_msg>XFAIL run-pass/task-killjoin<commit_after>// xfail-stage1
// xfail-stage2
// xfail-stage3

// Create a task that is supervised by another task,
// join the supervised task from the supervising task,
// then fail the supervised task. The supervised task
// will kill the supervising task, waking it up. The
// supervising task no longer needs to be wakened when
// the supervised task exits.

use std;
import std::task;

fn supervised() {
    // Yield to make sure the supervisor joins before we
    // fail. This is currently not needed because the supervisor
    // runs first, but I can imagine that changing.
    task::yield();
    fail;
}

fn supervisor() {
    // Unsupervise this task so the process doesn't return a failure status as
    // a result of the main task being killed.
    task::unsupervise();
    let t = task::_spawn(bind supervised());
    task::join_id(t);
}

fn main() {
    let dom2 = task::_spawn(bind supervisor());
    task::join_id(dom2);
}

// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
<|endoftext|>


<commit_before>use std::time::{Instant, Duration};
use std::future::Future;
use std::sync::Arc;

use glutin::{
    GlProfile,
    GlRequest,
    ContextBuilder,
    WindowedContext,
    PossiblyCurrent,
    dpi::{LogicalSize, PhysicalPosition},
    window::{WindowBuilder, Fullscreen},
    event::{
        Event as GlutinEvent,
        StartCause,
        WindowEvent,
        KeyboardInput,
        VirtualKeyCode,
        ElementState,
    },
    event_loop::{ControlFlow, EventLoop},
    platform::desktop::EventLoopExtDesktop,
};
use tokio::{
    sync::{mpsc, Mutex},
    runtime::Handle,
};

use crate::Event;
use crate::ipc_protocol::{ServerConnection, ConnectionError};

use super::{
    app::App,
    coords::ScreenPoint,
    renderer::{
        Renderer,
        display_list::DisplayList,
    },
    event_loop_notifier::{EventLoopNotifier, MainThreadAction},
};

/// The maximum rendering FPS allowed
///
/// Rendering is intentionally throttled to avoid too much contention over the display list. If
/// multiple turtles are used or if many lines are drawn quickly, we may get >= 1 redraw request
/// per *millisecond* this is far too many redraws. Limiting to this rate helps avoid that.
const MAX_RENDERING_FPS: u64 = 60;

// 1,000,000 us in 1 s
const MICROS_PER_SEC: u64 = 1_000_000;

fn new_event_loop<T>() -> EventLoop<T> {
    cfg_if::cfg_if! {
        if #[cfg(target_os = "macos")] {
            EventLoop::with_user_event()

        } else if #[cfg(target_os = "windows")] {
            use glutin::platform::unix::EventLoopExtWindows;
            EventLoop::new_any_thread()

        } else {
            use glutin::platform::unix::EventLoopExtUnix;
            EventLoop::new_any_thread()
        }
    }
}

/// Run the window event loop in the current thread/task
///
/// When the window is opened, this will spawn a task that establishes the server connection using
/// the given future and begin to serve client requests.
///
/// On some platforms this function may only run on the main thread
pub fn run_main(
    // A handle used to block on asynchronous code and spawn new tasks
    //
    // Necessary because this function is not run on a runtime thread in all backends
    handle: Handle,

    // Polled to establish the server connection
    establish_connection: impl Future<Output=Result<ServerConnection, ConnectionError>> + Send + 'static,

    // Polled when the window is closed and the application is about to quit
    event_loop_quit: impl Future<Output=()> + 'static,
) {
    // The state of the drawing and the state/drawings associated with each turtle
    let app = Arc::new(App::default());
    // All of the drawing primitives in the order in which they wil be drawn
    //
    // This is managed separately from the rest of the app state because the display list is shared
    // among pretty much everything and so critical sections containing the display list need to be
    // as short as possible.
    let display_list = Arc::new(Mutex::new(DisplayList::default()));

    let mut event_loop = new_event_loop();
    // Create the proxy that will be given to the thread managing IPC
    let event_loop_proxy = event_loop.create_proxy();
    let event_loop_notifier = Arc::new(EventLoopNotifier::new(event_loop_proxy));

    // A channel for transferring events
    let (events_sender, events_receiver) = mpsc::unbounded_channel();
    // Put the events_receiver in an Option so we can call `take()` in the event loop. Required
    // because borrow checker cannot verify that `Init` event is only fired once.
    let mut events_receiver = Some(events_receiver);
    let mut establish_connection = Some(establish_connection);
    let mut event_loop_quit = Some(event_loop_quit);

    let window_builder = {
        let drawing = handle.block_on(app.drawing_mut());
        WindowBuilder::new()
            .with_title(&drawing.title)
            .with_inner_size(LogicalSize {width: drawing.width, height: drawing.height})
    };

    // Create an OpenGL 3.x context for Pathfinder to use
    let gl_context = ContextBuilder::new()
        .with_gl(GlRequest::Latest)
        .with_gl_profile(GlProfile::Core)
        .with_vsync(true)
        .with_double_buffer(Some(true))
        .build_windowed(window_builder, &event_loop)
        .expect("either could not create window or could not build OpenGL context");

    // Load OpenGL, and make the context current
    let gl_context = unsafe { gl_context.make_current().unwrap() };
    gl::load_with(|name| gl_context.get_proc_address(name) as *const _);

    // Need to draw using the physical size in pixels, not the logical size
    let draw_size = gl_context.window().inner_size();
    let mut renderer = Renderer::new(draw_size, gl_context.window().scale_factor());

    // For rate limiting rendering
    let min_render_delay = Duration::from_micros(MICROS_PER_SEC / MAX_RENDERING_FPS);
    // Subtracting the delay so we do an initial render right away
    let mut last_render = Instant::now() - min_render_delay;
    // Very important to use `run_return` here instead of `run` because `run` calls process::exit()
    // and that is not appropriate for the multithreaded backend as that would cause the entire
    // process to end when the window is closed.
    event_loop.run_return(move |event, _, control_flow| match event {
        GlutinEvent::NewEvents(StartCause::Init) => {
            // Spawn the actual server thread(s) that will handle incoming IPC messages and
            // asynchronous update the shared state
            //
            // Note that putting this code here instead of before the event loop causes the
            // `Turtle::new()`, etc. methods not to return before the window opens. Those methods
            // can't return because the connection handshake cannot complete before the thread used
            // for IPC is spawned.
            spawn_async_server(
                &handle,
                app.clone(),
                display_list.clone(),
                event_loop_notifier.clone(),
                events_receiver.take().expect("bug: init event should only occur once"),
                establish_connection.take().expect("bug: init event should only occur once"),
            );
        },

        GlutinEvent::NewEvents(StartCause::ResumeTimeReached {..}) => {
            // A render was delayed in the `RedrawRequested` so let's try to do it again now that
            // we have resumed
            gl_context.window().request_redraw();
        },

        // Quit if the window is closed or if Esc is pressed and then released
        GlutinEvent::WindowEvent {
            event: WindowEvent::CloseRequested,
            ..
        } | GlutinEvent::WindowEvent {
            event: WindowEvent::Destroyed,
            ..
        } | GlutinEvent::WindowEvent {
            event: WindowEvent::KeyboardInput {
                input: KeyboardInput {
                    state: ElementState::Released,
                    virtual_keycode: Some(VirtualKeyCode::Escape),
                    ..
                },
                ..
            },
            ..
        } => {
            *control_flow = ControlFlow::Exit;
        },

        GlutinEvent::WindowEvent {
            event: WindowEvent::ScaleFactorChanged {scale_factor, ..},
            ..
        } => {
            renderer.set_scale_factor(scale_factor);
            //TODO: No idea if this next line is necessary or not
            gl_context.window().request_redraw();
        },

        GlutinEvent::WindowEvent {event, ..} => {
            let scale_factor = renderer.scale_factor();
            match event {
                WindowEvent::Resized(size) => {
                    let size = size.to_logical(scale_factor);
                    let mut drawing = handle.block_on(app.drawing_mut());
                    drawing.width = size.width;
                    drawing.height = size.height;
                    //TODO: No idea if this next line is necessary or not
                    gl_context.window().request_redraw();
                },

                //TODO: There are currently no events for updating is_maximized, so that property
                // should not be relied on. https://github.com/rust-windowing/glutin/issues/1298

                _ => {},
            }

            // Converts to logical coordinates, only locking the drawing if this is actually called
            let to_logical = |pos: PhysicalPosition<f64>| {
                let drawing = handle.block_on(app.drawing_mut());
                let center = drawing.center;
                let draw_size = gl_context.window().inner_size();
                let fb_center = ScreenPoint {
                    x: draw_size.width as f64 / 2.0,
                    y: draw_size.height as f64 / 2.0,
                };

                let pos: ScreenPoint = pos.into();
                pos.to_logical(scale_factor, center, fb_center)
            };

            //TODO: There is no guarantee that sending this event here will actually allow a client
            // to receive it. After all, if the window closes and this process exits, there will be
            // no way to handle subsequent `NextEvent` requests.
            if let Some(event) = Event::from_window_event(event, scale_factor, to_logical) {
                match events_sender.send(event) {
                    Ok(()) => {},
                    // Sending may fail if the IPC thread has ended due to a disconnection when the
                    // main process ends.
                    Err(_) => {},
                }
            }
        },

        // Window events are currently sufficient for the turtle event API
        GlutinEvent::DeviceEvent {..} => {},

        GlutinEvent::UserEvent(MainThreadAction::Redraw) => {
            gl_context.window().request_redraw();
        },

        GlutinEvent::UserEvent(MainThreadAction::SetTitle(title)) => {
            gl_context.window().set_title(&title);
        },

        GlutinEvent::UserEvent(MainThreadAction::SetSize(size)) => {
            gl_context.window().set_inner_size(size);
            //TODO: No idea if this next line is necessary or not
            gl_context.window().request_redraw();
        },

        GlutinEvent::UserEvent(MainThreadAction::SetIsMaximized(is_maximized)) => {
            gl_context.window().set_maximized(is_maximized);
            //TODO: No idea if this next line is necessary or not
            gl_context.window().request_redraw();
        },

        GlutinEvent::UserEvent(MainThreadAction::SetIsFullscreen(is_fullscreen)) => {
            gl_context.window().set_fullscreen(if is_fullscreen {
                Some(Fullscreen::Borderless(gl_context.window().current_monitor()))
            } else { None });

            //TODO: No idea if this next line is necessary or not
            gl_context.window().request_redraw();
        },

        GlutinEvent::RedrawRequested(_) => {
            // Check if we just rendered
            let last_render_delay = last_render.elapsed();
            if last_render_delay < min_render_delay {
                let remaining = min_render_delay - last_render_delay;
                *control_flow = ControlFlow::WaitUntil(Instant::now() + remaining);
                return;
            }

            handle.block_on(redraw(&app, &display_list, &gl_context, &mut renderer));
            *control_flow = ControlFlow::Wait;
            last_render = Instant::now();
        },

        GlutinEvent::LoopDestroyed => {
            let event_loop_quit = event_loop_quit.take()
                .expect("bug: loop destroyed event should only occur once");
            handle.block_on(event_loop_quit);
        },

        _ => {},
    });
}

async fn redraw(
    app: &App,
    display_list: &Mutex<DisplayList>,
    gl_context: &WindowedContext<PossiblyCurrent>,
    renderer: &mut Renderer,
) {
    let drawing = {
        // Hold the drawing lock for as little time as possible
        let drawing = app.drawing_mut().await;
        drawing.clone()
    };

    // Locking the turtles before the display list to be consistent with all of the request
    // handlers. Inconsistent lock ordering can cause deadlock.
    let mut turtles = Vec::new();
    for id in app.turtle_ids().await {
        turtles.push(app.turtle(id).await);
    }
    // Very important to have all the data locked before rendering. Do not want renderer to have
    // to figure out how to lock.
    let mut locked_turtles = Vec::with_capacity(turtles.len());
    for turtle in &turtles {
        locked_turtles.push(turtle.lock().await);
    }
    // Renderer only needs (read-only) access to TurtleState
    // Doing this also decouples renderer code from runtime by not having to
    // know about the `MutexGuard` type in tokio
    let turtle_states = locked_turtles.iter().map(|t| &t.state);

    let display_list = display_list.lock().await;

    let draw_size = gl_context.window().inner_size();
    renderer.render(draw_size, &display_list, &drawing, turtle_states);
    gl_context.swap_buffers().expect("unable to swap the buffer (for double buffering)");
}

fn spawn_async_server(
    handle: &Handle,
    app: Arc<App>,
    display_list: Arc<Mutex<DisplayList>>,
    event_loop: Arc<EventLoopNotifier>,
    events_receiver: mpsc::UnboundedReceiver<Event>,
    establish_connection: impl Future<Output=Result<ServerConnection, ConnectionError>> + Send + 'static,
) {
    // Spawn root task
    handle.spawn(async {
        let conn = establish_connection.await
            .expect("unable to establish turtle server connection");
        super::serve(conn, app, display_list, event_loop, events_receiver).await;
    });
}
<commit_msg>Fixed typo in EventLoopExtWindows import<commit_after>use std::time::{Instant, Duration};
use std::future::Future;
use std::sync::Arc;

use glutin::{
    GlProfile,
    GlRequest,
    ContextBuilder,
    WindowedContext,
    PossiblyCurrent,
    dpi::{LogicalSize, PhysicalPosition},
    window::{WindowBuilder, Fullscreen},
    event::{
        Event as GlutinEvent,
        StartCause,
        WindowEvent,
        KeyboardInput,
        VirtualKeyCode,
        ElementState,
    },
    event_loop::{ControlFlow, EventLoop},
    platform::desktop::EventLoopExtDesktop,
};
use tokio::{
    sync::{mpsc, Mutex},
    runtime::Handle,
};

use crate::Event;
use crate::ipc_protocol::{ServerConnection, ConnectionError};

use super::{
    app::App,
    coords::ScreenPoint,
    renderer::{
        Renderer,
        display_list::DisplayList,
    },
    event_loop_notifier::{EventLoopNotifier, MainThreadAction},
};

/// The maximum rendering FPS allowed
///
/// Rendering is intentionally throttled to avoid too much contention over the display list. If
/// multiple turtles are used or if many lines are drawn quickly, we may get >= 1 redraw request
/// per *millisecond* this is far too many redraws. Limiting to this rate helps avoid that.
const MAX_RENDERING_FPS: u64 = 60;

// 1,000,000 us in 1 s
const MICROS_PER_SEC: u64 = 1_000_000;

fn new_event_loop<T>() -> EventLoop<T> {
    cfg_if::cfg_if! {
        if #[cfg(target_os = "macos")] {
            EventLoop::with_user_event()

        } else if #[cfg(target_os = "windows")] {
            use glutin::platform::windows::EventLoopExtWindows;
            EventLoop::new_any_thread()

        } else {
            use glutin::platform::unix::EventLoopExtUnix;
            EventLoop::new_any_thread()
        }
    }
}

/// Run the window event loop in the current thread/task
///
/// When the window is opened, this will spawn a task that establishes the server connection using
/// the given future and begin to serve client requests.
///
/// On some platforms this function may only run on the main thread
pub fn run_main(
    // A handle used to block on asynchronous code and spawn new tasks
    //
    // Necessary because this function is not run on a runtime thread in all backends
    handle: Handle,

    // Polled to establish the server connection
    establish_connection: impl Future<Output=Result<ServerConnection, ConnectionError>> + Send + 'static,

    // Polled when the window is closed and the application is about to quit
    event_loop_quit: impl Future<Output=()> + 'static,
) {
    // The state of the drawing and the state/drawings associated with each turtle
    let app = Arc::new(App::default());
    // All of the drawing primitives in the order in which they wil be drawn
    //
    // This is managed separately from the rest of the app state because the display list is shared
    // among pretty much everything and so critical sections containing the display list need to be
    // as short as possible.
    let display_list = Arc::new(Mutex::new(DisplayList::default()));

    let mut event_loop = new_event_loop();
    // Create the proxy that will be given to the thread managing IPC
    let event_loop_proxy = event_loop.create_proxy();
    let event_loop_notifier = Arc::new(EventLoopNotifier::new(event_loop_proxy));

    // A channel for transferring events
    let (events_sender, events_receiver) = mpsc::unbounded_channel();
    // Put the events_receiver in an Option so we can call `take()` in the event loop. Required
    // because borrow checker cannot verify that `Init` event is only fired once.
    let mut events_receiver = Some(events_receiver);
    let mut establish_connection = Some(establish_connection);
    let mut event_loop_quit = Some(event_loop_quit);

    let window_builder = {
        let drawing = handle.block_on(app.drawing_mut());
        WindowBuilder::new()
            .with_title(&drawing.title)
            .with_inner_size(LogicalSize {width: drawing.width, height: drawing.height})
    };

    // Create an OpenGL 3.x context for Pathfinder to use
    let gl_context = ContextBuilder::new()
        .with_gl(GlRequest::Latest)
        .with_gl_profile(GlProfile::Core)
        .with_vsync(true)
        .with_double_buffer(Some(true))
        .build_windowed(window_builder, &event_loop)
        .expect("either could not create window or could not build OpenGL context");

    // Load OpenGL, and make the context current
    let gl_context = unsafe { gl_context.make_current().unwrap() };
    gl::load_with(|name| gl_context.get_proc_address(name) as *const _);

    // Need to draw using the physical size in pixels, not the logical size
    let draw_size = gl_context.window().inner_size();
    let mut renderer = Renderer::new(draw_size, gl_context.window().scale_factor());

    // For rate limiting rendering
    let min_render_delay = Duration::from_micros(MICROS_PER_SEC / MAX_RENDERING_FPS);
    // Subtracting the delay so we do an initial render right away
    let mut last_render = Instant::now() - min_render_delay;
    // Very important to use `run_return` here instead of `run` because `run` calls process::exit()
    // and that is not appropriate for the multithreaded backend as that would cause the entire
    // process to end when the window is closed.
    event_loop.run_return(move |event, _, control_flow| match event {
        GlutinEvent::NewEvents(StartCause::Init) => {
            // Spawn the actual server thread(s) that will handle incoming IPC messages and
            // asynchronous update the shared state
            //
            // Note that putting this code here instead of before the event loop causes the
            // `Turtle::new()`, etc. methods not to return before the window opens. Those methods
            // can't return because the connection handshake cannot complete before the thread used
            // for IPC is spawned.
            spawn_async_server(
                &handle,
                app.clone(),
                display_list.clone(),
                event_loop_notifier.clone(),
                events_receiver.take().expect("bug: init event should only occur once"),
                establish_connection.take().expect("bug: init event should only occur once"),
            );
        },

        GlutinEvent::NewEvents(StartCause::ResumeTimeReached {..}) => {
            // A render was delayed in the `RedrawRequested` so let's try to do it again now that
            // we have resumed
            gl_context.window().request_redraw();
        },

        // Quit if the window is closed or if Esc is pressed and then released
        GlutinEvent::WindowEvent {
            event: WindowEvent::CloseRequested,
            ..
        } | GlutinEvent::WindowEvent {
            event: WindowEvent::Destroyed,
            ..
        } | GlutinEvent::WindowEvent {
            event: WindowEvent::KeyboardInput {
                input: KeyboardInput {
                    state: ElementState::Released,
                    virtual_keycode: Some(VirtualKeyCode::Escape),
                    ..
                },
                ..
            },
            ..
        } => {
            *control_flow = ControlFlow::Exit;
        },

        GlutinEvent::WindowEvent {
            event: WindowEvent::ScaleFactorChanged {scale_factor, ..},
            ..
        } => {
            renderer.set_scale_factor(scale_factor);
            //TODO: No idea if this next line is necessary or not
            gl_context.window().request_redraw();
        },

        GlutinEvent::WindowEvent {event, ..} => {
            let scale_factor = renderer.scale_factor();
            match event {
                WindowEvent::Resized(size) => {
                    let size = size.to_logical(scale_factor);
                    let mut drawing = handle.block_on(app.drawing_mut());
                    drawing.width = size.width;
                    drawing.height = size.height;
                    //TODO: No idea if this next line is necessary or not
                    gl_context.window().request_redraw();
                },

                //TODO: There are currently no events for updating is_maximized, so that property
                // should not be relied on. https://github.com/rust-windowing/glutin/issues/1298

                _ => {},
            }

            // Converts to logical coordinates, only locking the drawing if this is actually called
            let to_logical = |pos: PhysicalPosition<f64>| {
                let drawing = handle.block_on(app.drawing_mut());
                let center = drawing.center;
                let draw_size = gl_context.window().inner_size();
                let fb_center = ScreenPoint {
                    x: draw_size.width as f64 / 2.0,
                    y: draw_size.height as f64 / 2.0,
                };

                let pos: ScreenPoint = pos.into();
                pos.to_logical(scale_factor, center, fb_center)
            };

            //TODO: There is no guarantee that sending this event here will actually allow a client
            // to receive it. After all, if the window closes and this process exits, there will be
            // no way to handle subsequent `NextEvent` requests.
            if let Some(event) = Event::from_window_event(event, scale_factor, to_logical) {
                match events_sender.send(event) {
                    Ok(()) => {},
                    // Sending may fail if the IPC thread has ended due to a disconnection when the
                    // main process ends.
                    Err(_) => {},
                }
            }
        },

        // Window events are currently sufficient for the turtle event API
        GlutinEvent::DeviceEvent {..} => {},

        GlutinEvent::UserEvent(MainThreadAction::Redraw) => {
            gl_context.window().request_redraw();
        },

        GlutinEvent::UserEvent(MainThreadAction::SetTitle(title)) => {
            gl_context.window().set_title(&title);
        },

        GlutinEvent::UserEvent(MainThreadAction::SetSize(size)) => {
            gl_context.window().set_inner_size(size);
            //TODO: No idea if this next line is necessary or not
            gl_context.window().request_redraw();
        },

        GlutinEvent::UserEvent(MainThreadAction::SetIsMaximized(is_maximized)) => {
            gl_context.window().set_maximized(is_maximized);
            //TODO: No idea if this next line is necessary or not
            gl_context.window().request_redraw();
        },

        GlutinEvent::UserEvent(MainThreadAction::SetIsFullscreen(is_fullscreen)) => {
            gl_context.window().set_fullscreen(if is_fullscreen {
                Some(Fullscreen::Borderless(gl_context.window().current_monitor()))
            } else { None });

            //TODO: No idea if this next line is necessary or not
            gl_context.window().request_redraw();
        },

        GlutinEvent::RedrawRequested(_) => {
            // Check if we just rendered
            let last_render_delay = last_render.elapsed();
            if last_render_delay < min_render_delay {
                let remaining = min_render_delay - last_render_delay;
                *control_flow = ControlFlow::WaitUntil(Instant::now() + remaining);
                return;
            }

            handle.block_on(redraw(&app, &display_list, &gl_context, &mut renderer));
            *control_flow = ControlFlow::Wait;
            last_render = Instant::now();
        },

        GlutinEvent::LoopDestroyed => {
            let event_loop_quit = event_loop_quit.take()
                .expect("bug: loop destroyed event should only occur once");
            handle.block_on(event_loop_quit);
        },

        _ => {},
    });
}

async fn redraw(
    app: &App,
    display_list: &Mutex<DisplayList>,
    gl_context: &WindowedContext<PossiblyCurrent>,
    renderer: &mut Renderer,
) {
    let drawing = {
        // Hold the drawing lock for as little time as possible
        let drawing = app.drawing_mut().await;
        drawing.clone()
    };

    // Locking the turtles before the display list to be consistent with all of the request
    // handlers. Inconsistent lock ordering can cause deadlock.
    let mut turtles = Vec::new();
    for id in app.turtle_ids().await {
        turtles.push(app.turtle(id).await);
    }
    // Very important to have all the data locked before rendering. Do not want renderer to have
    // to figure out how to lock.
    let mut locked_turtles = Vec::with_capacity(turtles.len());
    for turtle in &turtles {
        locked_turtles.push(turtle.lock().await);
    }
    // Renderer only needs (read-only) access to TurtleState
    // Doing this also decouples renderer code from runtime by not having to
    // know about the `MutexGuard` type in tokio
    let turtle_states = locked_turtles.iter().map(|t| &t.state);

    let display_list = display_list.lock().await;

    let draw_size = gl_context.window().inner_size();
    renderer.render(draw_size, &display_list, &drawing, turtle_states);
    gl_context.swap_buffers().expect("unable to swap the buffer (for double buffering)");
}

fn spawn_async_server(
    handle: &Handle,
    app: Arc<App>,
    display_list: Arc<Mutex<DisplayList>>,
    event_loop: Arc<EventLoopNotifier>,
    events_receiver: mpsc::UnboundedReceiver<Event>,
    establish_connection: impl Future<Output=Result<ServerConnection, ConnectionError>> + Send + 'static,
) {
    // Spawn root task
    handle.spawn(async {
        let conn = establish_connection.await
            .expect("unable to establish turtle server connection");
        super::serve(conn, app, display_list, event_loop, events_receiver).await;
    });
}
<|endoftext|>


<commit_before>use crate::cargo;
use crate::error::{Error, Result};
use crate::gen::fs;
use std::env;
use std::ops::Deref;
use std::path::{Path, PathBuf};

pub(crate) struct TargetDir(pub PathBuf);

impl Deref for TargetDir {
    type Target = Path;
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

fn out_dir() -> Result<PathBuf> {
    env::var_os("OUT_DIR")
        .map(PathBuf::from)
        .ok_or(Error::MissingOutDir)
}

pub(crate) fn cc_build(target_dir: &TargetDir) -> cc::Build {
    try_cc_build(target_dir).unwrap_or_default()
}

fn try_cc_build(target_dir: &TargetDir) -> Result<cc::Build> {
    let mut build = cc::Build::new();
    build.include(include_dir(target_dir));
    build.include(target_dir.parent().unwrap());
    Ok(build)
}

// Symlink the header file into a predictable place. The header generated from
// path/to/mod.rs gets linked to targets/cxxbridge/path/to/mod.rs.h.
pub(crate) fn symlink_header(path: &Path, original: &Path, target_dir: &TargetDir) {
    let _ = try_symlink_header(path, original, target_dir);
}

fn try_symlink_header(path: &Path, original: &Path, target_dir: &TargetDir) -> Result<()> {
    let suffix = relative_to_parent_of_target_dir(original, target_dir)?;
    let ref dst = include_dir(target_dir).join(suffix);

    fs::create_dir_all(dst.parent().unwrap())?;
    let _ = fs::remove_file(dst);
    symlink_or_copy(path, dst)?;

    let mut file_name = dst.file_name().unwrap().to_os_string();
    file_name.push(".h");
    let ref dst2 = dst.with_file_name(file_name);
    symlink_or_copy(path, dst2)?;

    Ok(())
}

fn relative_to_parent_of_target_dir(original: &Path, target_dir: &TargetDir) -> Result<PathBuf> {
    let mut outer = target_dir.parent().unwrap();
    let original = canonicalize(original)?;
    loop {
        if let Ok(suffix) = original.strip_prefix(outer) {
            return Ok(suffix.to_owned());
        }
        match outer.parent() {
            Some(parent) => outer = parent,
            None => return Ok(original.components().skip(1).collect()),
        }
    }
}

pub(crate) fn out_with_extension(
    path: &Path,
    ext: &str,
    target_dir: &TargetDir,
) -> Result<PathBuf> {
    let mut file_name = path.file_name().unwrap().to_owned();
    file_name.push(ext);

    let out_dir = out_dir()?;
    let rel = relative_to_parent_of_target_dir(path, target_dir)?;
    Ok(out_dir.join(rel).with_file_name(file_name))
}

pub(crate) fn include_dir(target_dir: &TargetDir) -> PathBuf {
    target_dir.join("cxxbridge")
}

pub(crate) fn target_dir() -> Result<TargetDir> {
    let fallback_err = match cargo::target_dir() {
        Ok(target_dir) => return Ok(target_dir),
        Err(err) => Error::TargetDir(err),
    };

    // Fallback if Cargo did not work.
    let mut dir = out_dir().and_then(canonicalize)?;
    loop {
        if dir.ends_with("target") {
            return Ok(TargetDir(dir));
        }
        if !dir.pop() {
            return Err(fallback_err);
        }
    }
}

#[cfg(not(windows))]
fn canonicalize(path: impl AsRef<Path>) -> Result<PathBuf> {
    Ok(fs::canonicalize(path)?)
}

#[cfg(windows)]
fn canonicalize(path: impl AsRef<Path>) -> Result<PathBuf> {
    // Real fs::canonicalize on Windows produces UNC paths which cl.exe is
    // unable to handle in includes. Use a poor approximation instead.
    // https://github.com/rust-lang/rust/issues/42869
    // https://github.com/alexcrichton/cc-rs/issues/169
    Ok(fs::current_dir()?.join(path))
}

#[cfg(unix)]
use self::fs::symlink_file as symlink_or_copy;

#[cfg(windows)]
fn symlink_or_copy(src: &Path, dst: &Path) -> Result<()> {
    // Pre-Windows 10, symlinks require admin privileges. Since Windows 10, they
    // require Developer Mode. If it fails, fall back to copying the file.
    if fs::symlink_file(src, dst).is_err() {
        fs::copy(src, dst)?;
    }
    Ok(())
}

#[cfg(not(any(unix, windows)))]
use self::fs::copy as symlink_or_copy;
<commit_msg>Construction of cc build can be infallible<commit_after>use crate::cargo;
use crate::error::{Error, Result};
use crate::gen::fs;
use std::env;
use std::ops::Deref;
use std::path::{Path, PathBuf};

pub(crate) struct TargetDir(pub PathBuf);

impl Deref for TargetDir {
    type Target = Path;
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

fn out_dir() -> Result<PathBuf> {
    env::var_os("OUT_DIR")
        .map(PathBuf::from)
        .ok_or(Error::MissingOutDir)
}

pub(crate) fn cc_build(target_dir: &TargetDir) -> cc::Build {
    let mut build = cc::Build::new();
    build.include(include_dir(target_dir));
    build.include(target_dir.parent().unwrap());
    build
}

// Symlink the header file into a predictable place. The header generated from
// path/to/mod.rs gets linked to targets/cxxbridge/path/to/mod.rs.h.
pub(crate) fn symlink_header(path: &Path, original: &Path, target_dir: &TargetDir) {
    let _ = try_symlink_header(path, original, target_dir);
}

fn try_symlink_header(path: &Path, original: &Path, target_dir: &TargetDir) -> Result<()> {
    let suffix = relative_to_parent_of_target_dir(original, target_dir)?;
    let ref dst = include_dir(target_dir).join(suffix);

    fs::create_dir_all(dst.parent().unwrap())?;
    let _ = fs::remove_file(dst);
    symlink_or_copy(path, dst)?;

    let mut file_name = dst.file_name().unwrap().to_os_string();
    file_name.push(".h");
    let ref dst2 = dst.with_file_name(file_name);
    symlink_or_copy(path, dst2)?;

    Ok(())
}

fn relative_to_parent_of_target_dir(original: &Path, target_dir: &TargetDir) -> Result<PathBuf> {
    let mut outer = target_dir.parent().unwrap();
    let original = canonicalize(original)?;
    loop {
        if let Ok(suffix) = original.strip_prefix(outer) {
            return Ok(suffix.to_owned());
        }
        match outer.parent() {
            Some(parent) => outer = parent,
            None => return Ok(original.components().skip(1).collect()),
        }
    }
}

pub(crate) fn out_with_extension(
    path: &Path,
    ext: &str,
    target_dir: &TargetDir,
) -> Result<PathBuf> {
    let mut file_name = path.file_name().unwrap().to_owned();
    file_name.push(ext);

    let out_dir = out_dir()?;
    let rel = relative_to_parent_of_target_dir(path, target_dir)?;
    Ok(out_dir.join(rel).with_file_name(file_name))
}

pub(crate) fn include_dir(target_dir: &TargetDir) -> PathBuf {
    target_dir.join("cxxbridge")
}

pub(crate) fn target_dir() -> Result<TargetDir> {
    let fallback_err = match cargo::target_dir() {
        Ok(target_dir) => return Ok(target_dir),
        Err(err) => Error::TargetDir(err),
    };

    // Fallback if Cargo did not work.
    let mut dir = out_dir().and_then(canonicalize)?;
    loop {
        if dir.ends_with("target") {
            return Ok(TargetDir(dir));
        }
        if !dir.pop() {
            return Err(fallback_err);
        }
    }
}

#[cfg(not(windows))]
fn canonicalize(path: impl AsRef<Path>) -> Result<PathBuf> {
    Ok(fs::canonicalize(path)?)
}

#[cfg(windows)]
fn canonicalize(path: impl AsRef<Path>) -> Result<PathBuf> {
    // Real fs::canonicalize on Windows produces UNC paths which cl.exe is
    // unable to handle in includes. Use a poor approximation instead.
    // https://github.com/rust-lang/rust/issues/42869
    // https://github.com/alexcrichton/cc-rs/issues/169
    Ok(fs::current_dir()?.join(path))
}

#[cfg(unix)]
use self::fs::symlink_file as symlink_or_copy;

#[cfg(windows)]
fn symlink_or_copy(src: &Path, dst: &Path) -> Result<()> {
    // Pre-Windows 10, symlinks require admin privileges. Since Windows 10, they
    // require Developer Mode. If it fails, fall back to copying the file.
    if fs::symlink_file(src, dst).is_err() {
        fs::copy(src, dst)?;
    }
    Ok(())
}

#[cfg(not(any(unix, windows)))]
use self::fs::copy as symlink_or_copy;
<|endoftext|>


<commit_before>extern crate find_folder;

use screen::*;
use ::object;
use piston_window;
use gfx_device_gl;

pub struct BattleScreen {
    player: object::Object,
    up: bool,
    down: bool,
    left: bool,
    right: bool,
}

// TODO: Replace by sprite loader?
// TODO: Remove
fn load_sprite(window: &piston_window::PistonWindow, name: &str) -> piston_window::Texture<gfx_device_gl::Resources> {
    // TODO: Create and use default sprite in case of failure during loading?
    let assets = find_folder::Search::ParentsThenKids(3, 3).for_folder("assets").unwrap();
    let sprite = assets.join(name);
    piston_window::Texture::from_path(&mut *window.factory.borrow_mut(), &sprite, piston_window::Flip::None, &piston_window::TextureSettings::new()).unwrap()
}

impl BattleScreen {
    pub fn new(window: &piston_window::PistonWindow) -> BattleScreen {
        BattleScreen{ player: load_sprite(&window, "skeleton.png"), }
    }
}

impl Screen for BattleScreen {
    fn on_input(&mut self, input: &piston_window::Input, window: &piston_window::PistonWindow) -> InputResults {
        use piston_window::{Input, Button, Key};

        let result = Vec::new();

        match input {
            &Input::Press(button) => {
                match button {
                    Button::Keyboard(Key::Up) => { self.up = true; }
                    Button::Keyboard(Key::Down) => { self.down = true; }
                    Button::Keyboard(Key::Left) => { self.left = true; }
                    Button::Keyboard(Key::Right) => { self.right = true; }
                    _ => {}
                }
            }
            &Input::Release(button) => {
                match button {
                    Button::Keyboard(Key::Up) => { self.up = false; }
                    Button::Keyboard(Key::Down) => { self.down = false; }
                    Button::Keyboard(Key::Left) => { self.left = false; }
                    Button::Keyboard(Key::Right) => { self.right = false; }
                    _ => {}
                }
            }
            _ => {}
        }

        result
    }

    fn on_draw(&mut self, args: &piston_window::RenderArgs, window: &piston_window::PistonWindow) {
	window.draw_2d(|context, graphics| {
	    piston_window::clear([0.0, 0.0, 0.0, 1.0], graphics);

            let center = context.transform.trans((args.width / 2) as f64, (args.height / 2) as f64);
            self.player.render(graphics, &center);
	});
    }

    fn on_update(&mut self, args: &piston_window::UpdateArgs) {
	if self.up   { self.player.mov(0.0, -150.0 * args.dt); }
        if self.down { self.player.mov(0.0, 150.0 * args.dt); }
        if self.left { self.player.mov(-150.0 * args.dt, 0.0); }
        if self.right { self.player.mov(150.0 * args.dt, 0.0); }
    }
}
<commit_msg>BattleScreen constructor fix<commit_after>extern crate find_folder;

use screen::*;
use ::object;
use piston_window;
use gfx_device_gl;

pub struct BattleScreen {
    player: object::Object,
    up: bool,
    down: bool,
    left: bool,
    right: bool,
}

// TODO: Replace by sprite loader?
// TODO: Remove
fn load_sprite(window: &piston_window::PistonWindow, name: &str) -> piston_window::Texture<gfx_device_gl::Resources> {
    // TODO: Create and use default sprite in case of failure during loading?
    let assets = find_folder::Search::ParentsThenKids(3, 3).for_folder("assets").unwrap();
    let sprite = assets.join(name);
    piston_window::Texture::from_path(&mut *window.factory.borrow_mut(), &sprite, piston_window::Flip::None, &piston_window::TextureSettings::new()).unwrap()
}

impl BattleScreen {
    pub fn new(window: &piston_window::PistonWindow) -> BattleScreen {
        BattleScreen {
    	    player: object::Object::new(load_sprite(&window, "skeleton.png")),
    	    up: false, down: false, left: false, right: false,
        }
    }
}

impl Screen for BattleScreen {
    fn on_input(&mut self, input: &piston_window::Input, window: &piston_window::PistonWindow) -> InputResults {
        use piston_window::{Input, Button, Key};

        let result = Vec::new();

        match input {
            &Input::Press(button) => {
                match button {
                    Button::Keyboard(Key::Up) => { self.up = true; }
                    Button::Keyboard(Key::Down) => { self.down = true; }
                    Button::Keyboard(Key::Left) => { self.left = true; }
                    Button::Keyboard(Key::Right) => { self.right = true; }
                    _ => {}
                }
            }
            &Input::Release(button) => {
                match button {
                    Button::Keyboard(Key::Up) => { self.up = false; }
                    Button::Keyboard(Key::Down) => { self.down = false; }
                    Button::Keyboard(Key::Left) => { self.left = false; }
                    Button::Keyboard(Key::Right) => { self.right = false; }
                    _ => {}
                }
            }
            _ => {}
        }

        result
    }

    fn on_draw(&mut self, args: &piston_window::RenderArgs, window: &piston_window::PistonWindow) {
	window.draw_2d(|context, graphics| {
	    piston_window::clear([0.0, 0.0, 0.0, 1.0], graphics);

            let center = context.transform.trans((args.width / 2) as f64, (args.height / 2) as f64);
            self.player.render(graphics, &center);
	});
    }

    fn on_update(&mut self, args: &piston_window::UpdateArgs) {
	if self.up   { self.player.mov(0.0, -150.0 * args.dt); }
        if self.down { self.player.mov(0.0, 150.0 * args.dt); }
        if self.left { self.player.mov(-150.0 * args.dt, 0.0); }
        if self.right { self.player.mov(150.0 * args.dt, 0.0); }
    }
}
<|endoftext|>


<commit_before>use std::io;
use byteorder::{LittleEndian, ByteOrder};
use super::{Error, Deserialize, Serialize};

/// Unsigned variable-length integer, limited to 32 bits,
/// represented by at most 5 bytes that may contain padding 0x80 bytes.
#[derive(Copy, Clone)]
pub struct VarUint32(u32);

impl From<VarUint32> for usize {
    fn from(var: VarUint32) -> usize {
        var.0 as usize
    }
}

impl From<VarUint32> for u32 {
    fn from(var: VarUint32) -> u32 {
        var.0
    }
}

impl From<u32> for VarUint32 {
    fn from(i: u32) -> VarUint32 {
        VarUint32(i)
    }
}

impl From<usize> for VarUint32 {
    fn from(i: usize) -> VarUint32 {
        assert!(i <= ::std::u32::MAX as usize);
        VarUint32(i as u32)
    }
}

impl Deserialize for VarUint32 {
    type Error = Error;

    fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
        let mut res = 0;
        let mut shift = 0;
        let mut u8buf = [0u8; 1];
        loop {
            reader.read_exact(&mut u8buf)?;
            let b = u8buf[0] as u32;
            res |= (b & 0x7f) << shift;
            shift += 7;
            if (b >> 7) == 0 {
                break;
            }
        }
        Ok(VarUint32(res))
    }
}

impl Serialize for VarUint32 {
    type Error = Error;

    fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
        let mut buf = [0u8; 1];
        let mut v = self.0;
        while v >= 0x80 {
            buf[0] = ((v & 0xff) as u8) | 0x80;
            writer.write_all(&buf[..])?;
            v >>= 7;
        }
        buf[0] = (v & 0xff) as u8;
        writer.write_all(&buf[..])?;

        Ok(())
    }
}

/// Unsigned variable-length integer, limited to 64 bits,
/// represented by at most 9 bytes that may contain padding 0x80 bytes.
#[derive(Copy, Clone)]
pub struct VarUint64(u64);

impl From<VarUint64> for u64 {
    fn from(var: VarUint64) -> u64 {
        var.0
    }
}

impl Deserialize for VarUint64 {
    type Error = Error;

    fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
        let mut res = 0;
        let mut shift = 0;
        let mut u8buf = [0u8; 1];
        loop {
            reader.read_exact(&mut u8buf)?;
            let b = u8buf[0] as u64;
            res |= (b & 0x7f) << shift;
            shift += 7;
            if (b >> 7) == 0 {
                break;
            }
        }
        Ok(VarUint64(res))
    }
}

impl Serialize for VarUint64 {
    type Error = Error;

    fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
        let mut buf = [0u8; 1];
        let mut v = self.0;
        while v >= 0x80 {
            buf[0] = ((v & 0xff) as u8) | 0x80;
            writer.write_all(&buf[..])?;
            v >>= 7;
        }
        buf[0] = (v & 0xff) as u8;
        writer.write_all(&buf[..])?;

        Ok(())
    }
}

impl From<u64> for VarUint64 {
    fn from(u: u64) -> VarUint64 {
        VarUint64(u)
    }
}

/// 7-bit unsigned integer, encoded in LEB128 (always 1 byte length)
#[derive(Copy, Clone)]
pub struct VarUint7(u8);

impl From<VarUint7> for u8 {
    fn from(v: VarUint7) -> u8 {
        v.0
    }
}

impl From<u8> for VarUint7 {
    fn from(v: u8) -> Self {
        VarUint7(v)
    }
}

impl Deserialize for VarUint7 {
    type Error = Error;

    fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
        let mut u8buf = [0u8; 1];
        reader.read_exact(&mut u8buf)?;
        Ok(VarUint7(u8buf[0]))
    }
}

impl Serialize for VarUint7 {
    type Error = Error;

    fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
        // todo check range?
        writer.write_all(&[self.0])?;
        Ok(())
    }
}

/// 7-bit signed integer, encoded in LEB128 (always 1 byte length)
#[derive(Copy, Clone)]
pub struct VarInt7(i8);

impl From<VarInt7> for i8 {
    fn from(v: VarInt7) -> i8 {
        v.0
    }
}

impl From<i8> for VarInt7 {
    fn from(v: i8) -> VarInt7 {
        VarInt7(v)
    }
}

impl Deserialize for VarInt7 {
    type Error = Error;

    fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
        let mut u8buf = [0u8; 1];
        reader.read_exact(&mut u8buf)?;
        // expand sign
        if u8buf[0] & 0b0100_0000 == 0b0100_0000 { u8buf[0] |= 0b1000_0000 }
        // todo check range
        Ok(VarInt7(unsafe { ::std::mem::transmute (u8buf[0]) }))
    }
}

impl Serialize for VarInt7 {
    type Error = Error;

    fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
        // todo check range?
        let mut b: u8 = self.0 as u8;
        if self.0 < 0 { b |= 0b0100_0000 }
        writer.write_all(&[b])?;
        Ok(())
    }
}

/// 32-bit unsigned integer, encoded in little endian
#[derive(Copy, Clone)]
pub struct Uint32(u32);

impl Deserialize for Uint32 {
    type Error = Error;

    fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
        let mut buf = [0u8; 4];
        reader.read_exact(&mut buf)?;
        // todo check range
        Ok(Uint32(LittleEndian::read_u32(&buf)))
    }
}

impl From<Uint32> for u32 {
    fn from(var: Uint32) -> u32 {
        var.0
    }
}

impl Serialize for Uint32 {
    type Error = Error;

    fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
        let mut buf = [0u8; 4];
        LittleEndian::write_u32(&mut buf, self.0);
        writer.write_all(&buf)?;
        Ok(())
    }
}

impl From<u32> for Uint32 {
    fn from(u: u32) -> Self { Uint32(u) }
}

/// 64-bit unsigned integer, encoded in little endian
#[derive(Copy, Clone)]
pub struct Uint64(u64);

impl Deserialize for Uint64 {
    type Error = Error;

    fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
        let mut buf = [0u8; 8];
        reader.read_exact(&mut buf)?;
        // todo check range
        Ok(Uint64(LittleEndian::read_u64(&buf)))
    }
}

impl Serialize for Uint64 {
    type Error = Error;

    fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
        let mut buf = [0u8; 8];
        LittleEndian::write_u64(&mut buf, self.0);
        writer.write_all(&buf)?;
        Ok(())
    }
}

impl From<u64> for Uint64 {
    fn from(u: u64) -> Self { Uint64(u) }
}

impl From<Uint64> for u64 {
    fn from(var: Uint64) -> u64 {
        var.0
    }
}

/// VarUint1, 1-bit value (0/1)
#[derive(Copy, Clone)]
pub struct VarUint1(bool);

impl From<VarUint1> for bool {
    fn from(v: VarUint1) -> bool {
        v.0
    }
}

impl From<bool> for VarUint1 {
    fn from(b: bool) -> Self {
        VarUint1(b)
    }
}

impl Deserialize for VarUint1 {
    type Error = Error;

    fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
        let mut u8buf = [0u8; 1];
        reader.read_exact(&mut u8buf)?;
        // todo check range
        Ok(VarUint1(u8buf[0] == 1))
    }
}

impl Serialize for VarUint1 {
    type Error = Error;

    fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
        writer.write_all(&[
            if self.0 { 1u8 } else { 0u8 }
        ])?;
        Ok(())
    }
}

impl Deserialize for String {
    type Error = Error;

    fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
        let length = VarUint32::deserialize(reader)?.into();
        if length > 0 {
            let mut buf = vec![0u8; length];
            reader.read_exact(&mut buf)?;
            String::from_utf8(buf).map_err(|_| Error::NonUtf8String)
        }
        else {
            Ok(String::new())
        }
    }
}

impl Serialize for String {
    type Error = Error;

    fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Error> {
        VarUint32::from(self.len()).serialize(writer)?;
        writer.write_all(&self.into_bytes()[..])?;
        Ok(())
    }
}

/// List for reading sequence of elements typed `T`, given
/// they are preceded by length (serialized as VarUint32)
pub struct CountedList<T: Deserialize>(Vec<T>);

impl<T: Deserialize> CountedList<T> {
    /// Destroy counted list returing inner vector.
    pub fn into_inner(self) -> Vec<T> { self.0 }
}

impl<T: Deserialize> Deserialize for CountedList<T> where T::Error: From<Error> {
    type Error = T::Error;

    fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
        let count: usize = VarUint32::deserialize(reader)?.into();
        let mut result = Vec::new();
        for _ in 0..count { result.push(T::deserialize(reader)?); }
        Ok(CountedList(result))
    }
}

/// Helper struct to write payload which is preceded by
/// it's own length in bytes.
pub struct CountedWriter<'a, W: 'a + io::Write> {
    writer: &'a mut W,
    data: Vec<u8>,
}

impl<'a, W: 'a + io::Write> CountedWriter<'a, W> {
    /// New counted writer on top of the given serial writer
    pub fn new(writer: &'a mut W) -> Self {
        CountedWriter {
            writer: writer,
            data: Vec::new(),
        }
    }

    /// Finish counted writer routing, which writes accumulated length
    /// and actual payload.
    pub fn done(self) -> io::Result<()> {
        let writer = self.writer;
        let data = self.data;
        VarUint32::from(data.len())
            .serialize(writer)
            .map_err(
                |_| io::Error::new(
                    io::ErrorKind::Other,
                    "Length serialization error",
                )
            )?;
        writer.write_all(&data[..])?;
        Ok(())
    }
}

impl<'a, W: 'a + io::Write> io::Write for CountedWriter<'a, W> {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.data.extend(buf.to_vec());
        Ok(buf.len())
    }

    fn flush(&mut self) -> io::Result<()> {
        Ok(())
    }
}

/// Helper struct to write series of `T` preceded by the length of the sequence
/// serialized as VarUint32
pub struct CountedListWriter<I: Serialize<Error=::elements::Error>, T: IntoIterator<Item=I>>(pub usize, pub T);

impl<I: Serialize<Error=::elements::Error>, T: IntoIterator<Item=I>> Serialize for CountedListWriter<I, T> {
    type Error = Error;

    fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
        let len_us = self.0;
        let data = self.1;
        let len: VarUint32 = len_us.into();
        len.serialize(writer)?;
        for data_element in data { data_element.serialize(writer)? }

        Ok(())
    }
}

#[cfg(test)]
mod tests {

    use super::super::{deserialize_buffer, Serialize};
    use super::{CountedList, VarInt7, VarUint32};

    fn varuint32_ser_test(val: u32, expected: Vec<u8>) {
        let mut buf = Vec::new();
        let v1: VarUint32 = val.into();
        v1.serialize(&mut buf).expect("to be serialized ok");
        assert_eq!(expected, buf);
    }

    fn varuint32_de_test(dt: Vec<u8>, expected: u32) {
        let val: VarUint32 = super::super::deserialize_buffer(dt).expect("buf to be serialized");
        assert_eq!(expected, val.into());
    }

    fn varuint32_serde_test(dt: Vec<u8>, val: u32) {
        varuint32_de_test(dt.clone(), val);
        varuint32_ser_test(val, dt);
    }

    #[test]
    fn varuint32_0() {
        varuint32_serde_test(vec![0u8; 1], 0);
    }

    #[test]
    fn varuint32_1() {
        varuint32_serde_test(vec![1u8; 1], 1);
    }

    #[test]
    fn varuint32_135() {
        varuint32_serde_test(vec![135u8, 0x01], 135);
    }

    #[test]
    fn counted_list() {
        let payload = vec![
            133u8, //(128+5), length is 5
                0x80, 0x80, 0x80, 0x0, // padding
            0x01,
            0x7d,
            0x05,
            0x07,
            0x09,
        ];

        let list: CountedList<VarInt7> =
            deserialize_buffer(payload).expect("type_section be deserialized");

        let vars = list.into_inner();
        assert_eq!(5, vars.len());
        let v3: i8 = (*vars.get(1).unwrap()).into();
        assert_eq!(-0x03i8, v3);
    }
}
<commit_msg>fix varint7 serialization<commit_after>use std::io;
use byteorder::{LittleEndian, ByteOrder};
use super::{Error, Deserialize, Serialize};

/// Unsigned variable-length integer, limited to 32 bits,
/// represented by at most 5 bytes that may contain padding 0x80 bytes.
#[derive(Copy, Clone)]
pub struct VarUint32(u32);

impl From<VarUint32> for usize {
    fn from(var: VarUint32) -> usize {
        var.0 as usize
    }
}

impl From<VarUint32> for u32 {
    fn from(var: VarUint32) -> u32 {
        var.0
    }
}

impl From<u32> for VarUint32 {
    fn from(i: u32) -> VarUint32 {
        VarUint32(i)
    }
}

impl From<usize> for VarUint32 {
    fn from(i: usize) -> VarUint32 {
        assert!(i <= ::std::u32::MAX as usize);
        VarUint32(i as u32)
    }
}

impl Deserialize for VarUint32 {
    type Error = Error;

    fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
        let mut res = 0;
        let mut shift = 0;
        let mut u8buf = [0u8; 1];
        loop {
            reader.read_exact(&mut u8buf)?;
            let b = u8buf[0] as u32;
            res |= (b & 0x7f) << shift;
            shift += 7;
            if (b >> 7) == 0 {
                break;
            }
        }
        Ok(VarUint32(res))
    }
}

impl Serialize for VarUint32 {
    type Error = Error;

    fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
        let mut buf = [0u8; 1];
        let mut v = self.0;
        while v >= 0x80 {
            buf[0] = ((v & 0xff) as u8) | 0x80;
            writer.write_all(&buf[..])?;
            v >>= 7;
        }
        buf[0] = (v & 0xff) as u8;
        writer.write_all(&buf[..])?;

        Ok(())
    }
}

/// Unsigned variable-length integer, limited to 64 bits,
/// represented by at most 9 bytes that may contain padding 0x80 bytes.
#[derive(Copy, Clone)]
pub struct VarUint64(u64);

impl From<VarUint64> for u64 {
    fn from(var: VarUint64) -> u64 {
        var.0
    }
}

impl Deserialize for VarUint64 {
    type Error = Error;

    fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
        let mut res = 0;
        let mut shift = 0;
        let mut u8buf = [0u8; 1];
        loop {
            reader.read_exact(&mut u8buf)?;
            let b = u8buf[0] as u64;
            res |= (b & 0x7f) << shift;
            shift += 7;
            if (b >> 7) == 0 {
                break;
            }
        }
        Ok(VarUint64(res))
    }
}

impl Serialize for VarUint64 {
    type Error = Error;

    fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
        let mut buf = [0u8; 1];
        let mut v = self.0;
        while v >= 0x80 {
            buf[0] = ((v & 0xff) as u8) | 0x80;
            writer.write_all(&buf[..])?;
            v >>= 7;
        }
        buf[0] = (v & 0xff) as u8;
        writer.write_all(&buf[..])?;

        Ok(())
    }
}

impl From<u64> for VarUint64 {
    fn from(u: u64) -> VarUint64 {
        VarUint64(u)
    }
}

/// 7-bit unsigned integer, encoded in LEB128 (always 1 byte length)
#[derive(Copy, Clone)]
pub struct VarUint7(u8);

impl From<VarUint7> for u8 {
    fn from(v: VarUint7) -> u8 {
        v.0
    }
}

impl From<u8> for VarUint7 {
    fn from(v: u8) -> Self {
        VarUint7(v)
    }
}

impl Deserialize for VarUint7 {
    type Error = Error;

    fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
        let mut u8buf = [0u8; 1];
        reader.read_exact(&mut u8buf)?;
        Ok(VarUint7(u8buf[0]))
    }
}

impl Serialize for VarUint7 {
    type Error = Error;

    fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
        // todo check range?
        writer.write_all(&[self.0])?;
        Ok(())
    }
}

/// 7-bit signed integer, encoded in LEB128 (always 1 byte length)
#[derive(Copy, Clone)]
pub struct VarInt7(i8);

impl From<VarInt7> for i8 {
    fn from(v: VarInt7) -> i8 {
        v.0
    }
}

impl From<i8> for VarInt7 {
    fn from(v: i8) -> VarInt7 {
        VarInt7(v)
    }
}

impl Deserialize for VarInt7 {
    type Error = Error;

    fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
        let mut u8buf = [0u8; 1];
        reader.read_exact(&mut u8buf)?;
        // expand sign
        if u8buf[0] & 0b0100_0000 == 0b0100_0000 { u8buf[0] |= 0b1000_0000 }
        // todo check range
        Ok(VarInt7(unsafe { ::std::mem::transmute (u8buf[0]) }))
    }
}

impl Serialize for VarInt7 {
    type Error = Error;

    fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
        // todo check range?
        let mut b: u8 = self.0 as u8;
        if self.0 < 0 { b |= 0b0100_0000; b &= 0b0111_1111; }
        writer.write_all(&[b])?;
        Ok(())
    }
}

/// 32-bit unsigned integer, encoded in little endian
#[derive(Copy, Clone)]
pub struct Uint32(u32);

impl Deserialize for Uint32 {
    type Error = Error;

    fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
        let mut buf = [0u8; 4];
        reader.read_exact(&mut buf)?;
        // todo check range
        Ok(Uint32(LittleEndian::read_u32(&buf)))
    }
}

impl From<Uint32> for u32 {
    fn from(var: Uint32) -> u32 {
        var.0
    }
}

impl Serialize for Uint32 {
    type Error = Error;

    fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
        let mut buf = [0u8; 4];
        LittleEndian::write_u32(&mut buf, self.0);
        writer.write_all(&buf)?;
        Ok(())
    }
}

impl From<u32> for Uint32 {
    fn from(u: u32) -> Self { Uint32(u) }
}

/// 64-bit unsigned integer, encoded in little endian
#[derive(Copy, Clone)]
pub struct Uint64(u64);

impl Deserialize for Uint64 {
    type Error = Error;

    fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
        let mut buf = [0u8; 8];
        reader.read_exact(&mut buf)?;
        // todo check range
        Ok(Uint64(LittleEndian::read_u64(&buf)))
    }
}

impl Serialize for Uint64 {
    type Error = Error;

    fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
        let mut buf = [0u8; 8];
        LittleEndian::write_u64(&mut buf, self.0);
        writer.write_all(&buf)?;
        Ok(())
    }
}

impl From<u64> for Uint64 {
    fn from(u: u64) -> Self { Uint64(u) }
}

impl From<Uint64> for u64 {
    fn from(var: Uint64) -> u64 {
        var.0
    }
}

/// VarUint1, 1-bit value (0/1)
#[derive(Copy, Clone)]
pub struct VarUint1(bool);

impl From<VarUint1> for bool {
    fn from(v: VarUint1) -> bool {
        v.0
    }
}

impl From<bool> for VarUint1 {
    fn from(b: bool) -> Self {
        VarUint1(b)
    }
}

impl Deserialize for VarUint1 {
    type Error = Error;

    fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
        let mut u8buf = [0u8; 1];
        reader.read_exact(&mut u8buf)?;
        // todo check range
        Ok(VarUint1(u8buf[0] == 1))
    }
}

impl Serialize for VarUint1 {
    type Error = Error;

    fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
        writer.write_all(&[
            if self.0 { 1u8 } else { 0u8 }
        ])?;
        Ok(())
    }
}

impl Deserialize for String {
    type Error = Error;

    fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
        let length = VarUint32::deserialize(reader)?.into();
        if length > 0 {
            let mut buf = vec![0u8; length];
            reader.read_exact(&mut buf)?;
            String::from_utf8(buf).map_err(|_| Error::NonUtf8String)
        }
        else {
            Ok(String::new())
        }
    }
}

impl Serialize for String {
    type Error = Error;

    fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Error> {
        VarUint32::from(self.len()).serialize(writer)?;
        writer.write_all(&self.into_bytes()[..])?;
        Ok(())
    }
}

/// List for reading sequence of elements typed `T`, given
/// they are preceded by length (serialized as VarUint32)
pub struct CountedList<T: Deserialize>(Vec<T>);

impl<T: Deserialize> CountedList<T> {
    /// Destroy counted list returing inner vector.
    pub fn into_inner(self) -> Vec<T> { self.0 }
}

impl<T: Deserialize> Deserialize for CountedList<T> where T::Error: From<Error> {
    type Error = T::Error;

    fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
        let count: usize = VarUint32::deserialize(reader)?.into();
        let mut result = Vec::new();
        for _ in 0..count { result.push(T::deserialize(reader)?); }
        Ok(CountedList(result))
    }
}

/// Helper struct to write payload which is preceded by
/// it's own length in bytes.
pub struct CountedWriter<'a, W: 'a + io::Write> {
    writer: &'a mut W,
    data: Vec<u8>,
}

impl<'a, W: 'a + io::Write> CountedWriter<'a, W> {
    /// New counted writer on top of the given serial writer
    pub fn new(writer: &'a mut W) -> Self {
        CountedWriter {
            writer: writer,
            data: Vec::new(),
        }
    }

    /// Finish counted writer routing, which writes accumulated length
    /// and actual payload.
    pub fn done(self) -> io::Result<()> {
        let writer = self.writer;
        let data = self.data;
        VarUint32::from(data.len())
            .serialize(writer)
            .map_err(
                |_| io::Error::new(
                    io::ErrorKind::Other,
                    "Length serialization error",
                )
            )?;
        writer.write_all(&data[..])?;
        Ok(())
    }
}

impl<'a, W: 'a + io::Write> io::Write for CountedWriter<'a, W> {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.data.extend(buf.to_vec());
        Ok(buf.len())
    }

    fn flush(&mut self) -> io::Result<()> {
        Ok(())
    }
}

/// Helper struct to write series of `T` preceded by the length of the sequence
/// serialized as VarUint32
pub struct CountedListWriter<I: Serialize<Error=::elements::Error>, T: IntoIterator<Item=I>>(pub usize, pub T);

impl<I: Serialize<Error=::elements::Error>, T: IntoIterator<Item=I>> Serialize for CountedListWriter<I, T> {
    type Error = Error;

    fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
        let len_us = self.0;
        let data = self.1;
        let len: VarUint32 = len_us.into();
        len.serialize(writer)?;
        for data_element in data { data_element.serialize(writer)? }

        Ok(())
    }
}

#[cfg(test)]
mod tests {

    use super::super::{deserialize_buffer, Serialize};
    use super::{CountedList, VarInt7, VarUint32};

    fn varuint32_ser_test(val: u32, expected: Vec<u8>) {
        let mut buf = Vec::new();
        let v1: VarUint32 = val.into();
        v1.serialize(&mut buf).expect("to be serialized ok");
        assert_eq!(expected, buf);
    }

    fn varuint32_de_test(dt: Vec<u8>, expected: u32) {
        let val: VarUint32 = super::super::deserialize_buffer(dt).expect("buf to be serialized");
        assert_eq!(expected, val.into());
    }

    fn varuint32_serde_test(dt: Vec<u8>, val: u32) {
        varuint32_de_test(dt.clone(), val);
        varuint32_ser_test(val, dt);
    }

    #[test]
    fn varuint32_0() {
        varuint32_serde_test(vec![0u8; 1], 0);
    }

    #[test]
    fn varuint32_1() {
        varuint32_serde_test(vec![1u8; 1], 1);
    }

    #[test]
    fn varuint32_135() {
        varuint32_serde_test(vec![135u8, 0x01], 135);
    }

    #[test]
    fn counted_list() {
        let payload = vec![
            133u8, //(128+5), length is 5
                0x80, 0x80, 0x80, 0x0, // padding
            0x01,
            0x7d,
            0x05,
            0x07,
            0x09,
        ];

        let list: CountedList<VarInt7> =
            deserialize_buffer(payload).expect("type_section be deserialized");

        let vars = list.into_inner();
        assert_eq!(5, vars.len());
        let v3: i8 = (*vars.get(1).unwrap()).into();
        assert_eq!(-0x03i8, v3);
    }
}
<|endoftext|>


<commit_before>use crate::time::driver::{Handle, TimerEntry};
use crate::time::{error::Error, Duration, Instant};

use pin_project_lite::pin_project;
use std::future::Future;
use std::pin::Pin;
use std::task::{self, Poll};

/// Waits until `deadline` is reached.
///
/// No work is performed while awaiting on the sleep future to complete. `Sleep`
/// operates at millisecond granularity and should not be used for tasks that
/// require high-resolution timers.
///
/// # Cancellation
///
/// Canceling a sleep instance is done by dropping the returned future. No additional
/// cleanup work is required.
// Alias for old name in 0.x
#[cfg_attr(docsrs, doc(alias = "delay_until"))]
pub fn sleep_until(deadline: Instant) -> Sleep {
    Sleep::new_timeout(deadline)
}

/// Waits until `duration` has elapsed.
///
/// Equivalent to `sleep_until(Instant::now() + duration)`. An asynchronous
/// analog to `std::thread::sleep`.
///
/// No work is performed while awaiting on the sleep future to complete. `Sleep`
/// operates at millisecond granularity and should not be used for tasks that
/// require high-resolution timers.
///
/// To run something regularly on a schedule, see [`interval`].
///
/// The maximum duration for a sleep is 68719476734 milliseconds (approximately 2.2 years).
///
/// # Cancellation
///
/// Canceling a sleep instance is done by dropping the returned future. No additional
/// cleanup work is required.
///
/// # Examples
///
/// Wait 100ms and print "100 ms have elapsed".
///
/// ```
/// use tokio::time::{sleep, Duration};
///
/// #[tokio::main]
/// async fn main() {
///     sleep(Duration::from_millis(100)).await;
///     println!("100 ms have elapsed");
/// }
/// ```
///
/// [`interval`]: crate::time::interval()
// Alias for old name in 0.x
#[cfg_attr(docsrs, doc(alias = "delay_for"))]
#[cfg_attr(docsrs, doc(alias = "wait"))]
pub fn sleep(duration: Duration) -> Sleep {
    match Instant::now().checked_add(duration) {
        Some(deadline) => sleep_until(deadline),
        None => sleep_until(Instant::far_future()),
    }
}

pin_project! {
    /// Future returned by [`sleep`](sleep) and [`sleep_until`](sleep_until).
    ///
    /// This type does not implement the `Unpin` trait, which means that if you
    /// use it with [`select!`] or by calling `poll`, you have to pin it first.
    /// If you use it with `.await`, this does not apply.
    ///
    /// # Examples
    ///
    /// Wait 100ms and print "100 ms have elapsed".
    ///
    /// ```
    /// use tokio::time::{sleep, Duration};
    ///
    /// #[tokio::main]
    /// async fn main() {
    ///     sleep(Duration::from_millis(100)).await;
    ///     println!("100 ms have elapsed");
    /// }
    /// ```
    ///
    /// Use with [`select!`]. Pinning the `Sleep` with [`tokio::pin!`] is
    /// necessary when the same `Sleep` is selected on multiple times.
    /// ```no_run
    /// use tokio::time::{self, Duration, Instant};
    ///
    /// #[tokio::main]
    /// async fn main() {
    ///     let sleep = time::sleep(Duration::from_millis(10));
    ///     tokio::pin!(sleep);
    ///
    ///     loop {
    ///         tokio::select! {
    ///             () = &mut sleep => {
    ///                 println!("timer elapsed");
    ///                 sleep.as_mut().reset(Instant::now() + Duration::from_millis(50));
    ///             },
    ///         }
    ///     }
    /// }
    /// ```
    /// Use in a struct with boxing. By pinning the `Sleep` with a `Box`, the
    /// `HasSleep` struct implements `Unpin`, even though `Sleep` does not.
    /// ```
    /// use std::future::Future;
    /// use std::pin::Pin;
    /// use std::task::{Context, Poll};
    /// use tokio::time::Sleep;
    ///
    /// struct HasSleep {
    ///     sleep: Pin<Box<Sleep>>,
    /// }
    ///
    /// impl Future for HasSleep {
    ///     type Output = ();
    ///
    ///     fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
    ///         self.sleep.as_mut().poll(cx)
    ///     }
    /// }
    /// ```
    /// Use in a struct with pin projection. This method avoids the `Box`, but
    /// the `HasSleep` struct will not be `Unpin` as a consequence.
    /// ```
    /// use std::future::Future;
    /// use std::pin::Pin;
    /// use std::task::{Context, Poll};
    /// use tokio::time::Sleep;
    /// use pin_project_lite::pin_project;
    ///
    /// pin_project! {
    ///     struct HasSleep {
    ///         #[pin]
    ///         sleep: Sleep,
    ///     }
    /// }
    ///
    /// impl Future for HasSleep {
    ///     type Output = ();
    ///
    ///     fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
    ///         self.project().sleep.poll(cx)
    ///     }
    /// }
    /// ```
    ///
    /// [`select!`]: ../macro.select.html
    /// [`tokio::pin!`]: ../macro.pin.html
    // Alias for old name in 0.2
    #[cfg_attr(docsrs, doc(alias = "Delay"))]
    #[derive(Debug)]
    #[must_use = "futures do nothing unless you `.await` or poll them"]
    pub struct Sleep {
        deadline: Instant,

        // The link between the `Sleep` instance and the timer that drives it.
        #[pin]
        entry: TimerEntry,
    }
}

impl Sleep {
    pub(crate) fn new_timeout(deadline: Instant) -> Sleep {
        let handle = Handle::current();
        let entry = TimerEntry::new(&handle, deadline);

        Sleep { deadline, entry }
    }

    pub(crate) fn far_future() -> Sleep {
        Self::new_timeout(Instant::far_future())
    }

    /// Returns the instant at which the future will complete.
    pub fn deadline(&self) -> Instant {
        self.deadline
    }

    /// Returns `true` if `Sleep` has elapsed.
    ///
    /// A `Sleep` instance is elapsed when the requested duration has elapsed.
    pub fn is_elapsed(&self) -> bool {
        self.entry.is_elapsed()
    }

    /// Resets the `Sleep` instance to a new deadline.
    ///
    /// Calling this function allows changing the instant at which the `Sleep`
    /// future completes without having to create new associated state.
    ///
    /// This function can be called both before and after the future has
    /// completed.
    ///
    /// To call this method, you will usually combine the call with
    /// [`Pin::as_mut`], which lets you call the method without consuming the
    /// `Sleep` itself.
    ///
    /// # Example
    ///
    /// ```
    /// use tokio::time::{Duration, Instant};
    ///
    /// # #[tokio::main(flavor = "current_thread")]
    /// # async fn main() {
    /// let sleep = tokio::time::sleep(Duration::from_millis(10));
    /// tokio::pin!(sleep);
    ///
    /// sleep.as_mut().reset(Instant::now() + Duration::from_millis(20));
    /// # }
    /// ```
    ///
    /// [`Pin::as_mut`]: fn@std::pin::Pin::as_mut
    pub fn reset(self: Pin<&mut Self>, deadline: Instant) {
        let me = self.project();
        me.entry.reset(deadline);
        *me.deadline = deadline;
    }

    fn poll_elapsed(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Result<(), Error>> {
        let me = self.project();

        // Keep track of task budget
        let coop = ready!(crate::coop::poll_proceed(cx));

        me.entry.poll_elapsed(cx).map(move |r| {
            coop.made_progress();
            r
        })
    }
}

impl Future for Sleep {
    type Output = ();

    fn poll(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> {
        // `poll_elapsed` can return an error in two cases:
        //
        // - AtCapacity: this is a pathological case where far too many
        //   sleep instances have been scheduled.
        // - Shutdown: No timer has been setup, which is a mis-use error.
        //
        // Both cases are extremely rare, and pretty accurately fit into
        // "logic errors", so we just panic in this case. A user couldn't
        // really do much better if we passed the error onwards.
        match ready!(self.as_mut().poll_elapsed(cx)) {
            Ok(()) => Poll::Ready(()),
            Err(e) => panic!("timer error: {}", e),
        }
    }
}
<commit_msg>time: make Sleep examples easier to find (#4040)<commit_after>use crate::time::driver::{Handle, TimerEntry};
use crate::time::{error::Error, Duration, Instant};

use pin_project_lite::pin_project;
use std::future::Future;
use std::pin::Pin;
use std::task::{self, Poll};

/// Waits until `deadline` is reached.
///
/// No work is performed while awaiting on the sleep future to complete. `Sleep`
/// operates at millisecond granularity and should not be used for tasks that
/// require high-resolution timers.
///
/// To run something regularly on a schedule, see [`interval`].
///
/// # Cancellation
///
/// Canceling a sleep instance is done by dropping the returned future. No additional
/// cleanup work is required.
///
/// # Examples
///
/// Wait 100ms and print "100 ms have elapsed".
///
/// ```
/// use tokio::time::{sleep_until, Instant, Duration};
///
/// #[tokio::main]
/// async fn main() {
///     sleep_until(Instant::now() + Duration::from_millis(100)).await;
///     println!("100 ms have elapsed");
/// }
/// ```
///
/// See the documentation for the [`Sleep`] type for more examples.
///
/// [`Sleep`]: struct@crate::time::Sleep
/// [`interval`]: crate::time::interval()
// Alias for old name in 0.x
#[cfg_attr(docsrs, doc(alias = "delay_until"))]
pub fn sleep_until(deadline: Instant) -> Sleep {
    Sleep::new_timeout(deadline)
}

/// Waits until `duration` has elapsed.
///
/// Equivalent to `sleep_until(Instant::now() + duration)`. An asynchronous
/// analog to `std::thread::sleep`.
///
/// No work is performed while awaiting on the sleep future to complete. `Sleep`
/// operates at millisecond granularity and should not be used for tasks that
/// require high-resolution timers.
///
/// To run something regularly on a schedule, see [`interval`].
///
/// The maximum duration for a sleep is 68719476734 milliseconds (approximately 2.2 years).
///
/// # Cancellation
///
/// Canceling a sleep instance is done by dropping the returned future. No additional
/// cleanup work is required.
///
/// # Examples
///
/// Wait 100ms and print "100 ms have elapsed".
///
/// ```
/// use tokio::time::{sleep, Duration};
///
/// #[tokio::main]
/// async fn main() {
///     sleep(Duration::from_millis(100)).await;
///     println!("100 ms have elapsed");
/// }
/// ```
///
/// See the documentation for the [`Sleep`] type for more examples.
///
/// [`Sleep`]: struct@crate::time::Sleep
/// [`interval`]: crate::time::interval()
// Alias for old name in 0.x
#[cfg_attr(docsrs, doc(alias = "delay_for"))]
#[cfg_attr(docsrs, doc(alias = "wait"))]
pub fn sleep(duration: Duration) -> Sleep {
    match Instant::now().checked_add(duration) {
        Some(deadline) => sleep_until(deadline),
        None => sleep_until(Instant::far_future()),
    }
}

pin_project! {
    /// Future returned by [`sleep`](sleep) and [`sleep_until`](sleep_until).
    ///
    /// This type does not implement the `Unpin` trait, which means that if you
    /// use it with [`select!`] or by calling `poll`, you have to pin it first.
    /// If you use it with `.await`, this does not apply.
    ///
    /// # Examples
    ///
    /// Wait 100ms and print "100 ms have elapsed".
    ///
    /// ```
    /// use tokio::time::{sleep, Duration};
    ///
    /// #[tokio::main]
    /// async fn main() {
    ///     sleep(Duration::from_millis(100)).await;
    ///     println!("100 ms have elapsed");
    /// }
    /// ```
    ///
    /// Use with [`select!`]. Pinning the `Sleep` with [`tokio::pin!`] is
    /// necessary when the same `Sleep` is selected on multiple times.
    /// ```no_run
    /// use tokio::time::{self, Duration, Instant};
    ///
    /// #[tokio::main]
    /// async fn main() {
    ///     let sleep = time::sleep(Duration::from_millis(10));
    ///     tokio::pin!(sleep);
    ///
    ///     loop {
    ///         tokio::select! {
    ///             () = &mut sleep => {
    ///                 println!("timer elapsed");
    ///                 sleep.as_mut().reset(Instant::now() + Duration::from_millis(50));
    ///             },
    ///         }
    ///     }
    /// }
    /// ```
    /// Use in a struct with boxing. By pinning the `Sleep` with a `Box`, the
    /// `HasSleep` struct implements `Unpin`, even though `Sleep` does not.
    /// ```
    /// use std::future::Future;
    /// use std::pin::Pin;
    /// use std::task::{Context, Poll};
    /// use tokio::time::Sleep;
    ///
    /// struct HasSleep {
    ///     sleep: Pin<Box<Sleep>>,
    /// }
    ///
    /// impl Future for HasSleep {
    ///     type Output = ();
    ///
    ///     fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
    ///         self.sleep.as_mut().poll(cx)
    ///     }
    /// }
    /// ```
    /// Use in a struct with pin projection. This method avoids the `Box`, but
    /// the `HasSleep` struct will not be `Unpin` as a consequence.
    /// ```
    /// use std::future::Future;
    /// use std::pin::Pin;
    /// use std::task::{Context, Poll};
    /// use tokio::time::Sleep;
    /// use pin_project_lite::pin_project;
    ///
    /// pin_project! {
    ///     struct HasSleep {
    ///         #[pin]
    ///         sleep: Sleep,
    ///     }
    /// }
    ///
    /// impl Future for HasSleep {
    ///     type Output = ();
    ///
    ///     fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
    ///         self.project().sleep.poll(cx)
    ///     }
    /// }
    /// ```
    ///
    /// [`select!`]: ../macro.select.html
    /// [`tokio::pin!`]: ../macro.pin.html
    // Alias for old name in 0.2
    #[cfg_attr(docsrs, doc(alias = "Delay"))]
    #[derive(Debug)]
    #[must_use = "futures do nothing unless you `.await` or poll them"]
    pub struct Sleep {
        deadline: Instant,

        // The link between the `Sleep` instance and the timer that drives it.
        #[pin]
        entry: TimerEntry,
    }
}

impl Sleep {
    pub(crate) fn new_timeout(deadline: Instant) -> Sleep {
        let handle = Handle::current();
        let entry = TimerEntry::new(&handle, deadline);

        Sleep { deadline, entry }
    }

    pub(crate) fn far_future() -> Sleep {
        Self::new_timeout(Instant::far_future())
    }

    /// Returns the instant at which the future will complete.
    pub fn deadline(&self) -> Instant {
        self.deadline
    }

    /// Returns `true` if `Sleep` has elapsed.
    ///
    /// A `Sleep` instance is elapsed when the requested duration has elapsed.
    pub fn is_elapsed(&self) -> bool {
        self.entry.is_elapsed()
    }

    /// Resets the `Sleep` instance to a new deadline.
    ///
    /// Calling this function allows changing the instant at which the `Sleep`
    /// future completes without having to create new associated state.
    ///
    /// This function can be called both before and after the future has
    /// completed.
    ///
    /// To call this method, you will usually combine the call with
    /// [`Pin::as_mut`], which lets you call the method without consuming the
    /// `Sleep` itself.
    ///
    /// # Example
    ///
    /// ```
    /// use tokio::time::{Duration, Instant};
    ///
    /// # #[tokio::main(flavor = "current_thread")]
    /// # async fn main() {
    /// let sleep = tokio::time::sleep(Duration::from_millis(10));
    /// tokio::pin!(sleep);
    ///
    /// sleep.as_mut().reset(Instant::now() + Duration::from_millis(20));
    /// # }
    /// ```
    ///
    /// See also the top-level examples.
    ///
    /// [`Pin::as_mut`]: fn@std::pin::Pin::as_mut
    pub fn reset(self: Pin<&mut Self>, deadline: Instant) {
        let me = self.project();
        me.entry.reset(deadline);
        *me.deadline = deadline;
    }

    fn poll_elapsed(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Result<(), Error>> {
        let me = self.project();

        // Keep track of task budget
        let coop = ready!(crate::coop::poll_proceed(cx));

        me.entry.poll_elapsed(cx).map(move |r| {
            coop.made_progress();
            r
        })
    }
}

impl Future for Sleep {
    type Output = ();

    fn poll(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> {
        // `poll_elapsed` can return an error in two cases:
        //
        // - AtCapacity: this is a pathological case where far too many
        //   sleep instances have been scheduled.
        // - Shutdown: No timer has been setup, which is a mis-use error.
        //
        // Both cases are extremely rare, and pretty accurately fit into
        // "logic errors", so we just panic in this case. A user couldn't
        // really do much better if we passed the error onwards.
        match ready!(self.as_mut().poll_elapsed(cx)) {
            Ok(()) => Poll::Ready(()),
            Err(e) => panic!("timer error: {}", e),
        }
    }
}
<|endoftext|>


<commit_before>use agent::*;

mod agent;

// Type Observer
pub trait Observer {
    fn see(&mut self, time: f64, crowd: &Crowd);
    fn request_at(&mut self, time: f64) -> bool;
}

//
// * Affichage à l'écran
//
struct ScreenPrinter {
    freq: uint,
    ticks: uint
}

pub impl ScreenPrinter {
    fn new(freq: uint) -> ScreenPrinter {
        ScreenPrinter { freq: freq, ticks: 0}
    }
}

impl Observer for ScreenPrinter {
    fn see(&mut self, time: f64, crowd: &Crowd) {
        io::println(fmt!("%f\n", time as float));
        io::println(crowd.to_str());
    }

    fn request_at(&mut self, time: f64) -> bool {
        self.ticks+=1;
        self.ticks % self.freq == 0
    }
}

//
// * Sortie sur le disque
//
struct DiskWriter {
    freq: uint,
    fname: ~str,
    curr_snap: uint,
    ticks: uint
}

pub impl DiskWriter {
    fn new(freq:uint, name: ~str) -> DiskWriter {
        DiskWriter {freq: freq, fname: copy name, curr_snap: 0, ticks: 0}
    }

    fn new_filename(&mut self) -> ~str {
        self.curr_snap+=1;
        fmt!("./%s-%u.vtk", self.fname, self.curr_snap-1)
    }
}

impl Observer for DiskWriter {
    fn see(&mut self, time: f64, crowd: &Crowd) {
        let outfile=self.new_filename();
        io::println(fmt!("%f : %d cells -> %s.\n",time as float, crowd.size() as int, outfile));
        let writer = result::get( &io::file_writer( &Path(outfile), [io::Create, io::Truncate] ) );

        // Ecriture de l'entête
        writer.write_str("# vtk DataFile Version 3.0\n");
        writer.write_str("Rusty_Cells\n");
        writer.write_str("ASCII\n");
        writer.write_str("DATASET UNSTRUCTURED_GRID\n");
        writer.write_str(fmt!("POINTS %u float\n", crowd.size()));

        // Coordonnées des cellules
        for crowd.cells.each |&cell| {
            writer.write_str(fmt!("%f %f 0\n",cell.x() as float, cell.y() as float))
        }

        // Données sur les nœuds
        writer.write_str(fmt!("POINT_DATA %u\nSCALARS %s float\nLOOKUP_TABLE default\n", crowd.size(), self.fname));
        for crowd.cells.each |&cell| {
            writer.write_str(fmt!("%u\n", cell.id));
        }
    }

    fn request_at(&mut self, time: f64) -> bool {
        self.ticks+=1;
        self.ticks % self.freq == 0
    }

}
<commit_msg>On utilise directement println plutôt que io::println<commit_after>use agent::*;

mod agent;

// Type Observer
pub trait Observer {
    fn see(&mut self, time: f64, crowd: &Crowd);
    fn request_at(&mut self, time: f64) -> bool;
}

//
// * Affichage à l'écran
//
struct ScreenPrinter {
    freq: uint,
    ticks: uint
}

pub impl ScreenPrinter {
    fn new(freq: uint) -> ScreenPrinter {
        ScreenPrinter { freq: freq, ticks: 0}
    }
}

impl Observer for ScreenPrinter {
    fn see(&mut self, time: f64, crowd: &Crowd) {
        println(fmt!("%f\n", time as float));
        println(crowd.to_str());
    }

    fn request_at(&mut self, time: f64) -> bool {
        self.ticks+=1;
        self.ticks % self.freq == 0
    }
}

//
// * Sortie sur le disque
//
struct DiskWriter {
    freq: uint,
    fname: ~str,
    curr_snap: uint,
    ticks: uint
}

pub impl DiskWriter {
    fn new(freq:uint, name: ~str) -> DiskWriter {
        DiskWriter {freq: freq, fname: copy name, curr_snap: 0, ticks: 0}
    }

    fn new_filename(&mut self) -> ~str {
        self.curr_snap+=1;
        fmt!("./%s-%u.vtk", self.fname, self.curr_snap-1)
    }
}

impl Observer for DiskWriter {
    fn see(&mut self, time: f64, crowd: &Crowd) {
        let outfile=self.new_filename();
        let writer = result::get( &io::file_writer( &Path(outfile), [io::Create, io::Truncate] ) );

        // Ecriture de l'entête
        writer.write_str("# vtk DataFile Version 3.0\n");
        writer.write_str("Rusty_Cells\n");
        writer.write_str("ASCII\n");
        writer.write_str("DATASET UNSTRUCTURED_GRID\n");
        writer.write_str(fmt!("POINTS %u float\n", crowd.size()));

        // Coordonnées des cellules
        for crowd.cells.each |&cell| {
            writer.write_str(fmt!("%f %f 0\n",cell.x() as float, cell.y() as float))
        }

        // Données sur les nœuds
        writer.write_str(fmt!("POINT_DATA %u\nSCALARS %s float\nLOOKUP_TABLE default\n", crowd.size(), self.fname));
        for crowd.cells.each |&cell| {
            writer.write_str(fmt!("%u\n", cell.id));
        }
    }

    fn request_at(&mut self, time: f64) -> bool {
        self.ticks+=1;
        self.ticks % self.freq == 0
    }

}
<|endoftext|>