<commit_before>extern crate qt_3d_core;
extern crate qt_3d_extras;
extern crate qt_3d_input;
extern crate qt_3d_logic;
extern crate qt_3d_render;
extern crate qt_core;
extern crate qt_gui;

use std::cell::*;

use qt_core::connection::*;
use qt_core::slots::*;

use qt_gui::color::*;
use qt_gui::gui_application::GuiApplication;
use qt_gui::surface_format::*;
use qt_gui::vector_3d::*;

use qt_3d_core::cpp_utils::*;
use qt_3d_core::entity::*;
use qt_3d_core::node::*;
use qt_3d_core::transform::*;

use qt_3d_input::keyboard_device::*;
use qt_3d_input::keyboard_handler::*;

use qt_3d_render::directional_light::*;
use qt_3d_render::point_light::*;
use qt_3d_render::spot_light::*;

use qt_3d_extras::metal_rough_material::*;
use qt_3d_extras::orbit_camera_controller::*;
use qt_3d_extras::plane_mesh::*;
use qt_3d_extras::qt_3d_window::*;
use qt_3d_extras::sphere_mesh::*;

fn to_node_ptr(entity: &mut Entity) -> *mut Node {
    static_cast_mut::<Node, Entity>(entity)
}

fn setup_scene(root: &mut Entity) -> Box<Fn() -> ()> {
    let mut scene = unsafe { Entity::new_unsafe(to_node_ptr(root)) };

    let mut sphere1 = unsafe { Entity::new_unsafe(to_node_ptr(scene.as_mut())) };
    let mut sphere1_mesh = SphereMesh::new();
    sphere1_mesh.set_radius(1.0);
    sphere1_mesh.set_rings(60);
    sphere1_mesh.set_slices(30);
    unsafe { sphere1.add_component(static_cast_mut(sphere1_mesh.into_raw())) };
    let mut sphere1_material = MetalRoughMaterial::new();
    sphere1_material.set_base_color(&Color::from_rgb((255, 255, 255)));
    sphere1_material.set_metalness(0.5);
    sphere1_material.set_roughness(0.2);
    unsafe { sphere1.add_component(static_cast_mut(sphere1_material.into_raw())) };
    let mut sphere1_transform = Transform::new();
    sphere1_transform.set_translation(&Vector3D::new((-2.0, 0.0, 0.0)));
    unsafe { sphere1.add_component(static_cast_mut(sphere1_transform.into_raw())) };
    sphere1.into_raw();

    let mut sphere2 = unsafe { Entity::new_unsafe(to_node_ptr(scene.as_mut())) };
    let mut sphere2_mesh = SphereMesh::new();
    sphere2_mesh.set_radius(1.0);
    sphere2_mesh.set_rings(60);
    sphere2_mesh.set_slices(30);
    unsafe { sphere2.add_component(static_cast_mut(sphere2_mesh.into_raw())) };
    let mut sphere2_material = MetalRoughMaterial::new();
    sphere2_material.set_base_color(&Color::from_rgb((255, 255, 255)));
    sphere2_material.set_metalness(0.5);
    sphere2_material.set_roughness(0.2);
    unsafe { sphere2.add_component(static_cast_mut(sphere2_material.into_raw())) };
    let mut sphere2_transform = Transform::new();
    sphere2_transform.set_translation(&Vector3D::new((2.0, 0.0, 0.0)));
    unsafe { sphere2.add_component(static_cast_mut(sphere2_transform.into_raw())) };
    sphere2.into_raw();

    let mut plane = unsafe { Entity::new_unsafe(to_node_ptr(scene.as_mut())) };
    unsafe { plane.add_component(static_cast_mut(PlaneMesh::new().into_raw())) };
    let mut plane_material = MetalRoughMaterial::new();
    plane_material.set_base_color(&Color::from_rgb((255, 255, 255)));
    plane_material.set_metalness(0.5);
    plane_material.set_roughness(0.5);
    unsafe { plane.add_component(static_cast_mut(plane_material.into_raw())) };
    let mut plane_transform = Transform::new();
    plane_transform.set_scale(100.0);
    plane_transform.set_translation(&Vector3D::new((0.0, -2.0, 0.0)));
    unsafe { plane.add_component(static_cast_mut(plane_transform.into_raw())) };
    plane.into_raw();

    let mut directional_light = DirectionalLight::new();
    directional_light.set_enabled(true);
    directional_light.set_color(&Color::from_rgb((255, 0, 0)));
    directional_light.set_intensity(1.0);
    directional_light.set_world_direction(&Vector3D::new((1.0, -1.0, 0.0)));
    unsafe { scene.add_component(static_cast_mut(directional_light.as_mut_ptr())) };

    let mut point_light_entity = unsafe { Entity::new_unsafe(to_node_ptr(scene.as_mut())) };
    let mut point_light = PointLight::new();
    point_light.set_enabled(false);
    point_light.set_color(&Color::from_rgb((0, 255, 0)));
    point_light.set_intensity(1.0);
    point_light.set_linear_attenuation(0.01);
    point_light.set_quadratic_attenuation(0.05);
    unsafe { point_light_entity.add_component(static_cast_mut(point_light.as_mut_ptr())) };
    let mut point_light_transform = Transform::new();
    point_light_transform.set_translation(&Vector3D::new((0.0, 3.0, 1.0)));
    unsafe { point_light_entity.add_component(static_cast_mut(point_light_transform.into_raw())) };
    point_light_entity.into_raw();

    let mut spot_light_entity = unsafe { Entity::new_unsafe(to_node_ptr(scene.as_mut())) };
    let mut spot_light = SpotLight::new();
    spot_light.set_enabled(false);
    spot_light.set_color(&Color::from_rgb((0, 0, 255)));
    spot_light.set_intensity(1.0);
    spot_light.set_local_direction(&Vector3D::new((-1.0, -1.0, 0.0)));
    spot_light.set_cut_off_angle(45.0);
    spot_light.set_linear_attenuation(0.05);
    spot_light.set_quadratic_attenuation(0.005);
    unsafe { spot_light_entity.add_component(static_cast_mut(spot_light.as_mut_ptr())) };
    let mut spot_light_transform = Transform::new();
    spot_light_transform.set_translation(&Vector3D::new((6.0, 6.0, 0.0)));
    unsafe { spot_light_entity.add_component(static_cast_mut(spot_light_transform.into_raw())) };
    spot_light_entity.into_raw();

    scene.into_raw();

    let directional_light = directional_light.into_raw();
    let point_light = point_light.into_raw();
    let spot_light = spot_light.into_raw();

    let active_light_cell = RefCell::new(0);
    Box::new(move || {
        let active_light = (*active_light_cell.borrow() + 1) % 3;
        unsafe {
            (*directional_light).set_enabled(active_light == 0);
            (*point_light).set_enabled(active_light == 1);
            (*spot_light).set_enabled(active_light == 2);
        }
        *active_light_cell.borrow_mut() = active_light;
    })
}

fn main() {
    let mut format = SurfaceFormat::new(());
    format.set_version(3, 3);
    format.set_profile(OpenGLContextProfile::Core);
    format.set_depth_buffer_size(24);
    format.set_samples(4);
    format.set_stencil_buffer_size(8);
    SurfaceFormat::set_default_format(&format);

    GuiApplication::create_and_exit(|_| {
        let mut window = Qt3DWindow::new();

        let mut root = Entity::new();
        let activate_next_light = setup_scene(&mut root);
        let next_light_slot = SlotNoArgs::new(activate_next_light.as_ref());

        let keyboard_device = unsafe { KeyboardDevice::new_unsafe(to_node_ptr(root.as_mut())) };
        let mut handler = unsafe { Entity::new_unsafe(to_node_ptr(root.as_mut())) };
        let mut keyboard_handler = KeyboardHandler::new();
        unsafe { keyboard_handler.set_source_device(keyboard_device.into_raw()) };
        keyboard_handler.set_focus(true);
        keyboard_handler
            .signals()
            .tab_pressed()
            .connect(&next_light_slot);
        keyboard_handler
            .signals()
            .space_pressed()
            .connect(&next_light_slot);
        unsafe { handler.add_component(static_cast_mut(keyboard_handler.into_raw())) };
        handler.into_raw();

        let camera = window.camera();
        unsafe { (*camera).set_position(&Vector3D::new((0.0, 0.0, 30.0))) };
        unsafe { (*camera).set_view_center(&Vector3D::new((0.0, 0.0, 0.0))) };

        let mut controller = unsafe { OrbitCameraController::new_unsafe(to_node_ptr(&mut root)) };
        unsafe { controller.set_camera(camera) };
        controller.set_linear_speed(50.0);
        controller.set_look_speed(180.0);
        controller.into_raw();

        unsafe { window.set_root_entity(root.into_raw()) };

        window.show();
        GuiApplication::exec()
    })
}
<commit_msg>update qt3d lights example<commit_after>use qt_3d_core::cpp_utils::*;
use qt_3d_core::*;
use qt_3d_extras::*;
use qt_3d_input::*;
use qt_3d_render::*;
use qt_core::*;
use qt_gui::{
    q_surface_format::OpenGLContextProfile, QColor, QGuiApplication, QSurfaceFormat, QVector3D,
};
use std::cell::*;

fn setup_scene(root: &mut QEntity) -> Box<Fn() -> ()> {
    unsafe {
        let mut scene = QEntity::new_1a(root.static_upcast_mut().into());

        let mut sphere1 = QEntity::new_1a(scene.static_upcast_mut().into());
        let mut sphere1_mesh = QSphereMesh::new_0a();
        sphere1_mesh.set_radius(1.0);
        sphere1_mesh.set_rings(60);
        sphere1_mesh.set_slices(30);
        sphere1.add_component(
            sphere1_mesh
                .into_ptr()
                .static_upcast_mut()
                .static_upcast_mut()
                .into(),
        );
        let mut sphere1_material = QMetalRoughMaterial::new_0a();
        sphere1_material.set_base_color(
            QColor::from_rgb_3a(255, 255, 255)
                .to_qt_core_q_variant()
                .as_ref(),
        );
        sphere1_material.set_metalness(QVariant::new12(0.5).as_ref());
        sphere1_material.set_roughness(QVariant::new12(0.2).as_ref());
        sphere1.add_component(
            sphere1_material
                .into_ptr()
                .static_upcast_mut()
                .static_upcast_mut()
                .into(),
        );
        let mut sphere1_transform = QTransform::new_0a();
        sphere1_transform.set_translation(QVector3D::new2(-2.0, 0.0, 0.0).as_ref());
        sphere1.add_component(sphere1_transform.into_ptr().static_upcast_mut().into());
        sphere1.into_raw_ptr();

        let mut sphere2 = QEntity::new_1a(scene.static_upcast_mut().into());
        let mut sphere2_mesh = QSphereMesh::new_0a();
        sphere2_mesh.set_radius(1.0);
        sphere2_mesh.set_rings(60);
        sphere2_mesh.set_slices(30);
        sphere2.add_component(
            sphere2_mesh
                .into_ptr()
                .static_upcast_mut()
                .static_upcast_mut()
                .into(),
        );
        let mut sphere2_material = QMetalRoughMaterial::new_0a();
        sphere2_material.set_base_color(
            QColor::from_rgb_3a(255, 255, 255)
                .to_qt_core_q_variant()
                .as_ref(),
        );
        sphere2_material.set_metalness(QVariant::new12(0.5).as_ref());
        sphere2_material.set_roughness(QVariant::new12(0.2).as_ref());
        sphere2.add_component(
            sphere2_material
                .into_ptr()
                .static_upcast_mut()
                .static_upcast_mut()
                .into(),
        );
        let mut sphere2_transform = QTransform::new_0a();
        sphere2_transform.set_translation(QVector3D::new2(2.0, 0.0, 0.0).as_ref());
        sphere2.add_component(sphere2_transform.into_ptr().static_upcast_mut().into());
        sphere2.into_raw_ptr();

        let mut plane = QEntity::new_1a(scene.static_upcast_mut().into());
        plane.add_component(
            QPlaneMesh::new_0a()
                .into_ptr()
                .static_upcast_mut()
                .static_upcast_mut()
                .into(),
        );
        let mut plane_material = QMetalRoughMaterial::new_0a();
        plane_material.set_base_color(
            QColor::from_rgb_3a(255, 255, 255)
                .to_qt_core_q_variant()
                .as_ref(),
        );
        plane_material.set_metalness(QVariant::new12(0.5).as_ref());
        plane_material.set_roughness(QVariant::new12(0.5).as_ref());
        plane.add_component(
            plane_material
                .into_ptr()
                .static_upcast_mut()
                .static_upcast_mut()
                .into(),
        );
        let mut plane_transform = QTransform::new_0a();
        plane_transform.set_scale(100.0);
        plane_transform.set_translation(QVector3D::new2(0.0, -2.0, 0.0).as_ref());
        plane.add_component(plane_transform.into_ptr().static_upcast_mut().into());
        plane.into_raw_ptr();

        let mut directional_light = QDirectionalLight::new_0a();
        directional_light.set_enabled(true);
        directional_light.set_color(QColor::from_rgb_3a(255, 0, 0).as_ref());
        directional_light.set_intensity(1.0);
        directional_light.set_world_direction(QVector3D::new2(1.0, -1.0, 0.0).as_ref());
        let mut directional_light = directional_light.into_ptr();
        scene.add_component(
            directional_light
                .static_upcast_mut()
                .static_upcast_mut()
                .into(),
        );

        let mut point_light_entity = QEntity::new_1a(scene.static_upcast_mut().into());
        let mut point_light = QPointLight::new_0a();
        point_light.set_enabled(false);
        point_light.set_color(QColor::from_rgb_3a(0, 255, 0).as_ref());
        point_light.set_intensity(1.0);
        point_light.set_linear_attenuation(0.01);
        point_light.set_quadratic_attenuation(0.05);
        let mut point_light = point_light.into_ptr();
        point_light_entity
            .add_component(point_light.static_upcast_mut().static_upcast_mut().into());
        let mut point_light_transform = QTransform::new_0a();
        point_light_transform.set_translation(QVector3D::new2(0.0, 3.0, 1.0).as_ref());
        point_light_entity
            .add_component(point_light_transform.into_ptr().static_upcast_mut().into());
        point_light_entity.into_raw_ptr();

        let mut spot_light_entity = QEntity::new_1a(scene.static_upcast_mut().into());
        let mut spot_light = QSpotLight::new_0a();
        spot_light.set_enabled(false);
        spot_light.set_color(QColor::from_rgb_3a(0, 0, 255).as_ref());
        spot_light.set_intensity(1.0);
        spot_light.set_local_direction(QVector3D::new2(-1.0, -1.0, 0.0).as_ref());
        spot_light.set_cut_off_angle(45.0);
        spot_light.set_linear_attenuation(0.05);
        spot_light.set_quadratic_attenuation(0.005);
        let mut spot_light = spot_light.into_ptr();
        spot_light_entity.add_component(spot_light.static_upcast_mut().static_upcast_mut().into());
        let mut spot_light_transform = QTransform::new_0a();
        spot_light_transform.set_translation(QVector3D::new2(6.0, 6.0, 0.0).as_ref());
        spot_light_entity.add_component(spot_light_transform.into_ptr().static_upcast_mut().into());
        spot_light_entity.into_raw_ptr();

        scene.into_raw_ptr();

        let active_light_cell = RefCell::new(0);
        Box::new(move || {
            let active_light = (*active_light_cell.borrow() + 1) % 3;
            directional_light.clone().set_enabled(active_light == 0);
            point_light.clone().set_enabled(active_light == 1);
            spot_light.clone().set_enabled(active_light == 2);
            *active_light_cell.borrow_mut() = active_light;
        })
    }
}

fn main() {
    unsafe {
        let mut format = QSurfaceFormat::new_0a();
        format.set_version(3, 3);
        format.set_profile(OpenGLContextProfile::CoreProfile);
        format.set_depth_buffer_size(24);
        format.set_samples(4);
        format.set_stencil_buffer_size(8);
        QSurfaceFormat::set_default_format(format.as_ref());

        QGuiApplication::create_and_exit(|_| {
            let mut window = Qt3DWindow::new_0a();

            let mut root = QEntity::new_0a();
            let activate_next_light = setup_scene(&mut root);
            let next_light_slot = Slot::new(activate_next_light.as_ref());

            let mut keyboard_device = QKeyboardDevice::new_1a(root.static_upcast_mut().into());
            let mut handler = QEntity::new_1a(root.static_upcast_mut().into());
            let mut keyboard_handler = QKeyboardHandler::new_0a();
            keyboard_handler.set_source_device(keyboard_device.as_mut_ptr());
            keyboard_handler.set_focus(true);
            keyboard_handler.tab_pressed().connect(&next_light_slot);
            keyboard_handler.space_pressed().connect(&next_light_slot);
            handler.add_component(keyboard_handler.static_upcast_mut().into());
            handler.into_raw_ptr();

            let mut camera = window.camera();
            camera.set_position(QVector3D::new2(0.0, 0.0, 30.0).as_ref());
            camera.set_view_center(QVector3D::new2(0.0, 0.0, 0.0).as_ref());

            let mut controller = QOrbitCameraController::new_1a(root.static_upcast_mut().into());
            controller.set_camera(camera);
            controller.set_linear_speed(50.0);
            controller.set_look_speed(180.0);
            controller.into_raw_ptr();

            window.set_root_entity(root.into_ptr());

            let mut window = window.into_ptr();
            window.show();
            QGuiApplication::exec()
        })
    }
}
<|endoftext|>


<commit_before>#![allow(dead_code)]

use std::mem;

use llvm_sys::{core, LLVMIntPredicate, LLVMRealPredicate};
use llvm_sys::prelude::{
  LLVMBuilderRef,
  LLVMValueRef
};
use libc::{c_char, c_uint};

use types::Ty;
use block::BasicBlock;
use value::{Function, Value, ValueRef, Predicate, PhiNode};

static NULL_NAME:[c_char; 1] = [0];

pub struct Builder(pub LLVMBuilderRef);
impl_dispose!(Builder, core::LLVMDisposeBuilder);

macro_rules! unary_instr (
  ($name:ident, $func:ident) => (
    pub fn $name(&self, value: &Value) -> Value {
      Value(unsafe {
        core::$func(self.0, value.0, NULL_NAME.as_ptr() as *const c_char)
      })
    }
  );
);

macro_rules! bin_instr (
  ($name:ident, $func:ident) => (
    pub fn $name(&self, lhs: &Value, rhs: &Value) -> Value
    {
      Value(unsafe {
        core::$func(self.0, lhs.0, rhs.0, NULL_NAME.as_ptr())
      })
    }
  );
  ($name:ident, $ifunc:ident, $ffunc:ident) => (
    pub fn $name(&self, lhs: &Value, rhs: &Value) -> Value {
      let lhs_ty = lhs.ty();
      let rhs_ty = rhs.ty();
      debug_assert_eq!(lhs_ty, rhs_ty);

      let instr_fn = if lhs_ty.is_integer() {
        core::$ifunc
      } else {
        core::$ffunc
      };

      Value(unsafe {
        instr_fn(self.0, lhs.0, rhs.0, NULL_NAME.as_ptr())
      })
    }
  );
);

impl Builder {

  pub fn get_insert_block(&self) -> BasicBlock
  {
    BasicBlock(unsafe { core::LLVMGetInsertBlock(self.0)})
  }

  /// Position the builder at `instr` within `block`.
  pub fn position_at(&self, block: &BasicBlock, instr: &Value)
  {
    unsafe { core::LLVMPositionBuilder(self.0, block.0, instr.0) }
  }

  /// Position the builder at the end of `block`.
  pub fn position_at_end(&self, block: &BasicBlock)
  {
    unsafe { core::LLVMPositionBuilderAtEnd(self.0, block.0) }
  }

  /// Build an instruction that returns from the function with void.
  pub fn create_ret_void(&self) -> Value
  {
    Value(unsafe {core::LLVMBuildRetVoid(self.0)})
  }

  /// Build an instruction that returns from the function with `value`.
  pub fn create_ret(&self, value: &Value) -> Value
  {
    Value(unsafe { core::LLVMBuildRet(self.0, value.0)})
  }

  /// Build an instruction that allocates an array with the element type `elem` and
  /// the size `size`.
  ///
  /// The size of this array will be the size of `elem` times `size`.
  pub fn build_array_alloca(&self, elem: &Ty, size: &Value) -> Value
  {
    Value(unsafe {
    	core::LLVMBuildArrayAlloca(self.0,
    														 elem.0,
    														 size.0,
    														 NULL_NAME.as_ptr() as *const c_char)
    })
  }

  /// Build an instruction that allocates a pointer to fit the size of `ty` then returns this
  /// pointer.
  ///
  /// Make sure to call `build_free` with the pointer value when you're done with it, or you're
  /// gonna have a bad time.
  pub fn create_alloca(&self, ty: &Ty) -> Value
  {
    Value(unsafe {
    	core::LLVMBuildAlloca(self.0,
    												ty.0,
    												NULL_NAME.as_ptr() as *const c_char)
    })
  }

  /// Build an instruction that frees the `val`, which _MUST_ be a pointer that was returned
  /// from `build_alloca`.
  pub fn create_free(&self, val: &Value) -> Value
  {
    Value(unsafe { core::LLVMBuildFree(self.0, val.0) })
  }

  /// Build an instruction that store the value `val` in the pointer `ptr`.
  pub fn create_store(&self, val: &Value, ptr: &Value) -> Value
  {
    Value(unsafe { core::LLVMBuildStore(self.0, val.0, ptr.0) })
  }

  /// Build an instruction that branches to the block `dest`.
  pub fn create_br(&self, dest: &BasicBlock) -> Value
  {
    Value(unsafe { core::LLVMBuildBr(self.0, dest.0)})
  }

  /// Build an instruction that branches to `if_block` if `cond` evaluates to true, and
  /// `else_block` otherwise.
  pub fn create_cond_br(&self, cond: &Value,
  	                    if_block: &BasicBlock, else_block: &BasicBlock) -> Value
  {
    Value(unsafe {
    	core::LLVMBuildCondBr(self.0,
    		                    cond.0,
    		                    if_block.0,
    		                    mem::transmute(else_block.0))
    })
  }

  /// Build an instruction that runs whichever block matches the value, or `default` if none of
  /// them matched it.
  pub fn create_switch(&self,
  	                   value: &Value,
  	                   default: &BasicBlock,
  	                   cases: &[(&Value, &BasicBlock)]) -> Value {
    Value(unsafe {
      let switch = core::LLVMBuildSwitch(self.0,
      	                                 value.0,
      	                                 default.0,
        	                                 cases.len() as c_uint);
      for case in cases {
        core::LLVMAddCase(switch, (case.0).0, (case.1).0);
      }

      switch
    })
  }

  /// Build an instruction that calls the function `func` with the arguments `args`.
  ///
  /// This will return the return value of the function.
  fn create_call_internal(&self, func: &Function, args: &[&Value], tail_call: bool) -> Value
  {
    let ref_array = to_llvmref_array!(args, LLVMValueRef);

    Value(unsafe {
        let call = core::LLVMBuildCall(self.0,
        	                             func.0,
                                       ref_array.as_ptr() as *mut LLVMValueRef,
        	                             args.len() as c_uint,
        	                             NULL_NAME.as_ptr());
        core::LLVMSetTailCall(call, if tail_call {1} else {0});
        call.into()
    })
  }

  /// Build an instruction that calls the function `func` with the arguments `args`.
  ///
  /// This will return the return value of the function.
  pub fn create_call(&self, func: &Function, args: &[&Value]) -> Value
  {
    self.create_call_internal(func, args, false)
  }

  /// Build an instruction that calls the function `func` with the arguments `args`.
  ///
  /// This will return the return value of the function.
  pub fn create_tail_call(&self, func: &Function, args: &[&Value]) -> Value
  {
    self.create_call_internal(func, args, true)
  }

  /// Build an instruction that yields to `true_val` if `cond` is equal to `1`, and `false_val`
  /// otherwise.
  pub fn create_select(&self, cond: &Value, true_val: &Value, false_val: &Value) -> Value
  {
    Value(unsafe {
    	core::LLVMBuildSelect(self.0,
    		                    cond.0,
    		                    true_val.0,
    		                    false_val.0,
    		                    NULL_NAME.as_ptr()) })
  }

  /// Build an instruction that casts a value into a certain type.
  pub fn create_bit_cast(&self, value: &Value, dest: &Ty) -> Value
  {
    Value(unsafe { core::LLVMBuildBitCast(
    		self.0,
    		value.0,
    		dest.0,
    		NULL_NAME.as_ptr())
    })
  }

  /// Build an instruction that inserts a value into an aggregate data value.
  pub fn create_insert_value(&self, agg: &Value, elem: &Value, index: usize) -> Value
  {
    Value(unsafe {
    	core::LLVMBuildInsertValue(self.0,
    		                         agg.0,
    		                         elem.0,
    		                         index as c_uint,
    		                         NULL_NAME.as_ptr())
    })
  }

  /// Build an instruction that extracts a value from an aggregate type.
	pub fn create_extract_value(&self, agg: &Value, index: usize) -> Value {
    Value(unsafe {
    	core::LLVMBuildExtractValue(self.0,
    		                          agg.0,
    		                          index as c_uint,
    		                          NULL_NAME.as_ptr())
   	})
  }

  unary_instr!{create_load, LLVMBuildLoad}
  unary_instr!{create_neg, LLVMBuildNeg}
  unary_instr!{create_not, LLVMBuildNot}

  bin_instr!{create_add, LLVMBuildAdd, LLVMBuildFAdd}
  bin_instr!{create_sub, LLVMBuildSub, LLVMBuildFSub}
  bin_instr!{create_mul, LLVMBuildMul, LLVMBuildFMul}
  bin_instr!{create_div, LLVMBuildSDiv, LLVMBuildFDiv}
  bin_instr!{create_rem, LLVMBuildSRem, LLVMBuildFRem}
  bin_instr!{create_shl, LLVMBuildShl}
  bin_instr!{create_ashr, LLVMBuildAShr}
  bin_instr!{create_and, LLVMBuildAnd}
  bin_instr!{create_or, LLVMBuildOr}
  bin_instr!{create_xor, LLVMBuildXor}

  /// Build an instruction to compare two values with the predicate given.
  pub fn create_cmp(&self, l: &Value, r: &Value, pred: Predicate) -> Value
  {
    self.create_cmp_internal(l, r, pred, true)
  }

  /// Build an instruction to compare two values with the predicate given.
  pub fn create_ucmp(&self, l: &Value, r: &Value, pred: Predicate) -> Value
  {
    self.create_cmp_internal(l, r, pred, false)
  }

  fn create_cmp_internal(&self, l: &Value, r: &Value,
  											 pred: Predicate, signed: bool) -> Value {
  	let (lhs_ty, rhs_ty) = (l.ty(), r.ty());
    assert_eq!(lhs_ty, rhs_ty);

    if lhs_ty.is_integer() {
	    let p = match (pred, signed) {
	    	(Predicate::Eq,    _)   => LLVMIntPredicate::LLVMIntEQ,
	    	(Predicate::NotEq, _)   => LLVMIntPredicate::LLVMIntNE,
	    	(Predicate::Lth, true)  => LLVMIntPredicate::LLVMIntSLT,
	    	(Predicate::Lth, false) => LLVMIntPredicate::LLVMIntULT,
	    	(Predicate::Leq, true)  => LLVMIntPredicate::LLVMIntSLE,
	    	(Predicate::Leq, false) => LLVMIntPredicate::LLVMIntULE,
	    	(Predicate::Gth, true)  => LLVMIntPredicate::LLVMIntSGT,
	    	(Predicate::Gth, false) => LLVMIntPredicate::LLVMIntUGT,
	    	(Predicate::Geq, true)  => LLVMIntPredicate::LLVMIntSGE,
	    	(Predicate::Geq, false) => LLVMIntPredicate::LLVMIntUGE,
	    };

	    Value(unsafe {
		    core::LLVMBuildICmp(self.0,
	    		                  p,
	     		                  l.0, r.0,
	     		                  NULL_NAME.as_ptr())
	    })

    } else if lhs_ty.is_float() {
    	let p = match pred {
        Predicate::Eq    => LLVMRealPredicate::LLVMRealOEQ,
        Predicate::NotEq => LLVMRealPredicate::LLVMRealONE,
        Predicate::Gth   => LLVMRealPredicate::LLVMRealOGT,
        Predicate::Geq   => LLVMRealPredicate::LLVMRealOGE,
        Predicate::Lth   => LLVMRealPredicate::LLVMRealOLT,
        Predicate::Leq   => LLVMRealPredicate::LLVMRealOLE
      };

   	  Value(unsafe {
      	core::LLVMBuildFCmp(self.0,
      		                 p, l.0, r.0,
      		                 NULL_NAME.as_ptr())
      })

    } else {
      panic!("expected numbers, got {:?}", lhs_ty)
    }
  }

  /// Build an instruction that computes the address of a subelement of an aggregate data
  /// structure.
  ///
  /// Basically type-safe pointer arithmetic.
  pub fn create_gep(&self, pointer: &Value, indices: &[&Value]) -> Value
  {
    let ref_array = to_llvmref_array!(indices, LLVMValueRef);

    Value(unsafe {
    	core::LLVMBuildInBoundsGEP(self.0,
    	                           pointer.0,
    	                           ref_array.as_ptr() as *mut LLVMValueRef,
    	                           indices.len() as c_uint,
    	                           NULL_NAME.as_ptr())
    })
  }

  /// Build an instruction to select a value depending on the predecessor of the current block.
  pub fn create_phi(&self, ty: &Ty, name: &str) -> PhiNode
  {
	  PhiNode(unsafe {
	  	core::LLVMBuildPhi(self.0, ty.0, ::util::chars::from_str(name))
  	})
  }
}

#[cfg(test)]
mod tests {
  use super::super::*;
  use types::LLVMTy;
  use value::{Predicate, ToValue};

	#[test]
	pub fn test_cond_br()
	{
		let jit = JitCompiler::new("test1").ok().unwrap();
    let ctx = jit.context();

    let func_ty = jit.create_func_ty(&u64::llvm_ty(ctx), &[&u64::llvm_ty(ctx)]);
    let func = jit.add_func("fib", &func_ty);
    let value = func.arg(0);

    let entry = func.append("entry");
    let then_bb = func.append("then_block");
    let else_bb = func.append("else_block");
    let merge_bb = func.append("merge_block");

    let builder = jit.builder();

    builder.position_at_end(&entry);
    let local = builder.create_alloca(&u64::llvm_ty(ctx));
    let cond = builder.create_cmp(&value.into(), &5u64.to_value(ctx), Predicate::Lth);
    builder.create_cond_br(&cond, &then_bb, &else_bb);

    builder.position_at_end(&then_bb);
    builder.create_store(&8u64.to_value(ctx), &local);
    builder.create_br(&merge_bb);

    builder.position_at_end(&else_bb);
    builder.create_store(&16u64.to_value(ctx), &local);
    builder.create_br(&merge_bb);

    builder.position_at_end(&merge_bb);
    let ret_val = builder.create_load(&local);
    builder.create_ret(&ret_val);

    jit.verify().unwrap();

    /*
    let ee = JitEngine::new(&module, JitOptions {opt_level: 0}).unwrap();
    ee.with_function(func, |fib: extern fn(u64) -> u64| {
      for i in 0..10 {
        if i < 5 {
          assert_eq!(8, fib(i));
        } else {
          assert_eq!(16, fib(i));
        }
      }
    });*/
	}
}<commit_msg>Fix unit tests in builder.rs.<commit_after>#![allow(dead_code)]

use std::mem;

use llvm_sys::{core, LLVMIntPredicate, LLVMRealPredicate};
use llvm_sys::prelude::{
  LLVMBuilderRef,
  LLVMValueRef
};
use libc::{c_char, c_uint};

use types::Ty;
use block::BasicBlock;
use value::{Function, Value, ValueRef, Predicate, PhiNode};

static NULL_NAME:[c_char; 1] = [0];

pub struct Builder(pub LLVMBuilderRef);
impl_dispose!(Builder, core::LLVMDisposeBuilder);

macro_rules! unary_instr (
  ($name:ident, $func:ident) => (
    pub fn $name(&self, value: &Value) -> Value {
      Value(unsafe {
        core::$func(self.0, value.0, NULL_NAME.as_ptr() as *const c_char)
      })
    }
  );
);

macro_rules! bin_instr (
  ($name:ident, $func:ident) => (
    pub fn $name(&self, lhs: &Value, rhs: &Value) -> Value
    {
      Value(unsafe {
        core::$func(self.0, lhs.0, rhs.0, NULL_NAME.as_ptr())
      })
    }
  );
  ($name:ident, $ifunc:ident, $ffunc:ident) => (
    pub fn $name(&self, lhs: &Value, rhs: &Value) -> Value {
      let lhs_ty = lhs.ty();
      let rhs_ty = rhs.ty();
      debug_assert_eq!(lhs_ty, rhs_ty);

      let instr_fn = if lhs_ty.is_integer() {
        core::$ifunc
      } else {
        core::$ffunc
      };

      Value(unsafe {
        instr_fn(self.0, lhs.0, rhs.0, NULL_NAME.as_ptr())
      })
    }
  );
);

impl Builder {

  pub fn get_insert_block(&self) -> BasicBlock
  {
    BasicBlock(unsafe { core::LLVMGetInsertBlock(self.0)})
  }

  /// Position the builder at `instr` within `block`.
  pub fn position_at(&self, block: &BasicBlock, instr: &Value)
  {
    unsafe { core::LLVMPositionBuilder(self.0, block.0, instr.0) }
  }

  /// Position the builder at the end of `block`.
  pub fn position_at_end(&self, block: &BasicBlock)
  {
    unsafe { core::LLVMPositionBuilderAtEnd(self.0, block.0) }
  }

  /// Build an instruction that returns from the function with void.
  pub fn create_ret_void(&self) -> Value
  {
    Value(unsafe {core::LLVMBuildRetVoid(self.0)})
  }

  /// Build an instruction that returns from the function with `value`.
  pub fn create_ret(&self, value: &Value) -> Value
  {
    Value(unsafe { core::LLVMBuildRet(self.0, value.0)})
  }

  /// Build an instruction that allocates an array with the element type `elem` and
  /// the size `size`.
  ///
  /// The size of this array will be the size of `elem` times `size`.
  pub fn build_array_alloca(&self, elem: &Ty, size: &Value) -> Value
  {
    Value(unsafe {
    	core::LLVMBuildArrayAlloca(self.0,
    														 elem.0,
    														 size.0,
    														 NULL_NAME.as_ptr() as *const c_char)
    })
  }

  /// Build an instruction that allocates a pointer to fit the size of `ty` then returns this
  /// pointer.
  ///
  /// Make sure to call `build_free` with the pointer value when you're done with it, or you're
  /// gonna have a bad time.
  pub fn create_alloca(&self, ty: &Ty) -> Value
  {
    Value(unsafe {
    	core::LLVMBuildAlloca(self.0,
    												ty.0,
    												NULL_NAME.as_ptr() as *const c_char)
    })
  }

  /// Build an instruction that frees the `val`, which _MUST_ be a pointer that was returned
  /// from `build_alloca`.
  pub fn create_free(&self, val: &Value) -> Value
  {
    Value(unsafe { core::LLVMBuildFree(self.0, val.0) })
  }

  /// Build an instruction that store the value `val` in the pointer `ptr`.
  pub fn create_store(&self, val: &Value, ptr: &Value) -> Value
  {
    Value(unsafe { core::LLVMBuildStore(self.0, val.0, ptr.0) })
  }

  /// Build an instruction that branches to the block `dest`.
  pub fn create_br(&self, dest: &BasicBlock) -> Value
  {
    Value(unsafe { core::LLVMBuildBr(self.0, dest.0)})
  }

  /// Build an instruction that branches to `if_block` if `cond` evaluates to true, and
  /// `else_block` otherwise.
  pub fn create_cond_br(&self, cond: &Value,
  	                    if_block: &BasicBlock, else_block: &BasicBlock) -> Value
  {
    Value(unsafe {
    	core::LLVMBuildCondBr(self.0,
    		                    cond.0,
    		                    if_block.0,
    		                    mem::transmute(else_block.0))
    })
  }

  /// Build an instruction that runs whichever block matches the value, or `default` if none of
  /// them matched it.
  pub fn create_switch(&self,
  	                   value: &Value,
  	                   default: &BasicBlock,
  	                   cases: &[(&Value, &BasicBlock)]) -> Value {
    Value(unsafe {
      let switch = core::LLVMBuildSwitch(self.0,
      	                                 value.0,
      	                                 default.0,
        	                                 cases.len() as c_uint);
      for case in cases {
        core::LLVMAddCase(switch, (case.0).0, (case.1).0);
      }

      switch
    })
  }

  /// Build an instruction that calls the function `func` with the arguments `args`.
  ///
  /// This will return the return value of the function.
  fn create_call_internal(&self, func: &Function, args: &[&Value], tail_call: bool) -> Value
  {
    let ref_array = to_llvmref_array!(args, LLVMValueRef);

    Value(unsafe {
        let call = core::LLVMBuildCall(self.0,
        	                             func.0,
                                       ref_array.as_ptr() as *mut LLVMValueRef,
        	                             args.len() as c_uint,
        	                             NULL_NAME.as_ptr());
        core::LLVMSetTailCall(call, if tail_call {1} else {0});
        call.into()
    })
  }

  /// Build an instruction that calls the function `func` with the arguments `args`.
  ///
  /// This will return the return value of the function.
  pub fn create_call(&self, func: &Function, args: &[&Value]) -> Value
  {
    self.create_call_internal(func, args, false)
  }

  /// Build an instruction that calls the function `func` with the arguments `args`.
  ///
  /// This will return the return value of the function.
  pub fn create_tail_call(&self, func: &Function, args: &[&Value]) -> Value
  {
    self.create_call_internal(func, args, true)
  }

  /// Build an instruction that yields to `true_val` if `cond` is equal to `1`, and `false_val`
  /// otherwise.
  pub fn create_select(&self, cond: &Value, true_val: &Value, false_val: &Value) -> Value
  {
    Value(unsafe {
    	core::LLVMBuildSelect(self.0,
    		                    cond.0,
    		                    true_val.0,
    		                    false_val.0,
    		                    NULL_NAME.as_ptr()) })
  }

  /// Build an instruction that casts a value into a certain type.
  pub fn create_bit_cast(&self, value: &Value, dest: &Ty) -> Value
  {
    Value(unsafe { core::LLVMBuildBitCast(
    		self.0,
    		value.0,
    		dest.0,
    		NULL_NAME.as_ptr())
    })
  }

  /// Build an instruction that inserts a value into an aggregate data value.
  pub fn create_insert_value(&self, agg: &Value, elem: &Value, index: usize) -> Value
  {
    Value(unsafe {
    	core::LLVMBuildInsertValue(self.0,
    		                         agg.0,
    		                         elem.0,
    		                         index as c_uint,
    		                         NULL_NAME.as_ptr())
    })
  }

  /// Build an instruction that extracts a value from an aggregate type.
	pub fn create_extract_value(&self, agg: &Value, index: usize) -> Value {
    Value(unsafe {
    	core::LLVMBuildExtractValue(self.0,
    		                          agg.0,
    		                          index as c_uint,
    		                          NULL_NAME.as_ptr())
   	})
  }

  unary_instr!{create_load, LLVMBuildLoad}
  unary_instr!{create_neg, LLVMBuildNeg}
  unary_instr!{create_not, LLVMBuildNot}

  bin_instr!{create_add, LLVMBuildAdd, LLVMBuildFAdd}
  bin_instr!{create_sub, LLVMBuildSub, LLVMBuildFSub}
  bin_instr!{create_mul, LLVMBuildMul, LLVMBuildFMul}
  bin_instr!{create_div, LLVMBuildSDiv, LLVMBuildFDiv}
  bin_instr!{create_rem, LLVMBuildSRem, LLVMBuildFRem}
  bin_instr!{create_shl, LLVMBuildShl}
  bin_instr!{create_ashr, LLVMBuildAShr}
  bin_instr!{create_and, LLVMBuildAnd}
  bin_instr!{create_or, LLVMBuildOr}
  bin_instr!{create_xor, LLVMBuildXor}

  /// Build an instruction to compare two values with the predicate given.
  pub fn create_cmp(&self, l: &Value, r: &Value, pred: Predicate) -> Value
  {
    self.create_cmp_internal(l, r, pred, true)
  }

  /// Build an instruction to compare two values with the predicate given.
  pub fn create_ucmp(&self, l: &Value, r: &Value, pred: Predicate) -> Value
  {
    self.create_cmp_internal(l, r, pred, false)
  }

  fn create_cmp_internal(&self, l: &Value, r: &Value,
  											 pred: Predicate, signed: bool) -> Value {
  	let (lhs_ty, rhs_ty) = (l.ty(), r.ty());
    assert_eq!(lhs_ty, rhs_ty);

    if lhs_ty.is_integer() {
	    let p = match (pred, signed) {
	    	(Predicate::Eq,    _)   => LLVMIntPredicate::LLVMIntEQ,
	    	(Predicate::NotEq, _)   => LLVMIntPredicate::LLVMIntNE,
	    	(Predicate::Lth, true)  => LLVMIntPredicate::LLVMIntSLT,
	    	(Predicate::Lth, false) => LLVMIntPredicate::LLVMIntULT,
	    	(Predicate::Leq, true)  => LLVMIntPredicate::LLVMIntSLE,
	    	(Predicate::Leq, false) => LLVMIntPredicate::LLVMIntULE,
	    	(Predicate::Gth, true)  => LLVMIntPredicate::LLVMIntSGT,
	    	(Predicate::Gth, false) => LLVMIntPredicate::LLVMIntUGT,
	    	(Predicate::Geq, true)  => LLVMIntPredicate::LLVMIntSGE,
	    	(Predicate::Geq, false) => LLVMIntPredicate::LLVMIntUGE,
	    };

	    Value(unsafe {
		    core::LLVMBuildICmp(self.0,
	    		                  p,
	     		                  l.0, r.0,
	     		                  NULL_NAME.as_ptr())
	    })

    } else if lhs_ty.is_float() {
    	let p = match pred {
        Predicate::Eq    => LLVMRealPredicate::LLVMRealOEQ,
        Predicate::NotEq => LLVMRealPredicate::LLVMRealONE,
        Predicate::Gth   => LLVMRealPredicate::LLVMRealOGT,
        Predicate::Geq   => LLVMRealPredicate::LLVMRealOGE,
        Predicate::Lth   => LLVMRealPredicate::LLVMRealOLT,
        Predicate::Leq   => LLVMRealPredicate::LLVMRealOLE
      };

   	  Value(unsafe {
      	core::LLVMBuildFCmp(self.0,
      		                 p, l.0, r.0,
      		                 NULL_NAME.as_ptr())
      })

    } else {
      panic!("expected numbers, got {:?}", lhs_ty)
    }
  }

  /// Build an instruction that computes the address of a subelement of an aggregate data
  /// structure.
  ///
  /// Basically type-safe pointer arithmetic.
  pub fn create_gep(&self, pointer: &Value, indices: &[&Value]) -> Value
  {
    let ref_array = to_llvmref_array!(indices, LLVMValueRef);

    Value(unsafe {
    	core::LLVMBuildInBoundsGEP(self.0,
    	                           pointer.0,
    	                           ref_array.as_ptr() as *mut LLVMValueRef,
    	                           indices.len() as c_uint,
    	                           NULL_NAME.as_ptr())
    })
  }

  /// Build an instruction to select a value depending on the predecessor of the current block.
  pub fn create_phi(&self, ty: &Ty, name: &str) -> PhiNode
  {
	  PhiNode(unsafe {
	  	core::LLVMBuildPhi(self.0, ty.0, ::util::chars::from_str(name))
  	})
  }
}

#[cfg(test)]
mod tests {
  use super::super::*;
  use types::LLVMTy;
  use value::{Predicate, ToValue};

	#[test]
	pub fn test_cond_br()
	{
		let jit = JitCompiler::new("test1").ok().unwrap();
    let ctx = jit.context();

    let func_ty = jit.create_func_ty(&u64::llvm_ty(ctx), &[&u64::llvm_ty(ctx)]);
    let func = jit.add_func("fib", &func_ty);
    let value = func.arg(0);

    let entry = func.append("entry");
    let then_bb = func.append("then_block");
    let else_bb = func.append("else_block");
    let merge_bb = func.append("merge_block");

    let builder = jit.builder();

    builder.position_at_end(&entry);
    let local = builder.create_alloca(&u64::llvm_ty(ctx));
    let cond = builder.create_cmp(&value.into(), &5u64.to_value(ctx), Predicate::Lth);
    builder.create_cond_br(&cond, &then_bb, &else_bb);

    builder.position_at_end(&then_bb);
    builder.create_store(&8u64.to_value(ctx), &local);
    builder.create_br(&merge_bb);

    builder.position_at_end(&else_bb);
    builder.create_store(&16u64.to_value(ctx), &local);
    builder.create_br(&merge_bb);

    builder.position_at_end(&merge_bb);
    let ret_val = builder.create_load(&local);
    builder.create_ret(&ret_val);

    jit.verify().unwrap();

    let fib: fn(u64) -> u64 = unsafe {
      ::std::mem::transmute(jit.get_func_ptr(&func).unwrap())
    };

    for i in 0..10 {
      if i < 5 {
        assert_eq!(8, fib(i));
      } else {
        assert_eq!(16, fib(i));
      }
    }
	}
}<|endoftext|>


<commit_before>extern crate clap;

use std::env;
use std::fs;
use std::path::Path;

use clap::ArgMatches;
use tempdir::TempDir;
use hyper::Client;
use util;
use extractor;
use downloader;
use profile;
use config::Config;

pub fn init() {
    let config = Config::new();
    if config.install_dir.exists() || config.shim_dir.exists() {
        println!("Already initalized. Reinitializing....");
    }
    fs::create_dir_all(&config.install_dir).expect("Could not create installation directory.");
    fs::create_dir_all(&config.shim_dir).expect("Could not create shims directory.");
    if !env::home_dir()
        .unwrap()
        .join("Documents")
        .join("WindowsPowerShell")
        .join("profile.ps1")
        .exists() {
        println!(r#"Please create profile.ps1 the following place:

$Env:USERPROFILE\Documents\WindowsPowerShell\profile.ps1

And write the following thing:

. $Env:USERPROFILE\.groonga\shims\bin\source-groonga.ps1
"#)
    }
}

pub fn install(m: &ArgMatches) {
    const BASE_URL: &'static str = "http://packages.groonga.org/windows/groonga";
    let config = Config::from_matches(m);
    println!("Value for architecture: {}", config.arch.clone().unwrap());
    println!("Obtaining Groonga version: {}", config.version.clone().unwrap());
    let groonga_dir = format!("groonga-{}-{}", config.version.unwrap(), config.arch.unwrap());
    let groonga_binary = format!("{}.zip", groonga_dir.clone());
    if config.versions_dir.join(groonga_dir.clone()).exists() {
        println!("Already installed. Ready to use it.");
        return ();
    }

    let download_dir = TempDir::new("grnenv-rs")
        .expect("Could not create temp dir.")
        .into_path();

    let client = Client::new();
    let filename = downloader::file_download(&client,
                                             &*format!("{}/{}", BASE_URL, groonga_binary),
                                             download_dir)
        .expect("Failed to download");
    extractor::extract_zip(&filename, &config.versions_dir);
}

pub fn switch(m: &ArgMatches) {
    let config = Config::from_matches(m);
    println!("Value for architecture: {}", config.arch.clone().unwrap());
    println!("Using Groonga version: {}", config.version.clone().unwrap());
    let groonga_dir = format!("groonga-{}-{}", config.version.unwrap(), config.arch.unwrap());
    match config.version {
        Some("system") => {
            profile::remove_grnenv_profile(&config.shim_dir).unwrap();
            return ()
        },
        Some(_) => profile::create_profile_source(&config.shim_dir, &groonga_dir, &config.versions_dir)
            .expect("Could not create source-groonga.ps1"),
        None => unreachable!(),
    }
}

pub fn versions() {
    let groonga_versioned_dir = util::obtain_groonga_versioned_path();
    let paths = fs::read_dir(&Path::new(&groonga_versioned_dir)).unwrap();

    let names = paths.filter_map(|entry| {
            entry.ok().and_then(|e| {
                e.path()
                    .file_name()
                    .and_then(|n| n.to_str().map(|s| String::from(s)))
            })
        })
        .collect::<Vec<String>>();

    println!("Installed Groonga:");
    println!("\tsystem");
    for entry in names {
        println!("\t{}", entry);
    }
}
<commit_msg>Add custom error messages for architecture<commit_after>extern crate clap;

use std::env;
use std::fs;
use std::path::Path;

use clap::ArgMatches;
use tempdir::TempDir;
use hyper::Client;
use util;
use extractor;
use downloader;
use profile;
use config::Config;

pub fn init() {
    let config = Config::new();
    if config.install_dir.exists() || config.shim_dir.exists() {
        println!("Already initalized. Reinitializing....");
    }
    fs::create_dir_all(&config.install_dir).expect("Could not create installation directory.");
    fs::create_dir_all(&config.shim_dir).expect("Could not create shims directory.");
    if !env::home_dir()
        .unwrap()
        .join("Documents")
        .join("WindowsPowerShell")
        .join("profile.ps1")
        .exists() {
        println!(r#"Please create profile.ps1 the following place:

$Env:USERPROFILE\Documents\WindowsPowerShell\profile.ps1

And write the following thing:

. $Env:USERPROFILE\.groonga\shims\bin\source-groonga.ps1
"#)
    }
}

pub fn install(m: &ArgMatches) {
    const BASE_URL: &'static str = "http://packages.groonga.org/windows/groonga";
    let config = Config::from_matches(m);
    println!("Value for architecture: {}", config.arch.clone().expect("unsupported platform"));
    println!("Obtaining Groonga version: {}", config.version.clone().unwrap());
    let groonga_dir = format!("groonga-{}-{}", config.version.unwrap(), config.arch.unwrap());
    let groonga_binary = format!("{}.zip", groonga_dir.clone());
    if config.versions_dir.join(groonga_dir.clone()).exists() {
        println!("Already installed. Ready to use it.");
        return ();
    }

    let download_dir = TempDir::new("grnenv-rs")
        .expect("Could not create temp dir.")
        .into_path();

    let client = Client::new();
    let filename = downloader::file_download(&client,
                                             &*format!("{}/{}", BASE_URL, groonga_binary),
                                             download_dir)
        .expect("Failed to download");
    extractor::extract_zip(&filename, &config.versions_dir);
}

pub fn switch(m: &ArgMatches) {
    let config = Config::from_matches(m);
    println!("Value for architecture: {}", config.arch.clone().expect("unsupported platform"));
    println!("Using Groonga version: {}", config.version.clone().unwrap());
    let groonga_dir = format!("groonga-{}-{}", config.version.unwrap(), config.arch.unwrap());
    match config.version {
        Some("system") => {
            profile::remove_grnenv_profile(&config.shim_dir).unwrap();
            return ()
        },
        Some(_) => profile::create_profile_source(&config.shim_dir, &groonga_dir, &config.versions_dir)
            .expect("Could not create source-groonga.ps1"),
        None => unreachable!(),
    }
}

pub fn versions() {
    let groonga_versioned_dir = util::obtain_groonga_versioned_path();
    let paths = fs::read_dir(&Path::new(&groonga_versioned_dir)).unwrap();

    let names = paths.filter_map(|entry| {
            entry.ok().and_then(|e| {
                e.path()
                    .file_name()
                    .and_then(|n| n.to_str().map(|s| String::from(s)))
            })
        })
        .collect::<Vec<String>>();

    println!("Installed Groonga:");
    println!("\tsystem");
    for entry in names {
        println!("\t{}", entry);
    }
}
<|endoftext|>


<commit_before>use na::Real;
use pipeline::broad_phase::BroadPhasePairFilter;
use pipeline::world::CollisionObject;

const SELF_COLLISION: u32 = 1 << 31;
const ALL_GROUPS: u32 = (1 << 30) - 1;
const NO_GROUP: u32 = 0;

/// Groups of collision used to filter which object interact with which other one.
///
/// There are at most 30 groups indexed from 0 to 29 (included). This identifies collidable
/// entities by combining three attributes:
///    * A set of group this structure is member of.
///    * A collision group whitelist.
///    * A collision group blacklist.
///
/// For two entities to interact, they must be member of at least one group part of each-other's
/// whitelists, and must not be part of any blacklisted group. The blacklist always has priority on
/// the whitelist.
///
/// ### Example
/// For example if the object A is such that:
///    * It is part of the groups 1, 3, and 6.
///    * It whitelists the groups 6 and 7.
///    * It blacklists the group 1.
/// Let the object B be such that:
///    * It is part of the groups 1, 3, and 7.
///    * It whitelists the groups 3 and 7.
///    * It does not blacklist anything.
/// For example if the object C is such that:
///    * It is part of the groups 6 and 9.
///    * It whitelists the groups 3 and 7.
///    * It does not blacklist anything.
///
/// Then we have:
///    * A and C can interact because A whitelists the group 6 (which C is part of), and,
///    reciprocally, C whitelists the group 3 (which A is part of).
///    * A and B will **not** interact because B is part of the group 1 which is blacklisted by A.
///    * Finally, B and C will **not** interact either because, even if C whitelists the group 3
///    (which B is part of), B does not whitelists the groups 6 nor 9 (which B is part of).
#[derive(Clone, Debug, Copy)]
pub struct CollisionGroups {
    membership: u32,
    whitelist: u32,
    blacklist: u32,
}

impl CollisionGroups {
    /// Creates a new `CollisionGroups` that enables interactions with everything except
    /// self-interaction.
    #[inline]
    pub fn new() -> CollisionGroups {
        CollisionGroups {
            membership: ALL_GROUPS,
            whitelist: ALL_GROUPS,
            blacklist: NO_GROUP,
        }
    }

    /// The maximum allowed group identifier.
    #[inline]
    pub fn max_group_id() -> usize {
        29
    }

    #[inline]
    fn modify_mask(mask: &mut u32, group_id: usize, add: bool) {
        assert!(
            group_id < 30,
            "There are at most 30 groups indexed from 0 to 29 (included)."
        );

        if add {
            *mask = *mask | (1 << group_id)
        } else {
            *mask = *mask & !(1 << group_id)
        }
    }

    #[inline]
    fn set_mask(mask: &mut u32, groups: &[usize]) {
        *mask = 0;
        for g in groups.iter() {
            CollisionGroups::modify_mask(mask, *g, true);
        }
    }

    /// Adds or removes this entity from the given group.
    #[inline]
    pub fn modify_membership(&mut self, group_id: usize, add: bool) {
        CollisionGroups::modify_mask(&mut self.membership, group_id, add);
    }

    /// Adds or removes the given group from this entity whitelist.
    #[inline]
    pub fn modify_whitelist(&mut self, group_id: usize, add: bool) {
        CollisionGroups::modify_mask(&mut self.whitelist, group_id, add);
    }

    /// Adds or removes this entity from the given group.
    #[inline]
    pub fn modify_blacklist(&mut self, group_id: usize, add: bool) {
        CollisionGroups::modify_mask(&mut self.blacklist, group_id, add);
    }

    /// Make this object member of the given groups only.
    #[inline]
    pub fn set_membership(&mut self, groups: &[usize]) {
        CollisionGroups::set_mask(&mut self.membership, groups);
    }

    /// Whitelists the given groups only (others will be un-whitelisted).
    #[inline]
    pub fn set_whitelist(&mut self, groups: &[usize]) {
        CollisionGroups::set_mask(&mut self.whitelist, groups);
    }

    /// Blacklists the given groups only (others will be un-blacklisted).
    #[inline]
    pub fn set_blacklist(&mut self, groups: &[usize]) {
        CollisionGroups::set_mask(&mut self.blacklist, groups);
    }

    /// Copies the membership of another collision groups.
    #[inline]
    pub fn copy_membership(&mut self, other: &CollisionGroups) {
        self.membership = other.membership
    }

    /// Copies the whitelist of another collision groups.
    #[inline]
    pub fn copy_whitelist(&mut self, other: &CollisionGroups) {
        self.whitelist = other.whitelist
    }

    /// Copies the blacklist of another collision groups.
    #[inline]
    pub fn copy_blacklist(&mut self, other: &CollisionGroups) {
        self.blacklist = other.blacklist
    }

    /// Allows the object to interact with itself.
    #[inline]
    pub fn enable_self_interaction(&mut self) {
        self.whitelist = self.whitelist | SELF_COLLISION;
    }

    /// Prevents the object from interacting with itself.
    #[inline]
    pub fn disable_self_interaction(&mut self) {
        self.whitelist = self.whitelist & !SELF_COLLISION;
    }

    #[inline]
    fn is_inside_mask(mask: u32, group_id: usize) -> bool {
        assert!(
            group_id < 30,
            "There are at most 30 groups indexed from 0 to 29 (included)."
        );
        mask & (1 << group_id) != 0
    }

    /// Tests if this entity is part of the given group.
    #[inline]
    pub fn is_member_of(&self, group_id: usize) -> bool {
        CollisionGroups::is_inside_mask(self.membership, group_id)
    }

    /// Tests if the given group is whitelisted.
    #[inline]
    pub fn is_group_whitelisted(&self, group_id: usize) -> bool {
        CollisionGroups::is_inside_mask(self.whitelist, group_id)
    }

    /// Tests if the given group is blacklisted.
    #[inline]
    pub fn is_group_blacklisted(&self, group_id: usize) -> bool {
        CollisionGroups::is_inside_mask(self.blacklist, group_id)
    }

    /// Tests whether interactinos with a given group is possible.
    ///
    /// Collision is possible if `group_id` is whitelisted but not blacklisted.
    #[inline]
    pub fn can_interact_with(&self, group_id: usize) -> bool {
        !CollisionGroups::is_inside_mask(self.blacklist, group_id)
            && CollisionGroups::is_inside_mask(self.whitelist, group_id)
    }

    /// Tests whether two collision groups have at least one group in common.
    #[inline]
    pub fn can_interact_with_groups(&self, other: &CollisionGroups) -> bool {
        // FIXME: is there a more bitwise-y way of doing this?
        self.membership & other.blacklist == 0 && other.membership & self.blacklist == 0
            && self.membership & other.whitelist != 0
            && other.membership & self.whitelist != 0
    }

    /// Tests whether self-interaction is enabled.
    #[inline]
    pub fn can_interact_with_self(&self) -> bool {
        self.whitelist & SELF_COLLISION != 0
    }
}

/// A collision filter based collision groups.
pub struct CollisionGroupsPairFilter;

impl CollisionGroupsPairFilter {
    /// Creates a new collision filter based collision groups.
    #[inline]
    pub fn new() -> CollisionGroupsPairFilter {
        CollisionGroupsPairFilter
    }
}

impl<N: Real, T> BroadPhasePairFilter<N, T> for CollisionGroupsPairFilter {
    fn is_pair_valid(
        &self,
        co1: &CollisionObject<N, T>,
        co2: &CollisionObject<N, T>,
    ) -> bool {
        if co1.handle() == co2.handle() {
            co1.collision_groups().can_interact_with_self()
        } else {
            co1.collision_groups()
                .can_interact_with_groups(co2.collision_groups())
        }
    }
}
<commit_msg>"interactinos" -> "interactions"<commit_after>use na::Real;
use pipeline::broad_phase::BroadPhasePairFilter;
use pipeline::world::CollisionObject;

const SELF_COLLISION: u32 = 1 << 31;
const ALL_GROUPS: u32 = (1 << 30) - 1;
const NO_GROUP: u32 = 0;

/// Groups of collision used to filter which object interact with which other one.
///
/// There are at most 30 groups indexed from 0 to 29 (included). This identifies collidable
/// entities by combining three attributes:
///    * A set of group this structure is member of.
///    * A collision group whitelist.
///    * A collision group blacklist.
///
/// For two entities to interact, they must be member of at least one group part of each-other's
/// whitelists, and must not be part of any blacklisted group. The blacklist always has priority on
/// the whitelist.
///
/// ### Example
/// For example if the object A is such that:
///    * It is part of the groups 1, 3, and 6.
///    * It whitelists the groups 6 and 7.
///    * It blacklists the group 1.
/// Let the object B be such that:
///    * It is part of the groups 1, 3, and 7.
///    * It whitelists the groups 3 and 7.
///    * It does not blacklist anything.
/// For example if the object C is such that:
///    * It is part of the groups 6 and 9.
///    * It whitelists the groups 3 and 7.
///    * It does not blacklist anything.
///
/// Then we have:
///    * A and C can interact because A whitelists the group 6 (which C is part of), and,
///    reciprocally, C whitelists the group 3 (which A is part of).
///    * A and B will **not** interact because B is part of the group 1 which is blacklisted by A.
///    * Finally, B and C will **not** interact either because, even if C whitelists the group 3
///    (which B is part of), B does not whitelists the groups 6 nor 9 (which B is part of).
#[derive(Clone, Debug, Copy)]
pub struct CollisionGroups {
    membership: u32,
    whitelist: u32,
    blacklist: u32,
}

impl CollisionGroups {
    /// Creates a new `CollisionGroups` that enables interactions with everything except
    /// self-interaction.
    #[inline]
    pub fn new() -> CollisionGroups {
        CollisionGroups {
            membership: ALL_GROUPS,
            whitelist: ALL_GROUPS,
            blacklist: NO_GROUP,
        }
    }

    /// The maximum allowed group identifier.
    #[inline]
    pub fn max_group_id() -> usize {
        29
    }

    #[inline]
    fn modify_mask(mask: &mut u32, group_id: usize, add: bool) {
        assert!(
            group_id < 30,
            "There are at most 30 groups indexed from 0 to 29 (included)."
        );

        if add {
            *mask = *mask | (1 << group_id)
        } else {
            *mask = *mask & !(1 << group_id)
        }
    }

    #[inline]
    fn set_mask(mask: &mut u32, groups: &[usize]) {
        *mask = 0;
        for g in groups.iter() {
            CollisionGroups::modify_mask(mask, *g, true);
        }
    }

    /// Adds or removes this entity from the given group.
    #[inline]
    pub fn modify_membership(&mut self, group_id: usize, add: bool) {
        CollisionGroups::modify_mask(&mut self.membership, group_id, add);
    }

    /// Adds or removes the given group from this entity whitelist.
    #[inline]
    pub fn modify_whitelist(&mut self, group_id: usize, add: bool) {
        CollisionGroups::modify_mask(&mut self.whitelist, group_id, add);
    }

    /// Adds or removes this entity from the given group.
    #[inline]
    pub fn modify_blacklist(&mut self, group_id: usize, add: bool) {
        CollisionGroups::modify_mask(&mut self.blacklist, group_id, add);
    }

    /// Make this object member of the given groups only.
    #[inline]
    pub fn set_membership(&mut self, groups: &[usize]) {
        CollisionGroups::set_mask(&mut self.membership, groups);
    }

    /// Whitelists the given groups only (others will be un-whitelisted).
    #[inline]
    pub fn set_whitelist(&mut self, groups: &[usize]) {
        CollisionGroups::set_mask(&mut self.whitelist, groups);
    }

    /// Blacklists the given groups only (others will be un-blacklisted).
    #[inline]
    pub fn set_blacklist(&mut self, groups: &[usize]) {
        CollisionGroups::set_mask(&mut self.blacklist, groups);
    }

    /// Copies the membership of another collision groups.
    #[inline]
    pub fn copy_membership(&mut self, other: &CollisionGroups) {
        self.membership = other.membership
    }

    /// Copies the whitelist of another collision groups.
    #[inline]
    pub fn copy_whitelist(&mut self, other: &CollisionGroups) {
        self.whitelist = other.whitelist
    }

    /// Copies the blacklist of another collision groups.
    #[inline]
    pub fn copy_blacklist(&mut self, other: &CollisionGroups) {
        self.blacklist = other.blacklist
    }

    /// Allows the object to interact with itself.
    #[inline]
    pub fn enable_self_interaction(&mut self) {
        self.whitelist = self.whitelist | SELF_COLLISION;
    }

    /// Prevents the object from interacting with itself.
    #[inline]
    pub fn disable_self_interaction(&mut self) {
        self.whitelist = self.whitelist & !SELF_COLLISION;
    }

    #[inline]
    fn is_inside_mask(mask: u32, group_id: usize) -> bool {
        assert!(
            group_id < 30,
            "There are at most 30 groups indexed from 0 to 29 (included)."
        );
        mask & (1 << group_id) != 0
    }

    /// Tests if this entity is part of the given group.
    #[inline]
    pub fn is_member_of(&self, group_id: usize) -> bool {
        CollisionGroups::is_inside_mask(self.membership, group_id)
    }

    /// Tests if the given group is whitelisted.
    #[inline]
    pub fn is_group_whitelisted(&self, group_id: usize) -> bool {
        CollisionGroups::is_inside_mask(self.whitelist, group_id)
    }

    /// Tests if the given group is blacklisted.
    #[inline]
    pub fn is_group_blacklisted(&self, group_id: usize) -> bool {
        CollisionGroups::is_inside_mask(self.blacklist, group_id)
    }

    /// Tests whether interactions with a given group is possible.
    ///
    /// Collision is possible if `group_id` is whitelisted but not blacklisted.
    #[inline]
    pub fn can_interact_with(&self, group_id: usize) -> bool {
        !CollisionGroups::is_inside_mask(self.blacklist, group_id)
            && CollisionGroups::is_inside_mask(self.whitelist, group_id)
    }

    /// Tests whether two collision groups have at least one group in common.
    #[inline]
    pub fn can_interact_with_groups(&self, other: &CollisionGroups) -> bool {
        // FIXME: is there a more bitwise-y way of doing this?
        self.membership & other.blacklist == 0 && other.membership & self.blacklist == 0
            && self.membership & other.whitelist != 0
            && other.membership & self.whitelist != 0
    }

    /// Tests whether self-interaction is enabled.
    #[inline]
    pub fn can_interact_with_self(&self) -> bool {
        self.whitelist & SELF_COLLISION != 0
    }
}

/// A collision filter based collision groups.
pub struct CollisionGroupsPairFilter;

impl CollisionGroupsPairFilter {
    /// Creates a new collision filter based collision groups.
    #[inline]
    pub fn new() -> CollisionGroupsPairFilter {
        CollisionGroupsPairFilter
    }
}

impl<N: Real, T> BroadPhasePairFilter<N, T> for CollisionGroupsPairFilter {
    fn is_pair_valid(
        &self,
        co1: &CollisionObject<N, T>,
        co2: &CollisionObject<N, T>,
    ) -> bool {
        if co1.handle() == co2.handle() {
            co1.collision_groups().can_interact_with_self()
        } else {
            co1.collision_groups()
                .can_interact_with_groups(co2.collision_groups())
        }
    }
}
<|endoftext|>


<commit_before>#![feature(std_misc)]
extern crate time;
extern crate "calx_util" as util;
extern crate "calx_backend" as backend;

use std::num::{Float};
use std::ascii::OwnedAsciiExt;
use util::{color, V2, Rgba, Rgb, Rect};
use backend::{CanvasBuilder, Key, Event, Fonter, CanvasUtil};

fn main() {
    let mut t = 0i32;
    let mut mouse_pos = V2(-1i32, -1i32);
    let pangrams = vec![
        "the quick brown fox jumps over the lazy dog",
        "the five boxing wizards jump quickly",
        "five quacking zephyrs jolt my wax bed",
        "jackdaws love my big sphinx of quartz",
        "the quick onyx goblin jumps over the lazy dwarf",
        "who packed five dozen old quart jugs in my box",
        "heavy boxes perform quick waltzes and jigs",
        "fix problem quickly with galvanized jets",
        "pack my red box with five dozen quality jugs",
        "why shouldn't a quixotic kazakh vampire jog barefoot",
        "have a pick: twenty-six letters - no forcing a jumbled quiz",
        "crazy frederick bought many very exquisite opal jewels",
        "grumpy wizards make toxic brew for the evil queen and jack",
        "just keep examining every low bid quoted for zinc etchings",
        "sylvia wagt quick den jux bei pforzheim",
        "franz jagt im komplett verwahrlosten taxi quer durch",
        "sic fugiens, dux, zelotypos, quam karus haberis",
        ".o'i mu xagji sofybakni cu zvati le purdi",
    ];
    let pattern_col = Rgb::parse("#420");

    for evt in CanvasBuilder::new().run() {
        // Change pangram every 10 seconds.
        let pangram_idx = (time::precise_time_s() / 10.0) as usize % pangrams.len();
        match evt {
            Event::Render(ctx) => {
                let img = ctx.font_image('@').unwrap();

                ctx.clear();
                for y in 0i32..(360/8) {
                    for x in 0i32..(640/8) {
                        let col = if Rect(V2(x * 8, y * 8), V2(8, 8)).contains(&mouse_pos) {
                            color::WHITE } else { pattern_col };
                        ctx.draw_image(img, V2(x as f32 * 8.0, y as f32 * 8.0 + 8.0),
                            0.4, &col, &color::BLACK);
                    }
                }

                // These should be clipped off the screen.
                let img = ctx.font_image('#').unwrap();
                ctx.draw_image(img, V2(316.0, 0.0), 0.4, &color::GREEN, &color::BLACK);
                ctx.draw_image(img, V2(316.0, 368.0), 0.4, &color::GREEN, &color::BLACK);
                ctx.draw_image(img, V2(-8.0, 184.0), 0.4, &color::GREEN, &color::BLACK);
                ctx.draw_image(img, V2(640.0, 184.0), 0.4, &color::GREEN, &color::BLACK);

                let center = V2(320.0, 180.0);
                let offset = V2(
                    ((t as f32 / 160.0).cos() * 128.0),
                    ((t as f32 / 160.0).sin() * 128.0));

                ctx.draw_line(3, center, center + offset, 0.3, &Rgba::new(0, 255, 255, 128));

                let fps = 1.0 / ctx.render_duration;
                {
                    let mut fonter = Fonter::new(ctx)
                        .color(&color::LIGHTGREEN)
                        .border(&color::BLACK)
                        .layer(0.1)
                        //.width(64.0)
                        .text(&format!("FPS {:.0}\n", fps)[..])
                        .text(&format!("{}\n", pangrams[pangram_idx].to_string().into_ascii_uppercase())[..])
                        .text(&format!("{}\n", pangrams[pangram_idx])[..])
                        .text(&format!("!\"#$%&'()*+,-./\n")[..])
                        .text(&format!("1234567890:;<=>?\n")[..])
                        .text(&format!("[\\]^_`{{|}}~\n")[..]);
                    fonter.draw(V2(0.0, 0.0));
                }

                t += 1;
            }
            Event::KeyPressed(Key::Escape) => {
                return;
            }
            Event::KeyPressed(k) => {
                println!("Pressed {:?}", k);
            }
            Event::Char(c) => {
                println!("Typed {:?}", c);
            }
            Event::MouseMoved((x, y)) => {
                mouse_pos = V2(x, y);
            }
            _ => ()
        }
    }
}
<commit_msg>Cleanup demo<commit_after>#![feature(std_misc)]
extern crate time;
extern crate "calx_util" as util;
extern crate "calx_backend" as backend;

use std::num::{Float};
use std::ascii::OwnedAsciiExt;
use util::{color, V2, Rgba, Rgb, Rect};
use backend::{CanvasBuilder, Key, Event, Fonter, CanvasUtil};

fn main() {
    let mut t = 0i32;
    let mut mouse_pos = V2(-1i32, -1i32);
    let pangrams = vec![
        "the quick brown fox jumps over the lazy dog",
        "the five boxing wizards jump quickly",
        "five quacking zephyrs jolt my wax bed",
        "jackdaws love my big sphinx of quartz",
        "the quick onyx goblin jumps over the lazy dwarf",
        "who packed five dozen old quart jugs in my box",
        "heavy boxes perform quick waltzes and jigs",
        "fix problem quickly with galvanized jets",
        "pack my red box with five dozen quality jugs",
        "why shouldn't a quixotic kazakh vampire jog barefoot",
        "have a pick: twenty-six letters - no forcing a jumbled quiz",
        "crazy frederick bought many very exquisite opal jewels",
        "grumpy wizards make toxic brew for the evil queen and jack",
        "just keep examining every low bid quoted for zinc etchings",
        "sylvia wagt quick den jux bei pforzheim",
        "franz jagt im komplett verwahrlosten taxi quer durch",
        "sic fugiens, dux, zelotypos, quam karus haberis",
        ".o'i mu xagji sofybakni cu zvati le purdi",
    ];
    let pattern_col = Rgb::parse("#420");

    for evt in CanvasBuilder::new().run() {
        // Change pangram every 10 seconds.
        let pangram_idx = (time::precise_time_s() / 10.0) as usize % pangrams.len();
        match evt {
            Event::Render(ctx) => {
                let img = ctx.font_image('@').unwrap();

                ctx.clear();
                for y in 0i32..(360/8) {
                    for x in 0i32..(640/8) {
                        let col = if Rect(V2(x * 8, y * 8), V2(8, 8)).contains(&mouse_pos) {
                            color::WHITE } else { pattern_col };
                        ctx.draw_image(img, V2(x as f32 * 8.0, y as f32 * 8.0 + 8.0),
                            0.4, &col, &color::BLACK);
                    }
                }

                // These should be clipped off the screen.
                let img = ctx.font_image('#').unwrap();
                ctx.draw_image(img, V2(316.0, 0.0), 0.4, &color::GREEN, &color::BLACK);
                ctx.draw_image(img, V2(316.0, 368.0), 0.4, &color::GREEN, &color::BLACK);
                ctx.draw_image(img, V2(-8.0, 184.0), 0.4, &color::GREEN, &color::BLACK);
                ctx.draw_image(img, V2(640.0, 184.0), 0.4, &color::GREEN, &color::BLACK);

                let center = V2(320.0, 180.0);
                let offset = V2(
                    ((t as f32 / 160.0).cos() * 128.0),
                    ((t as f32 / 160.0).sin() * 128.0));

                ctx.draw_line(3, center, center + offset, 0.3, &Rgba::new(0, 255, 255, 128));

                let fps = 1.0 / ctx.render_duration;
                {
                    let mut fonter = Fonter::new(ctx)
                        .color(&color::LIGHTGREEN)
                        .border(&color::BLACK)
                        .layer(0.1)
                        .text(&format!("FPS {:.0}\n", fps)[..])
                        .text(&format!("{}\n", pangrams[pangram_idx].to_string().into_ascii_uppercase())[..])
                        .text(&format!("{}\n", pangrams[pangram_idx])[..])
                        .text(&format!("!\"#$%&'()*+,-./\n")[..])
                        .text(&format!("1234567890:;<=>?\n")[..])
                        .text(&format!("[\\]^_`{{|}}~\n")[..]);
                    fonter.draw(V2(0.0, 0.0));
                }

                t += 1;
            }
            Event::KeyPressed(Key::Escape) => {
                return;
            }
            Event::KeyPressed(k) => {
                println!("Pressed {:?}", k);
            }
            Event::Char(c) => {
                println!("Typed {:?}", c);
            }
            Event::MouseMoved((x, y)) => {
                mouse_pos = V2(x, y);
            }
            _ => ()
        }
    }
}
<|endoftext|>


<commit_before>//! Book keeping for keeping diagnostics easily in sync with the client.
pub(crate) mod to_proto;

use std::{mem, sync::Arc};

use ide::FileId;
use rustc_hash::{FxHashMap, FxHashSet};

use crate::lsp_ext;

pub(crate) type CheckFixes = Arc<FxHashMap<FileId, Vec<Fix>>>;

#[derive(Debug, Default, Clone)]
pub struct DiagnosticsMapConfig {
    pub warnings_as_info: Vec<String>,
    pub warnings_as_hint: Vec<String>,
}

#[derive(Debug, Default, Clone)]
pub(crate) struct DiagnosticCollection {
    // FIXME: should be FxHashMap<FileId, Vec<ra_id::Diagnostic>>
    pub(crate) native: FxHashMap<FileId, Vec<lsp_types::Diagnostic>>,
    // FIXME: should be Vec<flycheck::Diagnostic>
    pub(crate) check: FxHashMap<FileId, Vec<lsp_types::Diagnostic>>,
    pub(crate) check_fixes: CheckFixes,
    changes: FxHashSet<FileId>,
}

#[derive(Debug, Clone)]
pub(crate) struct Fix {
    pub(crate) range: lsp_types::Range,
    pub(crate) action: lsp_ext::CodeAction,
}

impl DiagnosticCollection {
    pub(crate) fn clear_check(&mut self) {
        Arc::make_mut(&mut self.check_fixes).clear();
        self.changes.extend(self.check.drain().map(|(key, _value)| key))
    }

    pub(crate) fn add_check_diagnostic(
        &mut self,
        file_id: FileId,
        diagnostic: lsp_types::Diagnostic,
        fixes: Vec<lsp_ext::CodeAction>,
    ) {
        let diagnostics = self.check.entry(file_id).or_default();
        for existing_diagnostic in diagnostics.iter() {
            if are_diagnostics_equal(&existing_diagnostic, &diagnostic) {
                return;
            }
        }

        let check_fixes = Arc::make_mut(&mut self.check_fixes);
        check_fixes
            .entry(file_id)
            .or_default()
            .extend(fixes.into_iter().map(|action| Fix { range: diagnostic.range, action }));
        diagnostics.push(diagnostic);
        self.changes.insert(file_id);
    }

    pub(crate) fn set_native_diagnostics(
        &mut self,
        file_id: FileId,
        diagnostics: Vec<lsp_types::Diagnostic>,
    ) {
        self.native.insert(file_id, diagnostics);
        self.changes.insert(file_id);
    }

    pub(crate) fn diagnostics_for(
        &self,
        file_id: FileId,
    ) -> impl Iterator<Item = &lsp_types::Diagnostic> {
        let native = self.native.get(&file_id).into_iter().flatten();
        let check = self.check.get(&file_id).into_iter().flatten();
        native.chain(check)
    }

    pub(crate) fn take_changes(&mut self) -> Option<FxHashSet<FileId>> {
        if self.changes.is_empty() {
            return None;
        }
        Some(mem::take(&mut self.changes))
    }
}

fn are_diagnostics_equal(left: &lsp_types::Diagnostic, right: &lsp_types::Diagnostic) -> bool {
    left.source == right.source
        && left.severity == right.severity
        && left.range == right.range
        && left.message == right.message
}
<commit_msg>Avoid transmitting unchanged diagnostics<commit_after>//! Book keeping for keeping diagnostics easily in sync with the client.
pub(crate) mod to_proto;

use std::{mem, sync::Arc};

use ide::FileId;
use rustc_hash::{FxHashMap, FxHashSet};

use crate::lsp_ext;

pub(crate) type CheckFixes = Arc<FxHashMap<FileId, Vec<Fix>>>;

#[derive(Debug, Default, Clone)]
pub struct DiagnosticsMapConfig {
    pub warnings_as_info: Vec<String>,
    pub warnings_as_hint: Vec<String>,
}

#[derive(Debug, Default, Clone)]
pub(crate) struct DiagnosticCollection {
    // FIXME: should be FxHashMap<FileId, Vec<ra_id::Diagnostic>>
    pub(crate) native: FxHashMap<FileId, Vec<lsp_types::Diagnostic>>,
    // FIXME: should be Vec<flycheck::Diagnostic>
    pub(crate) check: FxHashMap<FileId, Vec<lsp_types::Diagnostic>>,
    pub(crate) check_fixes: CheckFixes,
    changes: FxHashSet<FileId>,
}

#[derive(Debug, Clone)]
pub(crate) struct Fix {
    pub(crate) range: lsp_types::Range,
    pub(crate) action: lsp_ext::CodeAction,
}

impl DiagnosticCollection {
    pub(crate) fn clear_check(&mut self) {
        Arc::make_mut(&mut self.check_fixes).clear();
        self.changes.extend(self.check.drain().map(|(key, _value)| key))
    }

    pub(crate) fn add_check_diagnostic(
        &mut self,
        file_id: FileId,
        diagnostic: lsp_types::Diagnostic,
        fixes: Vec<lsp_ext::CodeAction>,
    ) {
        let diagnostics = self.check.entry(file_id).or_default();
        for existing_diagnostic in diagnostics.iter() {
            if are_diagnostics_equal(&existing_diagnostic, &diagnostic) {
                return;
            }
        }

        let check_fixes = Arc::make_mut(&mut self.check_fixes);
        check_fixes
            .entry(file_id)
            .or_default()
            .extend(fixes.into_iter().map(|action| Fix { range: diagnostic.range, action }));
        diagnostics.push(diagnostic);
        self.changes.insert(file_id);
    }

    pub(crate) fn set_native_diagnostics(
        &mut self,
        file_id: FileId,
        diagnostics: Vec<lsp_types::Diagnostic>,
    ) {
        if let Some(existing_diagnostics) = self.native.get(&file_id) {
            if existing_diagnostics.len() == diagnostics.len()
                && diagnostics
                    .iter()
                    .zip(existing_diagnostics)
                    .all(|(new, existing)| are_diagnostics_equal(new, existing))
            {
                return;
            }
        }

        self.native.insert(file_id, diagnostics);
        self.changes.insert(file_id);
    }

    pub(crate) fn diagnostics_for(
        &self,
        file_id: FileId,
    ) -> impl Iterator<Item = &lsp_types::Diagnostic> {
        let native = self.native.get(&file_id).into_iter().flatten();
        let check = self.check.get(&file_id).into_iter().flatten();
        native.chain(check)
    }

    pub(crate) fn take_changes(&mut self) -> Option<FxHashSet<FileId>> {
        if self.changes.is_empty() {
            return None;
        }
        Some(mem::take(&mut self.changes))
    }
}

fn are_diagnostics_equal(left: &lsp_types::Diagnostic, right: &lsp_types::Diagnostic) -> bool {
    left.source == right.source
        && left.severity == right.severity
        && left.range == right.range
        && left.message == right.message
}
<|endoftext|>


<commit_before>use std::{
    io,
    sync::{
        atomic::{AtomicBool, AtomicU64, Ordering},
        Arc,
    },
    time::{Duration, Instant},
};

use crate::{
    config::ServerConfig,
    context::SharedContext,
    relay::{loadbalancing::server::LoadBalancer, socks5::Address, tcprelay::client::ServerClient},
};

use futures::{Future, Stream};
use log::{debug, error};
use tokio::{
    self,
    timer::{Interval, Timeout},
};

struct Server {
    config: Arc<ServerConfig>,
    elapsed: AtomicU64,
    available: AtomicBool,
}

impl Server {
    fn new(config: ServerConfig) -> Server {
        Server {
            config: Arc::new(config),
            elapsed: AtomicU64::new(0),
            available: AtomicBool::new(true),
        }
    }
}

#[derive(Clone)]
pub struct PingBalancer {
    servers: Vec<Arc<Server>>,
}

impl PingBalancer {
    pub fn new(context: SharedContext) -> PingBalancer {
        let config = context.config();

        if config.server.is_empty() {
            panic!("no servers");
        }

        let check_required = config.server.len() > 1;

        let mut servers = Vec::new();
        for svr in &config.server {
            let sc = Arc::new(Server::new(svr.clone()));
            servers.push(sc.clone());

            if !check_required {
                continue;
            }

            let addr = Address::DomainNameAddress("www.example.com".to_owned(), 80);
            let context = context.clone();

            tokio::spawn(
                // Check every 10 seconds
                Interval::new(Instant::now() + Duration::from_secs(1), Duration::from_secs(10))
                    .for_each(move |_| {
                        let sc = sc.clone();

                        let fut1 = PingBalancer::check_delay(sc.clone(), context.clone(), addr.clone());
                        let fut2 = PingBalancer::check_delay(sc.clone(), context.clone(), addr.clone());
                        let fut3 = PingBalancer::check_delay(sc.clone(), context.clone(), addr.clone());

                        fut1.join3(fut2, fut3).then(move |res| {
                            match res {
                                Ok((d1, d2, d3)) => {
                                    sc.available.store(true, Ordering::Release);
                                    sc.elapsed.store((d1 + d2 + d3) / 3, Ordering::Release);
                                }
                                Err(..) => {
                                    sc.available.store(false, Ordering::Release);
                                }
                            }

                            Ok(())
                        })
                    })
                    .map_err(|_| ()),
            );
        }

        PingBalancer { servers }
    }

    fn check_delay(
        sc: Arc<Server>,
        context: SharedContext,
        addr: Address,
    ) -> impl Future<Item = u64, Error = io::Error> {
        let start = Instant::now();
        let fut = ServerClient::connect(context, addr, sc.config.clone());
        Timeout::new(fut, Duration::from_secs(5)).then(move |res| {
            let elapsed = Instant::now() - start;
            let elapsed = elapsed.as_secs() * 1000 + u64::from(elapsed.subsec_millis()); // Converted to ms
            match res {
                Ok(..) => {
                    // Connected ... record its time
                    debug!(
                        "checked remote server {} connected with {} ms",
                        sc.config.addr(),
                        elapsed
                    );
                    Ok(elapsed)
                }
                Err(err) => {
                    match err.into_inner() {
                        Some(err) => {
                            error!("failed to check server {}, error: {}", sc.config.addr(), err);

                            // NOTE: connection / handshake error, server is down
                            Err(err)
                        }
                        None => {
                            // Timeout
                            error!("checked remote server {} connect timeout", sc.config.addr());

                            // NOTE: timeout is still available, but server is too slow
                            Ok(elapsed)
                        }
                    }
                }
            }
        })
    }
}

impl LoadBalancer for PingBalancer {
    fn pick_server(&mut self) -> Arc<ServerConfig> {
        if self.servers.is_empty() {
            panic!("No server");
        }

        // Choose the best one
        let mut choosen_svr = &self.servers[0];
        let mut found_one = false;

        for svr in &self.servers {
            if svr.available.load(Ordering::Acquire)
                && (!choosen_svr.available.load(Ordering::Acquire)
                    || svr.elapsed.load(Ordering::Acquire) < choosen_svr.elapsed.load(Ordering::Acquire))
            {
                found_one = true;
                choosen_svr = svr;
            }
        }

        if !found_one && !choosen_svr.available.load(Ordering::Acquire) {
            // Just choose one available
            for svr in &self.servers {
                if svr.available.load(Ordering::Acquire) {
                    choosen_svr = svr;
                }
            }

            debug!(
                "cannot find any available servers, picked {} delay {} ms",
                choosen_svr.config.addr(),
                choosen_svr.elapsed.load(Ordering::Acquire)
            );
        } else {
            debug!(
                "choosen the best server {} delay {} ms",
                choosen_svr.config.addr(),
                choosen_svr.elapsed.load(Ordering::Acquire)
            );
        }

        choosen_svr.config.clone()
    }

    fn total(&self) -> usize {
        self.servers.len()
    }
}
<commit_msg>Make picking server complexity O1<commit_after>use std::{
    io,
    sync::{
        atomic::{AtomicBool, AtomicU64, AtomicUsize, Ordering},
        Arc,
    },
    time::{Duration, Instant},
};

use crate::{
    config::ServerConfig,
    context::SharedContext,
    relay::{loadbalancing::server::LoadBalancer, socks5::Address, tcprelay::client::ServerClient},
};

use futures::{Future, Stream};
use log::{debug, error};
use tokio::{
    self,
    timer::{Interval, Timeout},
};

struct Server {
    config: Arc<ServerConfig>,
    elapsed: AtomicU64,
    available: AtomicBool,
}

impl Server {
    fn new(config: ServerConfig) -> Server {
        Server {
            config: Arc::new(config),
            elapsed: AtomicU64::new(0),
            available: AtomicBool::new(true),
        }
    }

    fn is_available(&self) -> bool {
        self.available.load(Ordering::Acquire)
    }

    fn delay(&self) -> u64 {
        self.elapsed.load(Ordering::Acquire)
    }
}

const DEFAULT_CHECK_INTERVAL_SEC: u64 = 10;

struct Inner {
    servers: Vec<Arc<Server>>,
    best_idx: AtomicUsize,
}

impl Inner {
    fn new(context: SharedContext) -> Inner {
        let config = context.config();

        if config.server.is_empty() {
            panic!("no servers");
        }

        let check_required = config.server.len() > 1;

        let mut servers = Vec::new();
        for svr in &config.server {
            let sc = Arc::new(Server::new(svr.clone()));
            servers.push(sc.clone());

            if !check_required {
                continue;
            }

            let addr = Address::DomainNameAddress("www.example.com".to_owned(), 80);
            let context = context.clone();

            tokio::spawn(
                // Check every 10 seconds
                Interval::new(
                    Instant::now() + Duration::from_secs(1),
                    Duration::from_secs(DEFAULT_CHECK_INTERVAL_SEC),
                )
                .for_each(move |_| {
                    let sc = sc.clone();

                    let fut1 = Inner::check_delay(sc.clone(), context.clone(), addr.clone());
                    let fut2 = Inner::check_delay(sc.clone(), context.clone(), addr.clone());
                    let fut3 = Inner::check_delay(sc.clone(), context.clone(), addr.clone());

                    fut1.join3(fut2, fut3).then(move |res| {
                        match res {
                            Ok((d1, d2, d3)) => {
                                sc.available.store(true, Ordering::Release);
                                sc.elapsed.store((d1 + d2 + d3) / 3, Ordering::Release);
                            }
                            Err(..) => {
                                sc.available.store(false, Ordering::Release);
                            }
                        }

                        Ok(())
                    })
                })
                .map_err(|_| ()),
            );
        }

        Inner {
            servers,
            best_idx: AtomicUsize::new(0),
        }
    }

    fn check_delay(
        sc: Arc<Server>,
        context: SharedContext,
        addr: Address,
    ) -> impl Future<Item = u64, Error = io::Error> {
        let start = Instant::now();
        let fut = ServerClient::connect(context, addr, sc.config.clone());
        Timeout::new(fut, Duration::from_secs(5)).then(move |res| {
            let elapsed = Instant::now() - start;
            let elapsed = elapsed.as_secs() * 1000 + u64::from(elapsed.subsec_millis()); // Converted to ms
            match res {
                Ok(..) => {
                    // Connected ... record its time
                    debug!(
                        "checked remote server {} connected with {} ms",
                        sc.config.addr(),
                        elapsed
                    );
                    Ok(elapsed)
                }
                Err(err) => {
                    match err.into_inner() {
                        Some(err) => {
                            error!("failed to check server {}, error: {}", sc.config.addr(), err);

                            // NOTE: connection / handshake error, server is down
                            Err(err)
                        }
                        None => {
                            // Timeout
                            error!("checked remote server {} connect timeout", sc.config.addr());

                            // NOTE: timeout is still available, but server is too slow
                            Ok(elapsed)
                        }
                    }
                }
            }
        })
    }
}

#[derive(Clone)]
pub struct PingBalancer {
    inner: Arc<Inner>,
}

impl PingBalancer {
    pub fn new(context: SharedContext) -> PingBalancer {
        let inner = Arc::new(Inner::new(context));

        let inner_cloned = inner.clone();
        tokio::spawn(
            Interval::new(
                Instant::now() + Duration::from_secs(2),
                Duration::from_secs(DEFAULT_CHECK_INTERVAL_SEC),
            )
            .for_each(move |_| {
                let inner = inner_cloned.clone();

                if inner.servers.is_empty() {
                    panic!("No server");
                }

                // Choose the best one
                let mut svr_idx = 0;

                for (idx, svr) in inner.servers.iter().enumerate() {
                    let choosen_svr = &inner.servers[svr_idx];
                    if svr.is_available() && (!choosen_svr.is_available() || svr.delay() < choosen_svr.delay()) {
                        svr_idx = idx;
                    }
                }

                let choosen_svr = &inner.servers[svr_idx];
                if svr_idx == 0 && !choosen_svr.is_available() {
                    // Cannot find any usable servers, use the first one (svr_idx = 0)
                    error!(
                        "cannot find any usable servers, picked {} delay {} ms",
                        choosen_svr.config.addr(),
                        choosen_svr.delay()
                    );
                } else {
                    debug!(
                        "chosen the best server {} delay {} ms",
                        choosen_svr.config.addr(),
                        choosen_svr.delay()
                    );
                }

                inner.best_idx.store(svr_idx, Ordering::Release);

                Ok(())
            })
            .map_err(|_| ()),
        );

        PingBalancer { inner }
    }
}

impl LoadBalancer for PingBalancer {
    fn pick_server(&mut self) -> Arc<ServerConfig> {
        if self.inner.servers.is_empty() {
            panic!("no server in configuration");
        }

        let idx = self.inner.best_idx.load(Ordering::Acquire);
        self.inner.servers[idx].config.clone()
    }

    fn total(&self) -> usize {
        self.inner.servers.len()
    }
}
<|endoftext|>


<commit_before>use std;
use glfw3;

import glfw3::*;

fn main() {

    // get version string
    io::println(~"GLFW version: " + glfwGetVersionString());

    // get version tuple
    let version = glfwGetVersion();
    match version {
        (major, minor, rev) => {
            io::println(fmt!("GLFW version: %d.%d.%d", major, minor, rev));
        }
    }

}<commit_msg>Take advantage of `let` destructuring<commit_after>use std;
use glfw3;

import glfw3::*;

fn main() {

    // get version string
    io::println(~"GLFW version: " + glfwGetVersionString());

    // get version tuple
    let (major, minor, rev) = glfwGetVersion();
    io::println(fmt!("GLFW version: %d.%d.%d", major, minor, rev));

}<|endoftext|>