<commit_before>extern crate byteorder;
extern crate tempfile;
#[macro_use]
extern crate wayland_client;
#[macro_use]
extern crate wlroots;

use std::thread;
use std::time::Duration;

use wlroots::{matrix_mul, matrix_rotate, matrix_scale, matrix_translate, Area, Compositor,
              CompositorBuilder, CursorBuilder, GenericRenderer, InputManagerHandler, Keyboard,
              KeyboardHandler, Origin, Output, OutputBuilder, OutputBuilderResult, OutputHandler,
              OutputLayout, OutputManagerHandler, Pointer, PointerHandler, Size, WlShellHandler,
              WlShellManagerHandler, WlShellSurface, WlShellSurfaceHandle, XCursorTheme};
use wlroots::key_events::KeyEvent;
use wlroots::pointer_events::{AxisEvent, ButtonEvent, MotionEvent};
use wlroots::utils::{init_logging, L_DEBUG};
use wlroots::wlroots_sys::wlr_button_state::WLR_BUTTON_RELEASED;
use wlroots::xkbcommon::xkb::keysyms::KEY_Escape;

/// Render the shells in the current compositor state on the given output.
fn render_shells(state: &mut State, output: &mut Output, renderer: &mut GenericRenderer) {
    let shells = state.shells.clone();
    for mut shell in shells {
        shell.run(|shell| {
                      shell.surface()
                           .run(|surface| {
                                    let (width, height) = {
                                        let current_state = surface.current_state();
                                        (current_state.width() as i32,
                                        current_state.height() as i32)
                                    };
                                    let (render_width, render_height) =
                                        (width * output.scale() as i32,
                                        height * output.scale() as i32);
                                    // TODO Some value from something else?
                                    let (lx, ly) = (0.0, 0.0);
                                    let (mut ox, mut oy) = (lx, ly);
                                    state.layout.output_coords(output, &mut ox, &mut oy);
                                    ox *= output.scale() as f64;
                                    oy *= output.scale() as f64;
                                    let render_box = Area::new(Origin::new(lx as i32, ly as i32),
                                                               Size::new(render_width,
                                                                         render_height));
                                    if state.layout.intersects(output, render_box) {
                                        let mut renderer = renderer.render(output);
                                        let mut matrix = [0.0; 16];
                                        let mut translate_center = [0.0; 16];
                                        matrix_translate(&mut translate_center,
                                                         (ox as i32 + render_width / 2) as f32,
                                                         (oy as i32 + render_height / 2) as f32,
                                                         0.0);
                                        let mut rotate = [0.0; 16];
                                        // TODO what is rotation
                                        let rotation = 0.0;
                                        matrix_rotate(&mut rotate, rotation);

                                        let mut translate_origin = [0.0; 16];
                                        matrix_translate(&mut translate_origin,
                                                         (-render_width / 2) as f32,
                                                         (-render_height / 2) as f32,
                                                         0.0);

                                        let mut scale = [0.0; 16];
                                        matrix_scale(&mut scale,
                                                     render_width as f32,
                                                     render_height as f32,
                                                     1.0);

                                        let mut transform = [0.0; 16];
                                        matrix_mul(&translate_center, &mut rotate, &mut transform);
                                        matrix_mul(&transform.clone(),
                                                   &mut translate_origin,
                                                   &mut transform);
                                        matrix_mul(&transform.clone(), &mut scale, &mut transform);

                                        // TODO Handle non transform normal on the output
                                        // if ... {}
                                        matrix_mul(&renderer.output.transform_matrix(),
                                                   &mut transform,
                                                   &mut matrix);
                                        renderer.render_with_matrix(&surface.texture(), &matrix);
                                        surface.send_frame_done(Duration::from_secs(1));
                                    }
                                })
                           .unwrap()
                  })
             .unwrap();
    }
}

struct State {
    color: [f32; 4],
    default_color: [f32; 4],
    xcursor_theme: XCursorTheme,
    layout: OutputLayout,
    shells: Vec<WlShellSurfaceHandle>
}

impl State {
    fn new(xcursor_theme: XCursorTheme, layout: OutputLayout) -> Self {
        State { color: [0.25, 0.25, 0.25, 1.0],
                default_color: [0.25, 0.25, 0.25, 1.0],
                xcursor_theme,
                layout,
                shells: vec![] }
    }
}

compositor_data!(State);

struct WlShellHandlerEx;
struct WlShellManager;

impl WlShellHandler for WlShellHandlerEx {}
impl WlShellManagerHandler for WlShellManager {
    fn new_surface(&mut self,
                   compositor: &mut Compositor,
                   shell: &mut WlShellSurface)
                   -> Option<Box<WlShellHandler>> {
        let state: &mut State = compositor.into();
        state.shells.push(shell.weak_reference());
        Some(Box::new(WlShellHandlerEx))
    }
}

struct OutputManager;

struct ExOutput;

struct InputManager;

struct ExPointer;

struct ExKeyboardHandler;

impl OutputManagerHandler for OutputManager {
    fn output_added<'output>(&mut self,
                             compositor: &mut Compositor,
                             builder: OutputBuilder<'output>)
                             -> Option<OutputBuilderResult<'output>> {
        let result = builder.build_best_mode(ExOutput);
        let state: &mut State = compositor.into();
        let xcursor = state.xcursor_theme
                           .get_cursor("left_ptr".into())
                           .expect("Could not load left_ptr cursor");
        let image = &xcursor.images()[0];
        // TODO use output config if present instead of auto
        state.layout.add_auto(result.output);
        let cursor = &mut state.layout.cursors()[0];
        cursor.set_cursor_image(image);
        let (x, y) = cursor.coords();
        // https://en.wikipedia.org/wiki/Mouse_warping
        cursor.warp(None, x, y);
        Some(result)
    }
}

impl KeyboardHandler for ExKeyboardHandler {
    fn on_key(&mut self, compositor: &mut Compositor, _: &mut Keyboard, key_event: &mut KeyEvent) {
        for key in key_event.pressed_keys() {
            if key == KEY_Escape {
                compositor.terminate()
            }
            // TODO This is a dumb way to compare these values
            else if key_event.key_state() as u32 == 1 {
                thread::spawn(move || {
                    use byteorder::{NativeEndian, WriteBytesExt};
                    use std::cmp::min;
                    use std::io::Write;
                    use std::os::unix::io::AsRawFd;
                    use wayland_client::EnvHandler;
                    use wayland_client::protocol::{wl_compositor, wl_shell, wl_shell_surface,
                                                   wl_shm};

                    wayland_env!(WaylandEnv,
                                 compositor: wl_compositor::WlCompositor,
                                 //seat: wl_seat::WlSeat,
                                 shell: wl_shell::WlShell,
                                 shm: wl_shm::WlShm);

                    fn shell_surface_impl() -> wl_shell_surface::Implementation<()> {
                        wl_shell_surface::Implementation { ping: |_, _, shell_surface, serial| {
                                                               shell_surface.pong(serial);
                                                           },
                                                           configure: |_, _, _, _, _, _| {
                                                               /* not used in this example */
                                                           },
                                                           popup_done: |_, _, _| {
                                                               /* not used in this example */
                                                           } }
                    }

                    let (display, mut event_queue) = match wayland_client::default_connect() {
                        Ok(ret) => ret,
                        Err(e) => panic!("Cannot connect to wayland server: {:?}", e)
                    };

                    let registry = display.get_registry();

                    let env_token = EnvHandler::<WaylandEnv>::init(&mut event_queue, &registry);

                    event_queue.sync_roundtrip().unwrap();

                    // buffer (and window) width and height
                    let buf_x: u32 = 320;
                    let buf_y: u32 = 240;

                    // create a tempfile to write the conents of the window on
                    let mut tmp = tempfile::tempfile().ok()
                                                      .expect("Unable to create a tempfile.");
                    // write the contents to it, lets put a nice color gradient
                    for i in 0..(buf_x * buf_y) {
                        let x = (i % buf_x) as u32;
                        let y = (i / buf_x) as u32;
                        let r: u32 =
                            min(((buf_x - x) * 0xFF) / buf_x, ((buf_y - y) * 0xFF) / buf_y);
                        let g: u32 = min((x * 0xFF) / buf_x, ((buf_y - y) * 0xFF) / buf_y);
                        let b: u32 = min(((buf_x - x) * 0xFF) / buf_x, (y * 0xFF) / buf_y);
                        let _ =
                            tmp.write_u32::<NativeEndian>((0xFF << 24) + (r << 16) + (g << 8) + b);
                    }
                    let _ = tmp.flush();

                    // retrieve the env
                    let env = event_queue.state().get(&env_token).clone_inner().unwrap();

                    // prepare the wayland surface
                    let surface = env.compositor.create_surface();
                    let shell_surface = env.shell.get_shell_surface(&surface);

                    let pool = env.shm.create_pool(tmp.as_raw_fd(), (buf_x * buf_y * 4) as i32);
                    // match a buffer on the part we wrote on
                    let buffer = pool.create_buffer(
                        0,
                        buf_x as i32,
                        buf_y as i32,
                        (buf_x * 4) as i32,
                        wl_shm::Format::Argb8888,
                    ).expect("The pool cannot be already dead");

                    // make our surface as a toplevel one
                    shell_surface.set_toplevel();
                    // attach the buffer to it
                    surface.attach(Some(&buffer), 0, 0);
                    // commit
                    surface.commit();

                    //let pointer = env.seat
                    //    .get_pointer()
                    //    .expect("Seat cannot be already destroyed.");

                    event_queue.register(&shell_surface, shell_surface_impl(), ());
                    //event_queue.register(&pointer, pointer_impl(), ());

                    loop {
                        display.flush().unwrap();
                        event_queue.dispatch().unwrap();
                    }
                });
            }
        }
    }
}

impl PointerHandler for ExPointer {
    fn on_motion(&mut self, compositor: &mut Compositor, _: &mut Pointer, event: &MotionEvent) {
        let state: &mut State = compositor.into();
        let (delta_x, delta_y) = event.delta();
        state.layout.cursors()[0].move_to(event.device(), delta_x, delta_y);
    }

    fn on_button(&mut self, compositor: &mut Compositor, _: &mut Pointer, event: &ButtonEvent) {
        let state: &mut State = compositor.into();
        if event.state() == WLR_BUTTON_RELEASED {
            state.color = state.default_color;
        } else {
            state.color = [0.25, 0.25, 0.25, 1.0];
            state.color[event.button() as usize % 3] = 1.0;
        }
    }

    fn on_axis(&mut self, compositor: &mut Compositor, _: &mut Pointer, event: &AxisEvent) {
        let state: &mut State = compositor.into();
        for color_byte in &mut state.default_color[..3] {
            *color_byte += if event.delta() > 0.0 { -0.05 } else { 0.05 };
            if *color_byte > 1.0 {
                *color_byte = 1.0
            }
            if *color_byte < 0.0 {
                *color_byte = 0.0
            }
        }
        state.color = state.default_color.clone()
    }
}

impl OutputHandler for ExOutput {
    fn on_frame(&mut self, compositor: &mut Compositor, output: &mut Output) {
        let renderer = compositor.renderer
                                 .as_mut()
                                 .expect("Compositor was not loaded with a renderer");
        let state: &mut State = compositor.data.downcast_mut().unwrap();
        // TODO Make the flashing go away by doing better buffer management
        output.make_current();
        render_shells(state, output, renderer);
        output.swap_buffers();
    }
}

impl InputManagerHandler for InputManager {
    fn pointer_added(&mut self,
                     _: &mut Compositor,
                     _: &mut Pointer)
                     -> Option<Box<PointerHandler>> {
        Some(Box::new(ExPointer))
    }

    fn keyboard_added(&mut self,
                      _: &mut Compositor,
                      _: &mut Keyboard)
                      -> Option<Box<KeyboardHandler>> {
        Some(Box::new(ExKeyboardHandler))
    }
}

fn main() {
    init_logging(L_DEBUG, None);
    let cursor = CursorBuilder::new().expect("Could not create cursor");
    let xcursor_theme = XCursorTheme::load_theme(None, 16).expect("Could not load theme");
    let mut layout = OutputLayout::new().expect("Could not construct an output layout");

    layout.attach_cursor(cursor);
    let compositor = CompositorBuilder::new().gles2(true)
                                             .build_auto(State::new(xcursor_theme, layout),
                                                         Some(Box::new(InputManager)),
                                                         Some(Box::new(OutputManager)),
                                                         Some(Box::new(WlShellManager)));
    compositor.run();
}
<commit_msg>Removed explicit swap_buffers<commit_after>extern crate byteorder;
extern crate tempfile;
#[macro_use]
extern crate wayland_client;
#[macro_use]
extern crate wlroots;

use std::thread;
use std::time::Duration;

use wlroots::{matrix_mul, matrix_rotate, matrix_scale, matrix_translate, Area, Compositor,
              CompositorBuilder, CursorBuilder, InputManagerHandler, Keyboard, KeyboardHandler,
              Origin, Output, OutputBuilder, OutputBuilderResult, OutputHandler, OutputLayout,
              OutputManagerHandler, Pointer, PointerHandler, Renderer, Size, WlShellHandler,
              WlShellManagerHandler, WlShellSurface, WlShellSurfaceHandle, XCursorTheme};
use wlroots::key_events::KeyEvent;
use wlroots::pointer_events::{AxisEvent, ButtonEvent, MotionEvent};
use wlroots::utils::{init_logging, L_DEBUG};
use wlroots::wlroots_sys::wlr_button_state::WLR_BUTTON_RELEASED;
use wlroots::xkbcommon::xkb::keysyms::KEY_Escape;

/// Render the shells in the current compositor state on the given output.
fn render_shells(state: &mut State, renderer: &mut Renderer) {
    let shells = state.shells.clone();
    for mut shell in shells {
        shell.run(|shell| {
                      shell.surface()
                           .run(|surface| {
                                    let (width, height) = {
                                        let current_state = surface.current_state();
                                        (current_state.width() as i32,
                                        current_state.height() as i32)
                                    };
                                    let (render_width, render_height) =
                                        (width * renderer.output.scale() as i32,
                                        height * renderer.output.scale() as i32);
                                    // TODO Some value from something else?
                                    let (lx, ly) = (0.0, 0.0);
                                    let (mut ox, mut oy) = (lx, ly);
                                    state.layout
                                         .output_coords(renderer.output, &mut ox, &mut oy);
                                    ox *= renderer.output.scale() as f64;
                                    oy *= renderer.output.scale() as f64;
                                    let render_box = Area::new(Origin::new(lx as i32, ly as i32),
                                                               Size::new(render_width,
                                                                         render_height));
                                    if state.layout.intersects(renderer.output, render_box) {
                                        let mut matrix = [0.0; 16];
                                        let mut translate_center = [0.0; 16];
                                        matrix_translate(&mut translate_center,
                                                         (ox as i32 + render_width / 2) as f32,
                                                         (oy as i32 + render_height / 2) as f32,
                                                         0.0);
                                        let mut rotate = [0.0; 16];
                                        // TODO what is rotation
                                        let rotation = 0.0;
                                        matrix_rotate(&mut rotate, rotation);

                                        let mut translate_origin = [0.0; 16];
                                        matrix_translate(&mut translate_origin,
                                                         (-render_width / 2) as f32,
                                                         (-render_height / 2) as f32,
                                                         0.0);

                                        let mut scale = [0.0; 16];
                                        matrix_scale(&mut scale,
                                                     render_width as f32,
                                                     render_height as f32,
                                                     1.0);

                                        let mut transform = [0.0; 16];
                                        matrix_mul(&translate_center, &mut rotate, &mut transform);
                                        matrix_mul(&transform.clone(),
                                                   &mut translate_origin,
                                                   &mut transform);
                                        matrix_mul(&transform.clone(), &mut scale, &mut transform);

                                        // TODO Handle non transform normal on the output
                                        // if ... {}
                                        matrix_mul(&renderer.output.transform_matrix(),
                                                   &mut transform,
                                                   &mut matrix);
                                        renderer.render_with_matrix(&surface.texture(), &matrix);
                                        surface.send_frame_done(Duration::from_secs(1));
                                    }
                                })
                           .unwrap()
                  })
             .unwrap();
    }
}

struct State {
    color: [f32; 4],
    default_color: [f32; 4],
    xcursor_theme: XCursorTheme,
    layout: OutputLayout,
    shells: Vec<WlShellSurfaceHandle>
}

impl State {
    fn new(xcursor_theme: XCursorTheme, layout: OutputLayout) -> Self {
        State { color: [0.25, 0.25, 0.25, 1.0],
                default_color: [0.25, 0.25, 0.25, 1.0],
                xcursor_theme,
                layout,
                shells: vec![] }
    }
}

compositor_data!(State);

struct WlShellHandlerEx;
struct WlShellManager;

impl WlShellHandler for WlShellHandlerEx {}
impl WlShellManagerHandler for WlShellManager {
    fn new_surface(&mut self,
                   compositor: &mut Compositor,
                   shell: &mut WlShellSurface)
                   -> Option<Box<WlShellHandler>> {
        let state: &mut State = compositor.into();
        state.shells.push(shell.weak_reference());
        Some(Box::new(WlShellHandlerEx))
    }
}

struct OutputManager;

struct ExOutput;

struct InputManager;

struct ExPointer;

struct ExKeyboardHandler;

impl OutputManagerHandler for OutputManager {
    fn output_added<'output>(&mut self,
                             compositor: &mut Compositor,
                             builder: OutputBuilder<'output>)
                             -> Option<OutputBuilderResult<'output>> {
        let result = builder.build_best_mode(ExOutput);
        let state: &mut State = compositor.into();
        let xcursor = state.xcursor_theme
                           .get_cursor("left_ptr".into())
                           .expect("Could not load left_ptr cursor");
        let image = &xcursor.images()[0];
        // TODO use output config if present instead of auto
        state.layout.add_auto(result.output);
        let cursor = &mut state.layout.cursors()[0];
        cursor.set_cursor_image(image);
        let (x, y) = cursor.coords();
        // https://en.wikipedia.org/wiki/Mouse_warping
        cursor.warp(None, x, y);
        Some(result)
    }
}

impl KeyboardHandler for ExKeyboardHandler {
    fn on_key(&mut self, compositor: &mut Compositor, _: &mut Keyboard, key_event: &mut KeyEvent) {
        for key in key_event.pressed_keys() {
            if key == KEY_Escape {
                compositor.terminate()
            }
            // TODO This is a dumb way to compare these values
            else if key_event.key_state() as u32 == 1 {
                thread::spawn(move || {
                    use byteorder::{NativeEndian, WriteBytesExt};
                    use std::cmp::min;
                    use std::io::Write;
                    use std::os::unix::io::AsRawFd;
                    use wayland_client::EnvHandler;
                    use wayland_client::protocol::{wl_compositor, wl_shell, wl_shell_surface,
                                                   wl_shm};

                    wayland_env!(WaylandEnv,
                                 compositor: wl_compositor::WlCompositor,
                                 //seat: wl_seat::WlSeat,
                                 shell: wl_shell::WlShell,
                                 shm: wl_shm::WlShm);

                    fn shell_surface_impl() -> wl_shell_surface::Implementation<()> {
                        wl_shell_surface::Implementation { ping: |_, _, shell_surface, serial| {
                                                               shell_surface.pong(serial);
                                                           },
                                                           configure: |_, _, _, _, _, _| {
                                                               /* not used in this example */
                                                           },
                                                           popup_done: |_, _, _| {
                                                               /* not used in this example */
                                                           } }
                    }

                    let (display, mut event_queue) = match wayland_client::default_connect() {
                        Ok(ret) => ret,
                        Err(e) => panic!("Cannot connect to wayland server: {:?}", e)
                    };

                    let registry = display.get_registry();

                    let env_token = EnvHandler::<WaylandEnv>::init(&mut event_queue, &registry);

                    event_queue.sync_roundtrip().unwrap();

                    // buffer (and window) width and height
                    let buf_x: u32 = 320;
                    let buf_y: u32 = 240;

                    // create a tempfile to write the conents of the window on
                    let mut tmp = tempfile::tempfile().ok()
                                                      .expect("Unable to create a tempfile.");
                    // write the contents to it, lets put a nice color gradient
                    for i in 0..(buf_x * buf_y) {
                        let x = (i % buf_x) as u32;
                        let y = (i / buf_x) as u32;
                        let r: u32 =
                            min(((buf_x - x) * 0xFF) / buf_x, ((buf_y - y) * 0xFF) / buf_y);
                        let g: u32 = min((x * 0xFF) / buf_x, ((buf_y - y) * 0xFF) / buf_y);
                        let b: u32 = min(((buf_x - x) * 0xFF) / buf_x, (y * 0xFF) / buf_y);
                        let _ =
                            tmp.write_u32::<NativeEndian>((0xFF << 24) + (r << 16) + (g << 8) + b);
                    }
                    let _ = tmp.flush();

                    // retrieve the env
                    let env = event_queue.state().get(&env_token).clone_inner().unwrap();

                    // prepare the wayland surface
                    let surface = env.compositor.create_surface();
                    let shell_surface = env.shell.get_shell_surface(&surface);

                    let pool = env.shm.create_pool(tmp.as_raw_fd(), (buf_x * buf_y * 4) as i32);
                    // match a buffer on the part we wrote on
                    let buffer = pool.create_buffer(
                        0,
                        buf_x as i32,
                        buf_y as i32,
                        (buf_x * 4) as i32,
                        wl_shm::Format::Argb8888,
                    ).expect("The pool cannot be already dead");

                    // make our surface as a toplevel one
                    shell_surface.set_toplevel();
                    // attach the buffer to it
                    surface.attach(Some(&buffer), 0, 0);
                    // commit
                    surface.commit();

                    //let pointer = env.seat
                    //    .get_pointer()
                    //    .expect("Seat cannot be already destroyed.");

                    event_queue.register(&shell_surface, shell_surface_impl(), ());
                    //event_queue.register(&pointer, pointer_impl(), ());

                    loop {
                        display.flush().unwrap();
                        event_queue.dispatch().unwrap();
                    }
                });
            }
        }
    }
}

impl PointerHandler for ExPointer {
    fn on_motion(&mut self, compositor: &mut Compositor, _: &mut Pointer, event: &MotionEvent) {
        let state: &mut State = compositor.into();
        let (delta_x, delta_y) = event.delta();
        state.layout.cursors()[0].move_to(event.device(), delta_x, delta_y);
    }

    fn on_button(&mut self, compositor: &mut Compositor, _: &mut Pointer, event: &ButtonEvent) {
        let state: &mut State = compositor.into();
        if event.state() == WLR_BUTTON_RELEASED {
            state.color = state.default_color;
        } else {
            state.color = [0.25, 0.25, 0.25, 1.0];
            state.color[event.button() as usize % 3] = 1.0;
        }
    }

    fn on_axis(&mut self, compositor: &mut Compositor, _: &mut Pointer, event: &AxisEvent) {
        let state: &mut State = compositor.into();
        for color_byte in &mut state.default_color[..3] {
            *color_byte += if event.delta() > 0.0 { -0.05 } else { 0.05 };
            if *color_byte > 1.0 {
                *color_byte = 1.0
            }
            if *color_byte < 0.0 {
                *color_byte = 0.0
            }
        }
        state.color = state.default_color.clone()
    }
}

impl OutputHandler for ExOutput {
    fn on_frame(&mut self, compositor: &mut Compositor, output: &mut Output) {
        let renderer = compositor.renderer
                                 .as_mut()
                                 .expect("Compositor was not loaded with a renderer");
        let state: &mut State = compositor.data.downcast_mut().unwrap();
        render_shells(state, &mut renderer.render(output));
    }
}

impl InputManagerHandler for InputManager {
    fn pointer_added(&mut self,
                     _: &mut Compositor,
                     _: &mut Pointer)
                     -> Option<Box<PointerHandler>> {
        Some(Box::new(ExPointer))
    }

    fn keyboard_added(&mut self,
                      _: &mut Compositor,
                      _: &mut Keyboard)
                      -> Option<Box<KeyboardHandler>> {
        Some(Box::new(ExKeyboardHandler))
    }
}

fn main() {
    init_logging(L_DEBUG, None);
    let cursor = CursorBuilder::new().expect("Could not create cursor");
    let xcursor_theme = XCursorTheme::load_theme(None, 16).expect("Could not load theme");
    let mut layout = OutputLayout::new().expect("Could not construct an output layout");

    layout.attach_cursor(cursor);
    let compositor = CompositorBuilder::new().gles2(true)
                                             .build_auto(State::new(xcursor_theme, layout),
                                                         Some(Box::new(InputManager)),
                                                         Some(Box::new(OutputManager)),
                                                         Some(Box::new(WlShellManager)));
    compositor.run();
}
<|endoftext|>


<commit_before>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// aux-build:use_from_trait_xc.rs

extern crate use_from_trait_xc;
pub use use_from_trait_xc::Trait;

fn main() {
    match () {
        Trait { x: 42u } => () //~ ERROR use of trait `Trait` in a struct pattern
    }
}
<commit_msg>Update the compile-fail-fulldeps tests with new isize/usize literal suffixes.<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// aux-build:use_from_trait_xc.rs

extern crate use_from_trait_xc;
pub use use_from_trait_xc::Trait;

fn main() {
    match () {
        Trait { x: 42us } => () //~ ERROR use of trait `Trait` in a struct pattern
    }
}
<|endoftext|>


<commit_before>// ignore-tidy-linelength

#![feature(const_generics)]

#![crate_name = "foo"]

pub enum Order {
    Sorted,
    Unsorted,
}

// @has foo/struct.VSet.html '//pre[@class="rust struct"]' 'pub struct VSet<T, const ORDER: Order>'
// @has foo/struct.VSet.html '//h3[@id="impl-Send"]/code' 'impl<const ORDER: Order, T> Send for VSet<T, ORDER>'
// @has foo/struct.VSet.html '//h3[@id="impl-Sync"]/code' 'impl<const ORDER: Order, T> Sync for VSet<T, ORDER>'
pub struct VSet<T, const ORDER: Order> {
    inner: Vec<T>,
}

// @has foo/struct.VSet.html '//h3[@id="impl"]/code' 'impl<T> VSet<T, { Order::Sorted }>'
impl <T> VSet<T, {Order::Sorted}> {
    pub fn new() -> Self {
        Self { inner: Vec::new() }
    }
}

// @has foo/struct.VSet.html '//h3[@id="impl-1"]/code' 'impl<T> VSet<T, { Order::Unsorted }>'
impl <T> VSet<T, {Order::Unsorted}> {
    pub fn new() -> Self {
        Self { inner: Vec::new() }
    }
}
<commit_msg>Fix rustdoc const generics test<commit_after>// ignore-tidy-linelength

#![feature(const_generics)]

#![crate_name = "foo"]

#[derive(PartialEq, Eq)]
pub enum Order {
    Sorted,
    Unsorted,
}

// @has foo/struct.VSet.html '//pre[@class="rust struct"]' 'pub struct VSet<T, const ORDER: Order>'
// @has foo/struct.VSet.html '//h3[@id="impl-Send"]/code' 'impl<const ORDER: Order, T> Send for VSet<T, ORDER>'
// @has foo/struct.VSet.html '//h3[@id="impl-Sync"]/code' 'impl<const ORDER: Order, T> Sync for VSet<T, ORDER>'
pub struct VSet<T, const ORDER: Order> {
    inner: Vec<T>,
}

// @has foo/struct.VSet.html '//h3[@id="impl"]/code' 'impl<T> VSet<T, { Order::Sorted }>'
impl <T> VSet<T, {Order::Sorted}> {
    pub fn new() -> Self {
        Self { inner: Vec::new() }
    }
}

// @has foo/struct.VSet.html '//h3[@id="impl-1"]/code' 'impl<T> VSet<T, { Order::Unsorted }>'
impl <T> VSet<T, {Order::Unsorted}> {
    pub fn new() -> Self {
        Self { inner: Vec::new() }
    }
}
<|endoftext|>


<commit_before>// Copyright 2016 The Grin Developers
//
// 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 std::net::SocketAddr;
use std::sync::{RwLock, Arc};

use futures::Future;
use tokio_core::net::TcpStream;

use core::core;
use core::core::hash::Hash;
use core::core::target::Difficulty;
use handshake::Handshake;
use types::*;

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum State {
	Connected,
	Disconnected,
	Banned,
}

pub struct Peer {
	pub info: PeerInfo,
	proto: Box<Protocol>,
	state: Arc<RwLock<State>>,
}

unsafe impl Sync for Peer {}
unsafe impl Send for Peer {}

impl Peer {
	/// Initiates the handshake with another peer.
	pub fn connect(conn: TcpStream,
	               capab: Capabilities,
	               total_difficulty: Difficulty,
	               self_addr: SocketAddr,
	               hs: &Handshake)
	               -> Box<Future<Item = (TcpStream, Peer), Error = Error>> {
		let connect_peer = hs.connect(capab, total_difficulty, self_addr, conn)
			.and_then(|(conn, proto, info)| {
				Ok((conn,
				    Peer {
					info: info,
					proto: Box::new(proto),
					state: Arc::new(RwLock::new(State::Connected)),
				}))
			});
		Box::new(connect_peer)
	}

	/// Accept a handshake initiated by another peer.
	pub fn accept(conn: TcpStream,
	              capab: Capabilities,
	              total_difficulty: Difficulty,
	              hs: &Handshake)
	              -> Box<Future<Item = (TcpStream, Peer), Error = Error>> {
		let hs_peer = hs.handshake(capab, total_difficulty, conn)
			.and_then(|(conn, proto, info)| {
				Ok((conn,
				    Peer {
					info: info,
					proto: Box::new(proto),
					state: Arc::new(RwLock::new(State::Connected)),
				}))
			});
		Box::new(hs_peer)
	}

	/// Main peer loop listening for messages and forwarding to the rest of the
	/// system.
	pub fn run(&self,
	           conn: TcpStream,
	           na: Arc<NetAdapter>)
	           -> Box<Future<Item = (), Error = Error>> {

		let addr = self.info.addr;
		let state = self.state.clone();
		Box::new(self.proto.handle(conn, na).then(move |res| {
			// handle disconnection, standard disconnections aren't considered an error
			let mut state = state.write().unwrap();
			match res {
				Ok(res) => {
					*state = State::Disconnected;
					info!("Client {} disconnected.", addr);
					Ok(())
				}
				Err(Error::Serialization(e)) => {
					*state = State::Banned;
					info!("Client {} corrupted, ban.", addr);
					Err(Error::Serialization(e))
				}
				Err(_) => {
					*state = State::Disconnected;
					info!("Client {} connection lost.", addr);
					Ok(())
				}
			}
		}))
	}

	/// Whether this peer is still connected.
	pub fn is_connected(&self) -> bool {
		let state = self.state.read().unwrap();
		*state == State::Connected
	}

	/// Whether this peer has been banned.
	pub fn is_banned(&self) -> bool {
		let state = self.state.read().unwrap();
		*state == State::Banned
	}

	/// Bytes sent and received by this peer to the remote peer.
	pub fn transmitted_bytes(&self) -> (u64, u64) {
		self.proto.transmitted_bytes()
	}

	pub fn send_ping(&self) -> Result<(), Error> {
		self.proto.send_ping()
	}

	/// Sends the provided block to the remote peer. The request may be dropped
	/// if the remote peer is known to already have the block.
	pub fn send_block(&self, b: &core::Block) -> Result<(), Error> {
		// TODO do not send if the peer sent us the block in the first place
		self.proto.send_block(b)
	}

	pub fn send_header_request(&self, locator: Vec<Hash>) -> Result<(), Error> {
		self.proto.send_header_request(locator)
	}

	pub fn send_block_request(&self, h: Hash) -> Result<(), Error> {
		debug!("Requesting block {} from peer {}.", h, self.info.addr);
		self.proto.send_block_request(h)
	}

	pub fn send_peer_request(&self, capab: Capabilities) -> Result<(), Error> {
		debug!("Asking {} for more peers.", self.info.addr);
		self.proto.send_peer_request(capab)
	}

	pub fn stop(&self) {
		self.proto.close();
	}
}
<commit_msg>Handle Invalid Error<commit_after>// Copyright 2016 The Grin Developers
//
// 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 std::net::SocketAddr;
use std::sync::{RwLock, Arc};

use futures::Future;
use tokio_core::net::TcpStream;

use core::core;
use core::core::hash::Hash;
use core::core::target::Difficulty;
use handshake::Handshake;
use types::*;

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum State {
	Connected,
	Disconnected,
	Banned,
}

pub struct Peer {
	pub info: PeerInfo,
	proto: Box<Protocol>,
	state: Arc<RwLock<State>>,
}

unsafe impl Sync for Peer {}
unsafe impl Send for Peer {}

impl Peer {
	/// Initiates the handshake with another peer.
	pub fn connect(conn: TcpStream,
	               capab: Capabilities,
	               total_difficulty: Difficulty,
	               self_addr: SocketAddr,
	               hs: &Handshake)
	               -> Box<Future<Item = (TcpStream, Peer), Error = Error>> {
		let connect_peer = hs.connect(capab, total_difficulty, self_addr, conn)
			.and_then(|(conn, proto, info)| {
				Ok((conn,
				    Peer {
					info: info,
					proto: Box::new(proto),
					state: Arc::new(RwLock::new(State::Connected)),
				}))
			});
		Box::new(connect_peer)
	}

	/// Accept a handshake initiated by another peer.
	pub fn accept(conn: TcpStream,
	              capab: Capabilities,
	              total_difficulty: Difficulty,
	              hs: &Handshake)
	              -> Box<Future<Item = (TcpStream, Peer), Error = Error>> {
		let hs_peer = hs.handshake(capab, total_difficulty, conn)
			.and_then(|(conn, proto, info)| {
				Ok((conn,
				    Peer {
					info: info,
					proto: Box::new(proto),
					state: Arc::new(RwLock::new(State::Connected)),
				}))
			});
		Box::new(hs_peer)
	}

	/// Main peer loop listening for messages and forwarding to the rest of the
	/// system.
	pub fn run(&self,
	           conn: TcpStream,
	           na: Arc<NetAdapter>)
	           -> Box<Future<Item = (), Error = Error>> {

		let addr = self.info.addr;
		let state = self.state.clone();
		Box::new(self.proto.handle(conn, na).then(move |res| {
			// handle disconnection, standard disconnections aren't considered an error
			let mut state = state.write().unwrap();
			match res {
				Ok(res) => {
					*state = State::Disconnected;
					info!("Client {} disconnected.", addr);
					Ok(())
				},
				Err(Error::Serialization(e)) => {
					*state = State::Banned;
					info!("Client {} corrupted, ban.", addr);
					Err(Error::Serialization(e))
				},
				Err(Error::Invalid) => {
					*state = State::Banned;
					info!("Client {} untrusted, ban.", addr);
					Err(Error::Invalid)
				},
				Err(_) => {
					*state = State::Disconnected;
					info!("Client {} connection lost.", addr);
					Ok(())
				}
			}
		}))
	}

	/// Whether this peer is still connected.
	pub fn is_connected(&self) -> bool {
		let state = self.state.read().unwrap();
		*state == State::Connected
	}

	/// Whether this peer has been banned.
	pub fn is_banned(&self) -> bool {
		let state = self.state.read().unwrap();
		*state == State::Banned
	}

	/// Bytes sent and received by this peer to the remote peer.
	pub fn transmitted_bytes(&self) -> (u64, u64) {
		self.proto.transmitted_bytes()
	}

	pub fn send_ping(&self) -> Result<(), Error> {
		self.proto.send_ping()
	}

	/// Sends the provided block to the remote peer. The request may be dropped
	/// if the remote peer is known to already have the block.
	pub fn send_block(&self, b: &core::Block) -> Result<(), Error> {
		// TODO do not send if the peer sent us the block in the first place
		self.proto.send_block(b)
	}

	pub fn send_header_request(&self, locator: Vec<Hash>) -> Result<(), Error> {
		self.proto.send_header_request(locator)
	}

	pub fn send_block_request(&self, h: Hash) -> Result<(), Error> {
		debug!("Requesting block {} from peer {}.", h, self.info.addr);
		self.proto.send_block_request(h)
	}

	pub fn send_peer_request(&self, capab: Capabilities) -> Result<(), Error> {
		debug!("Asking {} for more peers.", self.info.addr);
		self.proto.send_peer_request(capab)
	}

	pub fn stop(&self) {
		self.proto.close();
	}
}
<|endoftext|>


<commit_before>

use serde::de::Error;
use serde::{Serialize, Serializer, Deserialize, Deserializer};

use std::marker::PhantomData;

use prelude::*;

use EdgeType;
use graph::Node;
use graph::{IndexType, Edge};
use stable_graph::StableGraph;
use util::rev;
use serde_utils::MappedSequenceVisitor;
use serde_utils::CollectSeqWithLength;
use serde_utils::{IntoSerializable, FromDeserialized};

use super::super::serialization::{EdgeProperty, invalid_length_err, invalid_node_err};

// Serialization representation for StableGraph
// Keep in sync with deserialization and Graph
#[derive(Serialize)]
#[serde(rename = "Graph")]
#[serde(bound(serialize = "N: Serialize, E: Serialize, Ix: IndexType + Serialize"))]
pub struct SerStableGraph<'a, N: 'a, E: 'a, Ix: 'a + IndexType> {
    #[serde(serialize_with="ser_stable_graph_nodes")]
    nodes: &'a [Node<Option<N>, Ix>],
    #[serde(serialize_with="ser_stable_graph_node_holes")]
    node_holes: &'a [Node<Option<N>, Ix>],
    edge_property: EdgeProperty,
    #[serde(serialize_with="ser_stable_graph_edges")]
    edges: &'a [Edge<Option<E>, Ix>],
}

// Deserialization representation for StableGraph
// Keep in sync with serialization and Graph
#[derive(Deserialize)]
#[serde(rename = "Graph")]
#[serde(bound(deserialize = "N: Deserialize<'de>, E: Deserialize<'de>, Ix: IndexType + Deserialize<'de>"))]
pub struct DeserStableGraph<N, E, Ix> {
    #[serde(deserialize_with="deser_stable_graph_nodes")]
    nodes: Vec<Node<Option<N>, Ix>>,
    #[serde(default="Vec::new")]
    node_holes: Vec<NodeIndex<Ix>>,
    edge_property: EdgeProperty,
    #[serde(deserialize_with="deser_stable_graph_edges")]
    edges: Vec<Edge<Option<E>, Ix>>,
}

fn ser_stable_graph_nodes<S, N, Ix>(nodes: &&[Node<Option<N>, Ix>], serializer: S) -> Result<S::Ok, S::Error>
    where S: Serializer,
          N: Serialize,
          Ix: Serialize + IndexType,
{
    serializer.collect_seq_with_length(
        nodes.iter()
             .filter(|node| node.weight.is_some())
             .count(),
        nodes.iter()
             .filter_map(|node| node.weight.as_ref()))
}

fn ser_stable_graph_node_holes<S, N, Ix>(nodes: &&[Node<Option<N>, Ix>], serializer: S) -> Result<S::Ok, S::Error>
    where S: Serializer,
          N: Serialize,
          Ix: Serialize + IndexType,
{
    serializer.collect_seq_with_length(
        nodes.iter()
             .filter(|node| node.weight.is_none())
             .count(),
        nodes.iter()
             .enumerate()
             .filter_map(|(i, node)| if node.weight.is_none() { Some(NodeIndex::<Ix>::new(i)) } else { None }))
}

fn ser_stable_graph_edges<S, E, Ix>(edges: &&[Edge<Option<E>, Ix>], serializer: S) -> Result<S::Ok, S::Error>
    where S: Serializer,
          E: Serialize,
          Ix: Serialize + IndexType,
{
    serializer.collect_seq_exact(
        edges.iter()
            .map(|edge| edge.weight.as_ref().map(|w| (
               edge.source(),
               edge.target(),
               w
            ))))
}

fn deser_stable_graph_nodes<'de, D, N, Ix>(deserializer: D) -> Result<Vec<Node<Option<N>, Ix>>, D::Error>
    where D: Deserializer<'de>,
          N: Deserialize<'de>,
          Ix: IndexType + Deserialize<'de>,
{
    deserializer.deserialize_seq(MappedSequenceVisitor::new(|n|
        Ok(Node {
            weight: Some(n),
            next: [EdgeIndex::end(); 2],
        })
    ))
}

fn deser_stable_graph_edges<'de, D, N, Ix>(deserializer: D) -> Result<Vec<Edge<Option<N>, Ix>>, D::Error>
    where D: Deserializer<'de>,
          N: Deserialize<'de>,
          Ix: IndexType + Deserialize<'de>,
{
    deserializer.deserialize_seq(MappedSequenceVisitor::<Option<(NodeIndex<Ix>, NodeIndex<Ix>, N)>, _, _>::new(|x|
        if let Some((i, j, w)) = x {
            Ok(Edge {
                weight: Some(w),
                node: [i, j],
                next: [EdgeIndex::end(); 2],
            })
        } else {
            Ok(Edge {
                weight: None,
                node: [NodeIndex::end(); 2],
                next: [EdgeIndex::end(); 2],
            })
        }
    ))
}

impl<'a, N, E, Ty, Ix> IntoSerializable for &'a StableGraph<N, E, Ty, Ix>
    where Ix: IndexType,
          Ty: EdgeType,
{
    type Output = SerStableGraph<'a, N, E, Ix>;
    fn into_serializable(self) -> Self::Output {
        SerStableGraph {
            nodes: self.raw_nodes(),
            node_holes: self.raw_nodes(),
            edges: self.raw_edges(),
            edge_property: if self.is_directed() {
                EdgeProperty::Directed
            } else {
                EdgeProperty::Undirected
            },
        }
    }
}

impl<N, E, Ty, Ix> Serialize for StableGraph<N, E, Ty, Ix>
    where Ty: EdgeType,
          Ix: IndexType + Serialize,
          N: Serialize,
          E: Serialize,
{
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
        where S: Serializer
    {
        self.into_serializable().serialize(serializer)
    }
}

impl<'a, N, E, Ty, Ix> FromDeserialized for StableGraph<N, E, Ty, Ix>
    where Ix: IndexType,
          Ty: EdgeType,
{
    type Input = DeserStableGraph<N, E, Ix>;
    fn from_deserialized<E2>(input: Self::Input) -> Result<Self, E2>
        where E2: Error
    {
        let ty = PhantomData::<Ty>::from_deserialized(input.edge_property)?;
        let mut nodes = input.nodes;
        let node_holes = input.node_holes;
        let edges = input.edges;
        if nodes.len() >= <Ix as IndexType>::max().index() {
            Err(invalid_length_err::<Ix, _>("node", nodes.len()))?
        }

        if edges.len() >= <Ix as IndexType>::max().index() {
            Err(invalid_length_err::<Ix, _>("edge", edges.len()))?
        }

        // insert Nones for each hole
        let mut offset = node_holes.len();
        for hole_pos in rev(node_holes) {
            offset -= 1;
            nodes.insert(hole_pos.index() + offset, Node {
                weight: None,
                next: [EdgeIndex::end(); 2],
            });
        }

        let node_bound = nodes.len();
        let mut sgr = StableGraph {
            g: Graph {
                nodes: nodes,
                edges: edges,
                ty: ty,
            },
            node_count: 0,
            edge_count: 0,
            free_edge: EdgeIndex::end(),
            free_node: NodeIndex::end(),
        };
        sgr.link_edges().map_err(|i| invalid_node_err(i.index(), node_bound))?;
        Ok(sgr)
    }
}

impl<'de, N, E, Ty, Ix> Deserialize<'de> for StableGraph<N, E, Ty, Ix>
    where Ty: EdgeType,
          Ix: IndexType + Deserialize<'de>,
          N: Deserialize<'de>,
          E: Deserialize<'de>,
{
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
        where D: Deserializer<'de>
    {
        Self::from_deserialized(DeserStableGraph::deserialize(deserializer)?)
    }
}
<commit_msg>BUG: Fix node count check in StableGraph deserialization<commit_after>

use serde::de::Error;
use serde::{Serialize, Serializer, Deserialize, Deserializer};

use std::marker::PhantomData;

use prelude::*;

use EdgeType;
use graph::Node;
use graph::{IndexType, Edge};
use stable_graph::StableGraph;
use util::rev;
use serde_utils::MappedSequenceVisitor;
use serde_utils::CollectSeqWithLength;
use serde_utils::{IntoSerializable, FromDeserialized};

use super::super::serialization::{EdgeProperty, invalid_length_err, invalid_node_err};

// Serialization representation for StableGraph
// Keep in sync with deserialization and Graph
#[derive(Serialize)]
#[serde(rename = "Graph")]
#[serde(bound(serialize = "N: Serialize, E: Serialize, Ix: IndexType + Serialize"))]
pub struct SerStableGraph<'a, N: 'a, E: 'a, Ix: 'a + IndexType> {
    #[serde(serialize_with="ser_stable_graph_nodes")]
    nodes: &'a [Node<Option<N>, Ix>],
    #[serde(serialize_with="ser_stable_graph_node_holes")]
    node_holes: &'a [Node<Option<N>, Ix>],
    edge_property: EdgeProperty,
    #[serde(serialize_with="ser_stable_graph_edges")]
    edges: &'a [Edge<Option<E>, Ix>],
}

// Deserialization representation for StableGraph
// Keep in sync with serialization and Graph
#[derive(Deserialize)]
#[serde(rename = "Graph")]
#[serde(bound(deserialize = "N: Deserialize<'de>, E: Deserialize<'de>, Ix: IndexType + Deserialize<'de>"))]
pub struct DeserStableGraph<N, E, Ix> {
    #[serde(deserialize_with="deser_stable_graph_nodes")]
    nodes: Vec<Node<Option<N>, Ix>>,
    #[serde(default="Vec::new")]
    node_holes: Vec<NodeIndex<Ix>>,
    edge_property: EdgeProperty,
    #[serde(deserialize_with="deser_stable_graph_edges")]
    edges: Vec<Edge<Option<E>, Ix>>,
}

fn ser_stable_graph_nodes<S, N, Ix>(nodes: &&[Node<Option<N>, Ix>], serializer: S) -> Result<S::Ok, S::Error>
    where S: Serializer,
          N: Serialize,
          Ix: Serialize + IndexType,
{
    serializer.collect_seq_with_length(
        nodes.iter()
             .filter(|node| node.weight.is_some())
             .count(),
        nodes.iter()
             .filter_map(|node| node.weight.as_ref()))
}

fn ser_stable_graph_node_holes<S, N, Ix>(nodes: &&[Node<Option<N>, Ix>], serializer: S) -> Result<S::Ok, S::Error>
    where S: Serializer,
          N: Serialize,
          Ix: Serialize + IndexType,
{
    serializer.collect_seq_with_length(
        nodes.iter()
             .filter(|node| node.weight.is_none())
             .count(),
        nodes.iter()
             .enumerate()
             .filter_map(|(i, node)| if node.weight.is_none() { Some(NodeIndex::<Ix>::new(i)) } else { None }))
}

fn ser_stable_graph_edges<S, E, Ix>(edges: &&[Edge<Option<E>, Ix>], serializer: S) -> Result<S::Ok, S::Error>
    where S: Serializer,
          E: Serialize,
          Ix: Serialize + IndexType,
{
    serializer.collect_seq_exact(
        edges.iter()
            .map(|edge| edge.weight.as_ref().map(|w| (
               edge.source(),
               edge.target(),
               w
            ))))
}

fn deser_stable_graph_nodes<'de, D, N, Ix>(deserializer: D) -> Result<Vec<Node<Option<N>, Ix>>, D::Error>
    where D: Deserializer<'de>,
          N: Deserialize<'de>,
          Ix: IndexType + Deserialize<'de>,
{
    deserializer.deserialize_seq(MappedSequenceVisitor::new(|n|
        Ok(Node {
            weight: Some(n),
            next: [EdgeIndex::end(); 2],
        })
    ))
}

fn deser_stable_graph_edges<'de, D, N, Ix>(deserializer: D) -> Result<Vec<Edge<Option<N>, Ix>>, D::Error>
    where D: Deserializer<'de>,
          N: Deserialize<'de>,
          Ix: IndexType + Deserialize<'de>,
{
    deserializer.deserialize_seq(MappedSequenceVisitor::<Option<(NodeIndex<Ix>, NodeIndex<Ix>, N)>, _, _>::new(|x|
        if let Some((i, j, w)) = x {
            Ok(Edge {
                weight: Some(w),
                node: [i, j],
                next: [EdgeIndex::end(); 2],
            })
        } else {
            Ok(Edge {
                weight: None,
                node: [NodeIndex::end(); 2],
                next: [EdgeIndex::end(); 2],
            })
        }
    ))
}

impl<'a, N, E, Ty, Ix> IntoSerializable for &'a StableGraph<N, E, Ty, Ix>
    where Ix: IndexType,
          Ty: EdgeType,
{
    type Output = SerStableGraph<'a, N, E, Ix>;
    fn into_serializable(self) -> Self::Output {
        SerStableGraph {
            nodes: self.raw_nodes(),
            node_holes: self.raw_nodes(),
            edges: self.raw_edges(),
            edge_property: if self.is_directed() {
                EdgeProperty::Directed
            } else {
                EdgeProperty::Undirected
            },
        }
    }
}

impl<N, E, Ty, Ix> Serialize for StableGraph<N, E, Ty, Ix>
    where Ty: EdgeType,
          Ix: IndexType + Serialize,
          N: Serialize,
          E: Serialize,
{
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
        where S: Serializer
    {
        self.into_serializable().serialize(serializer)
    }
}

impl<'a, N, E, Ty, Ix> FromDeserialized for StableGraph<N, E, Ty, Ix>
    where Ix: IndexType,
          Ty: EdgeType,
{
    type Input = DeserStableGraph<N, E, Ix>;
    fn from_deserialized<E2>(input: Self::Input) -> Result<Self, E2>
        where E2: Error
    {
        let ty = PhantomData::<Ty>::from_deserialized(input.edge_property)?;
        let mut nodes = input.nodes;
        let node_holes = input.node_holes;
        let edges = input.edges;
        if edges.len() >= <Ix as IndexType>::max().index() {
            Err(invalid_length_err::<Ix, _>("edge", edges.len()))?
        }

        // insert Nones for each hole
        let mut offset = node_holes.len();
        for hole_pos in rev(node_holes) {
            offset -= 1;
            nodes.insert(hole_pos.index() + offset, Node {
                weight: None,
                next: [EdgeIndex::end(); 2],
            });
        }

        if nodes.len() >= <Ix as IndexType>::max().index() {
            Err(invalid_length_err::<Ix, _>("node", nodes.len()))?
        }

        let node_bound = nodes.len();
        let mut sgr = StableGraph {
            g: Graph {
                nodes: nodes,
                edges: edges,
                ty: ty,
            },
            node_count: 0,
            edge_count: 0,
            free_edge: EdgeIndex::end(),
            free_node: NodeIndex::end(),
        };
        sgr.link_edges().map_err(|i| invalid_node_err(i.index(), node_bound))?;
        Ok(sgr)
    }
}

impl<'de, N, E, Ty, Ix> Deserialize<'de> for StableGraph<N, E, Ty, Ix>
    where Ty: EdgeType,
          Ix: IndexType + Deserialize<'de>,
          N: Deserialize<'de>,
          E: Deserialize<'de>,
{
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
        where D: Deserializer<'de>
    {
        Self::from_deserialized(DeserStableGraph::deserialize(deserializer)?)
    }
}
<|endoftext|>


<commit_before>use name::*;
use art::*;
use std::hash;
use std::hash::Hash;
use std::result::Result;
use std::collections::HashMap;

//
// Cmd C ::= Skip
//        | C ; C
//        | While E C
//        | x := E
//
//     C ::= .. | Amb C C
//
// Exp E ::=
//        | x
//        | N
//        | E + E
//        | E < E
//

/// Nominal, artful commands for the while language
#[derive(Show,Hash,PartialEq,Eq,Clone)]
pub enum Cmd<'x> {
    Skip,
    //Continue,
    Assign(Var<'x>, ExpB<'x>),
    Seq(CmdB<'x>, CmdB<'x>),
    // WHILE-loops:
    While(ExpB<'x>, CmdB<'x>),
    If(ExpB<'x>, CmdB<'x>, CmdB<'x>),
    Again(ExpB<'x>, CmdB<'x>),
    Break,
    // ----
    Name(Name, CmdB<'x>),
    Art(Art<'x,CmdB<'x>>),
}
pub type CmdB<'x> = Box<Cmd<'x>>;

pub enum CmdCxt<'x> {
    Empty,
    Seq(CmdCxtB<'x>, CmdB<'x>),
    // ----
    Name(Name, CmdCxtB<'x>),
    Art(Art<'x,CmdCxtB<'x>>),
}
pub type CmdCxtB<'x> = Box<CmdCxt<'x>>;

/// Expressions for the while language
#[derive(Show,Hash,PartialEq,Eq,Clone)]
pub enum Exp<'x> {
    Var(Var<'x>),
    Plus(ExpB<'x>,ExpB<'x>),
    Less(ExpB<'x>,ExpB<'x>),
    Num(int),
}
pub type ExpB<'x> = Box<Exp<'x>>;

/// Variables for the while language
pub type Var<'x> = String;

pub trait Heap<L:Hash+Eq, V> {
    fn empty () -> Self ;
    fn update (Self, L, V) -> Self ;
    fn select (Self, L) -> (Self, Option<V>) ;
}

pub struct HashMapHeap { hm : HashMap<String, int> }

impl Heap<String, int> for HashMapHeap {
    fn empty () -> Self {
        HashMapHeap { hm : HashMap::new() }
    }
    fn update (hm:Self, l:String, v:int) -> Self {
        let mut hm = hm.hm.clone () ; // TODO: Avoid this clone.
        hm.insert(l,v) ;
        HashMapHeap{ hm : hm }
    }
    fn select (hm:Self, l:String) -> (Self, Option<int>) {
        let hmq = hm.hm.clone () ; // TODO: Avoid this clone.
        let x = hmq.get(&l) ;
        (hm, match x { None => None, Some(x) => Some(*x) })
    }
}

pub enum Error {
    VarNotDef(String),
}

pub fn eval_exp<'x>
    (heap:HashMapHeap, exp:Exp<'x>)
     -> (HashMapHeap, Result<int, Error>)
{
    match exp {
        Exp::Num(n) => (heap, Ok(n)),
        Exp::Var(v) => {
            let (heap,q) = Heap::select(heap, v.clone()) ;
            match q {
                None => (heap, Err(Error::VarNotDef(v))),
                Some(val) => (heap, Ok(val))
            }},

        Exp::Plus(l, r) => {
            let (heap, l) = eval_exp(heap, *l) ;
            let (heap, r) = eval_exp(heap, *r) ;
            match (l,r) {
                (Ok(l), Ok(r)) => (heap, Ok(l+r)),
                (Err(l), _) => (heap, Err(l)),
                (_, Err(r)) => (heap, Err(r))
            }},

        Exp::Less(l, r) => {
            let (heap, l) = eval_exp(heap, *l) ;
            let (heap, r) = eval_exp(heap, *r) ;
            match (l,r) {
                (Ok(l), Ok(r)) => (heap, Ok(if l < r { 1 } else { 0 })),
                (Err(l), _) => (heap, Err(l)),
                (_, Err(r)) => (heap, Err(r))
            }},

    }
}

fn do_break<'x> (cxt:CmdCxt<'x>) -> CmdCxt<'x> {
    match cxt {
        CmdCxt::Empty => CmdCxt::Empty, // Degenerate basecase.
        CmdCxt::Seq(cxt, cmd) =>
            match *cmd {
                Cmd::Again(_,_) => *cxt, // Normal basecase.
                // - - - - - - -
                // Keep searching for basecase...
                Cmd::Art(art) => do_break (CmdCxt::Seq(cxt, force(art))),
                // Cmd::Name(nm, cmd) => { do_break(CmdCxt::Seq(cxt, cmd)) },
                // - - - - - - -
                _ => do_break(*cxt),
            },
        // - - - - - - -
        CmdCxt::Name(_, cxt) => do_break(*cxt),
        CmdCxt::Art(art) => do_break(*force(art)),
    }
}

pub fn step_cmd<'x>
    (heap:HashMapHeap, cxt:CmdCxt<'x>, cmd:Cmd<'x>)
     -> (HashMapHeap, Option<(CmdCxt<'x>, Cmd<'x>)>)
{
    match (cxt, cmd) {
        (CmdCxt::Empty, Cmd::Skip) => (heap, None),
        (CmdCxt::Empty, Cmd::Break) => (heap, None),

        (CmdCxt::Seq(cxt, cmd), Cmd::Skip) => (heap, Some((*cxt, *cmd))),
        (cxt, Cmd::Break) => {
            let cxt = do_break(cxt) ;
            (heap, Some((cxt, Cmd::Skip)))
        }

        (cxt, Cmd::Seq(cmd1, cmd2)) => (heap, Some( (CmdCxt::Seq(box cxt, cmd2), *cmd1) )),

        // While becomes Again, which repeats again and again..
        // This case only fires when first entering the loop;
        // TODO: use it to extend the "loop path"
        (cxt, Cmd::While(exp, cmd)) => (heap, Some( (cxt, Cmd::Again(exp, cmd)) )),

        (cxt, Cmd::Again(exp, cmd)) =>
            (heap, Some( (CmdCxt::Seq(box cxt, box Cmd::Again(exp.clone(), cmd.clone())),
                          Cmd::If(exp, cmd, box Cmd::Break)
                          ) )),

        (cxt, Cmd::Assign(var, exp)) => {
            let (heap, r) = eval_exp (heap, *exp) ;
            match r {
                Err(error) => (heap, None),
                Ok(val) => {
                    let heap = Heap::update(heap, var, val) ;
                    (heap, Some(( cxt, Cmd::Skip )))
                }
            }
        },

        (cxt, Cmd::If(exp, cmd1, cmd2)) => {
            let (heap, r) = eval_exp (heap, *exp) ;
            match r {
                Err(error) => (heap, None),
                Ok(0) => { (heap, Some((cxt, *cmd2))) },
                Ok(_) => { (heap, Some((cxt, *cmd1))) },
            }
        },

        // - - - - - - - - -
        (cxt, Cmd::Art(art))         => { step_cmd(heap, cxt, *force(art)) },
        (cxt, Cmd::Name(nm, cmd))    => { step_cmd(heap, cxt, *cmd) }
        (CmdCxt::Art(art), cmd)      => { step_cmd(heap, *force(art), cmd) }
        (CmdCxt::Name(nm, cxt), cmd) => { step_cmd(heap, *cxt, cmd) }

    }
}

#[test]
pub fn doit () {
    println!("while lang!");
}
<commit_msg>noted next steps<commit_after>use name::*;
use art::*;
use std::hash;
use std::hash::Hash;
use std::result::Result;
use std::collections::HashMap;

//
// Cmd C ::= Skip
//        | C ; C
//        | While E C
//        | x := E
//
//     C ::= .. | Amb C C
//
// Exp E ::=
//        | x
//        | N
//        | E + E
//        | E < E
//

/// Nominal, artful commands for the while language
#[derive(Show,Hash,PartialEq,Eq,Clone)]
pub enum Cmd<'x> {
    Skip,
    //Continue,
    Assign(Var<'x>, ExpB<'x>),
    Seq(CmdB<'x>, CmdB<'x>),
    // WHILE-loops:
    While(ExpB<'x>, CmdB<'x>),
    If(ExpB<'x>, CmdB<'x>, CmdB<'x>),
    Again(ExpB<'x>, CmdB<'x>),
    Break,
    // ----
    Name(Name, CmdB<'x>),
    Art(Art<'x,CmdB<'x>>),
}
pub type CmdB<'x> = Box<Cmd<'x>>;

pub enum CmdCxt<'x> {
    Empty,
    Seq(CmdCxtB<'x>, CmdB<'x>),
    // ----
    Name(Name, CmdCxtB<'x>),
    Art(Art<'x,CmdCxtB<'x>>),
}
pub type CmdCxtB<'x> = Box<CmdCxt<'x>>;

/// Expressions for the while language
#[derive(Show,Hash,PartialEq,Eq,Clone)]
pub enum Exp<'x> {
    Var(Var<'x>),
    Plus(ExpB<'x>,ExpB<'x>),
    Less(ExpB<'x>,ExpB<'x>),
    Num(int),
}
pub type ExpB<'x> = Box<Exp<'x>>;

/// Variables for the while language
pub type Var<'x> = String;

pub trait Heap<L:Hash+Eq, V> {
    fn empty () -> Self ;
    fn update (Self, L, V) -> Self ;
    fn select (Self, L) -> (Self, Option<V>) ;
}

pub struct HashMapHeap { hm : HashMap<String, int> }

impl Heap<String, int> for HashMapHeap {
    fn empty () -> Self {
        HashMapHeap { hm : HashMap::new() }
    }
    fn update (hm:Self, l:String, v:int) -> Self {
        let mut hm = hm.hm.clone () ; // TODO: Avoid this clone. Use trie structure instead.
        hm.insert(l,v) ;
        HashMapHeap{ hm : hm }
    }
    fn select (hm:Self, l:String) -> (Self, Option<int>) {
        let hmq = hm.hm.clone () ; // TODO: Avoid this clone. Use trie structure instead.
        let x = hmq.get(&l) ;
        (hm, match x { None => None, Some(x) => Some(*x) })
    }
}

pub enum Error {
    VarNotDef(String),
}

pub fn eval_exp<'x>
    (heap:HashMapHeap, exp:Exp<'x>)
     -> (HashMapHeap, Result<int, Error>)
{
    match exp {
        Exp::Num(n) => (heap, Ok(n)),
        Exp::Var(v) => {
            let (heap,q) = Heap::select(heap, v.clone()) ;
            match q {
                None => (heap, Err(Error::VarNotDef(v))),
                Some(val) => (heap, Ok(val))
            }},

        Exp::Plus(l, r) => {
            let (heap, l) = eval_exp(heap, *l) ;
            let (heap, r) = eval_exp(heap, *r) ;
            match (l,r) {
                (Ok(l), Ok(r)) => (heap, Ok(l+r)),
                (Err(l), _) => (heap, Err(l)),
                (_, Err(r)) => (heap, Err(r))
            }},

        Exp::Less(l, r) => {
            let (heap, l) = eval_exp(heap, *l) ;
            let (heap, r) = eval_exp(heap, *r) ;
            match (l,r) {
                (Ok(l), Ok(r)) => (heap, Ok(if l < r { 1 } else { 0 })),
                (Err(l), _) => (heap, Err(l)),
                (_, Err(r)) => (heap, Err(r))
            }},

    }
}

fn do_break<'x> (cxt:CmdCxt<'x>) -> CmdCxt<'x> {
    match cxt {
        CmdCxt::Empty => CmdCxt::Empty, // Degenerate basecase.
        CmdCxt::Seq(cxt, cmd) =>
            match *cmd {
                Cmd::Again(_,_) => *cxt, // Normal basecase.
                // - - - - - - -
                // Keep searching for basecase...
                Cmd::Art(art) => do_break (CmdCxt::Seq(cxt, force(art))),
                // Cmd::Name(nm, cmd) => { do_break(CmdCxt::Seq(cxt, cmd)) },
                // - - - - - - -
                _ => do_break(*cxt),
            },
        // - - - - - - -
        CmdCxt::Name(_, cxt) => do_break(*cxt),
        CmdCxt::Art(art) => do_break(*force(art)),
    }
}

pub fn step_cmd<'x>
    (heap:HashMapHeap, cxt:CmdCxt<'x>, cmd:Cmd<'x>)
     -> (HashMapHeap, Option<(CmdCxt<'x>, Cmd<'x>)>)
{
    match (cxt, cmd) {
        (CmdCxt::Empty, Cmd::Skip) => (heap, None),
        (CmdCxt::Empty, Cmd::Break) => (heap, None),

        (CmdCxt::Seq(cxt, cmd), Cmd::Skip) => (heap, Some((*cxt, *cmd))),
        (cxt, Cmd::Break) => {
            let cxt = do_break(cxt) ;
            (heap, Some((cxt, Cmd::Skip)))
        }

        (cxt, Cmd::Seq(cmd1, cmd2)) => (heap, Some( (CmdCxt::Seq(box cxt, cmd2), *cmd1) )),

        // While becomes Again, which repeats again and again..
        // This case only fires when first entering the loop;
        // TODO: use it to extend the "loop path"
        (cxt, Cmd::While(exp, cmd)) => (heap, Some( (cxt, Cmd::Again(exp, cmd)) )),

        (cxt, Cmd::Again(exp, cmd)) =>
            (heap, Some( (CmdCxt::Seq(box cxt, box Cmd::Again(exp.clone(), cmd.clone())),
                          Cmd::If(exp, cmd, box Cmd::Break)
                          ) )),

        (cxt, Cmd::Assign(var, exp)) => {
            let (heap, r) = eval_exp (heap, *exp) ;
            match r {
                Err(error) => (heap, None),
                Ok(val) => {
                    let heap = Heap::update(heap, var, val) ;
                    (heap, Some(( cxt, Cmd::Skip )))
                }
            }
        },

        (cxt, Cmd::If(exp, cmd1, cmd2)) => {
            let (heap, r) = eval_exp (heap, *exp) ;
            match r {
                Err(error) => (heap, None),
                Ok(0) => { (heap, Some((cxt, *cmd2))) },
                Ok(_) => { (heap, Some((cxt, *cmd1))) },
            }
        },

        // TODO: Step to a name here.
        // TODO: to write eta, need "dynamic coordinate" for this static name nm.
        // TODO: This coordinate information consists of counts for each of the loops we are in now.
        (CmdCxt::Name(nm, cxt), cmd) => { step_cmd(heap, *cxt, cmd) }

        // - - - - - - - - -
        (cxt, Cmd::Art(art))         => { step_cmd(heap, cxt, *force(art)) },
        (cxt, Cmd::Name(nm, cmd))    => { step_cmd(heap, cxt, *cmd) }
        (CmdCxt::Art(art), cmd)      => { step_cmd(heap, *force(art), cmd) }

    }
}

#[test]
pub fn doit () {
    println!("while lang!");
}
<|endoftext|>


<commit_before>use encode::{add_padding, encode_to_slice};
use std::{cmp, str};
use Config;

/// The output mechanism for ChunkedEncoder's encoded bytes.
pub trait Sink {
    type Error;

    /// Handle a chunk of encoded base64 data (as UTF-8 bytes)
    fn write_encoded_bytes(&mut self, encoded: &[u8]) -> Result<(), Self::Error>;
}

const BUF_SIZE: usize = 1024;

/// A base64 encoder that emits encoded bytes in chunks without heap allocation.
pub struct ChunkedEncoder {
    config: Config,
    max_input_chunk_len: usize,
}

impl ChunkedEncoder {
    pub fn new(config: Config) -> ChunkedEncoder {
        ChunkedEncoder {
            config,
            max_input_chunk_len: max_input_length(BUF_SIZE, &config),
        }
    }

    pub fn encode<S: Sink>(&self, bytes: &[u8], sink: &mut S) -> Result<(), S::Error> {
        let mut encode_buf: [u8; BUF_SIZE] = [0; BUF_SIZE];
        let encode_table = self.config.char_set.encode_table();

        let mut input_index = 0;

        while input_index < bytes.len() {
            // either the full input chunk size, or it's the last iteration
            let input_chunk_len = cmp::min(self.max_input_chunk_len, bytes.len() - input_index);

            let chunk = &bytes[input_index..(input_index + input_chunk_len)];

            let mut b64_bytes_written = encode_to_slice(chunk, &mut encode_buf, encode_table);

            input_index += input_chunk_len;
            let more_input_left = input_index < bytes.len();

            if self.config.pad && !more_input_left {
                // no more input, add padding if needed. Buffer will have room because
                // max_input_length leaves room for it.
                b64_bytes_written += add_padding(bytes.len(), &mut encode_buf[b64_bytes_written..]);
            }

            sink.write_encoded_bytes(&encode_buf[0..b64_bytes_written])?;
        }

        Ok(())
    }
}

/// Calculate the longest input that can be encoded for the given output buffer size.
///
/// If the config requires padding, two bytes of buffer space will be set aside so that the last
/// chunk of input can be encoded safely.
///
/// The input length will always be a multiple of 3 so that no encoding state has to be carried over
/// between chunks.
fn max_input_length(encoded_buf_len: usize, config: &Config) -> usize {
    let effective_buf_len = if config.pad {
        // make room for padding
        encoded_buf_len
            .checked_sub(2)
            .expect("Don't use a tiny buffer")
    } else {
        encoded_buf_len
    };

    // No padding, so just normal base64 expansion.
    (effective_buf_len / 4) * 3
}

// A really simple sink that just appends to a string for testing
pub(crate) struct StringSink<'a> {
    string: &'a mut String,
}

impl<'a> StringSink<'a> {
    pub(crate) fn new(s: &mut String) -> StringSink {
        StringSink {
            string: s,
        }
    }
}

impl<'a> Sink for StringSink<'a> {
    type Error = ();

    fn write_encoded_bytes(&mut self, s: &[u8]) -> Result<(), Self::Error> {
        self.string.push_str(str::from_utf8(s).unwrap());

        Ok(())
    }
}

#[cfg(test)]
pub mod tests {
    extern crate rand;

    use super::*;
    use tests::random_config;
    use *;

    use self::rand::distributions::{Distribution, Range};
    use self::rand::{Rng, FromEntropy};

    #[test]
    fn chunked_encode_empty() {
        assert_eq!("", chunked_encode_str(&[], STANDARD));
    }

    #[test]
    fn chunked_encode_intermediate_fast_loop() {
        // > 8 bytes input, will enter the pretty fast loop
        assert_eq!(
            "Zm9vYmFyYmF6cXV4",
            chunked_encode_str(b"foobarbazqux", STANDARD)
        );
    }

    #[test]
    fn chunked_encode_fast_loop() {
        // > 32 bytes input, will enter the uber fast loop
        assert_eq!(
            "Zm9vYmFyYmF6cXV4cXV1eGNvcmdlZ3JhdWx0Z2FycGx5eg==",
            chunked_encode_str(b"foobarbazquxquuxcorgegraultgarplyz", STANDARD)
        );
    }

    #[test]
    fn chunked_encode_slow_loop_only() {
        // < 8 bytes input, slow loop only
        assert_eq!("Zm9vYmFy", chunked_encode_str(b"foobar", STANDARD));
    }

    #[test]
    fn chunked_encode_matches_normal_encode_random_string_sink() {
        let helper = StringSinkTestHelper;
        chunked_encode_matches_normal_encode_random(&helper);
    }

    #[test]
    fn max_input_length_no_pad() {
        let config = config_with_pad(false);
        assert_eq!(768, max_input_length(1024, &config));
    }

    #[test]
    fn max_input_length_with_pad_decrements_one_triple() {
        let config = config_with_pad(true);
        assert_eq!(765, max_input_length(1024, &config));
    }

    #[test]
    fn max_input_length_with_pad_one_byte_short() {
        let config = config_with_pad(true);
        assert_eq!(765, max_input_length(1025, &config));
    }

    #[test]
    fn max_input_length_with_pad_fits_exactly() {
        let config = config_with_pad(true);
        assert_eq!(768, max_input_length(1026, &config));
    }

    #[test]
    fn max_input_length_cant_use_extra_single_encoded_byte() {
        let config = Config::new(
            CharacterSet::Standard,
            false,
            false,
        );
        assert_eq!(300, max_input_length(401, &config));
    }

    pub fn chunked_encode_matches_normal_encode_random<S: SinkTestHelper>(sink_test_helper: &S) {
        let mut input_buf: Vec<u8> = Vec::new();
        let mut output_buf = String::new();
        let mut rng = rand::rngs::SmallRng::from_entropy();
        let input_len_range = Range::new(1, 10_000);

        for _ in 0..5_000 {
            input_buf.clear();
            output_buf.clear();

            let buf_len = input_len_range.sample(&mut rng);
            for _ in 0..buf_len {
                input_buf.push(rng.gen());
            }

            let config = random_config(&mut rng);

            let chunk_encoded_string = sink_test_helper.encode_to_string(config, &input_buf);
            encode_config_buf(&input_buf, config, &mut output_buf);

            assert_eq!(
                output_buf, chunk_encoded_string,
                "input len={}, config: pad={}",
                buf_len, config.pad
            );
        }
    }

    fn chunked_encode_str(bytes: &[u8], config: Config) -> String {
        let mut s = String::new();
        {
            let mut sink = StringSink::new(&mut s);
            let encoder = ChunkedEncoder::new(config);
            encoder.encode(bytes, &mut sink).unwrap();
        }

        return s;
    }

    fn config_with_pad(pad: bool) -> Config {
        Config::new(CharacterSet::Standard, pad, false)
    }

    // An abstraction around sinks so that we can have tests that easily to any sink implementation
    pub trait SinkTestHelper {
        fn encode_to_string(&self, config: Config, bytes: &[u8]) -> String;
    }

    struct StringSinkTestHelper;

    impl SinkTestHelper for StringSinkTestHelper {
        fn encode_to_string(&self, config: Config, bytes: &[u8]) -> String {
            let encoder = ChunkedEncoder::new(config);
            let mut s = String::new();
            {
                let mut sink = StringSink::new(&mut s);
                encoder.encode(bytes, &mut sink).unwrap();
            }

            s
        }
    }

}
<commit_msg>Fix a comment<commit_after>use encode::{add_padding, encode_to_slice};
use std::{cmp, str};
use Config;

/// The output mechanism for ChunkedEncoder's encoded bytes.
pub trait Sink {
    type Error;

    /// Handle a chunk of encoded base64 data (as UTF-8 bytes)
    fn write_encoded_bytes(&mut self, encoded: &[u8]) -> Result<(), Self::Error>;
}

const BUF_SIZE: usize = 1024;

/// A base64 encoder that emits encoded bytes in chunks without heap allocation.
pub struct ChunkedEncoder {
    config: Config,
    max_input_chunk_len: usize,
}

impl ChunkedEncoder {
    pub fn new(config: Config) -> ChunkedEncoder {
        ChunkedEncoder {
            config,
            max_input_chunk_len: max_input_length(BUF_SIZE, &config),
        }
    }

    pub fn encode<S: Sink>(&self, bytes: &[u8], sink: &mut S) -> Result<(), S::Error> {
        let mut encode_buf: [u8; BUF_SIZE] = [0; BUF_SIZE];
        let encode_table = self.config.char_set.encode_table();

        let mut input_index = 0;

        while input_index < bytes.len() {
            // either the full input chunk size, or it's the last iteration
            let input_chunk_len = cmp::min(self.max_input_chunk_len, bytes.len() - input_index);

            let chunk = &bytes[input_index..(input_index + input_chunk_len)];

            let mut b64_bytes_written = encode_to_slice(chunk, &mut encode_buf, encode_table);

            input_index += input_chunk_len;
            let more_input_left = input_index < bytes.len();

            if self.config.pad && !more_input_left {
                // no more input, add padding if needed. Buffer will have room because
                // max_input_length leaves room for it.
                b64_bytes_written += add_padding(bytes.len(), &mut encode_buf[b64_bytes_written..]);
            }

            sink.write_encoded_bytes(&encode_buf[0..b64_bytes_written])?;
        }

        Ok(())
    }
}

/// Calculate the longest input that can be encoded for the given output buffer size.
///
/// If the config requires padding, two bytes of buffer space will be set aside so that the last
/// chunk of input can be encoded safely.
///
/// The input length will always be a multiple of 3 so that no encoding state has to be carried over
/// between chunks.
fn max_input_length(encoded_buf_len: usize, config: &Config) -> usize {
    let effective_buf_len = if config.pad {
        // make room for padding
        encoded_buf_len
            .checked_sub(2)
            .expect("Don't use a tiny buffer")
    } else {
        encoded_buf_len
    };

    // No padding, so just normal base64 expansion.
    (effective_buf_len / 4) * 3
}

// A really simple sink that just appends to a string
pub(crate) struct StringSink<'a> {
    string: &'a mut String,
}

impl<'a> StringSink<'a> {
    pub(crate) fn new(s: &mut String) -> StringSink {
        StringSink {
            string: s,
        }
    }
}

impl<'a> Sink for StringSink<'a> {
    type Error = ();

    fn write_encoded_bytes(&mut self, s: &[u8]) -> Result<(), Self::Error> {
        self.string.push_str(str::from_utf8(s).unwrap());

        Ok(())
    }
}

#[cfg(test)]
pub mod tests {
    extern crate rand;

    use super::*;
    use tests::random_config;
    use *;

    use self::rand::distributions::{Distribution, Range};
    use self::rand::{Rng, FromEntropy};

    #[test]
    fn chunked_encode_empty() {
        assert_eq!("", chunked_encode_str(&[], STANDARD));
    }

    #[test]
    fn chunked_encode_intermediate_fast_loop() {
        // > 8 bytes input, will enter the pretty fast loop
        assert_eq!(
            "Zm9vYmFyYmF6cXV4",
            chunked_encode_str(b"foobarbazqux", STANDARD)
        );
    }

    #[test]
    fn chunked_encode_fast_loop() {
        // > 32 bytes input, will enter the uber fast loop
        assert_eq!(
            "Zm9vYmFyYmF6cXV4cXV1eGNvcmdlZ3JhdWx0Z2FycGx5eg==",
            chunked_encode_str(b"foobarbazquxquuxcorgegraultgarplyz", STANDARD)
        );
    }

    #[test]
    fn chunked_encode_slow_loop_only() {
        // < 8 bytes input, slow loop only
        assert_eq!("Zm9vYmFy", chunked_encode_str(b"foobar", STANDARD));
    }

    #[test]
    fn chunked_encode_matches_normal_encode_random_string_sink() {
        let helper = StringSinkTestHelper;
        chunked_encode_matches_normal_encode_random(&helper);
    }

    #[test]
    fn max_input_length_no_pad() {
        let config = config_with_pad(false);
        assert_eq!(768, max_input_length(1024, &config));
    }

    #[test]
    fn max_input_length_with_pad_decrements_one_triple() {
        let config = config_with_pad(true);
        assert_eq!(765, max_input_length(1024, &config));
    }

    #[test]
    fn max_input_length_with_pad_one_byte_short() {
        let config = config_with_pad(true);
        assert_eq!(765, max_input_length(1025, &config));
    }

    #[test]
    fn max_input_length_with_pad_fits_exactly() {
        let config = config_with_pad(true);
        assert_eq!(768, max_input_length(1026, &config));
    }

    #[test]
    fn max_input_length_cant_use_extra_single_encoded_byte() {
        let config = Config::new(
            CharacterSet::Standard,
            false,
            false,
        );
        assert_eq!(300, max_input_length(401, &config));
    }

    pub fn chunked_encode_matches_normal_encode_random<S: SinkTestHelper>(sink_test_helper: &S) {
        let mut input_buf: Vec<u8> = Vec::new();
        let mut output_buf = String::new();
        let mut rng = rand::rngs::SmallRng::from_entropy();
        let input_len_range = Range::new(1, 10_000);

        for _ in 0..5_000 {
            input_buf.clear();
            output_buf.clear();

            let buf_len = input_len_range.sample(&mut rng);
            for _ in 0..buf_len {
                input_buf.push(rng.gen());
            }

            let config = random_config(&mut rng);

            let chunk_encoded_string = sink_test_helper.encode_to_string(config, &input_buf);
            encode_config_buf(&input_buf, config, &mut output_buf);

            assert_eq!(
                output_buf, chunk_encoded_string,
                "input len={}, config: pad={}",
                buf_len, config.pad
            );
        }
    }

    fn chunked_encode_str(bytes: &[u8], config: Config) -> String {
        let mut s = String::new();
        {
            let mut sink = StringSink::new(&mut s);
            let encoder = ChunkedEncoder::new(config);
            encoder.encode(bytes, &mut sink).unwrap();
        }

        return s;
    }

    fn config_with_pad(pad: bool) -> Config {
        Config::new(CharacterSet::Standard, pad, false)
    }

    // An abstraction around sinks so that we can have tests that easily to any sink implementation
    pub trait SinkTestHelper {
        fn encode_to_string(&self, config: Config, bytes: &[u8]) -> String;
    }

    struct StringSinkTestHelper;

    impl SinkTestHelper for StringSinkTestHelper {
        fn encode_to_string(&self, config: Config, bytes: &[u8]) -> String {
            let encoder = ChunkedEncoder::new(config);
            let mut s = String::new();
            {
                let mut sink = StringSink::new(&mut s);
                encoder.encode(bytes, &mut sink).unwrap();
            }

            s
        }
    }

}
<|endoftext|>


<commit_before>//! A pure rust replacement for the [miniz](https://github.com/richgel999/miniz)
//! DEFLATE/zlib encoder/decoder.
//! The plan for this crate is to be used as a back-end for the
//! [flate2](https://github.com/alexcrichton/flate2-rs) crate and eventually remove the
//! need to depend on a C library.
//!
//! # Usage
//! ## Simple compression/decompression:
//! ``` rust
//!
//! use miniz_oxide::inflate::decompress_to_vec;
//! use miniz_oxide::deflate::compress_to_vec;
//!
//! fn roundtrip(data: &[u8]) {
//!     let compressed = compress_to_vec(data, 6);
//!     let decompressed = decompress_to_vec(compressed.as_slice()).expect("Failed to decompress!");
//! #   let _ = decompressed;
//! }
//!
//! # roundtrip(b"Test_data test data lalalal blabla");
//!
//! ```

#![forbid(unsafe_code)]
#![cfg_attr(not(feature = "std"), no_std)]

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

#[cfg(feature = "with-alloc")]
pub mod deflate;
pub mod inflate;
mod shared;

pub use crate::shared::update_adler32 as mz_adler32_oxide;
pub use crate::shared::{MZ_ADLER32_INIT, MZ_DEFAULT_WINDOW_BITS};

/// A list of flush types.
///
/// See <http://www.bolet.org/~pornin/deflate-flush.html> for more in-depth info.
#[repr(i32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum MZFlush {
    /// Don't force any flushing.
    /// Used when more input data is expected.
    None = 0,
    /// Zlib partial flush.
    /// Currently treated as [`Sync`].
    Partial = 1,
    /// Finish compressing the currently buffered data, and output an empty raw block.
    /// Has no use in decompression.
    Sync = 2,
    /// Same as [`Sync`], but resets the compression dictionary so that further compressed
    /// data does not depend on data compressed before the flush.
    ///
    /// Has no use in decompression, and is an error to supply in that case.
    Full = 3,
    /// Attempt to flush the remaining data and end the stream.
    Finish = 4,
    /// Not implemented.
    Block = 5,
}

impl MZFlush {
    /// Create an MZFlush value from an integer value.
    ///
    /// Returns `MZError::Param` on invalid values.
    pub fn new(flush: i32) -> Result<Self, MZError> {
        match flush {
            0 => Ok(MZFlush::None),
            1 | 2 => Ok(MZFlush::Sync),
            3 => Ok(MZFlush::Full),
            4 => Ok(MZFlush::Finish),
            _ => Err(MZError::Param),
        }
    }
}

/// A list of miniz successful status codes.
///
/// These are emitted as the [`Ok`] side of a [`MZResult`] in the [`StreamResult`] returned from
/// [`deflate::stream::deflate()`] or [`inflate::stream::inflate()`].
#[repr(i32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum MZStatus {
    /// Operation succeeded.
    ///
    /// Some data was decompressed or compressed; see the byte counters in the [`StreamResult`] for
    /// details.
    Ok = 0,

    /// Operation succeeded and end of deflate stream was found.
    ///
    /// X-ref [`TINFLStatus::Done`][inflate::TINFLStatus::Done] or
    /// [`TDEFLStatus::Done`][deflate::core::TDEFLStatus::Done] for `inflate` or `deflate`
    /// respectively.
    StreamEnd = 1,

    /// Unused
    NeedDict = 2,
}

/// A list of miniz failed status codes.
///
/// These are emitted as the [`Err`] side of a [`MZResult`] in the [`StreamResult`] returned from
/// [`deflate::stream::deflate()`] or [`inflate::stream::inflate()`].
#[repr(i32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum MZError {
    /// Unused
    ErrNo = -1,

    /// General stream error.
    ///
    /// See [`inflate::stream::inflate()`] docs for details of how it can occur there.
    ///
    /// See [`deflate::stream::deflate()`] docs for how it can in principle occur there, though it's
    /// believed impossible in practice.
    Stream = -2,

    /// Error in inflation; see [`inflate::stream::inflate()`] for details.
    ///
    /// Not returned from [`deflate::stream::deflate()`].
    Data = -3,

    /// Unused
    Mem = -4,

    /// Buffer-related error.
    ///
    /// See the docs of [`deflate::stream::deflate()`] or [`inflate::stream::inflate()`] for details
    /// of when it would trigger in the one you're using.
    Buf = -5,

    /// Unused
    Version = -6,

    /// Bad parameters.
    ///
    /// This can be returned from [`deflate::stream::deflate()`] in the case of bad parameters.  See
    /// [`TDEFLStatus::BadParam`][deflate::core::TDEFLStatus::BadParam].
    Param = -10_000,
}

/// How compressed data is wrapped.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum DataFormat {
    /// Wrapped using the [zlib](http://www.zlib.org/rfc-zlib.html) format.
    Zlib,
    /// Zlib wrapped but ignore and don't compute the adler32 checksum.
    /// Currently only used for inflate, behaves the same as Zlib for compression.
    ZLibIgnoreChecksum,
    /// Raw DEFLATE.
    Raw,
}

impl DataFormat {
    pub fn from_window_bits(window_bits: i32) -> DataFormat {
        if window_bits > 0 {
            DataFormat::Zlib
        } else {
            DataFormat::Raw
        }
    }

    pub fn to_window_bits(self) -> i32 {
        match self {
            DataFormat::Zlib | DataFormat::ZLibIgnoreChecksum => shared::MZ_DEFAULT_WINDOW_BITS,
            DataFormat::Raw => -shared::MZ_DEFAULT_WINDOW_BITS,
        }
    }
}

/// `Result` alias for all miniz status codes both successful and failed.
pub type MZResult = Result<MZStatus, MZError>;

/// A structure containg the result of a call to the inflate or deflate streaming functions.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct StreamResult {
    /// The number of bytes consumed from the input slice.
    pub bytes_consumed: usize,
    /// The number of bytes written to the output slice.
    pub bytes_written: usize,
    /// The return status of the call.
    pub status: MZResult,
}

impl StreamResult {
    #[inline]
    pub const fn error(error: MZError) -> StreamResult {
        StreamResult {
            bytes_consumed: 0,
            bytes_written: 0,
            status: Err(error),
        }
    }
}

impl core::convert::From<StreamResult> for MZResult {
    fn from(res: StreamResult) -> Self {
        res.status
    }
}

impl core::convert::From<&StreamResult> for MZResult {
    fn from(res: &StreamResult) -> Self {
        res.status
    }
}
<commit_msg>docs(core):Remoword obsolete info about flate2 use<commit_after>//! A pure rust replacement for the [miniz](https://github.com/richgel999/miniz)
//! DEFLATE/zlib encoder/decoder.
//! Used a rust back-end for the
//! [flate2](https://github.com/alexcrichton/flate2-rs) crate.
//!
//! # Usage
//! ## Simple compression/decompression:
//! ``` rust
//!
//! use miniz_oxide::inflate::decompress_to_vec;
//! use miniz_oxide::deflate::compress_to_vec;
//!
//! fn roundtrip(data: &[u8]) {
//!     let compressed = compress_to_vec(data, 6);
//!     let decompressed = decompress_to_vec(compressed.as_slice()).expect("Failed to decompress!");
//! #   let _ = decompressed;
//! }
//!
//! # roundtrip(b"Test_data test data lalalal blabla");
//!
//! ```

#![forbid(unsafe_code)]
#![cfg_attr(not(feature = "std"), no_std)]

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

#[cfg(feature = "with-alloc")]
pub mod deflate;
pub mod inflate;
mod shared;

pub use crate::shared::update_adler32 as mz_adler32_oxide;
pub use crate::shared::{MZ_ADLER32_INIT, MZ_DEFAULT_WINDOW_BITS};

/// A list of flush types.
///
/// See <http://www.bolet.org/~pornin/deflate-flush.html> for more in-depth info.
#[repr(i32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum MZFlush {
    /// Don't force any flushing.
    /// Used when more input data is expected.
    None = 0,
    /// Zlib partial flush.
    /// Currently treated as [`Sync`].
    Partial = 1,
    /// Finish compressing the currently buffered data, and output an empty raw block.
    /// Has no use in decompression.
    Sync = 2,
    /// Same as [`Sync`], but resets the compression dictionary so that further compressed
    /// data does not depend on data compressed before the flush.
    ///
    /// Has no use in decompression, and is an error to supply in that case.
    Full = 3,
    /// Attempt to flush the remaining data and end the stream.
    Finish = 4,
    /// Not implemented.
    Block = 5,
}

impl MZFlush {
    /// Create an MZFlush value from an integer value.
    ///
    /// Returns `MZError::Param` on invalid values.
    pub fn new(flush: i32) -> Result<Self, MZError> {
        match flush {
            0 => Ok(MZFlush::None),
            1 | 2 => Ok(MZFlush::Sync),
            3 => Ok(MZFlush::Full),
            4 => Ok(MZFlush::Finish),
            _ => Err(MZError::Param),
        }
    }
}

/// A list of miniz successful status codes.
///
/// These are emitted as the [`Ok`] side of a [`MZResult`] in the [`StreamResult`] returned from
/// [`deflate::stream::deflate()`] or [`inflate::stream::inflate()`].
#[repr(i32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum MZStatus {
    /// Operation succeeded.
    ///
    /// Some data was decompressed or compressed; see the byte counters in the [`StreamResult`] for
    /// details.
    Ok = 0,

    /// Operation succeeded and end of deflate stream was found.
    ///
    /// X-ref [`TINFLStatus::Done`][inflate::TINFLStatus::Done] or
    /// [`TDEFLStatus::Done`][deflate::core::TDEFLStatus::Done] for `inflate` or `deflate`
    /// respectively.
    StreamEnd = 1,

    /// Unused
    NeedDict = 2,
}

/// A list of miniz failed status codes.
///
/// These are emitted as the [`Err`] side of a [`MZResult`] in the [`StreamResult`] returned from
/// [`deflate::stream::deflate()`] or [`inflate::stream::inflate()`].
#[repr(i32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum MZError {
    /// Unused
    ErrNo = -1,

    /// General stream error.
    ///
    /// See [`inflate::stream::inflate()`] docs for details of how it can occur there.
    ///
    /// See [`deflate::stream::deflate()`] docs for how it can in principle occur there, though it's
    /// believed impossible in practice.
    Stream = -2,

    /// Error in inflation; see [`inflate::stream::inflate()`] for details.
    ///
    /// Not returned from [`deflate::stream::deflate()`].
    Data = -3,

    /// Unused
    Mem = -4,

    /// Buffer-related error.
    ///
    /// See the docs of [`deflate::stream::deflate()`] or [`inflate::stream::inflate()`] for details
    /// of when it would trigger in the one you're using.
    Buf = -5,

    /// Unused
    Version = -6,

    /// Bad parameters.
    ///
    /// This can be returned from [`deflate::stream::deflate()`] in the case of bad parameters.  See
    /// [`TDEFLStatus::BadParam`][deflate::core::TDEFLStatus::BadParam].
    Param = -10_000,
}

/// How compressed data is wrapped.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum DataFormat {
    /// Wrapped using the [zlib](http://www.zlib.org/rfc-zlib.html) format.
    Zlib,
    /// Zlib wrapped but ignore and don't compute the adler32 checksum.
    /// Currently only used for inflate, behaves the same as Zlib for compression.
    ZLibIgnoreChecksum,
    /// Raw DEFLATE.
    Raw,
}

impl DataFormat {
    pub fn from_window_bits(window_bits: i32) -> DataFormat {
        if window_bits > 0 {
            DataFormat::Zlib
        } else {
            DataFormat::Raw
        }
    }

    pub fn to_window_bits(self) -> i32 {
        match self {
            DataFormat::Zlib | DataFormat::ZLibIgnoreChecksum => shared::MZ_DEFAULT_WINDOW_BITS,
            DataFormat::Raw => -shared::MZ_DEFAULT_WINDOW_BITS,
        }
    }
}

/// `Result` alias for all miniz status codes both successful and failed.
pub type MZResult = Result<MZStatus, MZError>;

/// A structure containg the result of a call to the inflate or deflate streaming functions.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct StreamResult {
    /// The number of bytes consumed from the input slice.
    pub bytes_consumed: usize,
    /// The number of bytes written to the output slice.
    pub bytes_written: usize,
    /// The return status of the call.
    pub status: MZResult,
}

impl StreamResult {
    #[inline]
    pub const fn error(error: MZError) -> StreamResult {
        StreamResult {
            bytes_consumed: 0,
            bytes_written: 0,
            status: Err(error),
        }
    }
}

impl core::convert::From<StreamResult> for MZResult {
    fn from(res: StreamResult) -> Self {
        res.status
    }
}

impl core::convert::From<&StreamResult> for MZResult {
    fn from(res: &StreamResult) -> Self {
        res.status
    }
}
<|endoftext|>