<commit_before>/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

use crate::compiler_context::CompilerContext;
use graphql_ir::{FragmentDefinition, InlineFragment, LinkedField, OperationDefinition, Selection};
use std::sync::Arc;

///
/// Sorts selections in the fragments and queries (and their selections)
///
pub fn sort_selections<'s>(ctx: &'s CompilerContext<'s>) -> CompilerContext<'s> {
    let mut next_context = CompilerContext::new(ctx.schema());
    for fragment in ctx.fragments() {
        next_context.insert_fragment(transform_fragment(ctx, fragment));
    }
    for operation in ctx.operations() {
        next_context.insert_operation(transform_operation(ctx, operation));
    }
    next_context
}

fn transform_fragment(
    ctx: &CompilerContext<'_>,
    fragment: &FragmentDefinition,
) -> FragmentDefinition {
    FragmentDefinition {
        name: fragment.name,
        type_condition: fragment.type_condition,
        directives: fragment.directives.clone(),
        variable_definitions: fragment.variable_definitions.clone(),
        used_global_variables: fragment.used_global_variables.clone(),
        selections: transform_selections(ctx, &mut fragment.selections.clone()),
    }
}

fn transform_operation(
    ctx: &CompilerContext<'_>,
    operation: &OperationDefinition,
) -> OperationDefinition {
    OperationDefinition {
        kind: operation.kind.clone(),
        name: operation.name,
        type_: operation.type_,
        directives: operation.directives.clone(),
        variable_definitions: operation.variable_definitions.clone(),
        selections: transform_selections(ctx, &mut operation.selections.clone()),
    }
}

fn transfrom_inline_fragment(
    ctx: &CompilerContext<'_>,
    node: &InlineFragment,
) -> Arc<InlineFragment> {
    Arc::new(InlineFragment {
        type_condition: node.type_condition,
        directives: node.directives.clone(),
        selections: transform_selections(ctx, &mut node.selections.clone()),
    })
}

fn transfrom_linked_field(ctx: &CompilerContext<'_>, node: &LinkedField) -> Arc<LinkedField> {
    Arc::new(LinkedField {
        alias: node.alias,
        definition: node.definition,
        arguments: node.arguments.clone(),
        directives: node.directives.clone(),
        selections: transform_selections(ctx, &mut node.selections.clone()),
    })
}

fn transform_selections(
    ctx: &CompilerContext<'_>,
    selections: &mut Vec<Selection>,
) -> Vec<Selection> {
    selections.sort_unstable();

    selections
        .iter_mut()
        .map(|selection| match selection {
            Selection::ScalarField(_) => selection.clone(),
            Selection::FragmentSpread(_) => selection.clone(),
            Selection::LinkedField(node) => {
                Selection::LinkedField(transfrom_linked_field(ctx, node))
            }
            Selection::InlineFragment(node) => {
                Selection::InlineFragment(transfrom_inline_fragment(ctx, node))
            }
        })
        .collect()
}
<commit_msg>Use caching in sort transform<commit_after>/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

use crate::compiler_context::CompilerContext;
use crate::util::ArcAddress;

use graphql_ir::{FragmentDefinition, InlineFragment, LinkedField, OperationDefinition, Selection};
use std::collections::HashMap;
use std::sync::Arc;

// Note on correctness: the ArcAddress here is calculated from addresses of the input
// context. Beecause those value are still referenced, that memory cannot be freed/
// reused for the lifetime of the transform.
type Seen = HashMap<ArcAddress, Selection>;

///
/// Sorts selections in the fragments and queries (and their selections)
///
pub fn sort_selections<'s>(ctx: &'s CompilerContext<'s>) -> CompilerContext<'s> {
    let mut next_context = CompilerContext::new(ctx.schema());
    let mut transformer = Transformer::new();
    for fragment in ctx.fragments() {
        next_context.insert_fragment(transformer.transform_fragment(fragment));
    }
    for operation in ctx.operations() {
        next_context.insert_operation(transformer.transform_operation(operation));
    }
    next_context
}

struct Transformer {
    seen: Seen,
}

impl Transformer {
    fn new() -> Self {
        Self {
            seen: Default::default(),
        }
    }

    fn transform_fragment(&mut self, fragment: &FragmentDefinition) -> FragmentDefinition {
        FragmentDefinition {
            name: fragment.name,
            type_condition: fragment.type_condition,
            directives: fragment.directives.clone(),
            variable_definitions: fragment.variable_definitions.clone(),
            used_global_variables: fragment.used_global_variables.clone(),
            selections: self.transform_selections(&mut fragment.selections.clone()),
        }
    }

    fn transform_operation(&mut self, operation: &OperationDefinition) -> OperationDefinition {
        OperationDefinition {
            kind: operation.kind.clone(),
            name: operation.name,
            type_: operation.type_,
            directives: operation.directives.clone(),
            variable_definitions: operation.variable_definitions.clone(),
            selections: self.transform_selections(&mut operation.selections.clone()),
        }
    }

    fn transfrom_inline_fragment(&mut self, fragment: &Arc<InlineFragment>) -> Selection {
        let key = ArcAddress::new(fragment);
        if let Some(prev) = self.seen.get(&key) {
            return prev.clone();
        }
        let result = Selection::InlineFragment(Arc::new(InlineFragment {
            type_condition: fragment.type_condition,
            directives: fragment.directives.clone(),
            selections: self.transform_selections(&mut fragment.selections.clone()),
        }));
        self.seen.insert(key, result.clone());
        result
    }

    fn transfrom_linked_field(&mut self, linked_field: &Arc<LinkedField>) -> Selection {
        let key = ArcAddress::new(linked_field);
        if let Some(prev) = self.seen.get(&key) {
            return prev.clone();
        }
        let result = Selection::LinkedField(Arc::new(LinkedField {
            alias: linked_field.alias,
            definition: linked_field.definition,
            arguments: linked_field.arguments.clone(),
            directives: linked_field.directives.clone(),
            selections: self.transform_selections(&mut linked_field.selections.clone()),
        }));
        self.seen.insert(key, result.clone());
        result
    }

    fn transform_selections(&mut self, selections: &mut Vec<Selection>) -> Vec<Selection> {
        selections.sort_unstable();

        selections
            .iter_mut()
            .map(|selection| match selection {
                Selection::ScalarField(_) => selection.clone(),
                Selection::FragmentSpread(_) => selection.clone(),
                Selection::LinkedField(node) => self.transfrom_linked_field(node),
                Selection::InlineFragment(node) => self.transfrom_inline_fragment(node),
            })
            .collect()
    }
}
<|endoftext|>


<commit_before>// Generic AArch64 target for bare-metal code - Floating point disabled
//
// Can be used in conjunction with the `target-feature` and
// `target-cpu` compiler flags to opt-in more hardware-specific
// features.
//
// For example, `-C target-cpu=cortex-a53`.

use super::{LinkerFlavor, LldFlavor, PanicStrategy, Target, TargetOptions};

pub fn target() -> Target {
    let opts = TargetOptions {
        abi: "softfloat".to_string(),
        linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
        linker: Some("rust-lld".to_owned()),
        features: "-mmx,-sse,+soft-float".to_string(),
        executables: true,
        disable_redzone: true,
        panic_strategy: PanicStrategy::Abort,
        ..Default::default()
    };
    Target {
        llvm_target: "x86_64-unknown-none-elf".to_string(),
        pointer_width: 64,
        data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
            .to_string(),
        arch: "x86_64".to_string(),
        options: opts,
    }
}
<commit_msg>Use `CodeModel::Kernel` for `x86_64-unknown-none-elf`.<commit_after>// Generic AArch64 target for bare-metal code - Floating point disabled
//
// Can be used in conjunction with the `target-feature` and
// `target-cpu` compiler flags to opt-in more hardware-specific
// features.
//
// For example, `-C target-cpu=cortex-a53`.

use super::{CodeModel, LinkerFlavor, LldFlavor, PanicStrategy, Target, TargetOptions};

pub fn target() -> Target {
    let opts = TargetOptions {
        abi: "softfloat".to_string(),
        linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
        linker: Some("rust-lld".to_owned()),
        features: "-mmx,-sse,+soft-float".to_string(),
        executables: true,
        disable_redzone: true,
        panic_strategy: PanicStrategy::Abort,
        code_model: Some(CodeModel::Kernel),
        ..Default::default()
    };
    Target {
        llvm_target: "x86_64-unknown-none-elf".to_string(),
        pointer_width: 64,
        data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
            .to_string(),
        arch: "x86_64".to_string(),
        options: opts,
    }
}
<|endoftext|>


<commit_before>#[cfg(not(windows))]
compile_error!("This demo only runs on Windows.");

extern crate direct_composition;
extern crate winit;

use direct_composition::{DirectComposition, D3DVisual};
use winit::os::windows::WindowExt;

fn main() {
    let mut events_loop = winit::EventsLoop::new();
    let window = winit::WindowBuilder::new()
        .with_title("Hello, world!")
        .with_dimensions(1024, 768)
        .build(&events_loop)
        .unwrap();

    let composition = direct_composition_from_window(&window);

    let visual1 = composition.create_d3d_visual(300, 200).unwrap();
    visual1.set_offset_x(100.).unwrap();
    visual1.set_offset_y(50.).unwrap();

    let visual2 = composition.create_d3d_visual(400, 300).unwrap();
    let mut offset_y = 100.;
    visual2.set_offset_x(200.).unwrap();
    visual2.set_offset_y(offset_y).unwrap();

    composition.commit().unwrap();

    let mut rgba1 = [0., 0.2, 0.4, 1.];
    let mut rgba2 = [0., 0.5, 0., 0.5];
    render_plain_rgba_frame(&visual1, &rgba1);
    render_plain_rgba_frame(&visual2, &rgba2);

    let mut clicks: u32 = 0;

    events_loop.run_forever(|event| {
        if let winit::Event::WindowEvent { event, .. } = event {
            match event {
                winit::WindowEvent::Closed => {
                    return winit::ControlFlow::Break
                }
                winit::WindowEvent::MouseWheel { delta, .. } => {
                    let dy = match delta {
                        winit::MouseScrollDelta::LineDelta(_, dy) => dy,
                        winit::MouseScrollDelta::PixelDelta(_, dy) => dy,
                    };
                    offset_y = (offset_y - 10. * dy).max(0.).min(468.);

                    visual2.set_offset_y(offset_y).unwrap();
                    composition.commit().unwrap();
                }
                winit::WindowEvent::MouseInput {
                    button: winit::MouseButton::Left,
                    state: winit::ElementState::Pressed,
                    ..
                } => {
                    clicks += 1;
                    let (rgba, visual) = if clicks % 2 == 0 {
                        (&mut rgba1, &visual1)
                    } else {
                        (&mut rgba2, &visual2)
                    };
                    rgba[1] += 0.1;
                    rgba[1] %= 1.;
                    render_plain_rgba_frame(visual, rgba)
                }
                _ => {}
            }
        }
        winit::ControlFlow::Continue
    });
}

fn direct_composition_from_window(window: &winit::Window) -> DirectComposition {
    unsafe {
        DirectComposition::new(window.get_hwnd() as _).unwrap()
    }
}

fn render_plain_rgba_frame(visual: &D3DVisual, rgba: &[f32; 4]) {
    visual.make_current();
    visual.gleam.clear_color(rgba[0], rgba[1], rgba[2], rgba[3]);
    assert_eq!(visual.gleam.get_error(), 0);
    visual.present();
}
<commit_msg>Turns out ClearColor doesn’t clear, it just sets the color… Thanks Sotaro!<commit_after>#[cfg(not(windows))]
compile_error!("This demo only runs on Windows.");

extern crate direct_composition;
extern crate gleam;
extern crate winit;

use direct_composition::{DirectComposition, D3DVisual};
use winit::os::windows::WindowExt;

fn main() {
    let mut events_loop = winit::EventsLoop::new();
    let window = winit::WindowBuilder::new()
        .with_title("Hello, world!")
        .with_dimensions(1024, 768)
        .build(&events_loop)
        .unwrap();

    let composition = direct_composition_from_window(&window);

    let visual1 = composition.create_d3d_visual(300, 200).unwrap();
    visual1.set_offset_x(100.).unwrap();
    visual1.set_offset_y(50.).unwrap();

    let visual2 = composition.create_d3d_visual(400, 300).unwrap();
    let mut offset_y = 100.;
    visual2.set_offset_x(200.).unwrap();
    visual2.set_offset_y(offset_y).unwrap();

    composition.commit().unwrap();

    let mut rgba1 = [0., 0.2, 0.4, 1.];
    let mut rgba2 = [0., 0.5, 0., 0.5];
    render_plain_rgba_frame(&visual1, &rgba1);
    render_plain_rgba_frame(&visual2, &rgba2);

    let mut clicks: u32 = 0;

    events_loop.run_forever(|event| {
        if let winit::Event::WindowEvent { event, .. } = event {
            match event {
                winit::WindowEvent::Closed => {
                    return winit::ControlFlow::Break
                }
                winit::WindowEvent::MouseWheel { delta, .. } => {
                    let dy = match delta {
                        winit::MouseScrollDelta::LineDelta(_, dy) => dy,
                        winit::MouseScrollDelta::PixelDelta(_, dy) => dy,
                    };
                    offset_y = (offset_y - 10. * dy).max(0.).min(468.);

                    visual2.set_offset_y(offset_y).unwrap();
                    composition.commit().unwrap();
                }
                winit::WindowEvent::MouseInput {
                    button: winit::MouseButton::Left,
                    state: winit::ElementState::Pressed,
                    ..
                } => {
                    clicks += 1;
                    let (rgba, visual) = if clicks % 2 == 0 {
                        (&mut rgba1, &visual1)
                    } else {
                        (&mut rgba2, &visual2)
                    };
                    rgba[1] += 0.1;
                    rgba[1] %= 1.;
                    render_plain_rgba_frame(visual, rgba)
                }
                _ => {}
            }
        }
        winit::ControlFlow::Continue
    });
}

fn direct_composition_from_window(window: &winit::Window) -> DirectComposition {
    unsafe {
        DirectComposition::new(window.get_hwnd() as _).unwrap()
    }
}

fn render_plain_rgba_frame(visual: &D3DVisual, rgba: &[f32; 4]) {
    visual.make_current();
    visual.gleam.clear_color(rgba[0], rgba[1], rgba[2], rgba[3]);
    visual.gleam.clear(gleam::gl::COLOR_BUFFER_BIT);
    assert_eq!(visual.gleam.get_error(), 0);
    visual.present();
}
<|endoftext|>


<commit_before>use crate::descriptor::FileDescriptorProto;
use crate::OneofFull;

#[doc(hidden)]
pub struct GeneratedOneofDescriptorData {}

impl GeneratedOneofDescriptorData {
    #[doc(hidden)]
    pub fn new<O>(
        _name_in_message: &'static str,
    ) -> GeneratedOneofDescriptorData
    where
        O: OneofFull,
    {
        GeneratedOneofDescriptorData {}
    }

    #[doc(hidden)]
    pub fn new_2<O>(
        _name_in_file: &'static str,
        _index_in_file: usize,
    ) -> GeneratedOneofDescriptorData
    where
        O: OneofFull,
    {
        GeneratedOneofDescriptorData {}
    }
}

#[derive(Debug)]
pub(crate) struct GeneratedOneofDescriptor {}

impl GeneratedOneofDescriptor {
    pub(crate) fn _new(
        data: GeneratedOneofDescriptorData,
        expected_index: usize,
        file_descriptor_proto: &'static FileDescriptorProto,
    ) -> GeneratedOneofDescriptor {
        let _ = (data, expected_index, file_descriptor_proto);
        GeneratedOneofDescriptor {}
    }
}
<commit_msg>Dead code<commit_after>use crate::descriptor::FileDescriptorProto;
use crate::OneofFull;

#[doc(hidden)]
pub struct GeneratedOneofDescriptorData {}

impl GeneratedOneofDescriptorData {
    #[doc(hidden)]
    pub fn new<O>(_name_in_message: &'static str) -> GeneratedOneofDescriptorData
    where
        O: OneofFull,
    {
        GeneratedOneofDescriptorData {}
    }
}

#[derive(Debug)]
pub(crate) struct GeneratedOneofDescriptor {}

impl GeneratedOneofDescriptor {
    pub(crate) fn _new(
        data: GeneratedOneofDescriptorData,
        expected_index: usize,
        file_descriptor_proto: &'static FileDescriptorProto,
    ) -> GeneratedOneofDescriptor {
        let _ = (data, expected_index, file_descriptor_proto);
        GeneratedOneofDescriptor {}
    }
}
<|endoftext|>


<commit_before>//! Manager for wl_shell clients.

use libc;
use wayland_sys::server::signal::wl_signal_add;
use wlroots_sys::wlr_wl_shell_surface;

use super::wl_shell_handler::WlShell;
use {Surface, WlShellHandler, WlShellSurface};
use compositor::{Compositor, COMPOSITOR_PTR};

/// Handles making new Wayland shells as reported by clients.
pub trait WlShellManagerHandler {
    fn new_surface(&mut self,
                   &mut Compositor,
                   &mut WlShellSurface,
                   &mut Surface)
                   -> Option<Box<WlShellHandler>>;
}

wayland_listener!(WlShellManager, Box<WlShellManagerHandler>, [
    add_listener => add_notify: |this: &mut WlShellManager, data: *mut libc::c_void,| unsafe {
        let manager = &mut this.data;
        let data = data as *mut wlr_wl_shell_surface;
        wlr_log!(L_DEBUG, "New wl_shell_surface request {:p}", data);
        let compositor = &mut *COMPOSITOR_PTR;
        let mut surface = Surface::from_ptr((*data).surface);
        let mut shell_surface = WlShellSurface::new(data);
        let new_surface_res = manager.new_surface(compositor, &mut shell_surface, &mut surface);
        if let Some(shell_surface_handler) = new_surface_res {
            let mut shell_surface = WlShell::new((shell_surface, surface, shell_surface_handler));
            // Add the destroy event to this handler.
            wl_signal_add(&mut (*data).events.destroy as *mut _ as _,
                          shell_surface.destroy_listener() as _);

            // Add the ping timeout event to this handler.
            wl_signal_add(&mut (*data).events.ping_timeout as *mut _ as _,
                          shell_surface.ping_timeout_listener() as _);

            // Add the move request event to this handler.
            wl_signal_add(&mut (*data).events.request_move as *mut _ as _,
                          shell_surface.request_move_listener() as _);

            // Add the resize request event to this handler.
            wl_signal_add(&mut (*data).events.request_resize as *mut _ as _,
                          shell_surface.request_resize_listener() as _);

            // Add the fullscreen request event to this handler.
            wl_signal_add(&mut (*data).events.request_fullscreen as *mut _ as _,
                          shell_surface.request_fullscreen_listener() as _);

            // Add the maximize request event to this handler.
            wl_signal_add(&mut (*data).events.request_maximize as *mut _ as _,
                          shell_surface.request_maximize_listener() as _);

            // Add the set state request event to this handler.
            wl_signal_add(&mut (*data).events.set_state as *mut _ as _,
                          shell_surface.set_state_listener() as _);

            // Add the set title request event to this handler.
            wl_signal_add(&mut (*data).events.set_title as *mut _ as _,
                          shell_surface.set_title_listener() as _);

            // Add the set class request event to this handler.
            wl_signal_add(&mut (*data).events.set_class as *mut _ as _,
                          shell_surface.set_class_listener() as _);

            // NOTE This is cleaned up in the wl_shell_handler::destroy signal.
            ::std::mem::forget(shell_surface);
        }
    };
]);
<commit_msg>Added doc comment to WlShellManagerHandler::new_surface<commit_after>//! Manager for wl_shell clients.

use libc;
use wayland_sys::server::signal::wl_signal_add;
use wlroots_sys::wlr_wl_shell_surface;

use super::wl_shell_handler::WlShell;
use {Surface, WlShellHandler, WlShellSurface};
use compositor::{Compositor, COMPOSITOR_PTR};

/// Handles making new Wayland shells as reported by clients.
pub trait WlShellManagerHandler {
    /// Callback that is triggerde when a new wayland shell surface appears.
    fn new_surface(&mut self,
                   &mut Compositor,
                   &mut WlShellSurface,
                   &mut Surface)
                   -> Option<Box<WlShellHandler>>;
}

wayland_listener!(WlShellManager, Box<WlShellManagerHandler>, [
    add_listener => add_notify: |this: &mut WlShellManager, data: *mut libc::c_void,| unsafe {
        let manager = &mut this.data;
        let data = data as *mut wlr_wl_shell_surface;
        wlr_log!(L_DEBUG, "New wl_shell_surface request {:p}", data);
        let compositor = &mut *COMPOSITOR_PTR;
        let mut surface = Surface::from_ptr((*data).surface);
        let mut shell_surface = WlShellSurface::new(data);
        let new_surface_res = manager.new_surface(compositor, &mut shell_surface, &mut surface);
        if let Some(shell_surface_handler) = new_surface_res {
            let mut shell_surface = WlShell::new((shell_surface, surface, shell_surface_handler));
            // Add the destroy event to this handler.
            wl_signal_add(&mut (*data).events.destroy as *mut _ as _,
                          shell_surface.destroy_listener() as _);

            // Add the ping timeout event to this handler.
            wl_signal_add(&mut (*data).events.ping_timeout as *mut _ as _,
                          shell_surface.ping_timeout_listener() as _);

            // Add the move request event to this handler.
            wl_signal_add(&mut (*data).events.request_move as *mut _ as _,
                          shell_surface.request_move_listener() as _);

            // Add the resize request event to this handler.
            wl_signal_add(&mut (*data).events.request_resize as *mut _ as _,
                          shell_surface.request_resize_listener() as _);

            // Add the fullscreen request event to this handler.
            wl_signal_add(&mut (*data).events.request_fullscreen as *mut _ as _,
                          shell_surface.request_fullscreen_listener() as _);

            // Add the maximize request event to this handler.
            wl_signal_add(&mut (*data).events.request_maximize as *mut _ as _,
                          shell_surface.request_maximize_listener() as _);

            // Add the set state request event to this handler.
            wl_signal_add(&mut (*data).events.set_state as *mut _ as _,
                          shell_surface.set_state_listener() as _);

            // Add the set title request event to this handler.
            wl_signal_add(&mut (*data).events.set_title as *mut _ as _,
                          shell_surface.set_title_listener() as _);

            // Add the set class request event to this handler.
            wl_signal_add(&mut (*data).events.set_class as *mut _ as _,
                          shell_surface.set_class_listener() as _);

            // NOTE This is cleaned up in the wl_shell_handler::destroy signal.
            ::std::mem::forget(shell_surface);
        }
    };
]);
<|endoftext|>


<commit_before>
extern crate rs6502;

#[test]
fn INTEGRATION_CPU_can_add_basic_numbers_in_accumulator() {
    let asm = "
        LDA #$20
        ADC #$10    ; A register should equal 48
    ";

    let mut cpu = rs6502::Cpu::new();
    let mut assembler = rs6502::Assembler::new();

    let bytecode = assembler.assemble_string(asm).unwrap();
    cpu.load(&bytecode[..], None);

    cpu.step_n(2);

    assert_eq!(0x30, cpu.registers.A);
}

#[test]
fn INTEGRATION_CPU_can_add_binary_coded_decimal_numbers_in_accumulator() {
    let asm = "
        SED
        LDA #$20
        ADC #$05    ; A register should equal 0x25
    ";

    let mut cpu = rs6502::Cpu::new();
    let mut assembler = rs6502::Assembler::new();

    let bytecode = assembler.assemble_string(asm).unwrap();
    cpu.load(&bytecode[..], None);

    cpu.step_n(3);

    assert_eq!(0x25, cpu.registers.A);
}

#[test]
fn INTEGRATION_CPU_can_add_mixed_mode_numbers_in_accumulator() {
    let asm = "
        LDA #$20
        ADC #10    ; A register should equal 0x2A
    ";

    let mut cpu = rs6502::Cpu::new();
    let mut assembler = rs6502::Assembler::new();

    let bytecode = assembler.assemble_string(asm).unwrap();
    cpu.load(&bytecode[..], None);

    cpu.step_n(2);

    assert_eq!(0x2A, cpu.registers.A);
}

#[test]
fn INTEGRATION_CPU_can_store_bytes_in_memory() {
    let asm = "
        LDA #$20
        STA $2000
        LDA #10
        STA $2001
    ";

    let mut cpu = rs6502::Cpu::new();
    let mut assembler = rs6502::Assembler::new();

    let bytecode = assembler.assemble_string(asm).unwrap();
    cpu.load(&bytecode[..], None);

    cpu.step_n(4);

    assert_eq!(0x20, cpu.memory[0x2000]);
    assert_eq!(0x0A, cpu.memory[0x2001]);
    assert_eq!(0x00, cpu.memory[0x2002]);
}<commit_msg>Add self-modifying code integration test<commit_after>
extern crate rs6502;

#[test]
fn INTEGRATION_CPU_can_add_basic_numbers_in_accumulator() {
    let asm = "
        LDA #$20
        ADC #$10    ; A register should equal 48
    ";

    let mut cpu = rs6502::Cpu::new();
    let mut assembler = rs6502::Assembler::new();

    let bytecode = assembler.assemble_string(asm).unwrap();
    cpu.load(&bytecode[..], None);

    cpu.step_n(2);

    assert_eq!(0x30, cpu.registers.A);
}

#[test]
fn INTEGRATION_CPU_can_add_binary_coded_decimal_numbers_in_accumulator() {
    let asm = "
        SED
        LDA #$20
        ADC #$05    ; A register should equal 0x25
    ";

    let mut cpu = rs6502::Cpu::new();
    let mut assembler = rs6502::Assembler::new();

    let bytecode = assembler.assemble_string(asm).unwrap();
    cpu.load(&bytecode[..], None);

    cpu.step_n(3);

    assert_eq!(0x25, cpu.registers.A);
}

#[test]
fn INTEGRATION_CPU_can_add_mixed_mode_numbers_in_accumulator() {
    let asm = "
        LDA #$20
        ADC #10    ; A register should equal 0x2A
    ";

    let mut cpu = rs6502::Cpu::new();
    let mut assembler = rs6502::Assembler::new();

    let bytecode = assembler.assemble_string(asm).unwrap();
    cpu.load(&bytecode[..], None);

    cpu.step_n(2);

    assert_eq!(0x2A, cpu.registers.A);
}

#[test]
fn INTEGRATION_CPU_can_store_bytes_in_memory() {
    let asm = "
        LDA #$20
        STA $2000
        LDA #10
        STA $2001
    ";

    let mut cpu = rs6502::Cpu::new();
    let mut assembler = rs6502::Assembler::new();

    let bytecode = assembler.assemble_string(asm).unwrap();
    cpu.load(&bytecode[..], None);

    cpu.step_n(4);

    assert_eq!(0x20, cpu.memory[0x2000]);
    assert_eq!(0x0A, cpu.memory[0x2001]);
    assert_eq!(0x00, cpu.memory[0x2002]);
}

#[test]
fn INTEGRATION_CPU_can_overwrite_own_memory() {
    let asm = "
        LDA #$20
        STA $C006
        LDA #10
        STA $2000
    ";

    let mut cpu = rs6502::Cpu::new();
    let mut assembler = rs6502::Assembler::new();

    let bytecode = assembler.assemble_string(asm).unwrap();
    cpu.load(&bytecode[..], None);

    cpu.step_n(4);

    assert_eq!(0x20, cpu.memory[0x2000]);
}<|endoftext|>


<commit_before>extern crate hyper;
extern crate json;
extern crate requests;

use requests::{delete, get, head, post, put};

#[test]
fn simple_get() {
    const URL: &'static str = "http://httpbin.org/get";
    let res = get(URL).unwrap();
    assert_eq!(res.url(), URL);
    assert_eq!(res.status_code(), hyper::Ok);
    assert_eq!(res.reason(), "OK");
    let data = res.json().unwrap();
    println!("{:?}", data);
    assert_eq!(data["url"], URL);
    assert_eq!(data["headers"]["Host"], "httpbin.org");
    assert_eq!(data["headers"]["User-Agent"],
               concat!("requests-rs/", env!("CARGO_PKG_VERSION")));
}

#[test]
fn simple_post() {
    const URL: &'static str = "http://httpbin.org/post";
    let res = post(URL).unwrap();
    assert_eq!(res.url(), URL);
    assert_eq!(res.status_code(), hyper::Ok);
    assert_eq!(res.reason(), "OK");
}

#[test]
fn simple_put() {
    const URL: &'static str = "http://httpbin.org/put";
    let res = put(URL).unwrap();
    assert_eq!(res.url(), URL);
    assert_eq!(res.status_code(), hyper::Ok);
    assert_eq!(res.reason(), "OK");
}

#[test]
fn simple_head() {
    const URL: &'static str = "http://httpbin.org/get";
    let res = head(URL).unwrap();
    assert_eq!(res.url(), URL);
    assert_eq!(res.status_code(), hyper::Ok);
    assert_eq!(res.reason(), "OK");
}

#[test]
fn simple_delete() {
    const URL: &'static str = "http://httpbin.org/delete";
    let res = delete(URL).unwrap();
    assert_eq!(res.url(), URL);
    assert_eq!(res.status_code(), hyper::Ok);
    assert_eq!(res.reason(), "OK");
}

#[test]
fn user_agent() {
    let useragent = concat!("{\n  \"user-agent\": \"requests-rs/",
                            env!("CARGO_PKG_VERSION"),
                            "\"\n}\n");
    const URL: &'static str = "http://httpbin.org/user-agent";
    let res = get(URL).unwrap();
    assert_eq!(res.url(), URL);
    assert_eq!(res.status_code(), hyper::Ok);
    assert_eq!(res.reason(), "OK");
    assert_eq!(res.text(), Some(useragent));
}

#[test]
fn user_agent_json() {

    const URL: &'static str = "http://httpbin.org/user-agent";
    let res = get(URL).unwrap();
    assert!(res.is_json());

    let ua = res.json().unwrap();
    assert_eq!(ua["user-agent"],
               concat!("requests-rs/", env!("CARGO_PKG_VERSION")));
}

#[test]
fn content() {
    const URL: &'static str = "http://httpbin.org/headers";
    let res = get(URL).unwrap();
    let content = vec![123, 10, 32, 32, 34, 104, 101, 97, 100, 101, 114, 115, 34, 58, 32, 123, 10,
                       32, 32, 32, 32, 34, 72, 111, 115, 116, 34, 58, 32, 34, 104, 116, 116, 112,
                       98, 105, 110, 46, 111, 114, 103, 34, 44, 32, 10, 32, 32, 32, 32, 34, 85,
                       115, 101, 114, 45, 65, 103, 101, 110, 116, 34, 58, 32, 34, 114, 101, 113,
                       117, 101, 115, 116, 115, 45, 114, 115, 47, 48, 46, 48, 46, 49, 55, 34, 10,
                       32, 32, 125, 10, 125, 10];
    assert_eq!(res.content(), &content);
}

macro_rules! status_code_test {
    ($($name:ident: $numeric:expr,)+) => {
        $(#[test]
        fn $name() {
            let res = get(&format!("http://httpbin.org/status/{}", $numeric)).unwrap();
            println!("{}", res.text().unwrap());
            assert_eq!(res.status_code(), hyper::status::StatusCode::from_u16($numeric));
        })+
    }
}

status_code_test! {
    status_code_100: 100,
    status_code_101: 101,
    status_code_102: 102,
    status_code_200: 200,
    status_code_201: 201,
    status_code_202: 202,
    status_code_203: 203,
    status_code_400: 400,
    status_code_401: 401,
    status_code_402: 402,
    status_code_403: 403,
    status_code_404: 404,
    status_code_500: 500,
}
<commit_msg>Update tests<commit_after>extern crate hyper;
extern crate json;
extern crate requests;

use requests::{delete, get, head, post, put};

#[test]
fn simple_get() {
    const URL: &'static str = "http://httpbin.org/get";
    let res = get(URL).unwrap();
    assert_eq!(res.url(), URL);
    assert_eq!(res.status_code(), hyper::Ok);
    assert_eq!(res.reason(), "OK");
    let data = res.json().unwrap();
    println!("{:?}", data);
    assert_eq!(data["url"], URL);
    assert_eq!(data["headers"]["Host"], "httpbin.org");
    assert_eq!(data["headers"]["User-Agent"],
               concat!("requests-rs/", env!("CARGO_PKG_VERSION")));
}

#[test]
fn simple_post() {
    const URL: &'static str = "http://httpbin.org/post";
    let res = post(URL).unwrap();
    assert_eq!(res.url(), URL);
    assert_eq!(res.status_code(), hyper::Ok);
    assert_eq!(res.reason(), "OK");
}

#[test]
fn simple_put() {
    const URL: &'static str = "http://httpbin.org/put";
    let res = put(URL).unwrap();
    assert_eq!(res.url(), URL);
    assert_eq!(res.status_code(), hyper::Ok);
    assert_eq!(res.reason(), "OK");
}

#[test]
fn simple_head() {
    const URL: &'static str = "http://httpbin.org/get";
    let res = head(URL).unwrap();
    assert_eq!(res.url(), URL);
    assert_eq!(res.status_code(), hyper::Ok);
    assert_eq!(res.reason(), "OK");
}

#[test]
fn simple_delete() {
    const URL: &'static str = "http://httpbin.org/delete";
    let res = delete(URL).unwrap();
    assert_eq!(res.url(), URL);
    assert_eq!(res.status_code(), hyper::Ok);
    assert_eq!(res.reason(), "OK");
}

#[test]
fn user_agent() {
    let useragent = concat!("{\n  \"user-agent\": \"requests-rs/",
                            env!("CARGO_PKG_VERSION"),
                            "\"\n}\n");
    const URL: &'static str = "http://httpbin.org/user-agent";
    let res = get(URL).unwrap();
    assert_eq!(res.url(), URL);
    assert_eq!(res.status_code(), hyper::Ok);
    assert_eq!(res.reason(), "OK");
    assert_eq!(res.text(), Some(useragent));
}

#[test]
fn user_agent_json() {

    const URL: &'static str = "http://httpbin.org/user-agent";
    let res = get(URL).unwrap();
    assert!(res.is_json());

    let ua = res.json().unwrap();
    assert_eq!(ua["user-agent"],
               concat!("requests-rs/", env!("CARGO_PKG_VERSION")));
}

#[test]
fn content() {
    const URL: &'static str = "http://httpbin.org/headers";
    let res = get(URL).unwrap();
    let content = vec![123, 10, 32, 32, 34, 104, 101, 97, 100, 101, 114, 115, 34, 58, 32, 123, 10,
                       32, 32, 32, 32, 34, 72, 111, 115, 116, 34, 58, 32, 34, 104, 116, 116, 112,
                       98, 105, 110, 46, 111, 114, 103, 34, 44, 32, 10, 32, 32, 32, 32, 34, 85,
                       115, 101, 114, 45, 65, 103, 101, 110, 116, 34, 58, 32, 34, 114, 101, 113,
                       117, 101, 115, 116, 115, 45, 114, 115, 47, 48, 46, 48, 46, 49, 56, 34, 10,
                       32, 32, 125, 10, 125, 10];
    assert_eq!(res.content(), &content);
}

macro_rules! status_code_test {
    ($($name:ident: $numeric:expr,)+) => {
        $(#[test]
        fn $name() {
            let res = get(&format!("http://httpbin.org/status/{}", $numeric)).unwrap();
            println!("{}", res.text().unwrap());
            assert_eq!(res.status_code(), hyper::status::StatusCode::from_u16($numeric));
        })+
    }
}

status_code_test! {
    status_code_100: 100,
    status_code_101: 101,
    status_code_102: 102,
    status_code_200: 200,
    status_code_201: 201,
    status_code_202: 202,
    status_code_203: 203,
    status_code_400: 400,
    status_code_401: 401,
    status_code_402: 402,
    status_code_403: 403,
    status_code_404: 404,
    status_code_500: 500,
}
<|endoftext|>


<commit_before>extern crate assert;
extern crate dft;

use dft::{Operation, Plan, c64};

mod fixtures;

#[test]
fn complex_forward_1() {
    let mut data = vec![1.0, -2.0];
    dft::transform(as_c64_mut(&mut data), &Plan::new(Operation::Forward, 1));
    assert::close(&data, &[1.0, -2.0], 1e-14);
}

#[test]
fn complex_forward_2() {
    let mut data = vec![1.0, -2.0, 3.0, -4.0];
    dft::transform(as_c64_mut(&mut data), &Plan::new(Operation::Forward, 2));
    assert::close(&data, &[4.0, -6.0, -2.0, 2.0], 1e-14);
}

#[test]
fn complex_forward_128() {
    let mut data = fixtures::TIME_DATA_256.to_vec();
    dft::transform(as_c64_mut(&mut data), &Plan::new(Operation::Forward, 128));
    assert::close(&data, &fixtures::FREQUENCY_DATA_128_COMPLEX[..], 1e-14);
}

#[test]
fn complex_forward_real_256() {
    let mut data = to_c64(&fixtures::TIME_DATA_256);
    dft::transform(&mut data, &Plan::new(Operation::Forward, 256));
    assert::close(as_f64(&data), &fixtures::FREQUENCY_DATA_256_REAL_UNPACKED[..], 1e-13);
}

#[test]
fn complex_inverse_128() {
    let mut data = fixtures::FREQUENCY_DATA_128_COMPLEX.to_vec();
    dft::transform(as_c64_mut(&mut data), &Plan::new(Operation::Inverse, 128));
    assert::close(&data, &fixtures::TIME_DATA_256[..], 1e-14);
}

#[test]
fn real_forward_1() {
    let mut data = vec![1.0];
    dft::transform(&mut data, &Plan::new(Operation::Forward, 1));
    assert_eq!(dft::unpack(&data), vec![c64::new(1.0, 0.0)]);
}

#[test]
fn real_forward_2() {
    let mut data = vec![1.0, -2.0];
    dft::transform(&mut data, &Plan::new(Operation::Forward, 2));
    assert_eq!(dft::unpack(&data), vec![c64::new(-1.0, 0.0), c64::new(3.0, 0.0)]);
}

#[test]
fn real_forward_256() {
    let mut data = fixtures::TIME_DATA_256.to_vec();
    dft::transform(&mut data, &Plan::new(Operation::Forward, 256));
    assert::close(&data, &fixtures::FREQUENCY_DATA_256_REAL_PACKED[..], 1e-13);
    let data = dft::unpack(&data);
    assert::close(as_f64(&data), &fixtures::FREQUENCY_DATA_256_REAL_UNPACKED[..], 1e-13);
}

#[test]
fn real_forward_512() {
    let mut data = fixtures::TIME_DATA_512.to_vec();
    dft::transform(&mut data, &Plan::new(Operation::Forward, 512));
    let data = dft::unpack(&data);
    assert::close(as_f64(&data), &fixtures::FREQUENCY_DATA_512_REAL_UNPACKED[..], 1e-12);
}

#[test]
fn real_inverse_256() {
    let mut data = fixtures::FREQUENCY_DATA_256_REAL_PACKED.to_vec();
    dft::transform(&mut data, &Plan::new(Operation::Inverse, 256));
    assert::close(&data, &fixtures::TIME_DATA_256[..], 1e-14);
}

#[test]
fn real_inverse_512() {
    let mut data = fixtures::TIME_DATA_512.to_vec();
    dft::transform(&mut data, &Plan::new(Operation::Forward, 512));
    dft::transform(&mut data, &Plan::new(Operation::Inverse, 512));
    assert::close(&data, &fixtures::TIME_DATA_512[..], 1e-14);
}

fn as_f64(slice: &[c64]) -> &[f64] {
    unsafe { std::slice::from_raw_parts(slice.as_ptr() as *const _, 2 * slice.len()) }
}

fn as_c64_mut(slice: &mut [f64]) -> &mut [c64] {
    unsafe { std::slice::from_raw_parts_mut(slice.as_mut_ptr() as *mut _, slice.len() / 2) }
}

fn to_c64(slice: &[f64]) -> Vec<c64> {
    slice.iter().map(|&re| c64::new(re, 0.0)).collect()
}
<commit_msg>Adjust the tests<commit_after>extern crate assert;
extern crate dft;

use dft::{Operation, Plan, c64};

mod fixtures;

#[test]
fn complex_forward_1() {
    let mut data = vec![c64::new(1.0, -2.0)];
    dft::transform(&mut data, &Plan::new(Operation::Forward, 1));
    assert_eq!(data, vec![c64::new(1.0, -2.0)]);
}

#[test]
fn complex_forward_2() {
    let mut data = vec![c64::new(1.0, -2.0), c64::new(3.0, -4.0)];
    dft::transform(&mut data, &Plan::new(Operation::Forward, 2));
    assert_eq!(data, vec![c64::new(4.0, -6.0), c64::new(-2.0, 2.0)]);
}

#[test]
fn complex_forward_128() {
    let mut data = fixtures::TIME_DATA_256.to_vec();
    dft::transform(as_c64_mut(&mut data), &Plan::new(Operation::Forward, 128));
    assert::close(&data, &fixtures::FREQUENCY_DATA_128_COMPLEX[..], 1e-14);
}

#[test]
fn complex_forward_real_256() {
    let mut data = to_c64(&fixtures::TIME_DATA_256);
    dft::transform(&mut data, &Plan::new(Operation::Forward, 256));
    assert::close(as_f64(&data), &fixtures::FREQUENCY_DATA_256_REAL_UNPACKED[..], 1e-13);
}

#[test]
fn complex_inverse_128() {
    let mut data = fixtures::FREQUENCY_DATA_128_COMPLEX.to_vec();
    dft::transform(as_c64_mut(&mut data), &Plan::new(Operation::Inverse, 128));
    assert::close(&data, &fixtures::TIME_DATA_256[..], 1e-14);
}

#[test]
fn real_forward_1() {
    let mut data = vec![1.0];
    dft::transform(&mut data, &Plan::new(Operation::Forward, 1));
    assert_eq!(dft::unpack(&data), vec![c64::new(1.0, 0.0)]);
}

#[test]
fn real_forward_2() {
    let mut data = vec![1.0, -2.0];
    dft::transform(&mut data, &Plan::new(Operation::Forward, 2));
    assert_eq!(dft::unpack(&data), vec![c64::new(-1.0, 0.0), c64::new(3.0, 0.0)]);
}

#[test]
fn real_forward_256() {
    let mut data = fixtures::TIME_DATA_256.to_vec();
    dft::transform(&mut data, &Plan::new(Operation::Forward, 256));
    assert::close(&data, &fixtures::FREQUENCY_DATA_256_REAL_PACKED[..], 1e-13);
    let data = dft::unpack(&data);
    assert::close(as_f64(&data), &fixtures::FREQUENCY_DATA_256_REAL_UNPACKED[..], 1e-13);
}

#[test]
fn real_forward_512() {
    let mut data = fixtures::TIME_DATA_512.to_vec();
    dft::transform(&mut data, &Plan::new(Operation::Forward, 512));
    let data = dft::unpack(&data);
    assert::close(as_f64(&data), &fixtures::FREQUENCY_DATA_512_REAL_UNPACKED[..], 1e-12);
}

#[test]
fn real_inverse_256() {
    let mut data = fixtures::FREQUENCY_DATA_256_REAL_PACKED.to_vec();
    dft::transform(&mut data, &Plan::new(Operation::Inverse, 256));
    assert::close(&data, &fixtures::TIME_DATA_256[..], 1e-14);
}

#[test]
fn real_inverse_512() {
    let mut data = fixtures::TIME_DATA_512.to_vec();
    dft::transform(&mut data, &Plan::new(Operation::Forward, 512));
    dft::transform(&mut data, &Plan::new(Operation::Inverse, 512));
    assert::close(&data, &fixtures::TIME_DATA_512[..], 1e-14);
}

fn as_f64(slice: &[c64]) -> &[f64] {
    unsafe { std::slice::from_raw_parts(slice.as_ptr() as *const _, 2 * slice.len()) }
}

fn as_c64_mut(slice: &mut [f64]) -> &mut [c64] {
    unsafe { std::slice::from_raw_parts_mut(slice.as_mut_ptr() as *mut _, slice.len() / 2) }
}

fn to_c64(slice: &[f64]) -> Vec<c64> {
    slice.iter().map(|&re| c64::new(re, 0.0)).collect()
}
<|endoftext|>


<commit_before>use crate::logger::{self, Level};
use std::fs::{self, File, OpenOptions};
use std::io::{Read, Write};
use std::os::unix::fs::OpenOptionsExt;
use std::os::unix::io::AsRawFd;
use std::path::{Path, PathBuf};
use std::process;

fn remove_lock(lock_path: &Path) {
    fs::remove_file(lock_path).ok();
    log!(
        Level::Debug,
        "FsLock: removed lockfile {}",
        lock_path.display()
    );
}

#[derive(Default)]
pub struct FsLock {
    lock_path: PathBuf,
    lock_file: Option<File>,
}

impl Drop for FsLock {
    fn drop(&mut self) {
        if self.lock_file.is_some() {
            remove_lock(&self.lock_path);
        }
    }
}

impl FsLock {
    pub fn try_lock(&mut self, new_lock_path: &Path, pid: &mut libc::pid_t) -> bool {
        if self.lock_file.is_some() && self.lock_path == new_lock_path {
            return true;
        }

        // pid == 0 indicates that something went majorly wrong during locking
        *pid = 0;

        log!(
            Level::Debug,
            "FsLock: trying to lock `{}'",
            new_lock_path.display()
        );

        // first we open (and possibly create) the lock file
        let mut file = match OpenOptions::new().mode(0o600).open(&new_lock_path) {
            Ok(file) => file,
            Err(_) => return false,
        };

        // then we lock it (returns immediately if locking is not possible)
        if unsafe { libc::lockf(file.as_raw_fd(), libc::F_TLOCK, 0) } == 0 {
            log!(
                Level::Debug,
                "FsLock: locked `{}', writing PID...",
                new_lock_path.display()
            );
            let pid = process::id().to_string();
            let buf = pid.as_bytes();
            let success = file.write_all(&buf).is_ok();
            log!(
                Level::Debug,
                "FsLock: PID written successfully: {}",
                success as usize
            );
            if success {
                if self.lock_file.take().is_some() {
                    remove_lock(&self.lock_path);
                }
                self.lock_file = Some(file);
                self.lock_path = new_lock_path.to_owned();
            }
            success
        } else {
            log!(
                Level::Error,
                "FsLock: something went wrong during locking: {}",
                errno::errno()
            );

            // locking was not successful -> read PID of locking process from the file
            let mut buf = String::new();
            if file.read_to_string(&mut buf).is_ok() {
                *pid = buf.parse().unwrap_or(0);
            }
            log!(
                Level::Debug,
                "FsLock: locking failed, already locked by {}",
                pid
            );
            false
        }
    }
}
<commit_msg>Add missing truncate<commit_after>use crate::logger::{self, Level};
use std::fs::{self, File, OpenOptions};
use std::io::{Read, Write};
use std::os::unix::fs::OpenOptionsExt;
use std::os::unix::io::AsRawFd;
use std::path::{Path, PathBuf};
use std::process;

fn remove_lock(lock_path: &Path) {
    fs::remove_file(lock_path).ok();
    log!(
        Level::Debug,
        "FsLock: removed lockfile {}",
        lock_path.display()
    );
}

#[derive(Default)]
pub struct FsLock {
    lock_path: PathBuf,
    lock_file: Option<File>,
}

impl Drop for FsLock {
    fn drop(&mut self) {
        if self.lock_file.is_some() {
            remove_lock(&self.lock_path);
        }
    }
}

impl FsLock {
    pub fn try_lock(&mut self, new_lock_path: &Path, pid: &mut libc::pid_t) -> bool {
        if self.lock_file.is_some() && self.lock_path == new_lock_path {
            return true;
        }

        // pid == 0 indicates that something went majorly wrong during locking
        *pid = 0;

        log!(
            Level::Debug,
            "FsLock: trying to lock `{}'",
            new_lock_path.display()
        );

        // first we open (and possibly create) the lock file
        let mut options = OpenOptions::new();
        options.mode(0o600).truncate(true);
        let mut file = match options.open(&new_lock_path) {
            Ok(file) => file,
            Err(_) => return false,
        };

        // then we lock it (returns immediately if locking is not possible)
        if unsafe { libc::lockf(file.as_raw_fd(), libc::F_TLOCK, 0) } == 0 {
            log!(
                Level::Debug,
                "FsLock: locked `{}', writing PID...",
                new_lock_path.display()
            );
            let pid = process::id().to_string();
            let buf = pid.as_bytes();
            let success = file.write_all(&buf).is_ok();
            log!(
                Level::Debug,
                "FsLock: PID written successfully: {}",
                success as usize
            );
            if success {
                if self.lock_file.take().is_some() {
                    remove_lock(&self.lock_path);
                }
                self.lock_file = Some(file);
                self.lock_path = new_lock_path.to_owned();
            }
            success
        } else {
            log!(
                Level::Error,
                "FsLock: something went wrong during locking: {}",
                errno::errno()
            );

            // locking was not successful -> read PID of locking process from the file
            let mut buf = String::new();
            if file.read_to_string(&mut buf).is_ok() {
                *pid = buf.parse().unwrap_or(0);
            }
            log!(
                Level::Debug,
                "FsLock: locking failed, already locked by {}",
                pid
            );
            false
        }
    }
}
<|endoftext|>


<commit_before>// Claxon -- A FLAC decoding library in Rust
// Copyright 2018 Ruud van Asseldonk
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// A copy of the License has been included in the root of the repository.

#![no_main]

extern crate libfuzzer_sys;
extern crate claxon;

use std::io;
use std::io::Seek;
use std::iter;

#[export_name="rust_fuzzer_test_input"]
pub extern fn go(data: &[u8]) {
    // We want two distinct marker bytes.
    if data.len() < 2 || data[0] == data[1] {
        return
    }

    let mut cursor = io::Cursor::new(&data[2..]);

    // Allocate two large buffers filled with a marker byte. We will decode one
    // block twice, once into each buffer. If both decodes are successful, then
    // the two outputs should be identical. If we don't overwrite parts of the
    // buffer, then we would see a difference in the marker byte. The buffer
    // allocated up front should be large enough that Claxon does not need to
    // allocate a new one.
    let buffer0: Vec<i32> = iter::repeat(data[0] as i32).take(1024 * 1024 * 4).collect();
    let buffer1: Vec<i32> = iter::repeat(data[1] as i32).take(1024 * 1024 * 4).collect();

    let result0 = {
        let mut reader = match claxon::FlacReader::new(&mut cursor) {
            Ok(r) => r,
            Err(..) => return,
        };

        match reader.blocks().read_next_or_eof(buffer0) {
            Ok(Some(block)) => Some(block.into_buffer()),
            _ => None,
        }
    };

    cursor.seek(io::SeekFrom::Start(0)).unwrap();

    let result1 = {
        let mut reader = match claxon::FlacReader::new(&mut cursor) {
            Ok(r) => r,
            Err(..) => panic!("First time decoded fine, second time should too."),
        };

        match reader.blocks().read_next_or_eof(buffer1) {
            Ok(Some(block)) => Some(block.into_buffer()),
            _ => None,
        }
    };

    assert_eq!(result0, result1);
}
<commit_msg>Speed up differential fuzzer<commit_after>// Claxon -- A FLAC decoding library in Rust
// Copyright 2018 Ruud van Asseldonk
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// A copy of the License has been included in the root of the repository.

#![no_main]

extern crate libfuzzer_sys;
extern crate claxon;

use std::io::Seek;
use std::io;
use std::iter;

#[export_name="rust_fuzzer_test_input"]
pub extern fn go(data: &[u8]) {
    // We want two distinct marker bytes.
    if data.len() < 2 || data[0] == data[1] {
        return
    }

    let mut cursor = io::Cursor::new(&data[2..]);

    // Allocate two large buffers filled with a marker byte. We will decode one
    // block twice, once into each buffer. If both decodes are successful, then
    // the two outputs should be identical. If we don't overwrite parts of the
    // buffer, then we would see a difference in the marker byte. The buffer
    // allocated up front should be large enough that Claxon does not need to
    // allocate a new one, but small enough to keep the fuzzer fast.
    let buffer0: Vec<i32> = iter::repeat(data[0] as i32).take(1024 * 8).collect();
    let buffer1: Vec<i32> = iter::repeat(data[1] as i32).take(1024 * 8).collect();

    // NOTE: Somewhat surprisingly, the bove runs at about 4x the execs per
    // second of this version below. I should file a performance bug against Rust.
    // let mut buffer0: Vec<i32> = Vec::with_capacity(1024 * 8);
    // let mut buffer1: Vec<i32> = Vec::with_capacity(1024 * 8);
    // buffer0.resize(1024 * 16, data[0] as i32);
    // buffer1.resize(1024 * 16, data[1] as i32);

    let result0 = {
        let mut reader = match claxon::FlacReader::new(&mut cursor) {
            Ok(r) => r,
            Err(..) => return,
        };

        match reader.blocks().read_next_or_eof(buffer0) {
            Ok(Some(block)) => Some(block.into_buffer()),
            _ => None,
        }
    };

    cursor.seek(io::SeekFrom::Start(0)).unwrap();

    let result1 = {
        let mut reader = match claxon::FlacReader::new(&mut cursor) {
            Ok(r) => r,
            Err(..) => panic!("First time decoded fine, second time should too."),
        };

        match reader.blocks().read_next_or_eof(buffer1) {
            Ok(Some(block)) => Some(block.into_buffer()),
            _ => None,
        }
    };

    assert_eq!(result0, result1);
}
<|endoftext|>


<commit_before>use std::cell::Cell;
use std::sync::atomic::{AtomicUsize, Ordering};
use super::internal::*;
use super::*;
use super::len::*;

// The key optimization for find_first is that a consumer can stop its search if
// some consumer to its left already found a match (and similarly for consumers
// to the right for find_last). To make this work, all consumers need some
// notion of their position in the data relative to other consumers, including
// unindexed consumers that have no built-in notion of position.
//
// To solve this, we assign each consumer a lower and upper bound for an
// imaginary "range" of data that it consumes. The initial consumer starts with
// the range 0..usize::max_value(). The split divides this range in half so that
// one resulting consumer has the range 0..(usize::max_value() / 2), and the
// other has (usize::max_value() / 2)..usize::max_value(). Every subsequent
// split divides the range in half again until it cannot be split anymore
// (i.e. its length is 1), in which case the split returns two consumers with
// the same range. In that case both consumers will continue to consume all
// their data regardless of whether a better match is found, but the reducer
// will still return the correct answer.

#[derive(Copy, Clone)]
enum MatchPosition {
    Leftmost,
    Rightmost,
}

// Returns true if pos1 is a better match than pos2 according to MatchPosition
fn better_position(pos1: usize, pos2: usize, mp: MatchPosition) -> bool {
    match mp {
        MatchPosition::Leftmost => pos1 < pos2,
        MatchPosition::Rightmost => pos1 > pos2,
    }
}

pub fn find_first<PAR_ITER, FIND_OP>(pi: PAR_ITER, find_op: FIND_OP) -> Option<PAR_ITER::Item>
    where PAR_ITER: ParallelIterator,
          FIND_OP: Fn(&PAR_ITER::Item) -> bool + Sync
{
    let best_found = AtomicUsize::new(usize::max_value());
    let consumer = FindConsumer::new(&find_op, MatchPosition::Leftmost, &best_found);
    pi.drive_unindexed(consumer)
}

pub fn find_last<PAR_ITER, FIND_OP>(pi: PAR_ITER, find_op: FIND_OP) -> Option<PAR_ITER::Item>
    where PAR_ITER: ParallelIterator,
          FIND_OP: Fn(&PAR_ITER::Item) -> bool + Sync
{
    let best_found = AtomicUsize::new(0);
    let consumer = FindConsumer::new(&find_op, MatchPosition::Rightmost, &best_found);
    pi.drive_unindexed(consumer)
}

struct FindConsumer<'f, FIND_OP: 'f> {
    find_op: &'f FIND_OP,
    lower_bound: Cell<usize>,
    upper_bound: usize,
    match_position: MatchPosition,
    best_found: &'f AtomicUsize,
}

impl<'f, FIND_OP> FindConsumer<'f, FIND_OP> {
    fn new(find_op: &'f FIND_OP,
           match_position: MatchPosition,
           best_found: &'f AtomicUsize) -> Self {
        FindConsumer {
            find_op: find_op,
            lower_bound: Cell::new(0),
            upper_bound: usize::max_value(),
            match_position: match_position,
            best_found: best_found,
        }
    }

    fn current_index(&self) -> usize {
        match self.match_position {
            MatchPosition::Leftmost => self.lower_bound.get(),
            MatchPosition::Rightmost => self.upper_bound
        }
    }
}

impl<'f, ITEM, FIND_OP> Consumer<ITEM> for FindConsumer<'f, FIND_OP>
    where ITEM: Send,
          FIND_OP: Fn(&ITEM) -> bool + Sync
{
    type Folder = FindFolder<'f, ITEM, FIND_OP>;
    type Reducer = FindReducer;
    type Result = Option<ITEM>;

    fn cost(&mut self, cost: f64) -> f64 {
        cost * FUNC_ADJUSTMENT
    }

    fn split_at(self, _index: usize) -> (Self, Self, Self::Reducer) {
        let dir = self.match_position;
        (self.split_off(),
         self,
         FindReducer { match_position: dir })
    }

    fn into_folder(self) -> Self::Folder {
        FindFolder {
            find_op: self.find_op,
            boundary: self.current_index(),
            match_position: self.match_position,
            best_found: self.best_found,
            item: None,
        }
    }

    fn full(&self) -> bool {
        // can stop consuming if the best found index so far is *strictly*
        // better than anything this consumer will find
        better_position(self.best_found.load(Ordering::Relaxed),
                        self.current_index(),
                        self.match_position)
    }
}

impl<'f, ITEM, FIND_OP> UnindexedConsumer<ITEM> for FindConsumer<'f, FIND_OP>
    where ITEM: Send,
          FIND_OP: Fn(&ITEM) -> bool + Sync
{
    fn split_off(&self) -> Self {
        // Upper bound for one consumer will be lower bound for the other. This
        // overlap is okay, because only one of the bounds will be used for
        // comparing against best_found; the other is kept only to be able to
        // divide the range in half.
        //
        // This code assumes that the caller of split_off will use the result as
        // the *left* side of this iterator, and the remainder of self as the
        // *right* side.
        let old_lower_bound = self.lower_bound.get();
        let median = old_lower_bound + ((self.upper_bound - old_lower_bound) / 2);
        self.lower_bound.set(median);

        FindConsumer {
            find_op: self.find_op,
            lower_bound: Cell::new(old_lower_bound),
            upper_bound: median,
            match_position: self.match_position,
            best_found: self.best_found,
        }
    }

    fn to_reducer(&self) -> Self::Reducer {
        FindReducer { match_position: self.match_position }
    }
}

struct FindFolder<'f, ITEM, FIND_OP: 'f> {
    find_op: &'f FIND_OP,
    boundary: usize,
    match_position: MatchPosition,
    best_found: &'f AtomicUsize,
    item: Option<ITEM>,
}

impl<'f, FIND_OP: 'f + Fn(&ITEM) -> bool, ITEM> Folder<ITEM> for FindFolder<'f, ITEM, FIND_OP> {
    type Result = Option<ITEM>;

    fn consume(mut self, item: ITEM) -> Self {
        if (self.find_op)(&item) {
            // Continuously try to set best_found until we succeed or we
            // discover a better match was already found.
            let mut current = self.best_found.load(Ordering::Relaxed);
            let mut exchange_result = Result::Err(0);
            while better_position(self.boundary, current, self.match_position) &&
                  exchange_result.is_err() {
                exchange_result = self.best_found.compare_exchange_weak(current,
                                                                        self.boundary,
                                                                        Ordering::Relaxed,
                                                                        Ordering::Relaxed);
                if exchange_result.is_err() {
                    current = self.best_found.load(Ordering::Relaxed);
                }
            }

            if exchange_result.is_ok() {
                self.item = Some(item);
            }
        }
        self
    }

    fn complete(self) -> Self::Result {
        self.item
    }

    fn full(&self) -> bool {
        better_position(self.best_found.load(Ordering::Relaxed),
                        self.boundary,
                        self.match_position)
    }
}

struct FindReducer {
    match_position: MatchPosition
}

impl<ITEM> Reducer<Option<ITEM>> for FindReducer {
    fn reduce(self, left: Option<ITEM>, right: Option<ITEM>) -> Option<ITEM> {
        match self.match_position {
            MatchPosition::Leftmost => left.or(right),
            MatchPosition::Rightmost => right.or(left)
        }
    }
}
<commit_msg>Avoid clobbering earlier results in find_first<commit_after>use std::cell::Cell;
use std::sync::atomic::{AtomicUsize, Ordering};
use super::internal::*;
use super::*;
use super::len::*;

// The key optimization for find_first is that a consumer can stop its search if
// some consumer to its left already found a match (and similarly for consumers
// to the right for find_last). To make this work, all consumers need some
// notion of their position in the data relative to other consumers, including
// unindexed consumers that have no built-in notion of position.
//
// To solve this, we assign each consumer a lower and upper bound for an
// imaginary "range" of data that it consumes. The initial consumer starts with
// the range 0..usize::max_value(). The split divides this range in half so that
// one resulting consumer has the range 0..(usize::max_value() / 2), and the
// other has (usize::max_value() / 2)..usize::max_value(). Every subsequent
// split divides the range in half again until it cannot be split anymore
// (i.e. its length is 1), in which case the split returns two consumers with
// the same range. In that case both consumers will continue to consume all
// their data regardless of whether a better match is found, but the reducer
// will still return the correct answer.

#[derive(Copy, Clone)]
enum MatchPosition {
    Leftmost,
    Rightmost,
}

// Returns true if pos1 is a better match than pos2 according to MatchPosition
fn better_position(pos1: usize, pos2: usize, mp: MatchPosition) -> bool {
    match mp {
        MatchPosition::Leftmost => pos1 < pos2,
        MatchPosition::Rightmost => pos1 > pos2,
    }
}

pub fn find_first<PAR_ITER, FIND_OP>(pi: PAR_ITER, find_op: FIND_OP) -> Option<PAR_ITER::Item>
    where PAR_ITER: ParallelIterator,
          FIND_OP: Fn(&PAR_ITER::Item) -> bool + Sync
{
    let best_found = AtomicUsize::new(usize::max_value());
    let consumer = FindConsumer::new(&find_op, MatchPosition::Leftmost, &best_found);
    pi.drive_unindexed(consumer)
}

pub fn find_last<PAR_ITER, FIND_OP>(pi: PAR_ITER, find_op: FIND_OP) -> Option<PAR_ITER::Item>
    where PAR_ITER: ParallelIterator,
          FIND_OP: Fn(&PAR_ITER::Item) -> bool + Sync
{
    let best_found = AtomicUsize::new(0);
    let consumer = FindConsumer::new(&find_op, MatchPosition::Rightmost, &best_found);
    pi.drive_unindexed(consumer)
}

struct FindConsumer<'f, FIND_OP: 'f> {
    find_op: &'f FIND_OP,
    lower_bound: Cell<usize>,
    upper_bound: usize,
    match_position: MatchPosition,
    best_found: &'f AtomicUsize,
}

impl<'f, FIND_OP> FindConsumer<'f, FIND_OP> {
    fn new(find_op: &'f FIND_OP,
           match_position: MatchPosition,
           best_found: &'f AtomicUsize) -> Self {
        FindConsumer {
            find_op: find_op,
            lower_bound: Cell::new(0),
            upper_bound: usize::max_value(),
            match_position: match_position,
            best_found: best_found,
        }
    }

    fn current_index(&self) -> usize {
        match self.match_position {
            MatchPosition::Leftmost => self.lower_bound.get(),
            MatchPosition::Rightmost => self.upper_bound
        }
    }
}

impl<'f, ITEM, FIND_OP> Consumer<ITEM> for FindConsumer<'f, FIND_OP>
    where ITEM: Send,
          FIND_OP: Fn(&ITEM) -> bool + Sync
{
    type Folder = FindFolder<'f, ITEM, FIND_OP>;
    type Reducer = FindReducer;
    type Result = Option<ITEM>;

    fn cost(&mut self, cost: f64) -> f64 {
        cost * FUNC_ADJUSTMENT
    }

    fn split_at(self, _index: usize) -> (Self, Self, Self::Reducer) {
        let dir = self.match_position;
        (self.split_off(),
         self,
         FindReducer { match_position: dir })
    }

    fn into_folder(self) -> Self::Folder {
        FindFolder {
            find_op: self.find_op,
            boundary: self.current_index(),
            match_position: self.match_position,
            best_found: self.best_found,
            item: None,
        }
    }

    fn full(&self) -> bool {
        // can stop consuming if the best found index so far is *strictly*
        // better than anything this consumer will find
        better_position(self.best_found.load(Ordering::Relaxed),
                        self.current_index(),
                        self.match_position)
    }
}

impl<'f, ITEM, FIND_OP> UnindexedConsumer<ITEM> for FindConsumer<'f, FIND_OP>
    where ITEM: Send,
          FIND_OP: Fn(&ITEM) -> bool + Sync
{
    fn split_off(&self) -> Self {
        // Upper bound for one consumer will be lower bound for the other. This
        // overlap is okay, because only one of the bounds will be used for
        // comparing against best_found; the other is kept only to be able to
        // divide the range in half.
        //
        // This code assumes that the caller of split_off will use the result as
        // the *left* side of this iterator, and the remainder of self as the
        // *right* side.
        let old_lower_bound = self.lower_bound.get();
        let median = old_lower_bound + ((self.upper_bound - old_lower_bound) / 2);
        self.lower_bound.set(median);

        FindConsumer {
            find_op: self.find_op,
            lower_bound: Cell::new(old_lower_bound),
            upper_bound: median,
            match_position: self.match_position,
            best_found: self.best_found,
        }
    }

    fn to_reducer(&self) -> Self::Reducer {
        FindReducer { match_position: self.match_position }
    }
}

struct FindFolder<'f, ITEM, FIND_OP: 'f> {
    find_op: &'f FIND_OP,
    boundary: usize,
    match_position: MatchPosition,
    best_found: &'f AtomicUsize,
    item: Option<ITEM>,
}

impl<'f, FIND_OP: 'f + Fn(&ITEM) -> bool, ITEM> Folder<ITEM> for FindFolder<'f, ITEM, FIND_OP> {
    type Result = Option<ITEM>;

    fn consume(mut self, item: ITEM) -> Self {
        let found_best_in_range = match self.match_position {
            MatchPosition::Leftmost => self.item.is_some(),
            MatchPosition::Rightmost => false,
        };

        if !found_best_in_range && (self.find_op)(&item) {
            // Continuously try to set best_found until we succeed or we
            // discover a better match was already found.
            let mut current = self.best_found.load(Ordering::Relaxed);
            let mut exchange_result = Result::Err(0);
            while !better_position(current, self.boundary, self.match_position) &&
                  exchange_result.is_err() {
                exchange_result = self.best_found.compare_exchange_weak(current,
                                                                        self.boundary,
                                                                        Ordering::Relaxed,
                                                                        Ordering::Relaxed);
                if exchange_result.is_err() {
                    current = self.best_found.load(Ordering::Relaxed);
                }
            }

            if exchange_result.is_ok() {
                self.item = Some(item);
            }
        }
        self
    }

    fn complete(self) -> Self::Result {
        self.item
    }

    fn full(&self) -> bool {
        let found_best_in_range = match self.match_position {
            MatchPosition::Leftmost => self.item.is_some(),
            MatchPosition::Rightmost => false,
        };

        found_best_in_range ||
            better_position(self.best_found.load(Ordering::Relaxed),
                            self.boundary,
                            self.match_position)
    }
}

// These tests requires that a folder be assigned to an iterator with more than
// one element. We can't necessarily determine when that will happen for a given
// input to find_first/find_last, so we test the folder directly here instead.
#[test]
pub fn find_first_folder_does_not_clobber_first_found() {
    let best_found = AtomicUsize::new(usize::max_value());
    let f = FindFolder {
        find_op: &(|&x: &i32| -> bool { true }),
        boundary: 0,
        match_position: MatchPosition::Leftmost,
        best_found: &best_found,
        item: None,
    };
    let f = f.consume(0_i32).consume(1_i32).consume(2_i32);
    assert!(f.full());
    assert_eq!(f.complete(), Some(0_i32));
}

#[test]
pub fn find_last_folder_yields_last_match() {
    let best_found = AtomicUsize::new(0);
    let f = FindFolder {
        find_op: &(|&x: &i32| -> bool { true }),
        boundary: 0,
        match_position: MatchPosition::Rightmost,
        best_found: &best_found,
        item: None,
    };
    let f = f.consume(0_i32).consume(1_i32).consume(2_i32);
    assert_eq!(f.complete(), Some(2_i32));
}

struct FindReducer {
    match_position: MatchPosition
}

impl<ITEM> Reducer<Option<ITEM>> for FindReducer {
    fn reduce(self, left: Option<ITEM>, right: Option<ITEM>) -> Option<ITEM> {
        match self.match_position {
            MatchPosition::Leftmost => left.or(right),
            MatchPosition::Rightmost => right.or(left)
        }
    }
}
<|endoftext|>


<commit_before>//! Utilities to do with connections between a Minecraft or Forge client and Netherrack

extern crate chrono;
use self::chrono::duration::Duration;

use super::packet::{ PacketHeader,
                     ID_HANDSHAKE_CTS_HANDSHAKING,
                     ID_STATUS_CTS_REQUEST, ID_STATUS_CTS_PING
                   };

use std::collections::VecDeque;

use std::net::{Shutdown, TcpStream};

use std::io::Read;

use super::deque_buffer::DequeBuffer;

/// An enum describing the current connection's state
#[derive(PartialEq, Clone, Copy, Debug)]
pub enum ConnectionState {

    /// Connection is in handshake mode
    HANDSHAKE,

    /// Connection is in login mode
    LOGIN,

    /// Connection is in status mode
    STATUS,

    /// Connection is in play mode
    PLAY

}

/// A struct defining a game connection
#[derive(Debug)]
pub struct GameConnection {

    /// The TCP stream bound to this GameConnection
    pub stream: TcpStream,

    /// The state of this GameConnection
    pub state: ConnectionState

}

impl GameConnection {

    /// Creates a new GameConnection
    pub fn new(stream: TcpStream) -> GameConnection {
        GameConnection {
            stream: stream,
            state: ConnectionState::HANDSHAKE
        }
    }

    pub fn disconnect(&mut self) {
        //TODO: Check to see if in ConnectionState::PLAY, otherwise
        let result = self.stream.shutdown(Shutdown::Both);

        if result.is_ok() == false {
            error!("Error disconnecting: {:?}", result);
        }

    }

    /// Starts listening on the connection
    pub fn start_listening(&mut self) {

        trace!("Got a new client from {}!", self.stream.peer_addr().unwrap());

        let mut timeout_duration = Duration::zero();

        loop {

            if timeout_duration.num_seconds() >= 10 {
                info!("Client at {} timed out, dropping connection", self.stream.peer_addr().unwrap());
                self.disconnect();
                break;
            }

            let mut raw_buffer = vec![0u8; 512];

            match self.stream.read(&mut raw_buffer) {

                Err(error) => {
                    // Connection dropped out or something broke
                    // In the future, we use the customized NetherrackStream to see if we're in GAME mode, and if so, get the attached player and start saving their information and get rid of them
                    // For now, we just exit the loop
                    error!("Got an error! {}", error);

                    self.disconnect();
                    break;
                }
                Ok(count) => {
                    if count == 0 {
                        //Nothing in stream, let's sleep for a few milliseconds and try again
                        timeout_duration = timeout_duration + Duration::milliseconds(2);
                        ::std::thread::sleep_ms(2);
                    } else {

                        timeout_duration = Duration::zero();

                        // Now truncate the raw buffer - Don't worry, it will reallocate to 512 on the next networking loop
                        raw_buffer.truncate(count);

                        let mut backing: VecDeque<u8> = VecDeque::<u8>::with_capacity(count);

                        for b in raw_buffer {

                            backing.push_back(b);
                        }

                        let mut buffer = DequeBuffer::from(backing);

                        //drop(raw_buffer);

                        let length_result = buffer.read_unsigned_varint_32();
                        let id_result = buffer.read_unsigned_varint_32();

                        if length_result.is_err() || id_result.is_err() {
                            error!("Error while reading packet ID or length! Oh no, dropping connection");

                            self.disconnect();
                            break;
                        }

                        let packet_header = PacketHeader::new(length_result.unwrap(), id_result.unwrap());

                        if self.state == ConnectionState::HANDSHAKE {

                            match packet_header.id {

                                ID_HANDSHAKE_CTS_HANDSHAKING => {
                                    super::packet::incoming::handshake::HandshakePacket::decode(packet_header, self, &mut buffer).handle(self);
                                },
                                _ => debug!("Incoming handshake packet unhandled; ID: {}, Length: {}", packet_header.id, packet_header.length)

                            }

                        } else if self.state == ConnectionState::LOGIN {

                            match packet_header.id {

                                _ => debug!("Incoming login packet unhandled; ID: {}, Length: {}", packet_header.id, packet_header.length)

                            }

                        } else if self.state == ConnectionState::STATUS {

                            match packet_header.id {

                                ID_STATUS_CTS_REQUEST => {
                                    super::packet::incoming::status::StatusRequestPacket::decode(packet_header, self, &mut buffer).handle(self);
                                },
                                ID_STATUS_CTS_PING => {
                                    super::packet::incoming::status::ListPingPacket::decode(packet_header, self, &mut buffer).handle(self);
                                },
                                _ => debug!("Incoming play packet unhandled; ID: {}, Length: {}", packet_header.id, packet_header.length)

                            }

                        } else if self.state == ConnectionState::PLAY {

                            match packet_header.id {

                                _ => debug!("Incoming play packet unhandled; ID: {}, Length: {}", packet_header.id, packet_header.length)

                            }

                        }

                        // This is a memory leak. We need to get the time of last packet and check to see if it's more than 20 seconds ago
                    }
                }

            }

        }

        info!("Connection closed");

    }

}<commit_msg>Add a struct to GameConnection to help with future Forge work<commit_after>//! Utilities to do with connections between a Minecraft or Forge client and Netherrack

extern crate chrono;
use self::chrono::duration::Duration;

use super::packet::{ PacketHeader,
                     ID_HANDSHAKE_CTS_HANDSHAKING,
                     ID_STATUS_CTS_REQUEST, ID_STATUS_CTS_PING
                   };

use std::collections::VecDeque;

use std::net::{Shutdown, TcpStream};

use std::io::Read;

use super::deque_buffer::DequeBuffer;

/// An enum describing the current connection's state
#[derive(PartialEq, Clone, Copy, Debug)]
pub enum ConnectionState {

    /// Connection is in handshake mode
    HANDSHAKE,

    /// Connection is in login mode
    LOGIN,

    /// Connection is in status mode
    STATUS,

    /// Connection is in play mode
    PLAY

}

/// A struct defining a game connection
#[derive(Debug)]
pub struct GameConnection {

    /// The TCP stream bound to this GameConnection
    pub stream: TcpStream,

    /// The state of this GameConnection
    pub state: ConnectionState,

    /// Whether the client has the Forge Mod Loader injected into it
    ///
    /// This may change in 1.9 as FML is being destroyed and Forge is becoming the norm
    pub forge_enabled: bool

}

impl GameConnection {

    /// Creates a new GameConnection
    pub fn new(stream: TcpStream) -> GameConnection {
        GameConnection {
            stream: stream,
            state: ConnectionState::HANDSHAKE,
            forge_enabled: false
        }
    }

    pub fn disconnect(&mut self) {
        //TODO: Check to see if in ConnectionState::PLAY, otherwise
        let result = self.stream.shutdown(Shutdown::Both);

        if result.is_ok() == false {
            error!("Error disconnecting: {:?}", result);
        }

    }

    /// Starts listening on the connection
    pub fn start_listening(&mut self) {

        trace!("Got a new client from {}!", self.stream.peer_addr().unwrap());

        let mut timeout_duration = Duration::zero();

        loop {

            if timeout_duration.num_seconds() >= 10 {
                info!("Client at {} timed out, dropping connection", self.stream.peer_addr().unwrap());
                self.disconnect();
                break;
            }

            let mut raw_buffer = vec![0u8; 512];

            match self.stream.read(&mut raw_buffer) {

                Err(error) => {
                    // Connection dropped out or something broke
                    // In the future, we use the customized NetherrackStream to see if we're in GAME mode, and if so, get the attached player and start saving their information and get rid of them
                    // For now, we just exit the loop
                    error!("Got an error! {}", error);

                    self.disconnect();
                    break;
                }
                Ok(count) => {
                    if count == 0 {
                        //Nothing in stream, let's sleep for a few milliseconds and try again
                        timeout_duration = timeout_duration + Duration::milliseconds(2);
                        ::std::thread::sleep_ms(2);
                    } else {

                        timeout_duration = Duration::zero();

                        // Now truncate the raw buffer - Don't worry, it will reallocate to 512 on the next networking loop
                        raw_buffer.truncate(count);

                        let mut backing: VecDeque<u8> = VecDeque::<u8>::with_capacity(count);

                        for b in raw_buffer {

                            backing.push_back(b);
                        }

                        let mut buffer = DequeBuffer::from(backing);

                        //drop(raw_buffer);

                        let length_result = buffer.read_unsigned_varint_32();
                        let id_result = buffer.read_unsigned_varint_32();

                        if length_result.is_err() || id_result.is_err() {
                            error!("Error while reading packet ID or length! Oh no, dropping connection");

                            self.disconnect();
                            break;
                        }

                        let packet_header = PacketHeader::new(length_result.unwrap(), id_result.unwrap());

                        if self.state == ConnectionState::HANDSHAKE {

                            match packet_header.id {

                                ID_HANDSHAKE_CTS_HANDSHAKING => {
                                    super::packet::incoming::handshake::HandshakePacket::decode(packet_header, self, &mut buffer).handle(self);
                                },
                                _ => debug!("Incoming handshake packet unhandled; ID: {}, Length: {}", packet_header.id, packet_header.length)

                            }

                        } else if self.state == ConnectionState::LOGIN {

                            match packet_header.id {

                                _ => debug!("Incoming login packet unhandled; ID: {}, Length: {}", packet_header.id, packet_header.length)

                            }

                        } else if self.state == ConnectionState::STATUS {

                            match packet_header.id {

                                ID_STATUS_CTS_REQUEST => {
                                    super::packet::incoming::status::StatusRequestPacket::decode(packet_header, self, &mut buffer).handle(self);
                                },
                                ID_STATUS_CTS_PING => {
                                    super::packet::incoming::status::ListPingPacket::decode(packet_header, self, &mut buffer).handle(self);
                                },
                                _ => debug!("Incoming play packet unhandled; ID: {}, Length: {}", packet_header.id, packet_header.length)

                            }

                        } else if self.state == ConnectionState::PLAY {

                            match packet_header.id {

                                _ => debug!("Incoming play packet unhandled; ID: {}, Length: {}", packet_header.id, packet_header.length)

                            }

                        }

                        // This is a memory leak. We need to get the time of last packet and check to see if it's more than 20 seconds ago
                    }
                }

            }

        }

        info!("Connection closed");

    }

}<|endoftext|>


<commit_before>#![cfg_attr(feature = "bench", feature(test))]
#[cfg(feature = "bench")]
extern crate test;

extern crate gfx;
extern crate gfx_core;
extern crate gfx_window_glutin;
extern crate glutin;
extern crate time;
extern crate pretty_env_logger;
extern crate gfx_glyph;

#[cfg(feature = "bench")]
mod gfx_noop;

#[cfg(feature = "bench")]
const TEST_FONT: &[u8] = include_bytes!("../tests/DejaVuSansMono.ttf");

#[bench]
#[cfg(feature = "bench")]
fn render_3_medium_sections_fully(b: &mut ::test::Bencher) {
    use std::f32;
    use gfx_glyph::*;

    let brush = GlyphBrushBuilder::using_font(TEST_FONT);
    let text = include_str!("lipsum.txt");

    bench(b,
        &[(
            StaticSection {
                text,
                bounds: (600.0, f32::INFINITY),
                ..StaticSection::default() },
            Layout::Wrap(StandardLineBreaker, HorizontalAlign::Left)
        ), (
            StaticSection {
                text,
                screen_position: (600.0, 0.0),
                bounds: (600.0, f32::INFINITY),
                ..StaticSection::default() },
            Layout::Wrap(StandardLineBreaker, HorizontalAlign::Center)
        ), (
            StaticSection {
                text,
                screen_position: (1200.0, 0.0),
                bounds: (600.0, f32::INFINITY),
                ..StaticSection::default() },
            Layout::Wrap(StandardLineBreaker, HorizontalAlign::Right)
        )],
        brush);
}

#[bench]
#[cfg(feature = "bench")]
fn no_cache_render_3_medium_sections_fully(b: &mut ::test::Bencher) {
    use std::f32;
    use gfx_glyph::*;

    let brush = GlyphBrushBuilder::using_font(TEST_FONT)
        .cache_glyph_positioning(false)
        .cache_glyph_drawing(false);
    let text = include_str!("lipsum.txt");

    bench(b,
        &[(
            StaticSection {
                text,
                bounds: (600.0, f32::INFINITY),
                ..StaticSection::default() },
            Layout::Wrap(StandardLineBreaker, HorizontalAlign::Left)
        ), (
            StaticSection {
                text,
                screen_position: (600.0, 0.0),
                bounds: (600.0, f32::INFINITY),
                ..StaticSection::default() },
            Layout::Wrap(StandardLineBreaker, HorizontalAlign::Center)
        ), (
            StaticSection {
                text,
                screen_position: (1200.0, 0.0),
                bounds: (600.0, f32::INFINITY),
                ..StaticSection::default() },
            Layout::Wrap(StandardLineBreaker, HorizontalAlign::Right)
        )],
        brush);
}

#[bench]
#[cfg(feature = "bench")]
fn render_1_large_section_partially(b: &mut ::test::Bencher) {
    use gfx_glyph::*;

    let brush = GlyphBrushBuilder::using_font(TEST_FONT);
    let text = include_str!("lots_of_lipsum.txt");

    bench(b,
        &[(StaticSection {
            text,
            bounds: (600.0, 600.0),
            ..StaticSection::default()
        }, Layout::default())],
        brush);
}

#[bench]
#[cfg(feature = "bench")]
fn no_cache_render_1_large_section_partially(b: &mut ::test::Bencher) {
    use gfx_glyph::*;

    let brush = GlyphBrushBuilder::using_font(TEST_FONT)
        .cache_glyph_positioning(false)
        .cache_glyph_drawing(false);
    let text = include_str!("lots_of_lipsum.txt");

    bench(b,
        &[(StaticSection {
            text,
            bounds: (600.0, 600.0),
            ..StaticSection::default()
        }, Layout::default())],
        brush);
}

#[bench]
#[cfg(feature = "bench")]
fn render_100_small_sections_fully(b: &mut ::test::Bencher) {
    use std::f32;
    use gfx_glyph::*;

    let brush = GlyphBrushBuilder::using_font(TEST_FONT);
    let text = include_str!("small_lipsum.txt");

    let mut section_layouts = vec![];
    for i in 0..100 {
        section_layouts.push((StaticSection {
            text,
            screen_position: (i as f32, 0.0),
            bounds: (100.0, f32::INFINITY),
            ..StaticSection::default()
        }, Layout::default()));
    }

    bench(b, &section_layouts, brush);
}

#[bench]
#[cfg(feature = "bench")]
fn no_cache_render_100_small_sections_fully(b: &mut ::test::Bencher) {
    use std::f32;
    use gfx_glyph::*;

    let brush = GlyphBrushBuilder::using_font(TEST_FONT)
        .cache_glyph_positioning(false)
        .cache_glyph_drawing(false);
    let text = include_str!("small_lipsum.txt");

    let mut section_layouts = vec![];
    for i in 0..100 {
        section_layouts.push((StaticSection {
            text,
            screen_position: (i as f32, 0.0),
            bounds: (100.0, f32::INFINITY),
            ..StaticSection::default()
        }, Layout::default()));
    }

    bench(b, &section_layouts, brush);
}

fn bench<L: gfx_glyph::LineBreaker>(
    b: &mut ::test::Bencher,
    sections: &[(gfx_glyph::StaticSection, gfx_glyph::Layout<L>)],
    brush: gfx_glyph::GlyphBrushBuilder)
{
    use gfx::format;
    use std::env;

    let _ = pretty_env_logger::init();

    // winit wayland is currently still wip
    if cfg!(target_os = "linux") && env::var("WINIT_UNIX_BACKEND").is_err() {
        env::set_var("WINIT_UNIX_BACKEND", "x11");
    }

    // TODO use headless/fake
    let events_loop = glutin::EventsLoop::new();
    let (_window, _device, factory, main_color, _main_depth) =
        gfx_window_glutin::init::<format::Srgba8, format::Depth>(
            glutin::WindowBuilder::new().with_dimensions(1, 1),
            glutin::ContextBuilder::new(),
            &events_loop);
    let mut encoder: gfx::Encoder<_, _> = gfx_noop::NoopCommandBuffer.into();

    let mut glyph_brush = brush.build(factory.clone());

    b.iter(|| {
        for &(ref section, ref layout) in sections.iter() {
            glyph_brush.queue(section.clone(), layout);
        }
        glyph_brush.draw_queued(&mut encoder, &main_color).expect("draw");
    });
}
<commit_msg>Gate benchmark compilation with feature 'bench'<commit_after>#![cfg_attr(feature = "bench", feature(test))]
#[cfg(feature = "bench")]
extern crate test;

extern crate gfx;
extern crate gfx_core;
extern crate gfx_window_glutin;
extern crate glutin;
extern crate time;
extern crate pretty_env_logger;
extern crate gfx_glyph;

#[cfg(feature = "bench")]
mod gfx_noop;

#[cfg(feature = "bench")]
const TEST_FONT: &[u8] = include_bytes!("../tests/DejaVuSansMono.ttf");

#[bench]
#[cfg(feature = "bench")]
fn render_3_medium_sections_fully(b: &mut ::test::Bencher) {
    use std::f32;
    use gfx_glyph::*;

    let brush = GlyphBrushBuilder::using_font(TEST_FONT);
    let text = include_str!("lipsum.txt");

    bench(b,
        &[(
            StaticSection {
                text,
                bounds: (600.0, f32::INFINITY),
                ..StaticSection::default() },
            Layout::Wrap(StandardLineBreaker, HorizontalAlign::Left)
        ), (
            StaticSection {
                text,
                screen_position: (600.0, 0.0),
                bounds: (600.0, f32::INFINITY),
                ..StaticSection::default() },
            Layout::Wrap(StandardLineBreaker, HorizontalAlign::Center)
        ), (
            StaticSection {
                text,
                screen_position: (1200.0, 0.0),
                bounds: (600.0, f32::INFINITY),
                ..StaticSection::default() },
            Layout::Wrap(StandardLineBreaker, HorizontalAlign::Right)
        )],
        brush);
}

#[bench]
#[cfg(feature = "bench")]
fn no_cache_render_3_medium_sections_fully(b: &mut ::test::Bencher) {
    use std::f32;
    use gfx_glyph::*;

    let brush = GlyphBrushBuilder::using_font(TEST_FONT)
        .cache_glyph_positioning(false)
        .cache_glyph_drawing(false);
    let text = include_str!("lipsum.txt");

    bench(b,
        &[(
            StaticSection {
                text,
                bounds: (600.0, f32::INFINITY),
                ..StaticSection::default() },
            Layout::Wrap(StandardLineBreaker, HorizontalAlign::Left)
        ), (
            StaticSection {
                text,
                screen_position: (600.0, 0.0),
                bounds: (600.0, f32::INFINITY),
                ..StaticSection::default() },
            Layout::Wrap(StandardLineBreaker, HorizontalAlign::Center)
        ), (
            StaticSection {
                text,
                screen_position: (1200.0, 0.0),
                bounds: (600.0, f32::INFINITY),
                ..StaticSection::default() },
            Layout::Wrap(StandardLineBreaker, HorizontalAlign::Right)
        )],
        brush);
}

#[bench]
#[cfg(feature = "bench")]
fn render_1_large_section_partially(b: &mut ::test::Bencher) {
    use gfx_glyph::*;

    let brush = GlyphBrushBuilder::using_font(TEST_FONT);
    let text = include_str!("lots_of_lipsum.txt");

    bench(b,
        &[(StaticSection {
            text,
            bounds: (600.0, 600.0),
            ..StaticSection::default()
        }, Layout::default())],
        brush);
}

#[bench]
#[cfg(feature = "bench")]
fn no_cache_render_1_large_section_partially(b: &mut ::test::Bencher) {
    use gfx_glyph::*;

    let brush = GlyphBrushBuilder::using_font(TEST_FONT)
        .cache_glyph_positioning(false)
        .cache_glyph_drawing(false);
    let text = include_str!("lots_of_lipsum.txt");

    bench(b,
        &[(StaticSection {
            text,
            bounds: (600.0, 600.0),
            ..StaticSection::default()
        }, Layout::default())],
        brush);
}

#[bench]
#[cfg(feature = "bench")]
fn render_100_small_sections_fully(b: &mut ::test::Bencher) {
    use std::f32;
    use gfx_glyph::*;

    let brush = GlyphBrushBuilder::using_font(TEST_FONT);
    let text = include_str!("small_lipsum.txt");

    let mut section_layouts = vec![];
    for i in 0..100 {
        section_layouts.push((StaticSection {
            text,
            screen_position: (i as f32, 0.0),
            bounds: (100.0, f32::INFINITY),
            ..StaticSection::default()
        }, Layout::default()));
    }

    bench(b, &section_layouts, brush);
}

#[bench]
#[cfg(feature = "bench")]
fn no_cache_render_100_small_sections_fully(b: &mut ::test::Bencher) {
    use std::f32;
    use gfx_glyph::*;

    let brush = GlyphBrushBuilder::using_font(TEST_FONT)
        .cache_glyph_positioning(false)
        .cache_glyph_drawing(false);
    let text = include_str!("small_lipsum.txt");

    let mut section_layouts = vec![];
    for i in 0..100 {
        section_layouts.push((StaticSection {
            text,
            screen_position: (i as f32, 0.0),
            bounds: (100.0, f32::INFINITY),
            ..StaticSection::default()
        }, Layout::default()));
    }

    bench(b, &section_layouts, brush);
}

#[cfg(feature = "bench")]
fn bench<L: gfx_glyph::LineBreaker>(
    b: &mut ::test::Bencher,
    sections: &[(gfx_glyph::StaticSection, gfx_glyph::Layout<L>)],
    brush: gfx_glyph::GlyphBrushBuilder)
{
    use gfx::format;
    use std::env;

    let _ = pretty_env_logger::init();

    // winit wayland is currently still wip
    if cfg!(target_os = "linux") && env::var("WINIT_UNIX_BACKEND").is_err() {
        env::set_var("WINIT_UNIX_BACKEND", "x11");
    }

    // TODO use headless/fake
    let events_loop = glutin::EventsLoop::new();
    let (_window, _device, factory, main_color, _main_depth) =
        gfx_window_glutin::init::<format::Srgba8, format::Depth>(
            glutin::WindowBuilder::new().with_dimensions(1, 1),
            glutin::ContextBuilder::new(),
            &events_loop);
    let mut encoder: gfx::Encoder<_, _> = gfx_noop::NoopCommandBuffer.into();

    let mut glyph_brush = brush.build(factory.clone());

    b.iter(|| {
        for &(ref section, ref layout) in sections.iter() {
            glyph_brush.queue(section.clone(), layout);
        }
        glyph_brush.draw_queued(&mut encoder, &main_color).expect("draw");
    });
}
<|endoftext|>


<commit_before>use criterion::*;
use rand::{Rng, SeedableRng};
use rand_chacha::ChaChaRng;
use rav1e::bench::frame::*;

fn init_plane_u8(width: usize, height: usize) -> Plane<u8> {
  let mut ra = ChaChaRng::from_seed([0; 32]);
  let data: Vec<u8> = (0..(width * height)).map(|_| ra.gen()).collect();
  let out = Plane::from_slice(&data, width);
  if out.cfg.width % 2 == 0 && out.cfg.height % 2 == 0 {
    out
  } else {
    let xpad = out.cfg.width % 2;
    let ypad = out.cfg.height % 2;
    let mut padded =
      Plane::new(out.cfg.width, out.cfg.height, 0, 0, xpad, ypad);
    let mut padded_slice = padded.mut_slice(PlaneOffset { x: 0, y: 0 });
    for (dst_row, src_row) in padded_slice.rows_iter_mut().zip(out.rows_iter())
    {
      dst_row[..out.cfg.width].copy_from_slice(&src_row[..out.cfg.width]);
    }
    padded
  }
}

fn init_plane_u16(width: usize, height: usize) -> Plane<u16> {
  let mut ra = ChaChaRng::from_seed([0; 32]);
  let data: Vec<u16> = (0..(width * height)).map(|_| ra.gen()).collect();
  Plane::from_slice(&data, width)
}

pub fn downsample_8bit(c: &mut Criterion) {
  let input = init_plane_u8(1920, 1080);
  c.bench_function("downsample_8bit", move |b| {
    b.iter(|| {
      let _ = input.downsampled(input.cfg.width, input.cfg.height);
    })
  });
}

pub fn downsample_odd(c: &mut Criterion) {
  let input = init_plane_u8(1919, 1079);
  c.bench_function("downsample_odd", move |b| {
    b.iter(|| {
      let _ = input.downsampled(input.cfg.width, input.cfg.height);
    })
  });
}

pub fn downsample_10bit(c: &mut Criterion) {
  let input = init_plane_u16(1920, 1080);
  c.bench_function("downsample_10bit", move |b| {
    b.iter(|| {
      let _ = input.downsampled(input.cfg.width, input.cfg.height);
    })
  });
}

criterion_group!(plane, downsample_8bit, downsample_odd, downsample_10bit);
<commit_msg>Add benchmarks for copy_from_raw_u8<commit_after>use criterion::*;
use rand::{Rng, SeedableRng};
use rand_chacha::ChaChaRng;
use rav1e::bench::frame::*;

fn init_plane_u8(width: usize, height: usize) -> Plane<u8> {
  let mut ra = ChaChaRng::from_seed([0; 32]);
  let data: Vec<u8> = (0..(width * height)).map(|_| ra.gen()).collect();
  let out = Plane::from_slice(&data, width);
  if out.cfg.width % 2 == 0 && out.cfg.height % 2 == 0 {
    out
  } else {
    let xpad = out.cfg.width % 2;
    let ypad = out.cfg.height % 2;
    let mut padded =
      Plane::new(out.cfg.width, out.cfg.height, 0, 0, xpad, ypad);
    let mut padded_slice = padded.mut_slice(PlaneOffset { x: 0, y: 0 });
    for (dst_row, src_row) in padded_slice.rows_iter_mut().zip(out.rows_iter())
    {
      dst_row[..out.cfg.width].copy_from_slice(&src_row[..out.cfg.width]);
    }
    padded
  }
}

fn init_plane_u16(width: usize, height: usize) -> Plane<u16> {
  let mut ra = ChaChaRng::from_seed([0; 32]);
  let data: Vec<u16> = (0..(width * height)).map(|_| ra.gen()).collect();
  Plane::from_slice(&data, width)
}

pub fn downsample_8bit(c: &mut Criterion) {
  let input = init_plane_u8(1920, 1080);
  c.bench_function("downsample_8bit", move |b| {
    b.iter(|| {
      let _ = input.downsampled(input.cfg.width, input.cfg.height);
    })
  });
}

pub fn downsample_odd(c: &mut Criterion) {
  let input = init_plane_u8(1919, 1079);
  c.bench_function("downsample_odd", move |b| {
    b.iter(|| {
      let _ = input.downsampled(input.cfg.width, input.cfg.height);
    })
  });
}

pub fn downsample_10bit(c: &mut Criterion) {
  let input = init_plane_u16(1920, 1080);
  c.bench_function("downsample_10bit", move |b| {
    b.iter(|| {
      let _ = input.downsampled(input.cfg.width, input.cfg.height);
    })
  });
}

fn init_raw_plane_data(width: usize, height: usize) -> Vec<u8> {
  let mut ra = ChaChaRng::from_seed([0; 32]);
  (0..(width * height)).map(|_| ra.gen()).collect()
}

pub fn copy_from_raw_u8_8bit(c: &mut Criterion) {
  let input = init_raw_plane_data(1920, 1080);
  let dest = Plane::<u8>::new(1920, 1080, 0, 0, 0, 0);
  c.bench_function("copy_from_raw_u8", move |b| {
    b.iter(|| {
      let mut dest = dest.clone();
      let _ = dest.copy_from_raw_u8(&input, dest.cfg.stride, 1);
    })
  });
}

pub fn copy_from_raw_u8_10bit(c: &mut Criterion) {
  let input = init_raw_plane_data(1920, 1080);
  let dest = Plane::<u16>::new(1920, 1080, 0, 0, 0, 0);
  c.bench_function("copy_from_raw_u8", move |b| {
    b.iter(|| {
      let mut dest = dest.clone();
      let _ = dest.copy_from_raw_u8(&input, dest.cfg.stride, 2);
    })
  });
}

criterion_group!(
  plane,
  downsample_8bit,
  downsample_odd,
  downsample_10bit,
  copy_from_raw_u8_8bit,
  copy_from_raw_u8_10bit
);
<|endoftext|>