<commit_before>use std::convert::TryFrom;
use either::Either;

use crate::values::AsValueRef;
use crate::values::{FunctionValue, PointerValue, AnyValue};

use llvm_sys::prelude::LLVMValueRef;
use llvm_sys::core::{LLVMGetTypeKind, LLVMGetElementType, LLVMTypeOf, LLVMGetReturnType};
use llvm_sys::LLVMTypeKind;

/// A value that can be called with the [`build_call`] instruction.
///
/// In practice, the `F : Into<CallableValue<'ctx>>` bound of [`build_call`] means it is
/// possible to pass a [`FunctionValue`] to [`build_call`] directly. It will be implicitly converted
/// into a `CallableValue`.
///
/// [`build_call`]: crate::builder::Builder::build_call
///
/// ```no_run
/// use inkwell::context::Context;
///
/// // A simple function which calls itself:
/// let context = Context::create();
/// let module = context.create_module("ret");
/// let builder = context.create_builder();
/// let i32_type = context.i32_type();
/// let fn_type = i32_type.fn_type(&[i32_type.into()], false);
/// let fn_value = module.add_function("ret", fn_type, None);
/// let entry = context.append_basic_block(fn_value, "entry");
/// let i32_arg = fn_value.get_first_param().unwrap();
///
/// builder.position_at_end(entry);
///
/// let ret_val = builder.build_call(fn_value, &[i32_arg], "call")
///     .try_as_basic_value()
///     .left()
///     .unwrap();
///
/// builder.build_return(Some(&ret_val));
/// ```
///
/// A [`PointerValue`] cannot be implicitly converted to a `CallableValue` because the pointer may
/// point to a non-function value. Instead we can use [`TryFrom`] to handle this failure case explicitly.
///
/// ```no_run
/// use std::convert::TryFrom;
/// use inkwell::context::Context;
/// use inkwell::values::CallableValue;
///
/// // A simple function which calls itself:
/// let context = Context::create();
/// let module = context.create_module("ret");
/// let builder = context.create_builder();
/// let i32_type = context.i32_type();
/// let fn_type = i32_type.fn_type(&[i32_type.into()], false);
/// let fn_value = module.add_function("ret", fn_type, None);
/// let entry = context.append_basic_block(fn_value, "entry");
/// let i32_arg = fn_value.get_first_param().unwrap();
///
/// builder.position_at_end(entry);
///
/// // take a pointer to the function value
/// let fn_pointer_value = fn_value.as_global_value().as_pointer_value();
///
/// // convert that pointer value into a callable value
/// // explicitly handling the failure case (here with `unwrap`)
/// let callable_value = CallableValue::try_from(fn_pointer_value).unwrap();
///
/// let ret_val = builder.build_call(callable_value, &[i32_arg], "call")
///     .try_as_basic_value()
///     .left()
///     .unwrap();
///
/// builder.build_return(Some(&ret_val));
/// ```
#[derive(Debug)]
pub struct CallableValue<'ctx>(Either<FunctionValue<'ctx>, PointerValue<'ctx>>);

impl<'ctx> AsValueRef for CallableValue<'ctx> {
    fn as_value_ref(&self) -> LLVMValueRef {
        use either::Either::*;

        match self.0 {
            Left(function) => function.as_value_ref(),
            Right(pointer) => pointer.as_value_ref(),
        }
    }
}

impl<'ctx> AnyValue<'ctx> for CallableValue<'ctx> {}

impl<'ctx> CallableValue<'ctx> {
    pub(crate) fn returns_void(&self) -> bool {
        let return_type = unsafe {
            LLVMGetTypeKind(LLVMGetReturnType(LLVMGetElementType(LLVMTypeOf(self.as_value_ref()))))
        };

        matches!(return_type, LLVMTypeKind::LLVMVoidTypeKind)
    }
}

impl<'ctx> From<FunctionValue<'ctx>> for CallableValue<'ctx> {
    fn from(value: FunctionValue<'ctx>) -> Self {
        Self(Either::Left(value))
    }
}

impl<'ctx> TryFrom<PointerValue<'ctx>> for CallableValue<'ctx> {
    type Error = ();

    fn try_from(value: PointerValue<'ctx>) -> Result<Self, Self::Error> {
        // If using a pointer value, we must validate it's a valid function ptr
        let value_ref = value.as_value_ref();
        let ty_kind = unsafe { LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(value_ref))) };
        let is_a_fn_ptr = matches!(ty_kind, LLVMTypeKind::LLVMFunctionTypeKind);

        if is_a_fn_ptr {
            Ok(Self(Either::Right(value)))
        } else {
            Err(())
        }
    }
}
<commit_msg>Fix doctests<commit_after>use std::convert::TryFrom;
use either::Either;

use crate::values::AsValueRef;
use crate::values::{FunctionValue, PointerValue, AnyValue};

use llvm_sys::prelude::LLVMValueRef;
use llvm_sys::core::{LLVMGetTypeKind, LLVMGetElementType, LLVMTypeOf, LLVMGetReturnType};
use llvm_sys::LLVMTypeKind;

/// A value that can be called with the [`build_call`] instruction.
///
/// In practice, the `F : Into<CallableValue<'ctx>>` bound of [`build_call`] means it is
/// possible to pass a [`FunctionValue`] to [`build_call`] directly. It will be implicitly converted
/// into a `CallableValue`.
///
/// [`build_call`]: crate::builder::Builder::build_call
///
/// ```no_run
/// use inkwell::context::Context;
///
/// // A simple function which calls itself:
/// let context = Context::create();
/// let module = context.create_module("ret");
/// let builder = context.create_builder();
/// let i32_type = context.i32_type();
/// let fn_type = i32_type.fn_type(&[i32_type.into()], false);
/// let fn_value = module.add_function("ret", fn_type, None);
/// let entry = context.append_basic_block(fn_value, "entry");
/// let i32_arg = fn_value.get_first_param().unwrap();
///
/// builder.position_at_end(entry);
///
/// let ret_val = builder.build_call(fn_value, &[i32_arg.into()], "call")
///     .try_as_basic_value()
///     .left()
///     .unwrap();
///
/// builder.build_return(Some(&ret_val));
/// ```
///
/// A [`PointerValue`] cannot be implicitly converted to a `CallableValue` because the pointer may
/// point to a non-function value. Instead we can use [`TryFrom`] to handle this failure case explicitly.
///
/// ```no_run
/// use std::convert::TryFrom;
/// use inkwell::context::Context;
/// use inkwell::values::CallableValue;
///
/// // A simple function which calls itself:
/// let context = Context::create();
/// let module = context.create_module("ret");
/// let builder = context.create_builder();
/// let i32_type = context.i32_type();
/// let fn_type = i32_type.fn_type(&[i32_type.into()], false);
/// let fn_value = module.add_function("ret", fn_type, None);
/// let entry = context.append_basic_block(fn_value, "entry");
/// let i32_arg = fn_value.get_first_param().unwrap();
///
/// builder.position_at_end(entry);
///
/// // take a pointer to the function value
/// let fn_pointer_value = fn_value.as_global_value().as_pointer_value();
///
/// // convert that pointer value into a callable value
/// // explicitly handling the failure case (here with `unwrap`)
/// let callable_value = CallableValue::try_from(fn_pointer_value).unwrap();
///
/// let ret_val = builder.build_call(callable_value, &[i32_arg.into()], "call")
///     .try_as_basic_value()
///     .left()
///     .unwrap();
///
/// builder.build_return(Some(&ret_val));
/// ```
#[derive(Debug)]
pub struct CallableValue<'ctx>(Either<FunctionValue<'ctx>, PointerValue<'ctx>>);

impl<'ctx> AsValueRef for CallableValue<'ctx> {
    fn as_value_ref(&self) -> LLVMValueRef {
        use either::Either::*;

        match self.0 {
            Left(function) => function.as_value_ref(),
            Right(pointer) => pointer.as_value_ref(),
        }
    }
}

impl<'ctx> AnyValue<'ctx> for CallableValue<'ctx> {}

impl<'ctx> CallableValue<'ctx> {
    pub(crate) fn returns_void(&self) -> bool {
        let return_type = unsafe {
            LLVMGetTypeKind(LLVMGetReturnType(LLVMGetElementType(LLVMTypeOf(self.as_value_ref()))))
        };

        matches!(return_type, LLVMTypeKind::LLVMVoidTypeKind)
    }
}

impl<'ctx> From<FunctionValue<'ctx>> for CallableValue<'ctx> {
    fn from(value: FunctionValue<'ctx>) -> Self {
        Self(Either::Left(value))
    }
}

impl<'ctx> TryFrom<PointerValue<'ctx>> for CallableValue<'ctx> {
    type Error = ();

    fn try_from(value: PointerValue<'ctx>) -> Result<Self, Self::Error> {
        // If using a pointer value, we must validate it's a valid function ptr
        let value_ref = value.as_value_ref();
        let ty_kind = unsafe { LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(value_ref))) };
        let is_a_fn_ptr = matches!(ty_kind, LLVMTypeKind::LLVMFunctionTypeKind);

        if is_a_fn_ptr {
            Ok(Self(Either::Right(value)))
        } else {
            Err(())
        }
    }
}
<|endoftext|>


<commit_before>#![feature(phase)]
#![crate_name = "cube"]

extern crate cgmath;
extern crate gfx;
#[phase(plugin)]
extern crate gfx_macros;
extern crate glfw;
extern crate native;
extern crate time;

use cgmath::FixedArray;
use cgmath::{Matrix4, Point3, Vector3};
use cgmath::{Transform, AffineMatrix3};
use gfx::{Device, DeviceHelper};
use glfw::Context;

#[vertex_format]
struct Vertex {
    #[as_float]
    #[name = "a_Pos"]
    pos: [i8, ..3],

    #[as_float]
    #[name = "a_TexCoord"]
    tex_coord: [u8, ..2],
}

// The shader_param attribute makes sure the following struct can be used to
// pass parameters to a shader. Its argument is the name of the type that will
// be generated to represent your the program. Search for link_program below, to
// see how it's used.
#[shader_param(MyProgram)]
struct Params {
    #[name = "u_Model"]
    model: [[f32, ..4], ..4],

    #[name = "u_View"]
    view: [[f32, ..4], ..4],

    #[name = "u_Proj"]
    proj: [[f32, ..4], ..4],

    #[name = "t_Color"]
    color: gfx::shade::TextureParam,
}

static VERTEX_SRC: gfx::ShaderSource = shaders! {
GLSL_120: b"
    #version 120

    attribute vec3 a_Pos;
    attribute vec2 a_TexCoord;
    varying vec2 v_TexCoord;

    uniform mat4 u_Model;
    uniform mat4 u_View;
    uniform mat4 u_Proj;

    void main() {
        v_TexCoord = a_TexCoord;
        gl_Position = u_Proj * u_View * u_Model * vec4(a_Pos, 1.0);
    }
"
GLSL_150: b"
    #version 150 core

    in vec3 a_Pos;
    in vec2 a_TexCoord;
    out vec2 v_TexCoord;

    uniform mat4 u_Model;
    uniform mat4 u_View;
    uniform mat4 u_Proj;

    void main() {
        v_TexCoord = a_TexCoord;
        gl_Position = u_Proj * u_View * u_Model * vec4(a_Pos, 1.0);
    }
"
};

static FRAGMENT_SRC: gfx::ShaderSource = shaders! {
GLSL_120: b"
    #version 120

    varying vec2 v_TexCoord;
    uniform sampler2D t_Color;

    void main() {
        vec4 tex = texture2D(t_Color, v_TexCoord);
        float blend = dot(v_TexCoord-vec2(0.5,0.5), v_TexCoord-vec2(0.5,0.5));
        gl_FragColor = mix(tex, vec4(0.0,0.0,0.0,0.0), blend*1.0);
    }
"
GLSL_150: b"
    #version 150 core

    in vec2 v_TexCoord;
    out vec4 o_Color;

    uniform sampler2D t_Color;
    void main() {
        vec4 tex = texture(t_Color, v_TexCoord);
        float blend = dot(v_TexCoord-vec2(0.5,0.5), v_TexCoord-vec2(0.5,0.5));
        o_Color = mix(tex, vec4(0.0,0.0,0.0,0.0), blend*1.0);
    }
"
};

//----------------------------------------

// We need to run on the main thread, so ensure we are using the `native` runtime. This is
// technically not needed, since this is the default, but it's not guaranteed.
#[start]
fn start(argc: int, argv: *const *const u8) -> int {
     native::start(argc, argv, main)
}

fn main() {
    let glfw = glfw::init(glfw::FAIL_ON_ERRORS).unwrap();

    glfw.window_hint(glfw::ContextVersion(3, 2));
    glfw.window_hint(glfw::OpenglForwardCompat(true));
    glfw.window_hint(glfw::OpenglProfile(glfw::OpenGlCoreProfile));

    let (window, events) = glfw
        .create_window(640, 480, "Cube example", glfw::Windowed)
        .expect("Failed to create GLFW window.");

    window.make_current();
    glfw.set_error_callback(glfw::FAIL_ON_ERRORS);
    window.set_key_polling(true);

    let (w, h) = window.get_framebuffer_size();
    let frame = gfx::Frame::new(w as u16, h as u16);

    let mut device = gfx::GlDevice::new(|s| glfw.get_proc_address(s));
    let mut renderer = device.create_renderer();

    let state = gfx::DrawState::new().depth(gfx::state::LessEqual, true);

    let vertex_data = vec![
        // top (0, 0, 1)
        Vertex { pos: [-1, -1,  1], tex_coord: [0, 0] },
        Vertex { pos: [ 1, -1,  1], tex_coord: [1, 0] },
        Vertex { pos: [ 1,  1,  1], tex_coord: [1, 1] },
        Vertex { pos: [-1,  1,  1], tex_coord: [0, 1] },
        // bottom (0, 0, -1)
        Vertex { pos: [ 1,  1, -1], tex_coord: [0, 0] },
        Vertex { pos: [-1,  1, -1], tex_coord: [1, 0] },
        Vertex { pos: [-1, -1, -1], tex_coord: [1, 1] },
        Vertex { pos: [ 1, -1, -1], tex_coord: [0, 1] },
        // right (1, 0, 0)
        Vertex { pos: [ 1, -1, -1], tex_coord: [0, 0] },
        Vertex { pos: [ 1,  1, -1], tex_coord: [1, 0] },
        Vertex { pos: [ 1,  1,  1], tex_coord: [1, 1] },
        Vertex { pos: [ 1, -1,  1], tex_coord: [0, 1] },
        // left (-1, 0, 0)
        Vertex { pos: [-1,  1,  1], tex_coord: [0, 0] },
        Vertex { pos: [-1, -1,  1], tex_coord: [1, 0] },
        Vertex { pos: [-1, -1, -1], tex_coord: [1, 1] },
        Vertex { pos: [-1,  1, -1], tex_coord: [0, 1] },
        // front (0, 1, 0)
        Vertex { pos: [-1,  1, -1], tex_coord: [0, 0] },
        Vertex { pos: [ 1,  1, -1], tex_coord: [1, 0] },
        Vertex { pos: [ 1,  1,  1], tex_coord: [1, 1] },
        Vertex { pos: [-1,  1,  1], tex_coord: [0, 1] },
        // back (0, -1, 0)
        Vertex { pos: [ 1, -1,  1], tex_coord: [0, 0] },
        Vertex { pos: [-1, -1,  1], tex_coord: [1, 0] },
        Vertex { pos: [-1, -1, -1], tex_coord: [1, 1] },
        Vertex { pos: [ 1, -1, -1], tex_coord: [0, 1] },
    ];

    let mesh = device.create_mesh(vertex_data);

    let index_data: Vec<u8> = vec![
         0,  1,  2,  2,  3,  0, // top
         4,  5,  6,  6,  7,  4, // bottom
         8,  9, 10, 10, 11,  8, // right
        12, 13, 14, 14, 16, 12, // left
        16, 17, 18, 18, 19, 16, // front
        20, 21, 22, 22, 23, 20, // back
    ];

    let slice = {
        let buf = device.create_buffer_static(&index_data);
        gfx::IndexSlice8(gfx::TriangleList, buf, 0, 36)
    };

    let texture_info = gfx::tex::TextureInfo {
        width: 1,
        height: 1,
        depth: 1,
        levels: 1,
        kind: gfx::tex::Texture2D,
        format: gfx::tex::RGBA8,
    };
    let image_info = texture_info.to_image_info();
    let texture = device.create_texture(texture_info).unwrap();
    device.update_texture(&texture, &image_info,
                          &vec![0x20u8, 0xA0u8, 0xC0u8, 0x00u8])
        .unwrap();

    let sampler = device.create_sampler(
        gfx::tex::SamplerInfo::new(gfx::tex::Bilinear,
                                   gfx::tex::Clamp)
    );

    let prog: MyProgram = device
        .link_program(VERTEX_SRC.clone(), FRAGMENT_SRC.clone())
        .unwrap();

    let view: AffineMatrix3<f32> = Transform::look_at(
        &Point3::new(1.5f32, -5.0, 3.0),
        &Point3::new(0f32, 0.0, 0.0),
        &Vector3::unit_z(),
    );

    let aspect = w as f32 / h as f32;
    let data = Params {
        model: Matrix4::identity().into_fixed(),
        view: view.mat.into_fixed(),
        proj: cgmath::perspective(cgmath::deg(45.0f32), aspect,
                                  1.0, 10.0).into_fixed(),
        color: (texture, Some(sampler)),
    };

    let clear_data = gfx::ClearData {
        color: Some([0.3, 0.3, 0.3, 1.0]),
        depth: Some(1.0),
        stencil: None,
    };

    while !window.should_close() {
        glfw.poll_events();
        for (_, event) in glfw::flush_messages(&events) {
            match event {
                glfw::KeyEvent(glfw::KeyEscape, _, glfw::Press, _) =>
                    window.set_should_close(true),
                _ => {},
            }
        }

        renderer.reset();
        renderer.clear(clear_data, &frame);
        renderer.draw(&mesh, slice, &frame, (&prog, &data), &state).unwrap();
        device.submit(renderer.as_buffer());

        window.swap_buffers();
    }
}
<commit_msg>Combine model/view/proj matrices into single uniform for cube example<commit_after>#![feature(phase)]
#![crate_name = "cube"]

extern crate cgmath;
extern crate gfx;
#[phase(plugin)]
extern crate gfx_macros;
extern crate glfw;
extern crate native;
extern crate time;

use cgmath::FixedArray;
use cgmath::{Matrix, Point3, Vector3};
use cgmath::{Transform, AffineMatrix3};
use gfx::{Device, DeviceHelper};
use glfw::Context;

#[vertex_format]
struct Vertex {
    #[as_float]
    #[name = "a_Pos"]
    pos: [i8, ..3],

    #[as_float]
    #[name = "a_TexCoord"]
    tex_coord: [u8, ..2],
}

// The shader_param attribute makes sure the following struct can be used to
// pass parameters to a shader. Its argument is the name of the type that will
// be generated to represent your the program. Search for link_program below, to
// see how it's used.
#[shader_param(MyProgram)]
struct Params {
    #[name = "u_Transform"]
    transform: [[f32, ..4], ..4],

    #[name = "t_Color"]
    color: gfx::shade::TextureParam,
}

static VERTEX_SRC: gfx::ShaderSource = shaders! {
GLSL_120: b"
    #version 120

    attribute vec3 a_Pos;
    attribute vec2 a_TexCoord;
    varying vec2 v_TexCoord;

    uniform mat4 u_Transform;

    void main() {
        v_TexCoord = a_TexCoord;
        gl_Position = u_Transform * vec4(a_Pos, 1.0);
    }
"
GLSL_150: b"
    #version 150 core

    in vec3 a_Pos;
    in vec2 a_TexCoord;
    out vec2 v_TexCoord;

    uniform mat4 u_Transform;

    void main() {
        v_TexCoord = a_TexCoord;
        gl_Position = u_Transform * vec4(a_Pos, 1.0);
    }
"
};

static FRAGMENT_SRC: gfx::ShaderSource = shaders! {
GLSL_120: b"
    #version 120

    varying vec2 v_TexCoord;
    uniform sampler2D t_Color;

    void main() {
        vec4 tex = texture2D(t_Color, v_TexCoord);
        float blend = dot(v_TexCoord-vec2(0.5,0.5), v_TexCoord-vec2(0.5,0.5));
        gl_FragColor = mix(tex, vec4(0.0,0.0,0.0,0.0), blend*1.0);
    }
"
GLSL_150: b"
    #version 150 core

    in vec2 v_TexCoord;
    out vec4 o_Color;

    uniform sampler2D t_Color;
    void main() {
        vec4 tex = texture(t_Color, v_TexCoord);
        float blend = dot(v_TexCoord-vec2(0.5,0.5), v_TexCoord-vec2(0.5,0.5));
        o_Color = mix(tex, vec4(0.0,0.0,0.0,0.0), blend*1.0);
    }
"
};

//----------------------------------------

// We need to run on the main thread, so ensure we are using the `native` runtime. This is
// technically not needed, since this is the default, but it's not guaranteed.
#[start]
fn start(argc: int, argv: *const *const u8) -> int {
     native::start(argc, argv, main)
}

fn main() {
    let glfw = glfw::init(glfw::FAIL_ON_ERRORS).unwrap();

    glfw.window_hint(glfw::ContextVersion(3, 2));
    glfw.window_hint(glfw::OpenglForwardCompat(true));
    glfw.window_hint(glfw::OpenglProfile(glfw::OpenGlCoreProfile));

    let (window, events) = glfw
        .create_window(640, 480, "Cube example", glfw::Windowed)
        .expect("Failed to create GLFW window.");

    window.make_current();
    glfw.set_error_callback(glfw::FAIL_ON_ERRORS);
    window.set_key_polling(true);

    let (w, h) = window.get_framebuffer_size();
    let frame = gfx::Frame::new(w as u16, h as u16);

    let mut device = gfx::GlDevice::new(|s| glfw.get_proc_address(s));
    let mut renderer = device.create_renderer();

    let state = gfx::DrawState::new().depth(gfx::state::LessEqual, true);

    let vertex_data = vec![
        // top (0, 0, 1)
        Vertex { pos: [-1, -1,  1], tex_coord: [0, 0] },
        Vertex { pos: [ 1, -1,  1], tex_coord: [1, 0] },
        Vertex { pos: [ 1,  1,  1], tex_coord: [1, 1] },
        Vertex { pos: [-1,  1,  1], tex_coord: [0, 1] },
        // bottom (0, 0, -1)
        Vertex { pos: [ 1,  1, -1], tex_coord: [0, 0] },
        Vertex { pos: [-1,  1, -1], tex_coord: [1, 0] },
        Vertex { pos: [-1, -1, -1], tex_coord: [1, 1] },
        Vertex { pos: [ 1, -1, -1], tex_coord: [0, 1] },
        // right (1, 0, 0)
        Vertex { pos: [ 1, -1, -1], tex_coord: [0, 0] },
        Vertex { pos: [ 1,  1, -1], tex_coord: [1, 0] },
        Vertex { pos: [ 1,  1,  1], tex_coord: [1, 1] },
        Vertex { pos: [ 1, -1,  1], tex_coord: [0, 1] },
        // left (-1, 0, 0)
        Vertex { pos: [-1,  1,  1], tex_coord: [0, 0] },
        Vertex { pos: [-1, -1,  1], tex_coord: [1, 0] },
        Vertex { pos: [-1, -1, -1], tex_coord: [1, 1] },
        Vertex { pos: [-1,  1, -1], tex_coord: [0, 1] },
        // front (0, 1, 0)
        Vertex { pos: [-1,  1, -1], tex_coord: [0, 0] },
        Vertex { pos: [ 1,  1, -1], tex_coord: [1, 0] },
        Vertex { pos: [ 1,  1,  1], tex_coord: [1, 1] },
        Vertex { pos: [-1,  1,  1], tex_coord: [0, 1] },
        // back (0, -1, 0)
        Vertex { pos: [ 1, -1,  1], tex_coord: [0, 0] },
        Vertex { pos: [-1, -1,  1], tex_coord: [1, 0] },
        Vertex { pos: [-1, -1, -1], tex_coord: [1, 1] },
        Vertex { pos: [ 1, -1, -1], tex_coord: [0, 1] },
    ];

    let mesh = device.create_mesh(vertex_data);

    let index_data: Vec<u8> = vec![
         0,  1,  2,  2,  3,  0, // top
         4,  5,  6,  6,  7,  4, // bottom
         8,  9, 10, 10, 11,  8, // right
        12, 13, 14, 14, 16, 12, // left
        16, 17, 18, 18, 19, 16, // front
        20, 21, 22, 22, 23, 20, // back
    ];

    let slice = {
        let buf = device.create_buffer_static(&index_data);
        gfx::IndexSlice8(gfx::TriangleList, buf, 0, 36)
    };

    let texture_info = gfx::tex::TextureInfo {
        width: 1,
        height: 1,
        depth: 1,
        levels: 1,
        kind: gfx::tex::Texture2D,
        format: gfx::tex::RGBA8,
    };
    let image_info = texture_info.to_image_info();
    let texture = device.create_texture(texture_info).unwrap();
    device.update_texture(&texture, &image_info,
                          &vec![0x20u8, 0xA0u8, 0xC0u8, 0x00u8])
        .unwrap();

    let sampler = device.create_sampler(
        gfx::tex::SamplerInfo::new(gfx::tex::Bilinear,
                                   gfx::tex::Clamp)
    );

    let prog: MyProgram = device
        .link_program(VERTEX_SRC.clone(), FRAGMENT_SRC.clone())
        .unwrap();

    let view: AffineMatrix3<f32> = Transform::look_at(
        &Point3::new(1.5f32, -5.0, 3.0),
        &Point3::new(0f32, 0.0, 0.0),
        &Vector3::unit_z(),
    );
    let aspect = w as f32 / h as f32;
    let proj = cgmath::perspective(cgmath::deg(45.0f32), aspect, 1.0, 10.0);

    let data = Params {
        transform: proj.mul_m(&view.mat).into_fixed(),
        color: (texture, Some(sampler)),
    };

    let clear_data = gfx::ClearData {
        color: Some([0.3, 0.3, 0.3, 1.0]),
        depth: Some(1.0),
        stencil: None,
    };

    while !window.should_close() {
        glfw.poll_events();
        for (_, event) in glfw::flush_messages(&events) {
            match event {
                glfw::KeyEvent(glfw::KeyEscape, _, glfw::Press, _) =>
                    window.set_should_close(true),
                _ => {},
            }
        }

        renderer.reset();
        renderer.clear(clear_data, &frame);
        renderer.draw(&mesh, slice, &frame, (&prog, &data), &state).unwrap();
        device.submit(renderer.as_buffer());

        window.swap_buffers();
    }
}
<|endoftext|>


<commit_before>// See LICENSE file for copyright and license details.

use std::cell::RefCell;
use time::precise_time_ns;
use glfw;
use cgmath::vector::{Vector2};
use core::types::{Size2, MInt, Point2};
use core::conf::Config;
use core::fs::FileSystem;
use visualizer::mgl;
use visualizer::types::{MatId, ColorId, Time};
use visualizer::shader::Shader;
use visualizer::font_stash::FontStash;
use visualizer::context::Context;
use visualizer::state_visualizer::{
    StateVisualizer,
    StartGame,
    EndGame,
    QuitMenu,
};
use visualizer::game_state_visualizer::GameStateVisualizer;
use visualizer::menu_state_visualizer::MenuStateVisualizer;

type EventsReceiver = Receiver<(f64, glfw::WindowEvent)>;

pub struct Visualizer {
    visualizers: Vec<Box<StateVisualizer>>, // TODO: Vec -> Queue
    dtime: Time,
    last_time: Time,
    glfw: glfw::Glfw,
    events: EventsReceiver,
    context: Context,
    fs: FileSystem,
}

fn create_win(glfw: &glfw::Glfw, win_size: Size2<MInt>)
    -> (glfw::Window, EventsReceiver)
{
    let w = win_size.w as u32;
    let h = win_size.h as u32;
    let title = "Marauder";
    let flags = glfw::Windowed;
    glfw.create_window(w, h, title, flags).unwrap()
}

impl Visualizer {
    pub fn new() -> Visualizer {
        let fs = FileSystem::new();
        let glfw = glfw::init(glfw::FAIL_ON_ERRORS).unwrap();
        let config = Config::new(&fs.get(&Path::new("data/conf_visualizer.json")));
        let win_size = config.get::<Size2<MInt>>("screen_size");
        let (win, events) = create_win(&glfw, win_size);
        glfw.make_context_current(Some(&win));
        mgl::load_gl_funcs_with(|procname| glfw.get_proc_address(procname));
        mgl::init_opengl();
        win.set_all_polling(true);
        let font_size = config.get("font_size");
        let font_stash = FontStash::new(
            &fs.get(&Path::new("data/DroidSerif-Regular.ttf")), font_size);
        let shader = Shader::new(
            &fs.get(&Path::new("data/normal.vs.glsl")),
            &fs.get(&Path::new("data/normal.fs.glsl")),
        );
        let mvp_mat_id = MatId{id: shader.get_uniform("mvp_mat")};
        let basic_color_id = ColorId{id: shader.get_uniform("basic_color")};
        let context = Context {
            win: win,
            win_size: win_size,
            config: config,
            mouse_pos: Point2{v: Vector2::zero()},
            font_stash: RefCell::new(font_stash),
            shader: shader,
            mvp_mat_id: mvp_mat_id,
            basic_color_id: basic_color_id,
        };
        let visualizer = box MenuStateVisualizer::new(&context);
        Visualizer {
            visualizers: vec![visualizer as Box<StateVisualizer>],
            dtime: Time{n: 0},
            last_time: Time{n: precise_time_ns()},
            glfw: glfw,
            events: events,
            context: context,
            fs: fs,
        }
    }

    fn get_events(&mut self) -> Vec<glfw::WindowEvent> {
        self.glfw.poll_events();
        let mut events = Vec::new();
        for (_, event) in glfw::flush_messages(&self.events) {
            events.push(event);
        }
        events
    }

    pub fn is_running(&self) -> bool {
        !self.context.win.should_close() // TODO: check State
    }

    // TODO: simplify
    pub fn tick(&mut self) {
        {
            let events = self.get_events();
            let visualizer = self.visualizers.mut_last().unwrap(); // TODO: remove unwrap
            for event in events.iter() {
                visualizer.handle_event(&self.context, *event);
                self.context.handle_event(*event);
            }
            visualizer.logic();
            visualizer.draw(&self.context, self.dtime);
        }
        let cmd = self.visualizers.mut_last().unwrap().get_command(); // TODO: remove unwrap
        match cmd {
            Some(StartGame) => {
                let visualizer = box GameStateVisualizer::new(
                    &self.fs, &self.context);
                self.visualizers.push(visualizer as Box<StateVisualizer>);
            }
            Some(EndGame) => {
                self.visualizers.pop();
            },
            Some(QuitMenu) => {
                self.context.win.set_should_close(true);
            },
            None => {},
        }
        self.update_time();
    }

    pub fn update_time(&mut self) {
        let time = precise_time_ns();
        self.dtime.n = time - self.last_time.n;
        self.last_time.n = time;
    }
}

// vim: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab:
<commit_msg>Visualizer: Added 'should_close: bool' field<commit_after>// See LICENSE file for copyright and license details.

use std::cell::RefCell;
use time::precise_time_ns;
use glfw;
use cgmath::vector::{Vector2};
use core::types::{Size2, MInt, Point2};
use core::conf::Config;
use core::fs::FileSystem;
use visualizer::mgl;
use visualizer::types::{MatId, ColorId, Time};
use visualizer::shader::Shader;
use visualizer::font_stash::FontStash;
use visualizer::context::Context;
use visualizer::state_visualizer::{
    StateVisualizer,
    StartGame,
    EndGame,
    QuitMenu,
};
use visualizer::game_state_visualizer::GameStateVisualizer;
use visualizer::menu_state_visualizer::MenuStateVisualizer;

type EventsReceiver = Receiver<(f64, glfw::WindowEvent)>;

pub struct Visualizer {
    visualizers: Vec<Box<StateVisualizer>>, // TODO: Vec -> Queue
    dtime: Time,
    last_time: Time,
    glfw: glfw::Glfw,
    events: EventsReceiver,
    context: Context,
    fs: FileSystem,
    should_close: bool,
}

fn create_win(glfw: &glfw::Glfw, win_size: Size2<MInt>)
    -> (glfw::Window, EventsReceiver)
{
    let w = win_size.w as u32;
    let h = win_size.h as u32;
    let title = "Marauder";
    let flags = glfw::Windowed;
    glfw.create_window(w, h, title, flags).unwrap()
}

impl Visualizer {
    pub fn new() -> Visualizer {
        let fs = FileSystem::new();
        let glfw = glfw::init(glfw::FAIL_ON_ERRORS).unwrap();
        let config = Config::new(&fs.get(&Path::new("data/conf_visualizer.json")));
        let win_size = config.get::<Size2<MInt>>("screen_size");
        let (win, events) = create_win(&glfw, win_size);
        glfw.make_context_current(Some(&win));
        mgl::load_gl_funcs_with(|procname| glfw.get_proc_address(procname));
        mgl::init_opengl();
        win.set_all_polling(true);
        let font_size = config.get("font_size");
        let font_stash = FontStash::new(
            &fs.get(&Path::new("data/DroidSerif-Regular.ttf")), font_size);
        let shader = Shader::new(
            &fs.get(&Path::new("data/normal.vs.glsl")),
            &fs.get(&Path::new("data/normal.fs.glsl")),
        );
        let mvp_mat_id = MatId{id: shader.get_uniform("mvp_mat")};
        let basic_color_id = ColorId{id: shader.get_uniform("basic_color")};
        let context = Context {
            win: win,
            win_size: win_size,
            config: config,
            mouse_pos: Point2{v: Vector2::zero()},
            font_stash: RefCell::new(font_stash),
            shader: shader,
            mvp_mat_id: mvp_mat_id,
            basic_color_id: basic_color_id,
        };
        let visualizer = box MenuStateVisualizer::new(&context);
        Visualizer {
            visualizers: vec![visualizer as Box<StateVisualizer>],
            dtime: Time{n: 0},
            last_time: Time{n: precise_time_ns()},
            glfw: glfw,
            events: events,
            context: context,
            fs: fs,
            should_close: false,
        }
    }

    fn get_events(&mut self) -> Vec<glfw::WindowEvent> {
        self.glfw.poll_events();
        let mut events = Vec::new();
        for (_, event) in glfw::flush_messages(&self.events) {
            events.push(event);
        }
        events
    }

    pub fn is_running(&self) -> bool {
        !self.should_close
    }

    // TODO: simplify
    pub fn tick(&mut self) {
        {
            let events = self.get_events();
            let visualizer = self.visualizers.mut_last().unwrap(); // TODO: remove unwrap
            for event in events.iter() {
                visualizer.handle_event(&self.context, *event);
                self.context.handle_event(*event);
            }
            visualizer.logic();
            visualizer.draw(&self.context, self.dtime);
        }
        let cmd = self.visualizers.mut_last().unwrap().get_command(); // TODO: remove unwrap
        match cmd {
            Some(StartGame) => {
                let visualizer = box GameStateVisualizer::new(
                    &self.fs, &self.context);
                self.visualizers.push(visualizer as Box<StateVisualizer>);
            }
            Some(EndGame) => {
                self.visualizers.pop();
            },
            Some(QuitMenu) => {
                self.should_close = true;
            },
            None => {},
        }
        self.update_time();
    }

    pub fn update_time(&mut self) {
        let time = precise_time_ns();
        self.dtime.n = time - self.last_time.n;
        self.last_time.n = time;
    }
}

// vim: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab:
<|endoftext|>


<commit_before>#![no_std]

#![allow(improper_ctypes)]

#![feature(asm)]

extern crate core;

use core::iter::Iterator;
use core::str::StrExt;
use core::option::Option;

use core::marker::Copy;

impl Copy for Color {}

#[allow(dead_code)]
enum Color {
    Black      = 0,
    Blue       = 1,
    Green      = 2,
    Cyan       = 3,
    Red        = 4,
    Pink       = 5,
    Brown      = 6,
    LightGray  = 7,
    DarkGray   = 8,
    LightBlue  = 9,
    LightGreen = 10,
    LightCyan  = 11,
    LightRed   = 12,
    LightPink  = 13,
    Yellow     = 14,
    White      = 15,
}

struct IntRange {
    cur: isize,
    max: isize
}

impl IntRange {
    fn next(&mut self) -> Option<isize> {
        if self.cur < self.max {
            self.cur += 1;
            Option::Some(self.cur - 1)
        } else {
            Option::None
        }
    }
}

fn range(lo: isize, hi: isize) -> IntRange {
    IntRange { cur: lo, max: hi }
}

fn clear_screen(background: Color) {
    let mut r = range(0, 80 * 25);
    loop {
        match r.next() {
            Option::Some(x) => {
                unsafe {
                    *((0xb8000 + x * 2) as *mut u16) = (background as u16) << 12;
                }
            },
            Option::None =>{break}
        }
    }
}

fn print_string(string: &str) {
    let mut bytes = string.bytes();
    let mut count = 0;
    loop {
        match bytes.next() {
            Option::Some(x) => {
                unsafe {
                    *((0xb8000 + count) as *mut u8) = x;
                    *((0xb8000 + count + 1) as *mut u8) = 0x0f;
                }
                count = count + 2;
            },
            Option::None =>{break}
        }
    }
    move_cursor(0,string.len() as u8);
}

fn move_cursor(row: u8, col: u8) {
    let pos:u16 = (row*80 + col) as u16;
    outb(0x3D4,15);
    outb(0x3D5,(pos & 0xff) as u8);
    outb(0x3D4,14);
    outb(0x3D5,((pos >> 8) & 0xff) as u8);
}

fn outb(port:u16, value:u8) {
    unsafe {
        asm!(
        "out $0,$1"
        :
        : "{ax}"(value), "{dx}"(port)
        )
    }
}

struct IDTEntry {
    offset_lo: u16,
    selector: u16,
    zero: u8,
    type_attr: u8,
    offset_hi: u16
}

impl Copy for IDTEntry {}

struct IDT {
    entries: [IDTEntry; 256]
}

// Must be packed for lidt to read it correctly.
#[repr(packed)]
struct IDTR {
    length: u16,
    base: u32
}

static mut idt : IDT = IDT {entries: [IDTEntry {offset_lo: 0, selector: 0, zero: 0, type_attr: 0, offset_hi: 0};256]};

fn lidt() {
    unsafe {
        let idt_addr:*mut IDT = &mut idt;
        let mut idtr = IDTR {length: 256*8-1, base: idt_addr as u32};
        let idtr_addr:*mut IDTR = &mut idtr;
        asm!("lidt ($0)"::"{eax}"(idtr_addr as u32));
        //asm!("hlt");
    }
}

extern {
    fn asm_int_handler();
}

fn init_int_49() {
    unsafe {
        let fnptr:unsafe extern fn() = asm_int_handler;
        let fnptr_addr = fnptr as u32;
        idt.entries[49] = IDTEntry {
            offset_lo: fnptr_addr as u16,
            selector: 0x08,
            zero: 0,
            type_attr: 0x8e,
            offset_hi: (fnptr_addr >> 16) as u16
        };
        asm!("lidt ($0)"::"{eax}"(&idt.entries[49]));
        //asm!("hlt");
    }
}

extern {
    fn asm_int_49();
}

fn int_49() {
    unsafe {
        asm_int_49();
    }
}

#[no_mangle]
#[no_stack_check]
pub fn main() {
    clear_screen(Color::LightRed);
    print_string("Hello world");
    init_int_49();
    lidt();
    int_49();
    print_string("End world");
}

#[no_mangle]
pub extern fn int_handler() {
    clear_screen(Color::Blue);
}

<commit_msg>Working keyboard interrupt<commit_after>#![no_std]

#![allow(improper_ctypes)]

#![feature(asm)]

extern crate core;

use core::iter::Iterator;
use core::str::StrExt;
use core::option::Option;

use core::marker::Copy;

impl Copy for Color {}

#[allow(dead_code)]
enum Color {
    Black      = 0,
    Blue       = 1,
    Green      = 2,
    Cyan       = 3,
    Red        = 4,
    Pink       = 5,
    Brown      = 6,
    LightGray  = 7,
    DarkGray   = 8,
    LightBlue  = 9,
    LightGreen = 10,
    LightCyan  = 11,
    LightRed   = 12,
    LightPink  = 13,
    Yellow     = 14,
    White      = 15,
}

struct IntRange {
    cur: isize,
    max: isize
}

impl IntRange {
    fn next(&mut self) -> Option<isize> {
        if self.cur < self.max {
            self.cur += 1;
            Option::Some(self.cur - 1)
        } else {
            Option::None
        }
    }
}

fn range(lo: isize, hi: isize) -> IntRange {
    IntRange { cur: lo, max: hi }
}

fn clear_screen(background: Color) {
    let mut r = range(0, 80 * 25);
    loop {
        match r.next() {
            Option::Some(x) => {
                unsafe {
                    *((0xb8000 + x * 2) as *mut u16) = (background as u16) << 12;
                }
            },
            Option::None =>{break}
        }
    }
}

fn print_string(string: &str) {
    let mut bytes = string.bytes();
    let mut count = 0;
    loop {
        match bytes.next() {
            Option::Some(x) => {
                unsafe {
                    *((0xb8000 + count) as *mut u8) = x;
                    *((0xb8000 + count + 1) as *mut u8) = 0x0f;
                }
                count = count + 2;
            },
            Option::None =>{break}
        }
    }
    move_cursor(0,string.len() as u8);
}

fn move_cursor(row: u8, col: u8) {
    let pos:u16 = (row*80 + col) as u16;
    outb(0x3D4,15);
    outb(0x3D5,(pos & 0xff) as u8);
    outb(0x3D4,14);
    outb(0x3D5,((pos >> 8) & 0xff) as u8);
}

fn outb(port:u16, value:u8) {
    unsafe {
        asm!(
        "out $0,$1"
        :
        : "{ax}"(value), "{dx}"(port)
        )
    }
}

struct IDTEntry {
    offset_lo: u16,
    selector: u16,
    zero: u8,
    type_attr: u8,
    offset_hi: u16
}

impl Copy for IDTEntry {}

struct IDT {
    entries: [IDTEntry; 256]
}

// Must be packed for lidt to read it correctly.
#[repr(packed)]
struct IDTR {
    length: u16,
    base: u32
}

static mut idt : IDT = IDT {entries: [IDTEntry {offset_lo: 0, selector: 0, zero: 0, type_attr: 0, offset_hi: 0};256]};

fn lidt() {
    unsafe {
        let idt_addr:*mut IDT = &mut idt;
        let mut idtr = IDTR {length: 256*8-1, base: idt_addr as u32};
        let idtr_addr:*mut IDTR = &mut idtr;
        asm!("lidt ($0)"::"{eax}"(idtr_addr as u32));
        //asm!("hlt");
    }
}

extern {
    fn asm_int_handler();
}

fn init_interrupt_handlers() {
    unsafe {
        let fnptr:unsafe extern fn() = asm_int_handler;
        let fnptr_addr = fnptr as u32;
        idt.entries[0x21] = IDTEntry {
            offset_lo: fnptr_addr as u16,
            selector: 0x08,
            zero: 0,
            type_attr: 0x8e,
            offset_hi: (fnptr_addr >> 16) as u16
        };
        lidt();
        asm!("sti");
    }
}

extern {
    fn asm_int_49();
}

fn int_49() {
    unsafe {
        asm_int_49();
    }
}

fn init_pic() {
	outb(0x20 , 0x11);
	outb(0xA0 , 0x11);

    // Remap interrupts
	outb(0x21 , 0x20);
	outb(0xA1 , 0x28);

	outb(0x21 , 0x00);
	outb(0xA1 , 0x00);

	outb(0x21 , 0x01);
	outb(0xA1 , 0x01);

	// Disable all interrupts
	outb(0x21 , 0xff);
	outb(0xA1 , 0xff);
}

fn enable_keyboard_interrupt() {
    outb(0x21 , 0b11111101);
}

#[no_mangle]
#[no_stack_check]
pub fn main() {
    clear_screen(Color::LightRed);
    print_string("Hello world");
    init_pic();
    enable_keyboard_interrupt();
    init_interrupt_handlers();
    //int_49();
    print_string("End world");
}

#[no_mangle]
pub extern fn int_handler() {
    clear_screen(Color::Blue);
}

<|endoftext|>


<commit_before>#![feature(phase)]

#[phase(plugin, link)]
extern crate log;
extern crate rsfml;

use rsfml::window::{ContextSettings, VideoMode, event, DefaultStyle};
use rsfml::graphics::RenderWindow;
use rsfml::window::keyboard;

use std::os::args;
use std::rt;

mod cpu;

#[cfg(target_os="macos")]
#[start]
fn start(argc: int, argv: *const *const u8) -> int {
    rt::start(argc, argv, main)
}

fn main() {
    let arg_list = args();
    if arg_list.len() <= 1 {
        panic!("You must pass in a ROM for rustchip to read.");
    }

    // Create the window of the application
    let setting = ContextSettings::default();
    let mut window = match RenderWindow::new(VideoMode::new_init(640, 320, 32), "rustchip", DefaultStyle, &setting) {
        Some(window) => window,
        None => panic!("Cannot create a new Render Window.")
    };
    window.set_framerate_limit(60);
	let mut c8 = cpu::Cpu::new();

	c8.load(&arg_list[1]);

    while window.is_open() {
        loop {
            match window.poll_event() {
                event::Closed => { window.close()}
                event::NoEvent => { break }
                event::KeyPressed{code, alt, ..} => {
                    if code == keyboard::Key::R && alt {
                        c8 = cpu::Cpu::new();
                        c8.load(&arg_list[1]);
                    }
                    if c8.is_waiting() {
                        let val = match code {
                            keyboard::Key::Num1 => 1,
                            keyboard::Key::Num2 => 2,
                            keyboard::Key::Num3 => 3,
                            keyboard::Key::Num4 => 0xC,
                            keyboard::Key::Q => 4,
                            keyboard::Key::W => 5,
                            keyboard::Key::E => 6,
                            keyboard::Key::R => 0xD,
                            keyboard::Key::A => 7,
                            keyboard::Key::S => 8,
                            keyboard::Key::D => 9,
                            keyboard::Key::F => 0xE,
                            keyboard::Key::Z => 0xA,
                            keyboard::Key::X => 0,
                            keyboard::Key::C => 0xB,
                            keyboard::Key::V => 0xF,
                            _ => -1
                        };
                        if val != -1 {
                            c8.set_wait_register(val);
                        }
                    }
                }
                _ => {}
            }
        }

        if !c8.is_waiting() {
    		c8.run_cycle();
            c8.draw(&mut window);
            c8.update_keys();
        }
    }

}<commit_msg>Remove phase and replace with macro_use<commit_after>#[macro_use]
extern crate log;
extern crate rsfml;

use rsfml::window::{ContextSettings, VideoMode, event, DefaultStyle};
use rsfml::graphics::RenderWindow;
use rsfml::window::keyboard;

use std::os::args;
use std::rt;

mod cpu;

#[cfg(target_os="macos")]
#[start]
fn start(argc: int, argv: *const *const u8) -> int {
    rt::start(argc, argv, main)
}

fn main() {
    let arg_list = args();
    if arg_list.len() <= 1 {
        panic!("You must pass in a ROM for rustchip to read.");
    }

    // Create the window of the application
    let setting = ContextSettings::default();
    let mut window = match RenderWindow::new(VideoMode::new_init(640, 320, 32), "rustchip", DefaultStyle, &setting) {
        Some(window) => window,
        None => panic!("Cannot create a new Render Window.")
    };
    window.set_framerate_limit(60);
	let mut c8 = cpu::Cpu::new();

	c8.load(&arg_list[1]);

    while window.is_open() {
        loop {
            match window.poll_event() {
                event::Closed => { window.close()}
                event::NoEvent => { break }
                event::KeyPressed{code, alt, ..} => {
                    if code == keyboard::Key::R && alt {
                        c8 = cpu::Cpu::new();
                        c8.load(&arg_list[1]);
                    }
                    if c8.is_waiting() {
                        let val = match code {
                            keyboard::Key::Num1 => 1,
                            keyboard::Key::Num2 => 2,
                            keyboard::Key::Num3 => 3,
                            keyboard::Key::Num4 => 0xC,
                            keyboard::Key::Q => 4,
                            keyboard::Key::W => 5,
                            keyboard::Key::E => 6,
                            keyboard::Key::R => 0xD,
                            keyboard::Key::A => 7,
                            keyboard::Key::S => 8,
                            keyboard::Key::D => 9,
                            keyboard::Key::F => 0xE,
                            keyboard::Key::Z => 0xA,
                            keyboard::Key::X => 0,
                            keyboard::Key::C => 0xB,
                            keyboard::Key::V => 0xF,
                            _ => -1
                        };
                        if val != -1 {
                            c8.set_wait_register(val);
                        }
                    }
                }
                _ => {}
            }
        }

        if !c8.is_waiting() {
    		c8.run_cycle();
            c8.draw(&mut window);
            c8.update_keys();
        }
    }

}<|endoftext|>


<commit_before>//! Implementation of a simple uTP client and server.
#![feature(macro_rules)]

extern crate utp;
use std::io::net::ip::{Ipv4Addr, SocketAddr};

macro_rules! iotry(
    ($e:expr) => (match $e { Ok(v) => v, Err(e) => fail!("{}", e), })
)

fn usage() {
    println!("Usage: utp [-s|-c] <address> <port>");
}

fn main() {
    use utp::UtpStream;
    use std::from_str::FromStr;
    use std::io::{stdin, stdout, stderr};

    // Defaults
    let mut addr = SocketAddr { ip: Ipv4Addr(127,0,0,1), port: 8080 };

    let args = std::os::args();

    if args.len() != 2 && args.len() != 4 {
        usage();
        return;
    }

    if args.len() == 4 {
        addr = SocketAddr {
            ip:   FromStr::from_str(args[2].as_slice()).unwrap(),
            port: FromStr::from_str(args[3].as_slice()).unwrap(),
        };
    }

    match args[1].as_slice() {
        "-s" => {
            let mut stream = UtpStream::bind(addr);
            let mut writer = stdout();
            let _ = writeln!(stderr(), "Serving on {}", addr);

            let payload = iotry!(stream.read_to_end());
            iotry!(writer.write(payload.as_slice()));
        }
        "-c" => {
            let mut stream = UtpStream::connect(addr);
            let mut reader = stdin();

            let payload = iotry!(reader.read_to_end());
            iotry!(stream.write(payload.as_slice()));
            iotry!(stream.close());
            drop(stream);
        }
        _ => usage(),
    }
}
<commit_msg>Print reasoning behind IP and port parse failures.<commit_after>//! Implementation of a simple uTP client and server.
#![feature(macro_rules)]

extern crate utp;
use std::io::net::ip::{Ipv4Addr, SocketAddr};

macro_rules! iotry(
    ($e:expr) => (match $e { Ok(v) => v, Err(e) => fail!("{}", e), })
)

fn usage() {
    println!("Usage: utp [-s|-c] <address> <port>");
}

fn main() {
    use utp::UtpStream;
    use std::from_str::FromStr;
    use std::io::{stdin, stdout, stderr};

    // Defaults
    let mut addr = SocketAddr { ip: Ipv4Addr(127,0,0,1), port: 8080 };

    let args = std::os::args();

    if args.len() != 2 && args.len() != 4 {
        usage();
        return;
    }

    if args.len() == 4 {
        addr = SocketAddr {
            ip:   FromStr::from_str(args[2].as_slice()).expect("Invalid address"),
            port: FromStr::from_str(args[3].as_slice()).expect("Invalid port"),
        };
    }

    match args[1].as_slice() {
        "-s" => {
            let mut stream = UtpStream::bind(addr);
            let mut writer = stdout();
            let _ = writeln!(stderr(), "Serving on {}", addr);

            let payload = iotry!(stream.read_to_end());
            iotry!(writer.write(payload.as_slice()));
        }
        "-c" => {
            let mut stream = UtpStream::connect(addr);
            let mut reader = stdin();

            let payload = iotry!(reader.read_to_end());
            iotry!(stream.write(payload.as_slice()));
            iotry!(stream.close());
            drop(stream);
        }
        _ => usage(),
    }
}
<|endoftext|>


<commit_before>use std::{
    fs,
    collections::HashMap,
    path::{Path, PathBuf},
    process::{Command, Output, Stdio},
    io::{Error, ErrorKind}
};

use failure::bail;
use itertools::Itertools;

pub use teraron::{Mode, Overwrite, Verify};

pub type Result<T> = std::result::Result<T, failure::Error>;

pub const GRAMMAR: &str = "crates/ra_syntax/src/grammar.ron";
const GRAMMAR_DIR: &str = "crates/ra_parser/src/grammar";
const OK_INLINE_TESTS_DIR: &str = "crates/ra_syntax/tests/data/parser/inline/ok";
const ERR_INLINE_TESTS_DIR: &str = "crates/ra_syntax/tests/data/parser/inline/err";

pub const SYNTAX_KINDS: &str = "crates/ra_parser/src/syntax_kind/generated.rs.tera";
pub const AST: &str = "crates/ra_syntax/src/ast/generated.rs.tera";
const TOOLCHAIN: &str = "stable";

#[derive(Debug)]
pub struct Test {
    pub name: String,
    pub text: String,
    pub ok: bool,
}

pub fn collect_tests(s: &str) -> Vec<(usize, Test)> {
    let mut res = vec![];
    let prefix = "// ";
    let comment_blocks = s
        .lines()
        .map(str::trim_start)
        .enumerate()
        .group_by(|(_idx, line)| line.starts_with(prefix));

    'outer: for (is_comment, block) in comment_blocks.into_iter() {
        if !is_comment {
            continue;
        }
        let mut block = block.map(|(idx, line)| (idx, &line[prefix.len()..]));

        let mut ok = true;
        let (start_line, name) = loop {
            match block.next() {
                Some((idx, line)) if line.starts_with("test ") => {
                    break (idx, line["test ".len()..].to_string());
                }
                Some((idx, line)) if line.starts_with("test_err ") => {
                    ok = false;
                    break (idx, line["test_err ".len()..].to_string());
                }
                Some(_) => (),
                None => continue 'outer,
            }
        };
        let text: String =
            itertools::join(block.map(|(_, line)| line).chain(::std::iter::once("")), "\n");
        assert!(!text.trim().is_empty() && text.ends_with('\n'));
        res.push((start_line, Test { name, text, ok }))
    }
    res
}

pub fn generate(mode: Mode) -> Result<()> {
    let grammar = project_root().join(GRAMMAR);
    let syntax_kinds = project_root().join(SYNTAX_KINDS);
    let ast = project_root().join(AST);
    teraron::generate(&syntax_kinds, &grammar, mode)?;
    teraron::generate(&ast, &grammar, mode)?;
    Ok(())
}

pub fn project_root() -> PathBuf {
    Path::new(&env!("CARGO_MANIFEST_DIR")).ancestors().nth(2).unwrap().to_path_buf()
}

pub fn run(cmdline: &str, dir: &str) -> Result<()> {
    do_run(cmdline, dir, |c| {
        c.stdout(Stdio::inherit());
    })
    .map(|_| ())
}

pub fn run_with_output(cmdline: &str, dir: &str) -> Result<Output> {
    do_run(cmdline, dir, |_| {})
}

pub fn run_rustfmt(mode: Mode) -> Result<()> {
    match Command::new("rustup")
        .args(&["run", TOOLCHAIN, "--", "cargo", "fmt", "--version"])
        .stderr(Stdio::null())
        .stdout(Stdio::null())
        .status()
    {
        Ok(status) if status.success() => (),
        _ => install_rustfmt()?,
    };

    if mode == Verify {
        run(&format!("rustup run {} -- cargo fmt -- --check", TOOLCHAIN), ".")?;
    } else {
        run(&format!("rustup run {} -- cargo fmt", TOOLCHAIN), ".")?;
    }
    Ok(())
}

pub fn install_rustfmt() -> Result<()> {
    run(&format!("rustup install {}", TOOLCHAIN), ".")?;
    run(&format!("rustup component add rustfmt --toolchain {}", TOOLCHAIN), ".")
}

pub fn install_format_hook() -> Result<()> {
    let result_path = Path::new(if cfg!(windows) {
        "./.git/hooks/pre-commit.exe"
    } else {
        "./.git/hooks/pre-commit"
    });
    if !result_path.exists() {
        run("cargo build --package tools --bin pre-commit", ".")?;
        if cfg!(windows) {
            fs::copy("./target/debug/pre-commit.exe", result_path)?;
        } else {
            fs::copy("./target/debug/pre-commit", result_path)?;
        }
    } else {
        return Err(Error::new(ErrorKind::AlreadyExists, "Git hook already created").into());
    }
    Ok(())
}

pub fn run_clippy() -> Result<()> {
    match Command::new("rustup")
        .args(&["run", TOOLCHAIN, "--", "cargo", "clippy", "--version"])
        .stderr(Stdio::null())
        .stdout(Stdio::null())
        .status()
    {
        Ok(status) if status.success() => (),
        _ => install_clippy()?,
    };

    let allowed_lints =
        ["clippy::collapsible_if", "clippy::nonminimal_bool", "clippy::needless_pass_by_value"];
    run(
        &format!(
            "rustup run {} -- cargo clippy --all-features --all-targets -- -A {}",
            TOOLCHAIN,
            allowed_lints.join(" -A ")
        ),
        ".",
    )?;
    Ok(())
}

pub fn install_clippy() -> Result<()> {
    run(&format!("rustup install {}", TOOLCHAIN), ".")?;
    run(&format!("rustup component add clippy --toolchain {}", TOOLCHAIN), ".")
}

pub fn run_fuzzer() -> Result<()> {
    match Command::new("cargo")
        .args(&["fuzz", "--help"])
        .stderr(Stdio::null())
        .stdout(Stdio::null())
        .status()
    {
        Ok(status) if status.success() => (),
        _ => run("cargo install cargo-fuzz", ".")?,
    };

    run("rustup run nightly -- cargo fuzz run parser", "./crates/ra_syntax")
}

pub fn gen_tests(mode: Mode) -> Result<()> {
    let tests = tests_from_dir(&project_root().join(Path::new(GRAMMAR_DIR)))?;
    fn install_tests(tests: &HashMap<String, Test>, into: &str, mode: Mode) -> Result<()> {
        let tests_dir = project_root().join(into);
        if !tests_dir.is_dir() {
            fs::create_dir_all(&tests_dir)?;
        }
        // ok is never actually read, but it needs to be specified to create a Test in existing_tests
        let existing = existing_tests(&tests_dir, true)?;
        for t in existing.keys().filter(|&t| !tests.contains_key(t)) {
            panic!("Test is deleted: {}", t);
        }

        let mut new_idx = existing.len() + 1;
        for (name, test) in tests {
            let path = match existing.get(name) {
                Some((path, _test)) => path.clone(),
                None => {
                    let file_name = format!("{:04}_{}.rs", new_idx, name);
                    new_idx += 1;
                    tests_dir.join(file_name)
                }
            };
            teraron::update(&path, &test.text, mode)?;
        }
        Ok(())
    }
    install_tests(&tests.ok, OK_INLINE_TESTS_DIR, mode)?;
    install_tests(&tests.err, ERR_INLINE_TESTS_DIR, mode)
}

fn do_run<F>(cmdline: &str, dir: &str, mut f: F) -> Result<Output>
where
    F: FnMut(&mut Command),
{
    eprintln!("\nwill run: {}", cmdline);
    let proj_dir = project_root().join(dir);
    let mut args = cmdline.split_whitespace();
    let exec = args.next().unwrap();
    let mut cmd = Command::new(exec);
    f(cmd.args(args).current_dir(proj_dir).stderr(Stdio::inherit()));
    let output = cmd.output()?;
    if !output.status.success() {
        bail!("`{}` exited with {}", cmdline, output.status);
    }
    Ok(output)
}

#[derive(Default, Debug)]
struct Tests {
    pub ok: HashMap<String, Test>,
    pub err: HashMap<String, Test>,
}

fn tests_from_dir(dir: &Path) -> Result<Tests> {
    let mut res = Tests::default();
    for entry in ::walkdir::WalkDir::new(dir) {
        let entry = entry.unwrap();
        if !entry.file_type().is_file() {
            continue;
        }
        if entry.path().extension().unwrap_or_default() != "rs" {
            continue;
        }
        process_file(&mut res, entry.path())?;
    }
    let grammar_rs = dir.parent().unwrap().join("grammar.rs");
    process_file(&mut res, &grammar_rs)?;
    return Ok(res);
    fn process_file(res: &mut Tests, path: &Path) -> Result<()> {
        let text = fs::read_to_string(path)?;

        for (_, test) in collect_tests(&text) {
            if test.ok {
                if let Some(old_test) = res.ok.insert(test.name.clone(), test) {
                    bail!("Duplicate test: {}", old_test.name)
                }
            } else {
                if let Some(old_test) = res.err.insert(test.name.clone(), test) {
                    bail!("Duplicate test: {}", old_test.name)
                }
            }
        }
        Ok(())
    }
}

fn existing_tests(dir: &Path, ok: bool) -> Result<HashMap<String, (PathBuf, Test)>> {
    let mut res = HashMap::new();
    for file in fs::read_dir(dir)? {
        let file = file?;
        let path = file.path();
        if path.extension().unwrap_or_default() != "rs" {
            continue;
        }
        let name = {
            let file_name = path.file_name().unwrap().to_str().unwrap();
            file_name[5..file_name.len() - 3].to_string()
        };
        let text = fs::read_to_string(&path)?;
        let test = Test { name: name.clone(), text, ok };
        if let Some(old) = res.insert(name, (path, test)) {
            println!("Duplicate test: {:?}", old);
        }
    }
    Ok(res)
}
<commit_msg>Allow clippy::map_clone<commit_after>use std::{
    fs,
    collections::HashMap,
    path::{Path, PathBuf},
    process::{Command, Output, Stdio},
    io::{Error, ErrorKind}
};

use failure::bail;
use itertools::Itertools;

pub use teraron::{Mode, Overwrite, Verify};

pub type Result<T> = std::result::Result<T, failure::Error>;

pub const GRAMMAR: &str = "crates/ra_syntax/src/grammar.ron";
const GRAMMAR_DIR: &str = "crates/ra_parser/src/grammar";
const OK_INLINE_TESTS_DIR: &str = "crates/ra_syntax/tests/data/parser/inline/ok";
const ERR_INLINE_TESTS_DIR: &str = "crates/ra_syntax/tests/data/parser/inline/err";

pub const SYNTAX_KINDS: &str = "crates/ra_parser/src/syntax_kind/generated.rs.tera";
pub const AST: &str = "crates/ra_syntax/src/ast/generated.rs.tera";
const TOOLCHAIN: &str = "stable";

#[derive(Debug)]
pub struct Test {
    pub name: String,
    pub text: String,
    pub ok: bool,
}

pub fn collect_tests(s: &str) -> Vec<(usize, Test)> {
    let mut res = vec![];
    let prefix = "// ";
    let comment_blocks = s
        .lines()
        .map(str::trim_start)
        .enumerate()
        .group_by(|(_idx, line)| line.starts_with(prefix));

    'outer: for (is_comment, block) in comment_blocks.into_iter() {
        if !is_comment {
            continue;
        }
        let mut block = block.map(|(idx, line)| (idx, &line[prefix.len()..]));

        let mut ok = true;
        let (start_line, name) = loop {
            match block.next() {
                Some((idx, line)) if line.starts_with("test ") => {
                    break (idx, line["test ".len()..].to_string());
                }
                Some((idx, line)) if line.starts_with("test_err ") => {
                    ok = false;
                    break (idx, line["test_err ".len()..].to_string());
                }
                Some(_) => (),
                None => continue 'outer,
            }
        };
        let text: String =
            itertools::join(block.map(|(_, line)| line).chain(::std::iter::once("")), "\n");
        assert!(!text.trim().is_empty() && text.ends_with('\n'));
        res.push((start_line, Test { name, text, ok }))
    }
    res
}

pub fn generate(mode: Mode) -> Result<()> {
    let grammar = project_root().join(GRAMMAR);
    let syntax_kinds = project_root().join(SYNTAX_KINDS);
    let ast = project_root().join(AST);
    teraron::generate(&syntax_kinds, &grammar, mode)?;
    teraron::generate(&ast, &grammar, mode)?;
    Ok(())
}

pub fn project_root() -> PathBuf {
    Path::new(&env!("CARGO_MANIFEST_DIR")).ancestors().nth(2).unwrap().to_path_buf()
}

pub fn run(cmdline: &str, dir: &str) -> Result<()> {
    do_run(cmdline, dir, |c| {
        c.stdout(Stdio::inherit());
    })
    .map(|_| ())
}

pub fn run_with_output(cmdline: &str, dir: &str) -> Result<Output> {
    do_run(cmdline, dir, |_| {})
}

pub fn run_rustfmt(mode: Mode) -> Result<()> {
    match Command::new("rustup")
        .args(&["run", TOOLCHAIN, "--", "cargo", "fmt", "--version"])
        .stderr(Stdio::null())
        .stdout(Stdio::null())
        .status()
    {
        Ok(status) if status.success() => (),
        _ => install_rustfmt()?,
    };

    if mode == Verify {
        run(&format!("rustup run {} -- cargo fmt -- --check", TOOLCHAIN), ".")?;
    } else {
        run(&format!("rustup run {} -- cargo fmt", TOOLCHAIN), ".")?;
    }
    Ok(())
}

pub fn install_rustfmt() -> Result<()> {
    run(&format!("rustup install {}", TOOLCHAIN), ".")?;
    run(&format!("rustup component add rustfmt --toolchain {}", TOOLCHAIN), ".")
}

pub fn install_format_hook() -> Result<()> {
    let result_path = Path::new(if cfg!(windows) {
        "./.git/hooks/pre-commit.exe"
    } else {
        "./.git/hooks/pre-commit"
    });
    if !result_path.exists() {
        run("cargo build --package tools --bin pre-commit", ".")?;
        if cfg!(windows) {
            fs::copy("./target/debug/pre-commit.exe", result_path)?;
        } else {
            fs::copy("./target/debug/pre-commit", result_path)?;
        }
    } else {
        return Err(Error::new(ErrorKind::AlreadyExists, "Git hook already created").into());
    }
    Ok(())
}

pub fn run_clippy() -> Result<()> {
    match Command::new("rustup")
        .args(&["run", TOOLCHAIN, "--", "cargo", "clippy", "--version"])
        .stderr(Stdio::null())
        .stdout(Stdio::null())
        .status()
    {
        Ok(status) if status.success() => (),
        _ => install_clippy()?,
    };

    let allowed_lints = [
        "clippy::collapsible_if",
        "clippy::nonminimal_bool",
        "clippy::needless_pass_by_value",
        "clippy::map_clone", // FIXME: remove when Iterator::copied stabilizes (1.36.0)
    ];
    run(
        &format!(
            "rustup run {} -- cargo clippy --all-features --all-targets -- -A {}",
            TOOLCHAIN,
            allowed_lints.join(" -A ")
        ),
        ".",
    )?;
    Ok(())
}

pub fn install_clippy() -> Result<()> {
    run(&format!("rustup install {}", TOOLCHAIN), ".")?;
    run(&format!("rustup component add clippy --toolchain {}", TOOLCHAIN), ".")
}

pub fn run_fuzzer() -> Result<()> {
    match Command::new("cargo")
        .args(&["fuzz", "--help"])
        .stderr(Stdio::null())
        .stdout(Stdio::null())
        .status()
    {
        Ok(status) if status.success() => (),
        _ => run("cargo install cargo-fuzz", ".")?,
    };

    run("rustup run nightly -- cargo fuzz run parser", "./crates/ra_syntax")
}

pub fn gen_tests(mode: Mode) -> Result<()> {
    let tests = tests_from_dir(&project_root().join(Path::new(GRAMMAR_DIR)))?;
    fn install_tests(tests: &HashMap<String, Test>, into: &str, mode: Mode) -> Result<()> {
        let tests_dir = project_root().join(into);
        if !tests_dir.is_dir() {
            fs::create_dir_all(&tests_dir)?;
        }
        // ok is never actually read, but it needs to be specified to create a Test in existing_tests
        let existing = existing_tests(&tests_dir, true)?;
        for t in existing.keys().filter(|&t| !tests.contains_key(t)) {
            panic!("Test is deleted: {}", t);
        }

        let mut new_idx = existing.len() + 1;
        for (name, test) in tests {
            let path = match existing.get(name) {
                Some((path, _test)) => path.clone(),
                None => {
                    let file_name = format!("{:04}_{}.rs", new_idx, name);
                    new_idx += 1;
                    tests_dir.join(file_name)
                }
            };
            teraron::update(&path, &test.text, mode)?;
        }
        Ok(())
    }
    install_tests(&tests.ok, OK_INLINE_TESTS_DIR, mode)?;
    install_tests(&tests.err, ERR_INLINE_TESTS_DIR, mode)
}

fn do_run<F>(cmdline: &str, dir: &str, mut f: F) -> Result<Output>
where
    F: FnMut(&mut Command),
{
    eprintln!("\nwill run: {}", cmdline);
    let proj_dir = project_root().join(dir);
    let mut args = cmdline.split_whitespace();
    let exec = args.next().unwrap();
    let mut cmd = Command::new(exec);
    f(cmd.args(args).current_dir(proj_dir).stderr(Stdio::inherit()));
    let output = cmd.output()?;
    if !output.status.success() {
        bail!("`{}` exited with {}", cmdline, output.status);
    }
    Ok(output)
}

#[derive(Default, Debug)]
struct Tests {
    pub ok: HashMap<String, Test>,
    pub err: HashMap<String, Test>,
}

fn tests_from_dir(dir: &Path) -> Result<Tests> {
    let mut res = Tests::default();
    for entry in ::walkdir::WalkDir::new(dir) {
        let entry = entry.unwrap();
        if !entry.file_type().is_file() {
            continue;
        }
        if entry.path().extension().unwrap_or_default() != "rs" {
            continue;
        }
        process_file(&mut res, entry.path())?;
    }
    let grammar_rs = dir.parent().unwrap().join("grammar.rs");
    process_file(&mut res, &grammar_rs)?;
    return Ok(res);
    fn process_file(res: &mut Tests, path: &Path) -> Result<()> {
        let text = fs::read_to_string(path)?;

        for (_, test) in collect_tests(&text) {
            if test.ok {
                if let Some(old_test) = res.ok.insert(test.name.clone(), test) {
                    bail!("Duplicate test: {}", old_test.name)
                }
            } else {
                if let Some(old_test) = res.err.insert(test.name.clone(), test) {
                    bail!("Duplicate test: {}", old_test.name)
                }
            }
        }
        Ok(())
    }
}

fn existing_tests(dir: &Path, ok: bool) -> Result<HashMap<String, (PathBuf, Test)>> {
    let mut res = HashMap::new();
    for file in fs::read_dir(dir)? {
        let file = file?;
        let path = file.path();
        if path.extension().unwrap_or_default() != "rs" {
            continue;
        }
        let name = {
            let file_name = path.file_name().unwrap().to_str().unwrap();
            file_name[5..file_name.len() - 3].to_string()
        };
        let text = fs::read_to_string(&path)?;
        let test = Test { name: name.clone(), text, ok };
        if let Some(old) = res.insert(name, (path, test)) {
            println!("Duplicate test: {:?}", old);
        }
    }
    Ok(res)
}
<|endoftext|>


<commit_before>//! Task notification.

use core::fmt;

if_std! {
    use core::marker::PhantomData;
    use never::Never;
    use executor::Executor;
    type Exec<'a> = &'a mut Executor;
}

if_not_std! {
    type Exec<'a> = ();
}

mod atomic_waker;
pub use self::atomic_waker::AtomicWaker;

/// Information about the currently-running task.
///
/// Contexts are always tied to the stack, since they are set up specifically
/// when performing a single `poll` step on a task.
pub struct Context<'a> {
    waker: &'a Waker,
    map: &'a mut LocalMap,
    executor: Exec<'a>,
}

impl<'a> Context<'a> {
    /// Get the [`Waker`](::task::Waker) associated with the current task.
    ///
    /// The waker can subsequently be used to wake up the task when some
    /// event of interest has happened.
    pub fn waker(&self) -> Waker {
        self.waker.clone()
    }

    /// Produce a context like the current one, but using the given waker
    /// instead.
    ///
    /// This advanced method is primarily used when building "internal
    /// schedulers" within a task, where you want to provide some customized
    /// wakeup logic.
    pub fn with_waker<'b>(&'b mut self, waker: &'b Waker) -> Context<'b> {
        Context { map: self.map, executor: self.executor, waker }
    }

    /// Produce a context like the current one, but using the given task locals
    /// instead.
    ///
    /// This advanced method is primarily used when building "internal
    /// schedulers" within a task.
    pub fn with_locals<'b>(&'b mut self, map: &'b mut LocalMap)
        -> Context<'b>
    {
        Context { map, waker: self.waker, executor: self.executor }
    }
}

if_std! {
    use std::boxed::Box;
    use Future;

    impl<'a> Context<'a> {
        /// Create a new task context.
        ///
        /// Task contexts are always equipped with:
        ///
        /// - Task-local data
        /// - A means of waking the task
        /// - A means of spawning new tasks, i.e. an [executor]()
        pub fn new(map: &'a mut LocalMap, waker: &'a Waker, executor: &'a mut Executor) -> Context<'a> {
            Context { waker, map, executor }
        }

        /// Get the default executor associated with this task.
        ///
        /// This method is useful primarily if you want to explicitly handle
        /// spawn failures.
        pub fn executor(&mut self) -> &mut Executor {
            self.executor
        }

        /// Spawn a future onto the default executor.
        ///
        /// # Panics
        ///
        /// This method will panic if the default executor is unable to spawn.
        /// To handle executor errors, use [executor()](self::Context::executor)
        /// instead.
        pub fn spawn<F>(&mut self, f: F)
            where F: Future<Item = (), Error = Never> + 'static + Send
        {
            self.executor.spawn(Box::new(f)).unwrap()
        }
    }
}

if_not_std! {
    impl<'a> Context<'a> {
        /// Create a new task context.
        ///
        /// In no_std mode, task contexts are always equipped with:
        ///
        /// - Task-local data
        /// - A means of waking the task
        pub fn new(map: &'a mut LocalMap, waker: &'a Waker) -> Context<'a> {
            Context { waker, map, executor: () }
        }
    }
}

impl<'a> fmt::Debug for Context<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("Context")
         .finish()
    }
}

/// A map storing task-local data.
pub struct LocalMap {
    #[allow(dead_code)]
    inner: data::LocalMap,
}

impl LocalMap {
    /// Create an empty set of task-local data.
    pub fn new() -> LocalMap {
        LocalMap { inner: data::local_map() }
    }
}

impl fmt::Debug for LocalMap {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("LocalMap")
         .finish()
    }
}

/// An unsafe trait for implementing custom memory management for a
/// [`Waker`](::task::Waker).
///
/// A [`Waker`](::task::Waker) is a cloneable trait object for `Wake`, and is
/// most often essentially just `Arc<Wake>`. However, in some contexts
/// (particularly `no_std`), it's desirable to avoid `Arc` in favor of some
/// custom memory management strategy. This trait is designed to allow for such
/// customization.
///
/// A default implementation of the `UnsafeWake` trait is provided for the
/// `Arc` type in the standard library. If the `std` feature of this crate
/// is not available however, you'll be required to implement your own
/// instance of this trait to pass it into `Waker::new`.
///
/// # Unsafety
///
/// This trait manually encodes the memory management of the underlying trait
/// object. Implementors of this trait must guarantee:
///
/// * Calls to `clone_raw` produce uniquely owned `Waker` handles. These handles
/// should be independently usable and droppable.
///
/// * Calls to `drop_raw` work with `self` as a raw pointer, deallocating
///   resources associated with it. This is a pretty unsafe operation as it's
///   invalidating the `self` pointer, so extreme care needs to be taken.
///
/// In general it's recommended to review the trait documentation as well as the
/// implementation for `Arc` in this crate before attempting a custom
/// implementation.
pub unsafe trait UnsafeWake {
    /// Creates a new `Waker` from this instance of `UnsafeWake`.
    ///
    /// This function will create a new uniquely owned handle that under the
    /// hood references the same notification instance. In other words calls
    /// to `wake` on the returned handle should be equivalent to calls to
    /// `wake` on this handle.
    ///
    /// # Unsafety
    ///
    /// This is also unsafe to call because it's asserting the `UnsafeWake`
    /// value is in a consistent state, i.e. hasn't been dropped.
    unsafe fn clone_raw(&self) -> Waker;

    /// Drops this instance of `UnsafeWake`, deallocating resources
    /// associated with it.
    ///
    /// This method is intended to have a signature such as:
    ///
    /// ```ignore
    /// fn drop_raw(self: *mut Self);
    /// ```
    ///
    /// Unfortunately in Rust today that signature is not object safe.
    /// Nevertheless it's recommended to implement this function *as if* that
    /// were its signature. As such it is not safe to call on an invalid
    /// pointer, nor is the validity of the pointer guaranteed after this
    /// function returns.
    ///
    /// # Unsafety
    ///
    /// This is also unsafe to call because it's asserting the `UnsafeWake`
    /// value is in a consistent state, i.e. hasn't been dropped
    unsafe fn drop_raw(&self);

    /// Indicates that the associated task is ready to make progress and should
    /// be `poll`ed.
    ///
    /// Executors generally maintain a queue of "ready" tasks; `wake` should place
    /// the associated task onto this queue.
    ///
    /// # Panics
    ///
    /// Implementations should avoid panicking, but clients should also be prepared
    /// for panics.
    ///
    /// # Unsafety
    ///
    /// This is also unsafe to call because it's asserting the `UnsafeWake`
    /// value is in a consistent state, i.e. hasn't been dropped
    unsafe fn wake(&self);
}

/// A `Waker` is a handle for waking up a task by notifying its executor that it
/// is ready to be run.
///
/// This handle contains a trait object pointing to an instance of the `Wake`
/// trait, allowing notifications to get routed through it. Usually `Waker`
/// instances are provided by an executor.
///
/// If you're implementing an executor, the recommended way to create a `Waker`
/// is via `Waker::from` applied to an `Arc<T>` value where `T: Wake`. The
/// unsafe `new` constructor should be used only in niche, `no_std` settings.
pub struct Waker {
    inner: *mut UnsafeWake,
}

unsafe impl Send for Waker {}
unsafe impl Sync for Waker {}

impl Waker {
    /// Constructs a new `Waker` directly.
    ///
    /// Note that most code will not need to call this. Implementers of the
    /// `UnsafeWake` trait will typically provide a wrapper that calls this
    /// but you otherwise shouldn't call it directly.
    ///
    /// If you're working with the standard library then it's recommended to
    /// use the `Waker::from` function instead which works with the safe
    /// `Arc` type and the safe `Wake` trait.
    #[inline]
    pub unsafe fn new(inner: *mut UnsafeWake) -> Waker {
        Waker { inner: inner }
    }

    /// Wake up the task associated with this `Waker`.
    pub fn wake(&self) {
        unsafe { (*self.inner).wake() }
    }
}

impl Clone for Waker {
    #[inline]
    fn clone(&self) -> Self {
        unsafe {
            (*self.inner).clone_raw()
        }
    }
}

impl fmt::Debug for Waker {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("Waker")
         .finish()
    }
}

impl Drop for Waker {
    fn drop(&mut self) {
        unsafe {
            (*self.inner).drop_raw()
        }
    }
}

if_std! {
    use std::mem;
    use std::ptr;
    use std::sync::Arc;

    mod data;

    pub use self::data::LocalKey;

    /// A way of waking up a specific task.
    ///
    /// Any task executor must provide a way of signaling that a task it owns
    /// is ready to be `poll`ed again. Executors do so by implementing this trait.
    ///
    /// Note that, rather than working directly with `Wake` trait objects, this
    /// library instead uses a custom [`Waker`](::task::Waker) to allow for
    /// customization of memory management.
    pub trait Wake: Send + Sync {
        /// Indicates that the associated task is ready to make progress and should
        /// be `poll`ed.
        ///
        /// Executors generally maintain a queue of "ready" tasks; `wake` should place
        /// the associated task onto this queue.
        ///
        /// # Panics
        ///
        /// Implementations should avoid panicking, but clients should also be prepared
        /// for panics.
        fn wake(arc_self: &Arc<Self>);
    }

    // Safe implementation of `UnsafeWake` for `Arc` in the standard library.
    //
    // Note that this is a very unsafe implementation! The crucial pieces is that
    // these two values are considered equivalent:
    //
    // * Arc<T>
    // * *const ArcWrapped<T>
    //
    // We don't actually know the layout of `ArcWrapped<T>` as it's an
    // implementation detail in the standard library. We can work, though, by
    // casting it through and back an `Arc<T>`.
    //
    // This also means that you won't actually find `UnsafeWake for Arc<T>`
    // because it's the wrong level of indirection. These methods are sort of
    // receiving Arc<T>, but not an owned version. It's... complicated. We may be
    // one of the first users of unsafe trait objects!

    struct ArcWrapped<T>(PhantomData<T>);

    unsafe impl<T: Wake + 'static> UnsafeWake for ArcWrapped<T> {
        unsafe fn clone_raw(&self) -> Waker {
            let me: *const ArcWrapped<T> = self;
            let arc = (*(&me as *const *const ArcWrapped<T> as *const Arc<T>)).clone();
            Waker::from(arc)
        }

        unsafe fn drop_raw(&self) {
            let mut me: *const ArcWrapped<T> = self;
            let me = &mut me as *mut *const ArcWrapped<T> as *mut Arc<T>;
            ptr::drop_in_place(me);
        }

        unsafe fn wake(&self) {
            let me: *const ArcWrapped<T> = self;
            T::wake(&*(&me as *const *const ArcWrapped<T> as *const Arc<T>))
        }
    }

    impl<T> From<Arc<T>> for Waker
        where T: Wake + 'static,
    {
        fn from(rc: Arc<T>) -> Waker {
            unsafe {
                let ptr = mem::transmute::<Arc<T>, *mut ArcWrapped<T>>(rc);
                Waker::new(ptr)
            }
        }
    }
}

#[cfg(not(feature = "std"))]
mod data {
    pub struct LocalMap;

    pub fn local_map() -> LocalMap {
        LocalMap
    }
}
<commit_msg>Add comparison function for Wakers<commit_after>//! Task notification.

use core::fmt;

if_std! {
    use core::marker::PhantomData;
    use never::Never;
    use executor::Executor;
    type Exec<'a> = &'a mut Executor;
}

if_not_std! {
    type Exec<'a> = ();
}

mod atomic_waker;
pub use self::atomic_waker::AtomicWaker;

/// Information about the currently-running task.
///
/// Contexts are always tied to the stack, since they are set up specifically
/// when performing a single `poll` step on a task.
pub struct Context<'a> {
    waker: &'a Waker,
    map: &'a mut LocalMap,
    executor: Exec<'a>,
}

impl<'a> Context<'a> {
    /// Get the [`Waker`](::task::Waker) associated with the current task.
    ///
    /// The waker can subsequently be used to wake up the task when some
    /// event of interest has happened.
    pub fn waker(&self) -> Waker {
        self.waker.clone()
    }

    /// Produce a context like the current one, but using the given waker
    /// instead.
    ///
    /// This advanced method is primarily used when building "internal
    /// schedulers" within a task, where you want to provide some customized
    /// wakeup logic.
    pub fn with_waker<'b>(&'b mut self, waker: &'b Waker) -> Context<'b> {
        Context { map: self.map, executor: self.executor, waker }
    }

    /// Produce a context like the current one, but using the given task locals
    /// instead.
    ///
    /// This advanced method is primarily used when building "internal
    /// schedulers" within a task.
    pub fn with_locals<'b>(&'b mut self, map: &'b mut LocalMap)
        -> Context<'b>
    {
        Context { map, waker: self.waker, executor: self.executor }
    }
}

if_std! {
    use std::boxed::Box;
    use Future;

    impl<'a> Context<'a> {
        /// Create a new task context.
        ///
        /// Task contexts are always equipped with:
        ///
        /// - Task-local data
        /// - A means of waking the task
        /// - A means of spawning new tasks, i.e. an [executor]()
        pub fn new(map: &'a mut LocalMap, waker: &'a Waker, executor: &'a mut Executor) -> Context<'a> {
            Context { waker, map, executor }
        }

        /// Get the default executor associated with this task.
        ///
        /// This method is useful primarily if you want to explicitly handle
        /// spawn failures.
        pub fn executor(&mut self) -> &mut Executor {
            self.executor
        }

        /// Spawn a future onto the default executor.
        ///
        /// # Panics
        ///
        /// This method will panic if the default executor is unable to spawn.
        /// To handle executor errors, use [executor()](self::Context::executor)
        /// instead.
        pub fn spawn<F>(&mut self, f: F)
            where F: Future<Item = (), Error = Never> + 'static + Send
        {
            self.executor.spawn(Box::new(f)).unwrap()
        }
    }
}

if_not_std! {
    impl<'a> Context<'a> {
        /// Create a new task context.
        ///
        /// In no_std mode, task contexts are always equipped with:
        ///
        /// - Task-local data
        /// - A means of waking the task
        pub fn new(map: &'a mut LocalMap, waker: &'a Waker) -> Context<'a> {
            Context { waker, map, executor: () }
        }
    }
}

impl<'a> fmt::Debug for Context<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("Context")
         .finish()
    }
}

/// A map storing task-local data.
pub struct LocalMap {
    #[allow(dead_code)]
    inner: data::LocalMap,
}

impl LocalMap {
    /// Create an empty set of task-local data.
    pub fn new() -> LocalMap {
        LocalMap { inner: data::local_map() }
    }
}

impl fmt::Debug for LocalMap {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("LocalMap")
         .finish()
    }
}

/// An unsafe trait for implementing custom memory management for a
/// [`Waker`](::task::Waker).
///
/// A [`Waker`](::task::Waker) is a cloneable trait object for `Wake`, and is
/// most often essentially just `Arc<Wake>`. However, in some contexts
/// (particularly `no_std`), it's desirable to avoid `Arc` in favor of some
/// custom memory management strategy. This trait is designed to allow for such
/// customization.
///
/// A default implementation of the `UnsafeWake` trait is provided for the
/// `Arc` type in the standard library. If the `std` feature of this crate
/// is not available however, you'll be required to implement your own
/// instance of this trait to pass it into `Waker::new`.
///
/// # Unsafety
///
/// This trait manually encodes the memory management of the underlying trait
/// object. Implementors of this trait must guarantee:
///
/// * Calls to `clone_raw` produce uniquely owned `Waker` handles. These handles
/// should be independently usable and droppable.
///
/// * Calls to `drop_raw` work with `self` as a raw pointer, deallocating
///   resources associated with it. This is a pretty unsafe operation as it's
///   invalidating the `self` pointer, so extreme care needs to be taken.
///
/// In general it's recommended to review the trait documentation as well as the
/// implementation for `Arc` in this crate before attempting a custom
/// implementation.
pub unsafe trait UnsafeWake {
    /// Creates a new `Waker` from this instance of `UnsafeWake`.
    ///
    /// This function will create a new uniquely owned handle that under the
    /// hood references the same notification instance. In other words calls
    /// to `wake` on the returned handle should be equivalent to calls to
    /// `wake` on this handle.
    ///
    /// # Unsafety
    ///
    /// This is also unsafe to call because it's asserting the `UnsafeWake`
    /// value is in a consistent state, i.e. hasn't been dropped.
    unsafe fn clone_raw(&self) -> Waker;

    /// Drops this instance of `UnsafeWake`, deallocating resources
    /// associated with it.
    ///
    /// This method is intended to have a signature such as:
    ///
    /// ```ignore
    /// fn drop_raw(self: *mut Self);
    /// ```
    ///
    /// Unfortunately in Rust today that signature is not object safe.
    /// Nevertheless it's recommended to implement this function *as if* that
    /// were its signature. As such it is not safe to call on an invalid
    /// pointer, nor is the validity of the pointer guaranteed after this
    /// function returns.
    ///
    /// # Unsafety
    ///
    /// This is also unsafe to call because it's asserting the `UnsafeWake`
    /// value is in a consistent state, i.e. hasn't been dropped
    unsafe fn drop_raw(&self);

    /// Indicates that the associated task is ready to make progress and should
    /// be `poll`ed.
    ///
    /// Executors generally maintain a queue of "ready" tasks; `wake` should place
    /// the associated task onto this queue.
    ///
    /// # Panics
    ///
    /// Implementations should avoid panicking, but clients should also be prepared
    /// for panics.
    ///
    /// # Unsafety
    ///
    /// This is also unsafe to call because it's asserting the `UnsafeWake`
    /// value is in a consistent state, i.e. hasn't been dropped
    unsafe fn wake(&self);
}

/// A `Waker` is a handle for waking up a task by notifying its executor that it
/// is ready to be run.
///
/// This handle contains a trait object pointing to an instance of the `Wake`
/// trait, allowing notifications to get routed through it. Usually `Waker`
/// instances are provided by an executor.
///
/// If you're implementing an executor, the recommended way to create a `Waker`
/// is via `Waker::from` applied to an `Arc<T>` value where `T: Wake`. The
/// unsafe `new` constructor should be used only in niche, `no_std` settings.
pub struct Waker {
    inner: *mut UnsafeWake,
}

unsafe impl Send for Waker {}
unsafe impl Sync for Waker {}

impl Waker {
    /// Constructs a new `Waker` directly.
    ///
    /// Note that most code will not need to call this. Implementers of the
    /// `UnsafeWake` trait will typically provide a wrapper that calls this
    /// but you otherwise shouldn't call it directly.
    ///
    /// If you're working with the standard library then it's recommended to
    /// use the `Waker::from` function instead which works with the safe
    /// `Arc` type and the safe `Wake` trait.
    #[inline]
    pub unsafe fn new(inner: *mut UnsafeWake) -> Waker {
        Waker { inner: inner }
    }

    /// Wake up the task associated with this `Waker`.
    pub fn wake(&self) {
        unsafe { (*self.inner).wake() }
    }

    /// Returns whether or not this `Waker` and `other` awaken the same task.
    ///
    /// This function works on a best-effort basis, and may return false even
    /// when the `Waker`s would awaken the same task. However, if this function
    /// returns true, it is guaranteed that the `Waker`s will awaken the same
    /// task.
    ///
    /// This function is primarily used for optimization purposes.
    pub fn will_wake(&self, other: &Waker) -> bool {
        self.inner == other.inner
    }
}

impl Clone for Waker {
    #[inline]
    fn clone(&self) -> Self {
        unsafe {
            (*self.inner).clone_raw()
        }
    }
}

impl fmt::Debug for Waker {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("Waker")
         .finish()
    }
}

impl Drop for Waker {
    fn drop(&mut self) {
        unsafe {
            (*self.inner).drop_raw()
        }
    }
}

if_std! {
    use std::mem;
    use std::ptr;
    use std::sync::Arc;

    mod data;

    pub use self::data::LocalKey;

    /// A way of waking up a specific task.
    ///
    /// Any task executor must provide a way of signaling that a task it owns
    /// is ready to be `poll`ed again. Executors do so by implementing this trait.
    ///
    /// Note that, rather than working directly with `Wake` trait objects, this
    /// library instead uses a custom [`Waker`](::task::Waker) to allow for
    /// customization of memory management.
    pub trait Wake: Send + Sync {
        /// Indicates that the associated task is ready to make progress and should
        /// be `poll`ed.
        ///
        /// Executors generally maintain a queue of "ready" tasks; `wake` should place
        /// the associated task onto this queue.
        ///
        /// # Panics
        ///
        /// Implementations should avoid panicking, but clients should also be prepared
        /// for panics.
        fn wake(arc_self: &Arc<Self>);
    }

    // Safe implementation of `UnsafeWake` for `Arc` in the standard library.
    //
    // Note that this is a very unsafe implementation! The crucial pieces is that
    // these two values are considered equivalent:
    //
    // * Arc<T>
    // * *const ArcWrapped<T>
    //
    // We don't actually know the layout of `ArcWrapped<T>` as it's an
    // implementation detail in the standard library. We can work, though, by
    // casting it through and back an `Arc<T>`.
    //
    // This also means that you won't actually find `UnsafeWake for Arc<T>`
    // because it's the wrong level of indirection. These methods are sort of
    // receiving Arc<T>, but not an owned version. It's... complicated. We may be
    // one of the first users of unsafe trait objects!

    struct ArcWrapped<T>(PhantomData<T>);

    unsafe impl<T: Wake + 'static> UnsafeWake for ArcWrapped<T> {
        unsafe fn clone_raw(&self) -> Waker {
            let me: *const ArcWrapped<T> = self;
            let arc = (*(&me as *const *const ArcWrapped<T> as *const Arc<T>)).clone();
            Waker::from(arc)
        }

        unsafe fn drop_raw(&self) {
            let mut me: *const ArcWrapped<T> = self;
            let me = &mut me as *mut *const ArcWrapped<T> as *mut Arc<T>;
            ptr::drop_in_place(me);
        }

        unsafe fn wake(&self) {
            let me: *const ArcWrapped<T> = self;
            T::wake(&*(&me as *const *const ArcWrapped<T> as *const Arc<T>))
        }
    }

    impl<T> From<Arc<T>> for Waker
        where T: Wake + 'static,
    {
        fn from(rc: Arc<T>) -> Waker {
            unsafe {
                let ptr = mem::transmute::<Arc<T>, *mut ArcWrapped<T>>(rc);
                Waker::new(ptr)
            }
        }
    }
}

#[cfg(not(feature = "std"))]
mod data {
    pub struct LocalMap;

    pub fn local_map() -> LocalMap {
        LocalMap
    }
}
<|endoftext|>