<commit_before>use opencl;
use opencl::mem::{Buffer, CLBuffer};

use context::Context;
use matrix::Matrix;
use num::Num;

pub enum ClMatrixMode {
    In,
    Out,
    Mut,
}

pub struct ClMatrix<T: Num> {
    rows: usize,
    columns: usize,
    buffer: CLBuffer<T>,
}

impl<T: Num> ClMatrix<T> {
    pub fn new(ctx: &Context, rows: usize, columns: usize, mode: ClMatrixMode) -> ClMatrix<T> {
        let cl_mem_mode =
            match mode {
                ClMatrixMode::In => { opencl::cl::CL_MEM_READ_ONLY },
                ClMatrixMode::Out => { opencl::cl::CL_MEM_WRITE_ONLY },
                ClMatrixMode::Mut => { opencl::cl::CL_MEM_READ_WRITE},
            };
        ClMatrix {
            rows: rows,
            columns: columns,
            buffer: ctx.ctx.create_buffer(rows*columns, cl_mem_mode),
        }
    }

    pub fn from_matrix(ctx: &Context,
                       matrix: &Matrix<T>,
                       mode: ClMatrixMode) -> ClMatrix<T> {
        let cl_mem_mode =
            match mode {
                ClMatrixMode::In => { opencl::cl::CL_MEM_READ_ONLY },
                ClMatrixMode::Out => { opencl::cl::CL_MEM_WRITE_ONLY },
                ClMatrixMode::Mut => { opencl::cl::CL_MEM_READ_WRITE},
            };
        let cl_matrix =
            ClMatrix {
                rows: matrix.rows(),
                columns: matrix.columns(),
                buffer: ctx.ctx.create_buffer(matrix.rows()*matrix.columns(), cl_mem_mode),
            };

        ctx.queue.write(&cl_matrix.buffer, &&matrix.buffer()[..], ());
        cl_matrix
    }

    pub fn rows(&self) -> usize {
        self.rows
    }

    pub fn columns(&self) -> usize {
        self.columns
    }

    pub fn copy_to(&self, ctx: &Context, output: &ClMatrix<T>) -> Event {
        let kernel = ctx.program.create_kernel(format!("vector_copy_to_{}", T::name()).as_str());

        kernel.set_arg(0, &self.buffer);
        kernel.set_arg(1, &output.buffer);

        let event = ctx.queue.enqueue_async_kernel(&kernel, self.buffer.len(), None, ());
        Event(event)
    }

    pub fn add(&self, ctx: &Context, other: &ClMatrix<T>, output: &ClMatrix<T>) -> Event {
        let kernel = ctx.program.create_kernel(format!("vector_add_{}", T::name()).as_str());

        kernel.set_arg(0, &self.buffer);
        kernel.set_arg(1, &other.buffer);
        kernel.set_arg(2, &output.buffer);

        let event = ctx.queue.enqueue_async_kernel(&kernel, self.buffer.len(), None, ());
        Event(event)
    }

    pub fn sub(&self, ctx: &Context, other: &ClMatrix<T>, output: &ClMatrix<T>) -> Event {
        let kernel = ctx.program.create_kernel(format!("vector_sub_{}", T::name()).as_str());

        kernel.set_arg(0, &self.buffer);
        kernel.set_arg(1, &other.buffer);
        kernel.set_arg(2, &output.buffer);

        let event = ctx.queue.enqueue_async_kernel(&kernel, self.buffer.len(), None, ());
        Event(event)
    }

    pub fn multiply(&self, ctx: &Context, other: &ClMatrix<T>, output: &ClMatrix<T>) -> Event {
        let kernel = ctx.program.create_kernel(format!("vector_multiply_{}", T::name()).as_str());

        kernel.set_arg(0, &self.buffer);
        kernel.set_arg(1, &other.buffer);
        kernel.set_arg(2, &output.buffer);

        let event = ctx.queue.enqueue_async_kernel(&kernel, self.buffer.len(), None, ());
        Event(event)
    }

    pub fn transpose(&self, ctx: &Context, output: &ClMatrix<T>) -> Event {
        let kernel = ctx.program.create_kernel(format!("vector_transpose_{}", T::name()).as_str());

        kernel.set_arg(0, &self.buffer);
        kernel.set_arg(1, &output.buffer);
        kernel.set_arg(2, &self.rows);
        kernel.set_arg(3, &self.columns);

        let event = ctx.queue.enqueue_async_kernel(&kernel,
                                                   (self.rows, self.columns),
                                                   None, ());
        Event(event)
    }

    pub fn dot(&self, ctx: &Context, other: &ClMatrix<T>, output: &ClMatrix<T>) -> Event {
        let kernel = ctx.program.create_kernel(format!("vector_dot_{}", T::name()).as_str());

        kernel.set_arg(0, &self.buffer);
        kernel.set_arg(1, &other.buffer);
        kernel.set_arg(2, &output.buffer);
        kernel.set_arg(3, &self.columns);
        kernel.set_arg(4, &other.columns);

        let event = ctx.queue.enqueue_async_kernel(&kernel,
                                                   (self.rows, other.columns),
                                                   None, ());
        Event(event)
    }

    pub fn max(&self, ctx: &Context, threshold: T, output: &ClMatrix<T>) -> Event {
        let kernel = ctx.program.create_kernel(format!("vector_max_{}", T::name()).as_str());

        kernel.set_arg(0, &self.buffer);
        kernel.set_arg(1, &output.buffer);
        kernel.set_arg(2, &threshold);

        let event = ctx.queue.enqueue_async_kernel(&kernel, self.buffer.len(), None, ());
        Event(event)
    }

    pub fn min(&self, ctx: &Context, threshold: T, output: &ClMatrix<T>) -> Event {
        let kernel = ctx.program.create_kernel(format!("vector_min_{}", T::name()).as_str());

        kernel.set_arg(0, &self.buffer);
        kernel.set_arg(1, &output.buffer);
        kernel.set_arg(2, &threshold);

        let event = ctx.queue.enqueue_async_kernel(&kernel, self.buffer.len(), None, ());
        Event(event)
    }

    pub fn dmax(&self, ctx: &Context, threshold: T, output: &ClMatrix<T>) -> Event {
        let kernel = ctx.program.create_kernel(format!("vector_dmax_{}", T::name()).as_str());

        kernel.set_arg(0, &self.buffer);
        kernel.set_arg(1, &output.buffer);
        kernel.set_arg(2, &threshold);

        let event = ctx.queue.enqueue_async_kernel(&kernel, self.buffer.len(), None, ());
        Event(event)
    }

    pub fn dmin(&self, ctx: &Context, threshold: T, output: &ClMatrix<T>) -> Event {
        let kernel = ctx.program.create_kernel(format!("vector_dmin_{}", T::name()).as_str());

        kernel.set_arg(0, &self.buffer);
        kernel.set_arg(1, &output.buffer);
        kernel.set_arg(2, &threshold);

        let event = ctx.queue.enqueue_async_kernel(&kernel, self.buffer.len(), None, ());
        Event(event)
    }
}

pub struct Event(opencl::hl::Event);

impl Event {
    pub fn get<T: Num>(&self, ctx: &Context, cl_matrix: &ClMatrix<T>) -> Matrix<T> {
        let vec = ctx.queue.get(&cl_matrix.buffer, &self.0);
        Matrix::from_vec(cl_matrix.rows, cl_matrix.columns, vec)
    }
}

#[test]
fn cl_matrix_add() {
    let ref ctx = Context::new();

    let a = Matrix::from_vec(1, 10000, (0..10000).collect());
    let b = Matrix::from_vec(1, 10000, (0..10000).map(|x| x*2).collect());

    let a_cl = ClMatrix::from_matrix(ctx, &a, ClMatrixMode::In);
    let b_cl = ClMatrix::from_matrix(ctx, &b, ClMatrixMode::In);
    let c_cl: ClMatrix<i32> = ClMatrix::new(ctx, 1, 10000, ClMatrixMode::Out);

    let event = a_cl.add(ctx, &b_cl, &c_cl);

    let c = event.get(ctx, &c_cl);

    for i in 0..10000 {
        assert!(c[(0, i)] == a[(0, i)] + b[(0, i)]);
    }
}
<commit_msg>ClMatrix::set to send write CPU matrix to an existing GPU matrix<commit_after>use opencl;
use opencl::mem::{Buffer, CLBuffer};

use context::Context;
use matrix::Matrix;
use num::Num;

pub enum ClMatrixMode {
    In,
    Out,
    Mut,
}

pub struct ClMatrix<T: Num> {
    rows: usize,
    columns: usize,
    buffer: CLBuffer<T>,
}

impl<T: Num> ClMatrix<T> {
    pub fn new(ctx: &Context, rows: usize, columns: usize, mode: ClMatrixMode) -> ClMatrix<T> {
        let cl_mem_mode =
            match mode {
                ClMatrixMode::In => { opencl::cl::CL_MEM_READ_ONLY },
                ClMatrixMode::Out => { opencl::cl::CL_MEM_WRITE_ONLY },
                ClMatrixMode::Mut => { opencl::cl::CL_MEM_READ_WRITE},
            };
        ClMatrix {
            rows: rows,
            columns: columns,
            buffer: ctx.ctx.create_buffer(rows*columns, cl_mem_mode),
        }
    }

    pub fn from_matrix(ctx: &Context,
                       matrix: &Matrix<T>,
                       mode: ClMatrixMode) -> ClMatrix<T> {
        let cl_mem_mode =
            match mode {
                ClMatrixMode::In => { opencl::cl::CL_MEM_READ_ONLY },
                ClMatrixMode::Out => { opencl::cl::CL_MEM_WRITE_ONLY },
                ClMatrixMode::Mut => { opencl::cl::CL_MEM_READ_WRITE},
            };
        let cl_matrix =
            ClMatrix {
                rows: matrix.rows(),
                columns: matrix.columns(),
                buffer: ctx.ctx.create_buffer(matrix.rows()*matrix.columns(), cl_mem_mode),
            };

        ctx.queue.write(&cl_matrix.buffer, &&matrix.buffer()[..], ());
        cl_matrix
    }

    pub fn set(&self, ctx: &Context, matrix: &Matrix<T>) {
        ctx.queue.write(&self.buffer, &&matrix.buffer()[..], ());
    }

    pub fn rows(&self) -> usize {
        self.rows
    }

    pub fn columns(&self) -> usize {
        self.columns
    }

    pub fn copy_to(&self, ctx: &Context, output: &ClMatrix<T>) -> Event {
        let kernel = ctx.program.create_kernel(format!("vector_copy_to_{}", T::name()).as_str());

        kernel.set_arg(0, &self.buffer);
        kernel.set_arg(1, &output.buffer);

        let event = ctx.queue.enqueue_async_kernel(&kernel, self.buffer.len(), None, ());
        Event(event)
    }

    pub fn add(&self, ctx: &Context, other: &ClMatrix<T>, output: &ClMatrix<T>) -> Event {
        let kernel = ctx.program.create_kernel(format!("vector_add_{}", T::name()).as_str());

        kernel.set_arg(0, &self.buffer);
        kernel.set_arg(1, &other.buffer);
        kernel.set_arg(2, &output.buffer);

        let event = ctx.queue.enqueue_async_kernel(&kernel, self.buffer.len(), None, ());
        Event(event)
    }

    pub fn sub(&self, ctx: &Context, other: &ClMatrix<T>, output: &ClMatrix<T>) -> Event {
        let kernel = ctx.program.create_kernel(format!("vector_sub_{}", T::name()).as_str());

        kernel.set_arg(0, &self.buffer);
        kernel.set_arg(1, &other.buffer);
        kernel.set_arg(2, &output.buffer);

        let event = ctx.queue.enqueue_async_kernel(&kernel, self.buffer.len(), None, ());
        Event(event)
    }

    pub fn multiply(&self, ctx: &Context, other: &ClMatrix<T>, output: &ClMatrix<T>) -> Event {
        let kernel = ctx.program.create_kernel(format!("vector_multiply_{}", T::name()).as_str());

        kernel.set_arg(0, &self.buffer);
        kernel.set_arg(1, &other.buffer);
        kernel.set_arg(2, &output.buffer);

        let event = ctx.queue.enqueue_async_kernel(&kernel, self.buffer.len(), None, ());
        Event(event)
    }

    pub fn transpose(&self, ctx: &Context, output: &ClMatrix<T>) -> Event {
        let kernel = ctx.program.create_kernel(format!("vector_transpose_{}", T::name()).as_str());

        kernel.set_arg(0, &self.buffer);
        kernel.set_arg(1, &output.buffer);
        kernel.set_arg(2, &self.rows);
        kernel.set_arg(3, &self.columns);

        let event = ctx.queue.enqueue_async_kernel(&kernel,
                                                   (self.rows, self.columns),
                                                   None, ());
        Event(event)
    }

    pub fn dot(&self, ctx: &Context, other: &ClMatrix<T>, output: &ClMatrix<T>) -> Event {
        let kernel = ctx.program.create_kernel(format!("vector_dot_{}", T::name()).as_str());

        kernel.set_arg(0, &self.buffer);
        kernel.set_arg(1, &other.buffer);
        kernel.set_arg(2, &output.buffer);
        kernel.set_arg(3, &self.columns);
        kernel.set_arg(4, &other.columns);

        let event = ctx.queue.enqueue_async_kernel(&kernel,
                                                   (self.rows, other.columns),
                                                   None, ());
        Event(event)
    }

    pub fn max(&self, ctx: &Context, threshold: T, output: &ClMatrix<T>) -> Event {
        let kernel = ctx.program.create_kernel(format!("vector_max_{}", T::name()).as_str());

        kernel.set_arg(0, &self.buffer);
        kernel.set_arg(1, &output.buffer);
        kernel.set_arg(2, &threshold);

        let event = ctx.queue.enqueue_async_kernel(&kernel, self.buffer.len(), None, ());
        Event(event)
    }

    pub fn min(&self, ctx: &Context, threshold: T, output: &ClMatrix<T>) -> Event {
        let kernel = ctx.program.create_kernel(format!("vector_min_{}", T::name()).as_str());

        kernel.set_arg(0, &self.buffer);
        kernel.set_arg(1, &output.buffer);
        kernel.set_arg(2, &threshold);

        let event = ctx.queue.enqueue_async_kernel(&kernel, self.buffer.len(), None, ());
        Event(event)
    }

    pub fn dmax(&self, ctx: &Context, threshold: T, output: &ClMatrix<T>) -> Event {
        let kernel = ctx.program.create_kernel(format!("vector_dmax_{}", T::name()).as_str());

        kernel.set_arg(0, &self.buffer);
        kernel.set_arg(1, &output.buffer);
        kernel.set_arg(2, &threshold);

        let event = ctx.queue.enqueue_async_kernel(&kernel, self.buffer.len(), None, ());
        Event(event)
    }

    pub fn dmin(&self, ctx: &Context, threshold: T, output: &ClMatrix<T>) -> Event {
        let kernel = ctx.program.create_kernel(format!("vector_dmin_{}", T::name()).as_str());

        kernel.set_arg(0, &self.buffer);
        kernel.set_arg(1, &output.buffer);
        kernel.set_arg(2, &threshold);

        let event = ctx.queue.enqueue_async_kernel(&kernel, self.buffer.len(), None, ());
        Event(event)
    }
}

pub struct Event(opencl::hl::Event);

impl Event {
    pub fn get<T: Num>(&self, ctx: &Context, cl_matrix: &ClMatrix<T>) -> Matrix<T> {
        let vec = ctx.queue.get(&cl_matrix.buffer, &self.0);
        Matrix::from_vec(cl_matrix.rows, cl_matrix.columns, vec)
    }
}

#[test]
fn cl_matrix_add() {
    let ref ctx = Context::new();

    let a = Matrix::from_vec(1, 10000, (0..10000).collect());
    let b = Matrix::from_vec(1, 10000, (0..10000).map(|x| x*2).collect());

    let a_cl = ClMatrix::from_matrix(ctx, &a, ClMatrixMode::In);
    let b_cl = ClMatrix::from_matrix(ctx, &b, ClMatrixMode::In);
    let c_cl: ClMatrix<i32> = ClMatrix::new(ctx, 1, 10000, ClMatrixMode::Out);

    let event = a_cl.add(ctx, &b_cl, &c_cl);

    let c = event.get(ctx, &c_cl);

    for i in 0..10000 {
        assert!(c[(0, i)] == a[(0, i)] + b[(0, i)]);
    }
}
<|endoftext|>


<commit_before>use serde;
use super::{ActionType, ExecCondition, ON_CLOSED_DEFAULT, ON_OPENED_DEFAULT};

#[cfg(test)]
mod test;

impl serde::de::Deserialize for ActionType {
    fn deserialize<D>(deserializer: &mut D) -> Result<ActionType, D::Error>
        where D: serde::de::Deserializer
    {
        enum Field {
            Message,
        }

    impl serde::de::Deserialize for Field {
            #[inline]
            fn deserialize<D>(deserializer: &mut D) -> Result<Field, D::Error>
                where D: serde::de::Deserializer
            {
                struct FieldVisitor;

                impl serde::de::Visitor for FieldVisitor {
                    type Value = Field;

                    fn visit_str<E>(&mut self, value: &str) -> Result<Field, E>
                        where E: serde::de::Error
                    {
                        match value {
                            "message" => Ok(Field::Message),
                            _ => Err(serde::de::Error::unknown_field(value)),
                        }
                    }
                }

                deserializer.visit(FieldVisitor)
            }
        }

        struct Visitor;

        impl serde::de::EnumVisitor for Visitor {
            type Value = ActionType;

            fn visit<V>(&mut self, mut visitor: V) -> Result<ActionType, V::Error>
                where V: serde::de::VariantVisitor
            {
                match try!(visitor.visit_variant()) {
                    Field::Message => {
                        let value = try!(visitor.visit_newtype());
                        Ok(ActionType::Message(value))
                    }
                }
            }
        }

        const VARIANTS: &'static [&'static str] = &["message"];

        deserializer.visit_enum("ActionType", VARIANTS, Visitor)
    }
}

impl serde::de::Deserialize for ExecCondition {
    fn deserialize<D>(deserializer: &mut D) -> Result<ExecCondition, D::Error>
        where D: serde::de::Deserializer
    {
        enum Field {
            OnOpened,
            OnClosed,
        }

        impl serde::de::Deserialize for Field {
            fn deserialize<D>(deserializer: &mut D) -> Result<Field, D::Error>
                where D: serde::de::Deserializer
            {
                struct FieldVisitor;

                impl serde::de::Visitor for FieldVisitor {
                    type Value = Field;

                    fn visit_str<E>(&mut self, value: &str) -> Result<Field, E>
                        where E: serde::de::Error
                    {
                        match value {
                            "on_opened" => Ok(Field::OnOpened),
                            "on_closed" => Ok(Field::OnClosed),
                            _ => Err(serde::de::Error::syntax(&format!("Unexpected field: {}", value))),
                        }
                    }
                }

                deserializer.visit(FieldVisitor)
            }
        }

        struct ExecConditionVisitor;

        impl serde::de::Visitor for ExecConditionVisitor {
            type Value = ExecCondition;

            fn visit_map<V>(&mut self, mut visitor: V) -> Result<ExecCondition, V::Error>
                where V: serde::de::MapVisitor
            {
                let mut on_opened: Option<bool> = ON_OPENED_DEFAULT;
                let mut on_closed: Option<bool> = ON_CLOSED_DEFAULT;

                loop {
                    match try!(visitor.visit_key()) {
                        Some(Field::OnOpened) => {
                            on_opened = Some(try!(visitor.visit_value()));
                        }
                        Some(Field::OnClosed) => {
                            on_closed = Some(try!(visitor.visit_value()));
                        }
                        None => {
                            break;
                        }
                    }
                }

                try!(visitor.end());

                Ok(ExecCondition{on_opened: on_opened, on_closed: on_closed})
            }
        }
        deserializer.visit_struct("ExecCondition", &[], ExecConditionVisitor)
    }
}
<commit_msg>ExecCondition: simplify loop in visit_map()<commit_after>use serde;
use super::{ActionType, ExecCondition, ON_CLOSED_DEFAULT, ON_OPENED_DEFAULT};

#[cfg(test)]
mod test;

impl serde::de::Deserialize for ActionType {
    fn deserialize<D>(deserializer: &mut D) -> Result<ActionType, D::Error>
        where D: serde::de::Deserializer
    {
        enum Field {
            Message,
        }

    impl serde::de::Deserialize for Field {
            #[inline]
            fn deserialize<D>(deserializer: &mut D) -> Result<Field, D::Error>
                where D: serde::de::Deserializer
            {
                struct FieldVisitor;

                impl serde::de::Visitor for FieldVisitor {
                    type Value = Field;

                    fn visit_str<E>(&mut self, value: &str) -> Result<Field, E>
                        where E: serde::de::Error
                    {
                        match value {
                            "message" => Ok(Field::Message),
                            _ => Err(serde::de::Error::unknown_field(value)),
                        }
                    }
                }

                deserializer.visit(FieldVisitor)
            }
        }

        struct Visitor;

        impl serde::de::EnumVisitor for Visitor {
            type Value = ActionType;

            fn visit<V>(&mut self, mut visitor: V) -> Result<ActionType, V::Error>
                where V: serde::de::VariantVisitor
            {
                match try!(visitor.visit_variant()) {
                    Field::Message => {
                        let value = try!(visitor.visit_newtype());
                        Ok(ActionType::Message(value))
                    }
                }
            }
        }

        const VARIANTS: &'static [&'static str] = &["message"];

        deserializer.visit_enum("ActionType", VARIANTS, Visitor)
    }
}

impl serde::de::Deserialize for ExecCondition {
    fn deserialize<D>(deserializer: &mut D) -> Result<ExecCondition, D::Error>
        where D: serde::de::Deserializer
    {
        enum Field {
            OnOpened,
            OnClosed,
        }

        impl serde::de::Deserialize for Field {
            fn deserialize<D>(deserializer: &mut D) -> Result<Field, D::Error>
                where D: serde::de::Deserializer
            {
                struct FieldVisitor;

                impl serde::de::Visitor for FieldVisitor {
                    type Value = Field;

                    fn visit_str<E>(&mut self, value: &str) -> Result<Field, E>
                        where E: serde::de::Error
                    {
                        match value {
                            "on_opened" => Ok(Field::OnOpened),
                            "on_closed" => Ok(Field::OnClosed),
                            _ => Err(serde::de::Error::syntax(&format!("Unexpected field: {}", value))),
                        }
                    }
                }

                deserializer.visit(FieldVisitor)
            }
        }

        struct ExecConditionVisitor;

        impl serde::de::Visitor for ExecConditionVisitor {
            type Value = ExecCondition;

            fn visit_map<V>(&mut self, mut visitor: V) -> Result<ExecCondition, V::Error>
                where V: serde::de::MapVisitor
            {
                let mut on_opened: Option<bool> = ON_OPENED_DEFAULT;
                let mut on_closed: Option<bool> = ON_CLOSED_DEFAULT;

                while let Some(field) = try!(visitor.visit_key()) {
                    match field {
                        Field::OnOpened => on_opened = Some(try!(visitor.visit_value())),
                        Field::OnClosed => on_closed = Some(try!(visitor.visit_value()))
                    }
                }

                try!(visitor.end());

                Ok(ExecCondition{on_opened: on_opened, on_closed: on_closed})
            }
        }
        deserializer.visit_struct("ExecCondition", &[], ExecConditionVisitor)
    }
}
<|endoftext|>


<commit_before>//! Renders a textured quad to a window and adjusts the GPU buffer that contains the viewport's
//! height and width whenever the window is resized.

use std::path::PathBuf;

use cocoa::{appkit::NSView, base::id as cocoa_id};
use winit::dpi::LogicalSize;
use winit::event_loop::{ControlFlow, EventLoop};
use winit::platform::macos::WindowExtMacOS;
use winit::window::Window;

use cocoa::foundation::NSRange;
use metal::{
    Buffer, CGSize, CommandQueue, CoreAnimationLayer, Device, Library, MTLClearColor,
    MTLLoadAction, MTLOrigin, MTLPixelFormat, MTLPrimitiveType, MTLRegion, MTLResourceOptions,
    MTLSize, MTLStoreAction, RenderPassDescriptor, RenderPassDescriptorRef,
    RenderPipelineDescriptor, RenderPipelineState, Texture, TextureDescriptor, TextureRef,
};
use shader_bindings::{
    TextureIndex_TextureIndexBaseColor as TextureBaseColorIdx, TexturedVertex,
    VertexInputIndex_VertexInputIndexVertices as VerticesBufferIdx,
    VertexInputIndex_VertexInputIndexViewportSize as ViewportSizeBufferIdx,
};
use winit::event::{Event, WindowEvent};

mod shader_bindings;

const INITIAL_WINDOW_WIDTH: u32 = 800;
const INITIAL_WINDOW_HEIGHT: u32 = 600;
const PIXEL_FORMAT: MTLPixelFormat = MTLPixelFormat::BGRA8Unorm;

fn main() {
    let event_loop = EventLoop::new();
    let window = init_window(&event_loop);

    let device = Device::system_default().expect("No device found");
    let library = device.new_library_with_file(shader_metallib()).unwrap();

    let vertex_data = vertices();
    let vertex_buffer = device.new_buffer_with_data(
        vertex_data.as_ptr() as *const _,
        (vertex_data.len() * std::mem::size_of::<TexturedVertex>()) as u64,
        MTLResourceOptions::CPUCacheModeDefaultCache | MTLResourceOptions::StorageModeManaged,
    );

    let viewport_size_buffer = device.new_buffer(
        8,
        MTLResourceOptions::CPUCacheModeDefaultCache | MTLResourceOptions::StorageModeManaged,
    );
    let viewport_size = (window.inner_size().width, window.inner_size().height);
    update_viewport_size_buffer(&viewport_size_buffer, viewport_size);

    let texture_to_render = create_texture_to_display(&device);

    let layer = get_window_layer(&window, &device);
    let pipeline_state = prepare_pipeline_state(&device, &library);
    let command_queue = device.new_command_queue();

    event_loop.run(move |event, _, control_flow| {
        *control_flow = ControlFlow::Poll;

        match event {
            Event::WindowEvent { event, .. } => {
                handle_window_event(event, control_flow, &layer, &viewport_size_buffer)
            }
            Event::MainEventsCleared => window.request_redraw(),
            Event::RedrawRequested(_) => redraw(
                &layer,
                &pipeline_state,
                &command_queue,
                &vertex_buffer,
                &viewport_size_buffer,
                &texture_to_render,
            ),
            _ => {}
        }
    });
}

// The `TexturedVertex` type is generated by `build.rs` by parsing `shader_types.h`
// using rust-bindgen
fn vertices() -> [TexturedVertex; 6] {
    [
        textured_vertex([-200., -200.], [0., 1.]),
        textured_vertex([200., -200.], [1., 1.]),
        textured_vertex([200., 200.], [1., 0.]),
        textured_vertex([-200., -200.], [0., 1.]),
        textured_vertex([200., 200.], [1., 0.]),
        textured_vertex([-200., 200.], [0., 0.]),
    ]
}

fn textured_vertex(position: [f32; 2], texture_coord: [f32; 2]) -> TexturedVertex {
    unsafe {
        // The metal shader is expecting two floats, but the rust-bindgen generated
        // type is a u64.
        //
        // So, we transmute the 2 floats into a u64 so that when the shader receives
        // these 64 bits they'll be interpreted as a `vector_float2`.
        TexturedVertex {
            position: std::mem::transmute(position),
            texture_coord: std::mem::transmute(texture_coord),
        }
    }
}

fn create_texture_to_display(device: &Device) -> Texture {
    let img = include_bytes!("../gfx-rs.png");
    let decoder = png::Decoder::new(img.as_ref());
    let (info, mut reader) = decoder.read_info().unwrap();

    let mut buf = vec![0; info.buffer_size()];
    reader.next_frame(&mut buf).unwrap();

    let (width, height) = (info.width as u64, info.height as u64);

    for idx in 0..buf.len() / 4 {
        let idx = idx * 4;

        buf.swap(idx, idx + 2);
    }

    let texture = TextureDescriptor::new();
    texture.set_width(width);
    texture.set_height(height);
    texture.set_pixel_format(PIXEL_FORMAT);

    let texture = device.new_texture(&texture);

    texture.replace_region(
        MTLRegion {
            origin: MTLOrigin { x: 0, y: 0, z: 0 },
            size: MTLSize {
                width,
                height,
                depth: 1,
            },
        },
        0,
        width * 4,
        buf.as_ptr() as _,
    );

    texture
}

fn init_window(event_loop: &EventLoop<()>) -> Window {
    let window_size = LogicalSize::new(INITIAL_WINDOW_WIDTH, INITIAL_WINDOW_HEIGHT);

    winit::window::WindowBuilder::new()
        .with_inner_size(window_size)
        .with_title("Creating and Sampling Textures Example".to_string())
        .build(event_loop)
        .unwrap()
}

fn get_window_layer(window: &Window, device: &Device) -> CoreAnimationLayer {
    let layer = CoreAnimationLayer::new();

    layer.set_device(device);
    layer.set_pixel_format(PIXEL_FORMAT);
    // Presenting with transactions isn't necessary since we aren't synchonizing with other UIKit
    // draw calls.
    // https://developer.apple.com/documentation/quartzcore/cametallayer/1478157-presentswithtransaction
    layer.set_presents_with_transaction(false);

    layer.set_drawable_size(CGSize::new(
        window.inner_size().width as f64,
        window.inner_size().height as f64,
    ));

    unsafe {
        let view = window.ns_view() as cocoa_id;
        view.setWantsLayer(true as _);
        view.setLayer(std::mem::transmute(layer.as_ref()));
    }

    layer
}

fn shader_metallib() -> PathBuf {
    PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("shaders.metallib")
}

fn prepare_pipeline_state(device: &Device, library: &Library) -> RenderPipelineState {
    let pipeline_state_descriptor = RenderPipelineDescriptor::new();

    let vertex_shader = library.get_function("quad_vertex", None).unwrap();
    let fragment_shader = library.get_function("sampling_shader", None).unwrap();

    pipeline_state_descriptor.set_vertex_function(Some(&vertex_shader));
    pipeline_state_descriptor.set_fragment_function(Some(&fragment_shader));

    pipeline_state_descriptor
        .color_attachments()
        .object_at(0)
        .unwrap()
        .set_pixel_format(PIXEL_FORMAT);

    device
        .new_render_pipeline_state(&pipeline_state_descriptor)
        .unwrap()
}

fn handle_window_event(
    event: WindowEvent,
    control_flow: &mut ControlFlow,
    layer: &CoreAnimationLayer,
    viewport_size_buffer: &Buffer,
) {
    match event {
        WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit,
        WindowEvent::Resized(size) => {
            layer.set_drawable_size(CGSize::new(size.width as f64, size.height as f64));

            update_viewport_size_buffer(viewport_size_buffer, (size.width, size.height));
        }
        _ => {}
    }
}

fn update_viewport_size_buffer(viewport_size_buffer: &Buffer, size: (u32, u32)) {
    let contents = viewport_size_buffer.contents();
    let viewport_size: [u32; 2] = [size.0, size.1];
    let byte_count = (viewport_size.len() * std::mem::size_of::<u32>()) as usize;

    unsafe {
        std::ptr::copy(viewport_size.as_ptr(), contents as *mut u32, byte_count);
    }
    viewport_size_buffer.did_modify_range(NSRange::new(0, byte_count as u64));
}

fn redraw(
    layer: &CoreAnimationLayer,
    pipeline_state: &RenderPipelineState,
    command_queue: &CommandQueue,
    vertex_buffer: &Buffer,
    viewport_size_buffer: &Buffer,
    texture_to_render: &TextureRef,
) {
    let drawable = match layer.next_drawable() {
        Some(drawable) => drawable,
        None => return,
    };

    let render_pass_descriptor = RenderPassDescriptor::new();
    prepare_render_pass_descriptor(&render_pass_descriptor, drawable.texture());

    let command_buffer = command_queue.new_command_buffer();

    let encoder = command_buffer.new_render_command_encoder(&render_pass_descriptor);
    encoder.set_render_pipeline_state(&pipeline_state);

    encoder.set_vertex_buffer(VerticesBufferIdx as u64, Some(vertex_buffer), 0);
    encoder.set_vertex_buffer(ViewportSizeBufferIdx as u64, Some(viewport_size_buffer), 0);
    encoder.set_fragment_texture(TextureBaseColorIdx as u64, Some(texture_to_render));

    encoder.draw_primitives(MTLPrimitiveType::Triangle, 0, 6);
    encoder.end_encoding();

    command_buffer.present_drawable(&drawable);
    command_buffer.commit();
}

fn prepare_render_pass_descriptor(descriptor: &RenderPassDescriptorRef, texture: &TextureRef) {
    let color_attachment = descriptor.color_attachments().object_at(0).unwrap();

    color_attachment.set_texture(Some(texture));
    color_attachment.set_load_action(MTLLoadAction::Clear);
    color_attachment.set_clear_color(MTLClearColor::new(0.2, 0.5, 0.8, 1.0));
    color_attachment.set_store_action(MTLStoreAction::Store);
}
<commit_msg>Fix texture example<commit_after>//! Renders a textured quad to a window and adjusts the GPU buffer that contains the viewport's
//! height and width whenever the window is resized.

use std::path::PathBuf;

use cocoa::{appkit::NSView, base::id as cocoa_id};
use winit::dpi::LogicalSize;
use winit::event_loop::{ControlFlow, EventLoop};
use winit::platform::macos::WindowExtMacOS;
use winit::window::Window;

use cocoa::foundation::NSRange;
use metal::{
    Buffer, CGSize, CommandQueue, CoreAnimationLayer, Device, Library, MTLClearColor,
    MTLLoadAction, MTLOrigin, MTLPixelFormat, MTLPrimitiveType, MTLRegion, MTLResourceOptions,
    MTLSize, MTLStoreAction, RenderPassDescriptor, RenderPassDescriptorRef,
    RenderPipelineDescriptor, RenderPipelineState, Texture, TextureDescriptor, TextureRef,
};
use shader_bindings::{
    TextureIndex_TextureIndexBaseColor as TextureBaseColorIdx, TexturedVertex,
    VertexInputIndex_VertexInputIndexVertices as VerticesBufferIdx,
    VertexInputIndex_VertexInputIndexViewportSize as ViewportSizeBufferIdx,
};
use winit::event::{Event, WindowEvent};

mod shader_bindings;

const INITIAL_WINDOW_WIDTH: u32 = 800;
const INITIAL_WINDOW_HEIGHT: u32 = 600;
const PIXEL_FORMAT: MTLPixelFormat = MTLPixelFormat::BGRA8Unorm;

fn main() {
    let event_loop = EventLoop::new();
    let window = init_window(&event_loop);

    let device = Device::system_default().expect("No device found");
    let library = device.new_library_with_file(shader_metallib()).unwrap();

    let vertex_data = vertices();
    let vertex_buffer = device.new_buffer_with_data(
        vertex_data.as_ptr() as *const _,
        (vertex_data.len() * std::mem::size_of::<TexturedVertex>()) as u64,
        MTLResourceOptions::CPUCacheModeDefaultCache | MTLResourceOptions::StorageModeManaged,
    );

    let viewport_size_buffer = device.new_buffer(
        8,
        MTLResourceOptions::CPUCacheModeDefaultCache | MTLResourceOptions::StorageModeManaged,
    );
    let viewport_size = (window.inner_size().width, window.inner_size().height);
    update_viewport_size_buffer(&viewport_size_buffer, viewport_size);

    let texture_to_render = create_texture_to_display(&device);

    let layer = get_window_layer(&window, &device);
    let pipeline_state = prepare_pipeline_state(&device, &library);
    let command_queue = device.new_command_queue();

    event_loop.run(move |event, _, control_flow| {
        *control_flow = ControlFlow::Poll;

        match event {
            Event::WindowEvent { event, .. } => {
                handle_window_event(event, control_flow, &layer, &viewport_size_buffer)
            }
            Event::MainEventsCleared => window.request_redraw(),
            Event::RedrawRequested(_) => redraw(
                &layer,
                &pipeline_state,
                &command_queue,
                &vertex_buffer,
                &viewport_size_buffer,
                &texture_to_render,
            ),
            _ => {}
        }
    });
}

// The `TexturedVertex` type is generated by `build.rs` by parsing `shader_types.h`
// using rust-bindgen
fn vertices() -> [TexturedVertex; 6] {
    [
        textured_vertex([-200., -200.], [0., 1.]),
        textured_vertex([200., -200.], [1., 1.]),
        textured_vertex([200., 200.], [1., 0.]),
        textured_vertex([-200., -200.], [0., 1.]),
        textured_vertex([200., 200.], [1., 0.]),
        textured_vertex([-200., 200.], [0., 0.]),
    ]
}

fn textured_vertex(position: [f32; 2], texture_coord: [f32; 2]) -> TexturedVertex {
    unsafe {
        // The metal shader is expecting two floats, but the rust-bindgen generated
        // type is a u64.
        //
        // So, we transmute the 2 floats into a u64 so that when the shader receives
        // these 64 bits they'll be interpreted as a `vector_float2`.
        TexturedVertex {
            position: std::mem::transmute(position),
            texture_coord: std::mem::transmute(texture_coord),
        }
    }
}

fn create_texture_to_display(device: &Device) -> Texture {
    let img = include_bytes!("../gfx-rs.png");
    let decoder = png::Decoder::new(img.as_ref());
    let (info, mut reader) = decoder.read_info().unwrap();

    let mut buf = vec![0; info.buffer_size()];
    reader.next_frame(&mut buf).unwrap();

    let (width, height) = (info.width as u64, info.height as u64);

    for idx in 0..buf.len() / 4 {
        let idx = idx * 4;

        buf.swap(idx, idx + 2);
    }

    let texture = TextureDescriptor::new();
    texture.set_width(width);
    texture.set_height(height);
    texture.set_pixel_format(PIXEL_FORMAT);

    let texture = device.new_texture(&texture);

    texture.replace_region(
        MTLRegion {
            origin: MTLOrigin { x: 0, y: 0, z: 0 },
            size: MTLSize {
                width,
                height,
                depth: 1,
            },
        },
        0,
        buf.as_ptr() as _,
        width * 4,
    );

    texture
}

fn init_window(event_loop: &EventLoop<()>) -> Window {
    let window_size = LogicalSize::new(INITIAL_WINDOW_WIDTH, INITIAL_WINDOW_HEIGHT);

    winit::window::WindowBuilder::new()
        .with_inner_size(window_size)
        .with_title("Creating and Sampling Textures Example".to_string())
        .build(event_loop)
        .unwrap()
}

fn get_window_layer(window: &Window, device: &Device) -> CoreAnimationLayer {
    let layer = CoreAnimationLayer::new();

    layer.set_device(device);
    layer.set_pixel_format(PIXEL_FORMAT);
    // Presenting with transactions isn't necessary since we aren't synchonizing with other UIKit
    // draw calls.
    // https://developer.apple.com/documentation/quartzcore/cametallayer/1478157-presentswithtransaction
    layer.set_presents_with_transaction(false);

    layer.set_drawable_size(CGSize::new(
        window.inner_size().width as f64,
        window.inner_size().height as f64,
    ));

    unsafe {
        let view = window.ns_view() as cocoa_id;
        view.setWantsLayer(true as _);
        view.setLayer(std::mem::transmute(layer.as_ref()));
    }

    layer
}

fn shader_metallib() -> PathBuf {
    PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("shaders.metallib")
}

fn prepare_pipeline_state(device: &Device, library: &Library) -> RenderPipelineState {
    let pipeline_state_descriptor = RenderPipelineDescriptor::new();

    let vertex_shader = library.get_function("quad_vertex", None).unwrap();
    let fragment_shader = library.get_function("sampling_shader", None).unwrap();

    pipeline_state_descriptor.set_vertex_function(Some(&vertex_shader));
    pipeline_state_descriptor.set_fragment_function(Some(&fragment_shader));

    pipeline_state_descriptor
        .color_attachments()
        .object_at(0)
        .unwrap()
        .set_pixel_format(PIXEL_FORMAT);

    device
        .new_render_pipeline_state(&pipeline_state_descriptor)
        .unwrap()
}

fn handle_window_event(
    event: WindowEvent,
    control_flow: &mut ControlFlow,
    layer: &CoreAnimationLayer,
    viewport_size_buffer: &Buffer,
) {
    match event {
        WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit,
        WindowEvent::Resized(size) => {
            layer.set_drawable_size(CGSize::new(size.width as f64, size.height as f64));

            update_viewport_size_buffer(viewport_size_buffer, (size.width, size.height));
        }
        _ => {}
    }
}

fn update_viewport_size_buffer(viewport_size_buffer: &Buffer, size: (u32, u32)) {
    let contents = viewport_size_buffer.contents();
    let viewport_size: [u32; 2] = [size.0, size.1];
    let byte_count = (viewport_size.len() * std::mem::size_of::<u32>()) as usize;

    unsafe {
        std::ptr::copy(viewport_size.as_ptr(), contents as *mut u32, byte_count);
    }
    viewport_size_buffer.did_modify_range(NSRange::new(0, byte_count as u64));
}

fn redraw(
    layer: &CoreAnimationLayer,
    pipeline_state: &RenderPipelineState,
    command_queue: &CommandQueue,
    vertex_buffer: &Buffer,
    viewport_size_buffer: &Buffer,
    texture_to_render: &TextureRef,
) {
    let drawable = match layer.next_drawable() {
        Some(drawable) => drawable,
        None => return,
    };

    let render_pass_descriptor = RenderPassDescriptor::new();
    prepare_render_pass_descriptor(&render_pass_descriptor, drawable.texture());

    let command_buffer = command_queue.new_command_buffer();

    let encoder = command_buffer.new_render_command_encoder(&render_pass_descriptor);
    encoder.set_render_pipeline_state(&pipeline_state);

    encoder.set_vertex_buffer(VerticesBufferIdx as u64, Some(vertex_buffer), 0);
    encoder.set_vertex_buffer(ViewportSizeBufferIdx as u64, Some(viewport_size_buffer), 0);
    encoder.set_fragment_texture(TextureBaseColorIdx as u64, Some(texture_to_render));

    encoder.draw_primitives(MTLPrimitiveType::Triangle, 0, 6);
    encoder.end_encoding();

    command_buffer.present_drawable(&drawable);
    command_buffer.commit();
}

fn prepare_render_pass_descriptor(descriptor: &RenderPassDescriptorRef, texture: &TextureRef) {
    let color_attachment = descriptor.color_attachments().object_at(0).unwrap();

    color_attachment.set_texture(Some(texture));
    color_attachment.set_load_action(MTLLoadAction::Clear);
    color_attachment.set_clear_color(MTLClearColor::new(0.2, 0.5, 0.8, 1.0));
    color_attachment.set_store_action(MTLStoreAction::Store);
}
<|endoftext|>


<commit_before>pub(crate) use self::inner::{do_alloc, Allocator, Global};

#[cfg(feature = "nightly")]
mod inner {
    use crate::alloc::alloc::Layout;
    pub use crate::alloc::alloc::{Allocator, Global};
    use core::ptr::NonNull;

    #[allow(clippy::map_err_ignore)]
    pub fn do_alloc<A: Allocator>(alloc: &A, layout: Layout) -> Result<NonNull<u8>, ()> {
        alloc
            .allocate(layout)
            .map(|ptr| ptr.as_non_null_ptr())
            .map_err(|_| ())
    }

    #[cfg(feature = "bumpalo")]
    unsafe impl Allocator for crate::BumpWrapper<'_> {
        #[inline]
        fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, core::alloc::AllocError> {
            match self.0.try_alloc_layout(layout) {
                Ok(ptr) => Ok(NonNull::slice_from_raw_parts(ptr, layout.size())),
                Err(_) => Err(core::alloc::AllocError),
            }
        }
        #[inline]
        unsafe fn deallocate(&self, _ptr: NonNull<u8>, _layout: Layout) {}
    }
}

#[cfg(not(feature = "nightly"))]
mod inner {
    use crate::alloc::alloc::{alloc, dealloc, Layout};
    use core::ptr::NonNull;

    #[allow(clippy::missing_safety_doc)] // not exposed outside of this crate
    pub unsafe trait Allocator {
        fn allocate(&self, layout: Layout) -> Result<NonNull<u8>, ()>;
        unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout);
    }

    #[derive(Copy, Clone)]
    pub struct Global;
    unsafe impl Allocator for Global {
        #[inline]
        fn allocate(&self, layout: Layout) -> Result<NonNull<u8>, ()> {
            unsafe { NonNull::new(alloc(layout)).ok_or(()) }
        }
        #[inline]
        unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
            dealloc(ptr.as_ptr(), layout);
        }
    }
    impl Default for Global {
        #[inline]
        fn default() -> Self {
            Global
        }
    }

    pub fn do_alloc<A: Allocator>(alloc: &A, layout: Layout) -> Result<NonNull<u8>, ()> {
        alloc.allocate(layout)
    }

    #[cfg(feature = "bumpalo")]
    unsafe impl Allocator for crate::BumpWrapper<'_> {
        #[allow(clippy::map_err_ignore)]
        fn allocate(&self, layout: Layout) -> Result<NonNull<u8>, ()> {
            self.0.try_alloc_layout(layout).map_err(|_| ())
        }
        unsafe fn deallocate(&self, _ptr: NonNull<u8>, _layout: Layout) {}
    }
}
<commit_msg>Editing do_alloc for reducing LLVM IR<commit_after>pub(crate) use self::inner::{do_alloc, Allocator, Global};

#[cfg(feature = "nightly")]
mod inner {
    use crate::alloc::alloc::Layout;
    pub use crate::alloc::alloc::{Allocator, Global};
    use core::ptr::NonNull;

    #[allow(clippy::map_err_ignore)]
    pub fn do_alloc<A: Allocator>(alloc: &A, layout: Layout) -> Result<NonNull<u8>, ()> {
        match alloc.allocate(layout) {
            Ok(ptr) => Ok(ptr.as_non_null_ptr()),
            Err(_) => Err(()),
        }
    }

    #[cfg(feature = "bumpalo")]
    unsafe impl Allocator for crate::BumpWrapper<'_> {
        #[inline]
        fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, core::alloc::AllocError> {
            match self.0.try_alloc_layout(layout) {
                Ok(ptr) => Ok(NonNull::slice_from_raw_parts(ptr, layout.size())),
                Err(_) => Err(core::alloc::AllocError),
            }
        }
        #[inline]
        unsafe fn deallocate(&self, _ptr: NonNull<u8>, _layout: Layout) {}
    }
}

#[cfg(not(feature = "nightly"))]
mod inner {
    use crate::alloc::alloc::{alloc, dealloc, Layout};
    use core::ptr::NonNull;

    #[allow(clippy::missing_safety_doc)] // not exposed outside of this crate
    pub unsafe trait Allocator {
        fn allocate(&self, layout: Layout) -> Result<NonNull<u8>, ()>;
        unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout);
    }

    #[derive(Copy, Clone)]
    pub struct Global;
    unsafe impl Allocator for Global {
        #[inline]
        fn allocate(&self, layout: Layout) -> Result<NonNull<u8>, ()> {
            unsafe { NonNull::new(alloc(layout)).ok_or(()) }
        }
        #[inline]
        unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
            dealloc(ptr.as_ptr(), layout);
        }
    }
    impl Default for Global {
        #[inline]
        fn default() -> Self {
            Global
        }
    }

    pub fn do_alloc<A: Allocator>(alloc: &A, layout: Layout) -> Result<NonNull<u8>, ()> {
        alloc.allocate(layout)
    }

    #[cfg(feature = "bumpalo")]
    unsafe impl Allocator for crate::BumpWrapper<'_> {
        #[allow(clippy::map_err_ignore)]
        fn allocate(&self, layout: Layout) -> Result<NonNull<u8>, ()> {
            self.0.try_alloc_layout(layout).map_err(|_| ())
        }
        unsafe fn deallocate(&self, _ptr: NonNull<u8>, _layout: Layout) {}
    }
}
<|endoftext|>


<commit_before>// The MIT License (MIT)

// Copyright (c) 2014 Y. T. CHUNG <zonyitoo@gmail.com>

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

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

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

//! Relay server in local and server side implementations.

use std::io::{self, Read, Write};

pub use self::local::RelayLocal;
pub use self::server::RelayServer;

mod tcprelay;
#[cfg(feature = "enable-udp")]
mod udprelay;
pub mod local;
pub mod server;
mod loadbalancing;
pub mod socks5;

pub const COROUTINE_STACK_SIZE: usize = 32 * 1024; // 32KB

pub trait Relay {
    fn run(&self);
}

fn copy<R: Read, W: Write>(r: &mut R, w: &mut W, prefix: &str) -> io::Result<u64> {
    let mut buf = [0u8; 4096];
    let mut written = 0;
    loop {
        let len = match r.read(&mut buf) {
            Ok(0) => {
                trace!("{}: EOF from reader", prefix);
                return Ok(written);
            }
            Ok(len) => len,
            Err(ref e) if e.kind() == io::ErrorKind::Interrupted => continue,
            Err(e) => {
                trace!("{}: Error from reader {:?}", prefix, e);
                return Err(e);
            }
        };
        trace!("{}: Read {} bytes from reader", prefix, len);
        match w.write_all(&buf[..len]) {
            Ok(..) => {},
            Err(err) => {
                trace!("{}: Error from writer {:?}", prefix, err);
                return Err(err);
            }
        }
        trace!("{}: Write {} bytes to writer", prefix, len);
        written += len as u64;
    }
}
<commit_msg>fixed #19 by increasing stack size to 128K<commit_after>// The MIT License (MIT)

// Copyright (c) 2014 Y. T. CHUNG <zonyitoo@gmail.com>

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

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

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

//! Relay server in local and server side implementations.

use std::io::{self, Read, Write};

pub use self::local::RelayLocal;
pub use self::server::RelayServer;

mod tcprelay;
#[cfg(feature = "enable-udp")]
mod udprelay;
pub mod local;
pub mod server;
mod loadbalancing;
pub mod socks5;

pub const COROUTINE_STACK_SIZE: usize = 128 * 1024; // 128KB

pub trait Relay {
    fn run(&self);
}

fn copy<R: Read, W: Write>(r: &mut R, w: &mut W, prefix: &str) -> io::Result<u64> {
    let mut buf = [0u8; 4096];
    let mut written = 0;
    loop {
        let len = match r.read(&mut buf) {
            Ok(0) => {
                trace!("{}: EOF from reader", prefix);
                return Ok(written);
            }
            Ok(len) => len,
            Err(ref e) if e.kind() == io::ErrorKind::Interrupted => continue,
            Err(e) => {
                trace!("{}: Error from reader {:?}", prefix, e);
                return Err(e);
            }
        };
        trace!("{}: Read {} bytes from reader", prefix, len);
        match w.write_all(&buf[..len]) {
            Ok(..) => {},
            Err(err) => {
                trace!("{}: Error from writer {:?}", prefix, err);
                return Err(err);
            }
        }
        trace!("{}: Write {} bytes to writer", prefix, len);
        written += len as u64;
    }
}
<|endoftext|>


<commit_before>use bincode;

#[macro_export]
macro_rules! dispatch_rpc_service_functions {
    ($s:ty) => {
        impl $crate::rpc::RPCService for $s {
            fn dispatch(&self, data: Vec<u8>)
                -> Box<Future<Item = Vec<u8>, Error = $crate::rpc::RPCRequestError>>
                where Self: Sized
            {
                self.inner_dispatch(data)
            }
            fn register_shortcut_service(&self, service_ptr: usize, server_id: u64, service_id: u64) {
                let mut cbs = RPC_SVRS.write();
                let service = unsafe {Arc::from_raw(service_ptr as *const $s)};
                cbs.insert((server_id, service_id), service);
            }
        }
    };
}

// this macro expansion design took credits from tarpc by Google Inc.
#[macro_export]
macro_rules! service {
    (
        $(
            $(#[$attr:meta])*
            rpc $fn_name:ident( $( $arg:ident : $in_:ty ),* ) $(-> $out:ty)* $(| $error:ty)*;
        )*
    ) => {
        service! {{
            $(
                $(#[$attr])*
                rpc $fn_name( $( $arg : $in_ ),* ) $(-> $out)* $(| $error)*;
            )*
        }}
    };
    (
        {
            $(#[$attr:meta])*
            rpc $fn_name:ident( $( $arg:ident : $in_:ty ),* ); // No return, no error

            $( $unexpanded:tt )*
        }
        $( $expanded:tt )*
    ) => {
        service! {
            { $( $unexpanded )* }

            $( $expanded )*

            $(#[$attr])*
            rpc $fn_name( $( $arg : $in_ ),* ) -> () | ();
        }
    };
    (
        {
            $(#[$attr:meta])*
            rpc $fn_name:ident( $( $arg:ident : $in_:ty ),* ) -> $out:ty; //return, no error

            $( $unexpanded:tt )*
        }
        $( $expanded:tt )*
    ) => {
        service! {
            { $( $unexpanded )* }

            $( $expanded )*

            $(#[$attr])*
            rpc $fn_name( $( $arg : $in_ ),* ) -> $out | ();
        }
    };
    (
        {
            $(#[$attr:meta])*
            rpc $fn_name:ident( $( $arg:ident : $in_:ty ),* ) | $error:ty; //no return, error

            $( $unexpanded:tt )*
        }
        $( $expanded:tt )*
    ) => {
        service! {
            { $( $unexpanded )* }

            $( $expanded )*

            $(#[$attr])*
            rpc $fn_name( $( $arg : $in_ ),* ) -> () | $error;
        }
    };
    (
        {
            $(#[$attr:meta])*
            rpc $fn_name:ident( $( $arg:ident : $in_:ty ),* ) -> $out:ty | $error:ty; //return, error

            $( $unexpanded:tt )*
        }
        $( $expanded:tt )*
    ) => {
        service! {
            { $( $unexpanded )* }

            $( $expanded )*

            $(#[$attr])*
            rpc $fn_name( $( $arg : $in_ ),* ) -> $out | $error;
        }
    };
    (
        {} // all expanded
        $(
            $(#[$attr:meta])*
            rpc $fn_name:ident ( $( $arg:ident : $in_:ty ),* ) -> $out:ty | $error:ty;
        )*
    ) => {
        use std;
        use std::time::Duration;
        use std::sync::Arc;
        use $crate::utils::u8vec::*;
        use futures::{Future, future};

        lazy_static! {
            pub static ref RPC_SVRS:
            ::parking_lot::RwLock<::std::collections::BTreeMap<(u64, u64), Arc<Service>>>
            = ::parking_lot::RwLock::new(::std::collections::BTreeMap::new());
        }

        pub trait Service: RPCService {
           $(
                $(#[$attr])*
                fn $fn_name(&self, $($arg:$in_),*) -> Box<Future<Item = $out, Error = $error>>;
           )*
           fn inner_dispatch(&self, data: Vec<u8>) -> Box<Future<Item = Vec<u8>, Error = RPCRequestError>> {
               let (func_id, body) = extract_u64_head(data);
               match func_id as usize {
                   $(hash_ident!($fn_name) => {
                       let ($($arg,)*) : ($($in_,)*) = $crate::utils::bincode::deserialize(&body);
                       Box::new(
                           self.$fn_name($($arg,)*)
                               .then(|f_result| future::ok($crate::utils::bincode::serialize(&f_result)))
                               .map_err(|_:$error| RPCRequestError::Other) // in this case error it is impossible
                       )
                   }),*
                   _ => {
                       Box::new(future::err(RPCRequestError::FunctionIdNotFound))
                   }
               }
           }
        }
        pub fn get_local(server_id: u64, service_id: u64) -> Option<Arc<Service>> {
            let svrs = RPC_SVRS.read();
            match svrs.get(&(server_id, service_id)) {
                Some(s) => Some(s.clone()),
                _ => None
            }
        }
        pub struct AsyncServiceClient {
            pub service_id: u64,
            pub server_id: u64,
            pub client: Arc<RPCClient>,
        }
        impl AsyncServiceClient {
           $(
                #[allow(non_camel_case_types)]
                $(#[$attr])*
                pub fn $fn_name(&self, $($arg:&$in_),*) -> Box<Future<Item = std::result::Result<$out, $error>, Error = RPCError>> {
                    if let Some(ref local) = get_local(self.server_id, self.service_id) {
                        let local = local.clone();
                        Box::new(future::finished(local.$fn_name($($arg.clone()),*).wait()))
                    } else {
                        let req_data = ($($arg,)*);
                        let req_data_bytes = $crate::utils::bincode::serialize(&req_data);
                        let req_bytes = prepend_u64(hash_ident!($fn_name) as u64, req_data_bytes);
                        let res_bytes = self.client.send_async(self.service_id, req_bytes);
                        Box::new(res_bytes.then(|res_bytes| -> Result<std::result::Result<$out, $error>, RPCError> {
                            if let Ok(res_bytes) = res_bytes {
                                Ok($crate::utils::bincode::deserialize(&res_bytes))
                            } else {
                                Err(res_bytes.err().unwrap())
                            }
                        }))
                    }
                }
           )*
           pub fn new(service_id: u64, client: &Arc<RPCClient>) -> Arc<AsyncServiceClient> {
                Arc::new(AsyncServiceClient{
                    service_id: service_id,
                    server_id:client.server_id,
                    client: client.clone()
                })
           }
        }
    }
}

mod syntax_test {
    service! {
        rpc test(a: u32, b: u32) -> bool;
        rpc test2(a: u32);
        rpc test3(a: u32, b: u32, c: u32, d: u32);
        rpc test4(a: u32, b: u32, c: u32, d: u32) -> bool | String;
        rpc test5(a: u32, b: u32, c: u32, d: u32) | String;
    }
}

#[cfg(test)]
mod struct_test {

    #[derive(Serialize, Deserialize, Debug, Clone)]
    pub struct a {
        b: u32,
        d: u64,
        e: String,
        f: f32
    }

    service! {
        rpc test(a: a, b: u32) -> bool;
    }
}
<commit_msg>revert<commit_after>use bincode;

#[macro_export]
macro_rules! dispatch_rpc_service_functions {
    ($s:ty) => {
        impl $crate::rpc::RPCService for $s {
            fn dispatch(&self, data: Vec<u8>)
                -> Box<Future<Item = Vec<u8>, Error = $crate::rpc::RPCRequestError>>
                where Self: Sized
            {
                self.inner_dispatch(data)
            }
            fn register_shortcut_service(&self, service_ptr: usize, server_id: u64, service_id: u64) {
                let mut cbs = RPC_SVRS.write();
                let service = unsafe {Arc::from_raw(service_ptr as *const $s)};
                cbs.insert((server_id, service_id), service);
            }
        }
    };
}

// this macro expansion design took credits from tarpc by Google Inc.
#[macro_export]
macro_rules! service {
    (
        $(
            $(#[$attr:meta])*
            rpc $fn_name:ident( $( $arg:ident : $in_:ty ),* ) $(-> $out:ty)* $(| $error:ty)*;
        )*
    ) => {
        service! {{
            $(
                $(#[$attr])*
                rpc $fn_name( $( $arg : $in_ ),* ) $(-> $out)* $(| $error)*;
            )*
        }}
    };
    (
        {
            $(#[$attr:meta])*
            rpc $fn_name:ident( $( $arg:ident : $in_:ty ),* ); // No return, no error

            $( $unexpanded:tt )*
        }
        $( $expanded:tt )*
    ) => {
        service! {
            { $( $unexpanded )* }

            $( $expanded )*

            $(#[$attr])*
            rpc $fn_name( $( $arg : $in_ ),* ) -> () | ();
        }
    };
    (
        {
            $(#[$attr:meta])*
            rpc $fn_name:ident( $( $arg:ident : $in_:ty ),* ) -> $out:ty; //return, no error

            $( $unexpanded:tt )*
        }
        $( $expanded:tt )*
    ) => {
        service! {
            { $( $unexpanded )* }

            $( $expanded )*

            $(#[$attr])*
            rpc $fn_name( $( $arg : $in_ ),* ) -> $out | ();
        }
    };
    (
        {
            $(#[$attr:meta])*
            rpc $fn_name:ident( $( $arg:ident : $in_:ty ),* ) | $error:ty; //no return, error

            $( $unexpanded:tt )*
        }
        $( $expanded:tt )*
    ) => {
        service! {
            { $( $unexpanded )* }

            $( $expanded )*

            $(#[$attr])*
            rpc $fn_name( $( $arg : $in_ ),* ) -> () | $error;
        }
    };
    (
        {
            $(#[$attr:meta])*
            rpc $fn_name:ident( $( $arg:ident : $in_:ty ),* ) -> $out:ty | $error:ty; //return, error

            $( $unexpanded:tt )*
        }
        $( $expanded:tt )*
    ) => {
        service! {
            { $( $unexpanded )* }

            $( $expanded )*

            $(#[$attr])*
            rpc $fn_name( $( $arg : $in_ ),* ) -> $out | $error;
        }
    };
    (
        {} // all expanded
        $(
            $(#[$attr:meta])*
            rpc $fn_name:ident ( $( $arg:ident : $in_:ty ),* ) -> $out:ty | $error:ty;
        )*
    ) => {
        use std;
        use std::time::Duration;
        use std::sync::Arc;
        use $crate::rpc::*;
        use $crate::utils::u8vec::*;
        use futures::{Future, future};

        lazy_static! {
            pub static ref RPC_SVRS:
            ::parking_lot::RwLock<::std::collections::BTreeMap<(u64, u64), Arc<Service>>>
            = ::parking_lot::RwLock::new(::std::collections::BTreeMap::new());
        }

        pub trait Service: RPCService {
           $(
                $(#[$attr])*
                fn $fn_name(&self, $($arg:$in_),*) -> Box<Future<Item = $out, Error = $error>>;
           )*
           fn inner_dispatch(&self, data: Vec<u8>) -> Box<Future<Item = Vec<u8>, Error = RPCRequestError>> {
               let (func_id, body) = extract_u64_head(data);
               match func_id as usize {
                   $(hash_ident!($fn_name) => {
                       let ($($arg,)*) : ($($in_,)*) = $crate::utils::bincode::deserialize(&body);
                       Box::new(
                           self.$fn_name($($arg,)*)
                               .then(|f_result| future::ok($crate::utils::bincode::serialize(&f_result)))
                               .map_err(|_:$error| RPCRequestError::Other) // in this case error it is impossible
                       )
                   }),*
                   _ => {
                       Box::new(future::err(RPCRequestError::FunctionIdNotFound))
                   }
               }
           }
        }
        pub fn get_local(server_id: u64, service_id: u64) -> Option<Arc<Service>> {
            let svrs = RPC_SVRS.read();
            match svrs.get(&(server_id, service_id)) {
                Some(s) => Some(s.clone()),
                _ => None
            }
        }
        pub struct AsyncServiceClient {
            pub service_id: u64,
            pub server_id: u64,
            pub client: Arc<RPCClient>,
        }
        impl AsyncServiceClient {
           $(
                #[allow(non_camel_case_types)]
                $(#[$attr])*
                pub fn $fn_name(&self, $($arg:&$in_),*) -> Box<Future<Item = std::result::Result<$out, $error>, Error = RPCError>> {
                    if let Some(ref local) = get_local(self.server_id, self.service_id) {
                        let local = local.clone();
                        Box::new(future::finished(local.$fn_name($($arg.clone()),*).wait()))
                    } else {
                        let req_data = ($($arg,)*);
                        let req_data_bytes = $crate::utils::bincode::serialize(&req_data);
                        let req_bytes = prepend_u64(hash_ident!($fn_name) as u64, req_data_bytes);
                        let res_bytes = self.client.send_async(self.service_id, req_bytes);
                        Box::new(res_bytes.then(|res_bytes| -> Result<std::result::Result<$out, $error>, RPCError> {
                            if let Ok(res_bytes) = res_bytes {
                                Ok($crate::utils::bincode::deserialize(&res_bytes))
                            } else {
                                Err(res_bytes.err().unwrap())
                            }
                        }))
                    }
                }
           )*
           pub fn new(service_id: u64, client: &Arc<RPCClient>) -> Arc<AsyncServiceClient> {
                Arc::new(AsyncServiceClient{
                    service_id: service_id,
                    server_id:client.server_id,
                    client: client.clone()
                })
           }
        }
    }
}

mod syntax_test {
    service! {
        rpc test(a: u32, b: u32) -> bool;
        rpc test2(a: u32);
        rpc test3(a: u32, b: u32, c: u32, d: u32);
        rpc test4(a: u32, b: u32, c: u32, d: u32) -> bool | String;
        rpc test5(a: u32, b: u32, c: u32, d: u32) | String;
    }
}

#[cfg(test)]
mod struct_test {

    #[derive(Serialize, Deserialize, Debug, Clone)]
    pub struct a {
        b: u32,
        d: u64,
        e: String,
        f: f32
    }

    service! {
        rpc test(a: a, b: u32) -> bool;
    }
}
<|endoftext|>


<commit_before>extern crate timebomb;
extern crate zmq;

use std::thread;
use std::str;
use timebomb::timeout_ms;

#[test]
fn test_inproc() {
    timeout_ms(|| {
        shared_context("inproc://pub");
    }, 10000);
}

#[test]
fn test_tcp() {
    timeout_ms(|| {
        shared_context("tcp://127.0.0.1:*");
    }, 10000);
}

fn shared_context(address: &str) {
    let ctx = zmq::Context::new();

    let push_socket = ctx.socket(zmq::PUSH).unwrap();
    push_socket.bind(address).unwrap();
    let endpoint = push_socket.get_last_endpoint().unwrap().unwrap();
    let worker1 = fork(&ctx, endpoint);

    push_socket.send(b"Message1", 0).unwrap();

    worker1.join().unwrap();
}

fn fork(ctx: &zmq::Context, endpoint: String) -> thread::JoinHandle<()> {
    let w_ctx = ctx.clone();
    thread::spawn(move || { worker(&w_ctx, &endpoint); })
}

fn worker(ctx: &zmq::Context, endpoint: &str) {
    let pull_socket = connect_socket(ctx, zmq::PULL, endpoint).unwrap();

    let msg = pull_socket.recv_msg(0).unwrap();
    assert_eq!(&msg[..], b"Message1");
}

fn connect_socket(ctx: &zmq::Context,
                  typ: zmq::SocketType,
                  address: &str) -> Result<zmq::Socket, zmq::Error> {
    ctx.socket(typ).and_then(|socket| socket.connect(address).map(|_| socket))
}
<commit_msg>Extend shared-context test<commit_after>//! These are all tests using PUSH/PULL sockets created from a shared
//! context to connect two threads. As a compile-time test, this
//! creates one socket from a context, and passes this context to the
//! child thread, along with the endpoint address to connect to. The
//! second socket is the created in the child thread.

extern crate timebomb;
extern crate zmq;

use std::thread;
use std::str;
use timebomb::timeout_ms;

// TODO: factor out `test!` and use it here

#[test]
fn test_inproc() {
    timeout_ms(|| {
        run("inproc://pub", check_recv);
    }, 10000);
}

#[test]
fn test_tcp() {
    timeout_ms(|| {
        run("tcp://127.0.0.1:*", check_recv);
    }, 10000);
}

#[test]
fn test_poll_inproc() {
    timeout_ms(|| {
        run("inproc://pub", check_poll);
    }, 10000);
}

#[test]
fn test_poll_tcp() {
    timeout_ms(|| {
        run("tcp://127.0.0.1:*", check_poll);
    }, 10000);
}

fn run<F>(address: &str, worker: F)
    where F: Fn(zmq::Context, zmq::Socket) + Send + 'static
{
    let ctx = zmq::Context::new();

    let push_socket = ctx.socket(zmq::PUSH).unwrap();
    push_socket.bind(address).unwrap();
    let endpoint = push_socket.get_last_endpoint().unwrap().unwrap();

    let child = {
        let w_ctx = ctx.clone();
        thread::spawn(move || {
            let pull_socket = connect_socket(&w_ctx, zmq::PULL, &endpoint).unwrap();
            worker(w_ctx, pull_socket);
        })
    };

    push_socket.send(b"Message1", 0).unwrap();

    child.join().unwrap();
}

fn check_poll(ctx: zmq::Context, pull_socket: zmq::Socket) {
    {
        let mut poll_items = vec![pull_socket.as_poll_item(zmq::POLLIN)];
        assert_eq!(zmq::poll(&mut poll_items, 1000).unwrap(), 1);
        assert_eq!(poll_items[0].get_revents(), zmq::POLLIN);
    }

    check_recv(ctx, pull_socket);
}

fn check_recv(_ctx: zmq::Context, pull_socket: zmq::Socket) {
    let msg = pull_socket.recv_msg(0).unwrap();
    assert_eq!(&msg[..], b"Message1");
}

fn connect_socket(ctx: &zmq::Context,
                  typ: zmq::SocketType,
                  address: &str) -> Result<zmq::Socket, zmq::Error> {
    ctx.socket(typ).and_then(|socket| socket.connect(address).map(|_| socket))
}
<|endoftext|>


<commit_before>#![feature(phase)]

extern crate fuse;
#[phase(plugin)]
extern crate json_macros;
extern crate time;
extern crate libc;
extern crate serialize;

use std::io::{FileType, USER_FILE, USER_DIR};
use std::mem;
use std::os;
use libc::{ENOENT, ENOSYS};
use time::Timespec;
use fuse::{FileAttr, Filesystem, Request, ReplyAttr, ReplyEntry, ReplyDirectory};
use serialize::json;

struct JsonFilesystem {
    tree: json::Object,
}

impl Filesystem for JsonFilesystem {
    fn getattr(&mut self, _req: &Request, ino: u64, reply: ReplyAttr) {
        println!("getattr(ino={})", ino);
        let mut attr: FileAttr = unsafe { mem::zeroed() };
        let ttl = Timespec::new(1, 0);
        if ino == 1 {
            attr.ino = 1;
            attr.kind = FileType::Directory;
            attr.perm = USER_DIR;
            reply.attr(&ttl, &attr);
        } else {
            let tree_index = (ino - 2) as uint;
            println!("\ttree_index={}", tree_index);
            if tree_index < self.tree.len() {
                attr.ino = ino;
                attr.kind = FileType::RegularFile;
                attr.perm = USER_FILE;
                reply.attr(&ttl, &attr);
            } else {
                reply.error(ENOSYS);
            }
        }
    }

    fn lookup(&mut self, _req: &Request, parent: u64, name: &PosixPath, reply: ReplyEntry) {
        println!("lookup(parent={}, name={})", parent, name.display());
        let mut attr: FileAttr = unsafe { mem::zeroed() };
        let ttl = Timespec::new(1, 0);
        let name = name.as_str().unwrap();
        if name == "/" {
            attr.ino = 1;
            attr.kind = FileType::Directory;
            attr.perm = USER_DIR;
            reply.entry(&ttl, &attr, 0);
        } else {
            match self.tree.get(name) {
                Some(value) => {
                    println!("\t name={}, value={}", name, value);
                    attr.kind = FileType::RegularFile;
                    attr.perm = USER_FILE;
                    // TODO: correct attributes!
                    attr.ino = 2;
                    reply.entry(&ttl, &attr, 0);
                },
                None => reply.error(ENOENT)
            };
        }
    }

    fn readdir(&mut self, _req: &Request, ino: u64, fh: u64, offset: u64, mut reply: ReplyDirectory) {
        println!("readdir(ino={}, fh={}, offset={})", ino, fh, offset);
        if ino == 1 {
            if offset == 0 {
                reply.add(1, 0, FileType::Directory, &PosixPath::new("."));
                reply.add(1, 1, FileType::Directory, &PosixPath::new(".."));
                for (i, key) in self.tree.keys().enumerate() {
                    let inode: u64 = 2 + i as u64;
                    let offset: u64 = 2 + i as u64;
                    println!("\tkey={}, inode={}, offset={}", key, inode, offset);
                    reply.add(inode, offset, FileType::RegularFile, &PosixPath::new(key));
                }
            }
            reply.ok();
        } else {
            reply.error(ENOENT);
        }
    }
}

fn main() {
    println!("24 days of Rust - fuse (day N)");
    let data = json!({
        "foo": "bar",
        "answer": 42,
    });
    let tree = data.as_object().unwrap();
    let fs = JsonFilesystem { tree: tree.clone() };
    let mountpoint = match os::args().as_slice() {
        [_, ref path] => Path::new(path),
        _ => {
            println!("Usage: {} <MOUNTPOINT>", os::args()[0]);
            return;
        }
    };
    fuse::mount(fs, &mountpoint, &[]);
}
<commit_msg>Refactored FileAttr creation.<commit_after>#![feature(phase)]

extern crate fuse;
#[phase(plugin)]
extern crate json_macros;
extern crate time;
extern crate libc;
extern crate serialize;

use std::collections::TreeMap;
use std::io::{FileType, USER_FILE, USER_DIR};
use std::mem;
use std::os;
use libc::{ENOENT};
use time::Timespec;
use fuse::{FileAttr, Filesystem, Request, ReplyAttr, ReplyEntry, ReplyDirectory};
use serialize::json;

struct JsonFilesystem {
    tree: json::Object,
    attrs: TreeMap<u64, FileAttr>,
    inodes: TreeMap<String, u64>,
}

impl JsonFilesystem {
    fn new(tree: &json::Object) -> JsonFilesystem {
        let mut attrs = TreeMap::new();
        let mut inodes = TreeMap::new();
        let mut attr: FileAttr = unsafe { mem::zeroed() };
        attr.ino = 1;
        attr.kind = FileType::Directory;
        attr.perm = USER_DIR;
        attrs.insert(1, attr);
        inodes.insert("/".to_string(), 1);
        for (i, key) in tree.keys().enumerate() {
            let mut attr: FileAttr = unsafe { mem::zeroed() };
            attr.ino = i as u64 + 2;
            attr.kind = FileType::RegularFile;
            attr.perm = USER_FILE;
            attrs.insert(attr.ino, attr);
            inodes.insert(key.clone(), attr.ino);
        }
        JsonFilesystem { tree: tree.clone(), attrs: attrs, inodes: inodes }
    }
}

impl Filesystem for JsonFilesystem {
    fn getattr(&mut self, _req: &Request, ino: u64, reply: ReplyAttr) {
        println!("getattr(ino={})", ino);
        match self.attrs.get(&ino) {
            Some(attr) => {
                let ttl = Timespec::new(1, 0);
                reply.attr(&ttl, attr);
            },
            None => reply.error(ENOENT),
        };
    }

    fn lookup(&mut self, _req: &Request, parent: u64, name: &PosixPath, reply: ReplyEntry) {
        println!("lookup(parent={}, name={})", parent, name.display());
        let inode = match self.inodes.get(name.as_str().unwrap()) {
            Some(inode) => inode,
            None => {
                reply.error(ENOENT);
                return;
            },
        };
        match self.attrs.get(inode) {
            Some(attr) => {
                let ttl = Timespec::new(1, 0);
                reply.entry(&ttl, attr, 0);
            },
            None => reply.error(ENOENT),
        };

    }

    fn readdir(&mut self, _req: &Request, ino: u64, fh: u64, offset: u64, mut reply: ReplyDirectory) {
        println!("readdir(ino={}, fh={}, offset={})", ino, fh, offset);
        if ino == 1 {
            if offset == 0 {
                reply.add(1, 0, FileType::Directory, &PosixPath::new("."));
                reply.add(1, 1, FileType::Directory, &PosixPath::new(".."));
                for (i, key) in self.tree.keys().enumerate() {
                    let inode: u64 = 2 + i as u64;
                    let offset: u64 = 2 + i as u64;
                    println!("\tkey={}, inode={}, offset={}", key, inode, offset);
                    reply.add(inode, offset, FileType::RegularFile, &PosixPath::new(key));
                }
            }
            reply.ok();
        } else {
            reply.error(ENOENT);
        }
    }
}

fn main() {
    println!("24 days of Rust - fuse (day N)");
    let data = json!({
        "foo": "bar",
        "answer": 42,
    });
    let tree = data.as_object().unwrap();
    let fs = JsonFilesystem::new(tree);
    let mountpoint = match os::args().as_slice() {
        [_, ref path] => Path::new(path),
        _ => {
            println!("Usage: {} <MOUNTPOINT>", os::args()[0]);
            return;
        }
    };
    fuse::mount(fs, &mountpoint, &[]);
}
<|endoftext|>


<commit_before>use failure::{bail, ResultExt};
use flate2::write::GzEncoder;
use std::fs::{read_link, symlink_metadata};
use std::io::{self, empty, BufWriter, Write};
use std::path::Path;
use tar::{Builder, Header};
use walkdir::WalkDir;
use xz2::write::XzEncoder;

use crate::util::*;
use crate::Result;

actor! {
    #[derive(Debug)]
    pub struct Tarballer {
        /// The input folder to be compressed.
        input: String = "package",

        /// The prefix of the tarballs.
        output: String = "./dist",

        /// The folder in which the input is to be found.
        work_dir: String = "./workdir",
    }
}

impl Tarballer {
    /// Generates the actual tarballs
    pub fn run(self) -> Result<()> {
        let tar_gz = self.output.clone() + ".tar.gz";
        let tar_xz = self.output.clone() + ".tar.xz";

        // Remove any existing files.
        for file in &[&tar_gz, &tar_xz] {
            if Path::new(file).exists() {
                remove_file(file)?;
            }
        }

        // Sort files by their suffix, to group files with the same name from
        // different locations (likely identical) and files with the same
        // extension (likely containing similar data).
        let (dirs, mut files) = get_recursive_paths(&self.work_dir, &self.input)
            .with_context(|_| "failed to collect file paths")?;
        files.sort_by(|a, b| a.bytes().rev().cmp(b.bytes().rev()));

        // Prepare the `.tar.gz` file.
        let gz = GzEncoder::new(create_new_file(tar_gz)?, flate2::Compression::best());

        // Prepare the `.tar.xz` file.
        let stream = xz2::stream::MtStreamBuilder::new()
            .threads(num_cpus::get() as u32)
            .preset(6)
            .encoder()?;
        let xz = XzEncoder::new_stream(create_new_file(tar_xz)?, stream);

        // Write the tar into both encoded files. We write all directories
        // first, so files may be directly created. (See rust-lang/rustup.rs#1092.)
        let tee = RayonTee(xz, gz);
        let buf = BufWriter::with_capacity(1024 * 1024, tee);
        let mut builder = Builder::new(buf);

        let pool = rayon::ThreadPoolBuilder::new()
            .num_threads(2)
            .build()
            .unwrap();
        pool.install(move || {
            for path in dirs {
                let src = Path::new(&self.work_dir).join(&path);
                builder
                    .append_dir(&path, &src)
                    .with_context(|_| format!("failed to tar dir '{}'", src.display()))?;
            }
            for path in files {
                let src = Path::new(&self.work_dir).join(&path);
                append_path(&mut builder, &src, &path)
                    .with_context(|_| format!("failed to tar file '{}'", src.display()))?;
            }
            let RayonTee(xz, gz) = builder
                .into_inner()
                .with_context(|_| "failed to finish writing .tar stream")?
                .into_inner()
                .ok()
                .unwrap();

            // Finish both encoded files.
            let (rxz, rgz) = rayon::join(
                || {
                    xz.finish()
                        .with_context(|_| "failed to finish .tar.xz file")
                },
                || {
                    gz.finish()
                        .with_context(|_| "failed to finish .tar.gz file")
                },
            );
            rxz?;
            rgz?;
            Ok(())
        })
    }
}

fn append_path<W: Write>(builder: &mut Builder<W>, src: &Path, path: &String) -> Result<()> {
    let stat = symlink_metadata(src)?;
    let mut header = Header::new_gnu();
    header.set_metadata(&stat);
    if stat.file_type().is_symlink() {
        let link = read_link(src)?;
        header.set_link_name(&link)?;
        builder.append_data(&mut header, path, &mut empty())?;
    } else {
        if cfg!(windows) {
            // Windows doesn't really have a mode, so `tar` never marks files executable.
            // Use an extension whitelist to update files that usually should be so.
            const EXECUTABLES: [&'static str; 4] = ["exe", "dll", "py", "sh"];
            if let Some(ext) = src.extension().and_then(|s| s.to_str()) {
                if EXECUTABLES.contains(&ext) {
                    let mode = header.mode()?;
                    header.set_mode(mode | 0o111);
                }
            }
        }
        let file = open_file(src)?;
        builder.append_data(&mut header, path, &file)?;
    }
    Ok(())
}

/// Returns all `(directories, files)` under the source path.
fn get_recursive_paths<P, Q>(root: P, name: Q) -> Result<(Vec<String>, Vec<String>)>
where
    P: AsRef<Path>,
    Q: AsRef<Path>,
{
    let root = root.as_ref();
    let name = name.as_ref();

    if !name.is_relative() && !name.starts_with(root) {
        bail!(
            "input '{}' is not in work dir '{}'",
            name.display(),
            root.display()
        );
    }

    let mut dirs = vec![];
    let mut files = vec![];
    for entry in WalkDir::new(root.join(name)) {
        let entry = entry?;
        let path = entry.path().strip_prefix(root)?;
        let path = path_to_str(&path)?;

        if entry.file_type().is_dir() {
            dirs.push(path.to_owned());
        } else {
            files.push(path.to_owned());
        }
    }
    Ok((dirs, files))
}

struct RayonTee<A, B>(A, B);

impl<A: Write + Send, B: Write + Send> Write for RayonTee<A, B> {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.write_all(buf)?;
        Ok(buf.len())
    }

    fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
        let (a, b) = (&mut self.0, &mut self.1);
        let (ra, rb) = rayon::join(|| a.write_all(buf), || b.write_all(buf));
        ra.and(rb)
    }

    fn flush(&mut self) -> io::Result<()> {
        let (a, b) = (&mut self.0, &mut self.1);
        let (ra, rb) = rayon::join(|| a.flush(), || b.flush());
        ra.and(rb)
    }
}
<commit_msg>Use at most 8 threads for the xz stream<commit_after>use failure::{bail, ResultExt};
use flate2::write::GzEncoder;
use std::fs::{read_link, symlink_metadata};
use std::io::{self, empty, BufWriter, Write};
use std::path::Path;
use tar::{Builder, Header};
use walkdir::WalkDir;
use xz2::write::XzEncoder;

use crate::util::*;
use crate::Result;

actor! {
    #[derive(Debug)]
    pub struct Tarballer {
        /// The input folder to be compressed.
        input: String = "package",

        /// The prefix of the tarballs.
        output: String = "./dist",

        /// The folder in which the input is to be found.
        work_dir: String = "./workdir",
    }
}

impl Tarballer {
    /// Generates the actual tarballs
    pub fn run(self) -> Result<()> {
        let tar_gz = self.output.clone() + ".tar.gz";
        let tar_xz = self.output.clone() + ".tar.xz";

        // Remove any existing files.
        for file in &[&tar_gz, &tar_xz] {
            if Path::new(file).exists() {
                remove_file(file)?;
            }
        }

        // Sort files by their suffix, to group files with the same name from
        // different locations (likely identical) and files with the same
        // extension (likely containing similar data).
        let (dirs, mut files) = get_recursive_paths(&self.work_dir, &self.input)
            .with_context(|_| "failed to collect file paths")?;
        files.sort_by(|a, b| a.bytes().rev().cmp(b.bytes().rev()));

        // Prepare the `.tar.gz` file.
        let gz = GzEncoder::new(create_new_file(tar_gz)?, flate2::Compression::best());

        // Prepare the `.tar.xz` file. Note that preset 6 takes about 173MB of memory
        // per thread, so we limit the number of threads to not blow out 32-bit hosts.
        // (We could be more precise with `MtStreamBuilder::memusage()` if desired.)
        let stream = xz2::stream::MtStreamBuilder::new()
            .threads(Ord::min(num_cpus::get(), 8) as u32)
            .preset(6)
            .encoder()?;
        let xz = XzEncoder::new_stream(create_new_file(tar_xz)?, stream);

        // Write the tar into both encoded files. We write all directories
        // first, so files may be directly created. (See rust-lang/rustup.rs#1092.)
        let tee = RayonTee(xz, gz);
        let buf = BufWriter::with_capacity(1024 * 1024, tee);
        let mut builder = Builder::new(buf);

        let pool = rayon::ThreadPoolBuilder::new()
            .num_threads(2)
            .build()
            .unwrap();
        pool.install(move || {
            for path in dirs {
                let src = Path::new(&self.work_dir).join(&path);
                builder
                    .append_dir(&path, &src)
                    .with_context(|_| format!("failed to tar dir '{}'", src.display()))?;
            }
            for path in files {
                let src = Path::new(&self.work_dir).join(&path);
                append_path(&mut builder, &src, &path)
                    .with_context(|_| format!("failed to tar file '{}'", src.display()))?;
            }
            let RayonTee(xz, gz) = builder
                .into_inner()
                .with_context(|_| "failed to finish writing .tar stream")?
                .into_inner()
                .ok()
                .unwrap();

            // Finish both encoded files.
            let (rxz, rgz) = rayon::join(
                || {
                    xz.finish()
                        .with_context(|_| "failed to finish .tar.xz file")
                },
                || {
                    gz.finish()
                        .with_context(|_| "failed to finish .tar.gz file")
                },
            );
            rxz?;
            rgz?;
            Ok(())
        })
    }
}

fn append_path<W: Write>(builder: &mut Builder<W>, src: &Path, path: &String) -> Result<()> {
    let stat = symlink_metadata(src)?;
    let mut header = Header::new_gnu();
    header.set_metadata(&stat);
    if stat.file_type().is_symlink() {
        let link = read_link(src)?;
        header.set_link_name(&link)?;
        builder.append_data(&mut header, path, &mut empty())?;
    } else {
        if cfg!(windows) {
            // Windows doesn't really have a mode, so `tar` never marks files executable.
            // Use an extension whitelist to update files that usually should be so.
            const EXECUTABLES: [&'static str; 4] = ["exe", "dll", "py", "sh"];
            if let Some(ext) = src.extension().and_then(|s| s.to_str()) {
                if EXECUTABLES.contains(&ext) {
                    let mode = header.mode()?;
                    header.set_mode(mode | 0o111);
                }
            }
        }
        let file = open_file(src)?;
        builder.append_data(&mut header, path, &file)?;
    }
    Ok(())
}

/// Returns all `(directories, files)` under the source path.
fn get_recursive_paths<P, Q>(root: P, name: Q) -> Result<(Vec<String>, Vec<String>)>
where
    P: AsRef<Path>,
    Q: AsRef<Path>,
{
    let root = root.as_ref();
    let name = name.as_ref();

    if !name.is_relative() && !name.starts_with(root) {
        bail!(
            "input '{}' is not in work dir '{}'",
            name.display(),
            root.display()
        );
    }

    let mut dirs = vec![];
    let mut files = vec![];
    for entry in WalkDir::new(root.join(name)) {
        let entry = entry?;
        let path = entry.path().strip_prefix(root)?;
        let path = path_to_str(&path)?;

        if entry.file_type().is_dir() {
            dirs.push(path.to_owned());
        } else {
            files.push(path.to_owned());
        }
    }
    Ok((dirs, files))
}

struct RayonTee<A, B>(A, B);

impl<A: Write + Send, B: Write + Send> Write for RayonTee<A, B> {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.write_all(buf)?;
        Ok(buf.len())
    }

    fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
        let (a, b) = (&mut self.0, &mut self.1);
        let (ra, rb) = rayon::join(|| a.write_all(buf), || b.write_all(buf));
        ra.and(rb)
    }

    fn flush(&mut self) -> io::Result<()> {
        let (a, b) = (&mut self.0, &mut self.1);
        let (ra, rb) = rayon::join(|| a.flush(), || b.flush());
        ra.and(rb)
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2015 by Stacy Prowell.  All rights reserved.
//
// Licensed under the BSD 2-Clause license.  See the file LICENSE
// that is part of this distribution.  This file may not be copied,
// modified, or distributed except according to those terms.extern

//! Provide basic definitions of terms.

use std::collections::BitVec;
//use std::tuple::Tuple1;

/// Represents root terms.
struct Root ( () );
struct Any ( () );
struct ENone ( () );
#[derive(Debug)]
struct EString( String ) ;
struct Symbol( String );
#[derive(Debug)]
struct Integer( isize );
struct Float( f64 );
struct BitString( BitVec );
struct Boolean( bool );

trait Termable<T>{
    fn new(value: T) -> Self;
    fn native(&self) -> &T;
}

impl Termable<String> for EString{
    fn new(value: String) -> EString{
        EString(value)
    }
    fn native(&self) -> &String {
        &self.0
    }
}

#[derive(Debug)]
struct Term<T> {
    value: T,
}

impl<T> Term<T>
{
    pub fn new<U>(t: U) -> Term<U> where U: Termable<T> {
        Term { value: t }
    }
    pub fn unwrap(&self) -> &T {
        &self.value
    }
}

#[test]
fn term_type_check_test() -> (){
    let termable = EString::new("Test".to_string());
    let stringterm: Term<EString> = Term::new(termable);
   // let nestedterm = Term::new(Term::new(Integer(3)));
    let stringval = &stringterm.unwrap().native();
    panic!("Intentionial panic. {:?}", stringval);
}

<commit_msg>Removed undeeded type annotation.<commit_after>// Copyright (c) 2015 by Stacy Prowell.  All rights reserved.
//
// Licensed under the BSD 2-Clause license.  See the file LICENSE
// that is part of this distribution.  This file may not be copied,
// modified, or distributed except according to those terms.extern

//! Provide basic definitions of terms.

use std::collections::BitVec;
//use std::tuple::Tuple1;

/// Represents root terms.
struct Root ( () );
struct Any ( () );
struct ENone ( () );
#[derive(Debug)]
struct EString( String ) ;
struct Symbol( String );
#[derive(Debug)]
struct Integer( isize );
struct Float( f64 );
struct BitString( BitVec );
struct Boolean( bool );

trait Termable<T>{
    fn new(value: T) -> Self;
    fn native(&self) -> &T;
}

impl Termable<String> for EString{
    fn new(value: String) -> EString{
        EString(value)
    }
    fn native(&self) -> &String {
        &self.0
    }
}

#[derive(Debug)]
struct Term<T> {
    value: T,
}

impl<T> Term<T>
{
    pub fn new<U>(t: U) -> Term<U> where U: Termable<T> {
        Term { value: t }
    }
    pub fn unwrap(&self) -> &T {
        &self.value
    }
}

#[test]
fn term_type_check_test() -> (){
    let termable = EString::new("Test".to_string());
    let stringterm = Term::new(termable);
   // let nestedterm = Term::new(Term::new(Integer(3)));
    let stringval = &stringterm.unwrap().native();
    panic!("Intentionial panic. {:?}", stringval);
}

<|endoftext|>


<commit_before>//! A small module which handles all unit testing inside LRS.
//! Structured per-component to make the testing code easier to read,
//! understand and expand in areas that are still lacking.still
//!
//! If you find sections that need more testing or where test code is not
//! understandable, please don't shy away from creating a new module
//!
//!
//! Here is also a little guide how to write new unit tests for LRS. Generally
//! test cases should rely on as little external code as possible. A test case
//! should create it's own data, work on it and then assert success or failure.
//!
//! When creating a unit test for a module or datastructure, it is most
//! important to test the basic workflow of what developers can actually
//! do with said structure, such as...
//!
//!  - Creation
//!  - Cleanup
//!  - Basic queuries
//!  - Adding new elements
//!  - Removing existing elements
//!
//! Any further functionality is then very specific to a structure but the same general workflow
//! philosophy should be used.
//!
//! For any further questions about testing, don't hesitate to contact me
#![allow(unused)]
#![feature(test)]
#![cfg(test)]

mod symbols;
mod terms;
mod clauses;
mod benches;

use terms::*;
use clause::*;
use result::*;

/// A small function which tests result creation
#[test]
fn result_create() {
    let r = result![true, ("A", false), ("B", true)];
    assert_eq!(r.symbols.get(&symbol!["A"]).unwrap(), &false);
    assert_eq!(r.symbols.get(&symbol!["B"]).unwrap(), &true);
    assert_eq!(r.solvable, true);

    println!("{:?}", r);
}<commit_msg>Fixing the test setup<commit_after>//! A small module which handles all unit testing inside LRS.
//! Structured per-component to make the testing code easier to read,
//! understand and expand in areas that are still lacking.still
//!
//! If you find sections that need more testing or where test code is not
//! understandable, please don't shy away from creating a new module
//!
//!
//! Here is also a little guide how to write new unit tests for LRS. Generally
//! test cases should rely on as little external code as possible. A test case
//! should create it's own data, work on it and then assert success or failure.
//!
//! When creating a unit test for a module or datastructure, it is most
//! important to test the basic workflow of what developers can actually
//! do with said structure, such as...
//!
//!  - Creation
//!  - Cleanup
//!  - Basic queuries
//!  - Adding new elements
//!  - Removing existing elements
//!
//! Any further functionality is then very specific to a structure but the same general workflow
//! philosophy should be used.
//!
//! For any further questions about testing, don't hesitate to contact me
#![allow(unused)]
#![feature(test)]
#![cfg(test)]

mod symbols;
mod terms;
mod clauses;

use terms::*;
use clause::*;
use result::*;

/// A small function which tests result creation
#[test]
fn result_create() {
    let r = result![true, ("A", false), ("B", true)];
    assert_eq!(r.symbols.get(&symbol!["A"]).unwrap(), &false);
    assert_eq!(r.symbols.get(&symbol!["B"]).unwrap(), &true);
    assert_eq!(r.solvable, true);

    println!("{:?}", r);
}<|endoftext|>


<commit_before>#![allow(unused_imports)]
#![allow(non_snake_case)]

use std::cmp::{max, min, Ordering};
use std::collections::*;
use std::fmt::{Debug, Formatter};
use std::io::*;
use std::ops::*;
use std::*;

// -----------------------------------------------
// Framework
// -----------------------------------------------

#[allow(unused)]
fn rl() -> String {
    let mut buf = String::new();
    io::stdin().read_line(&mut buf).unwrap();
    buf.trim_right().to_owned()
}

#[allow(unused_macros)]
macro_rules! read {
    ([$t:ty] ; $n:expr) =>
        ((0..$n).map(|_| read!([$t])).collect::<Vec<_>>());
    ($($t:ty),+ ; $n:expr) =>
        ((0..$n).map(|_| read!($($t),+)).collect::<Vec<_>>());
    ([$t:ty]) =>
        (rl().split_whitespace().map(|w| w.parse().unwrap()).collect::<Vec<$t>>());
    ($t:ty) =>
        (rl().parse::<$t>().unwrap());
    ($($t:ty),*) => {{
        let buf = rl();
        let mut w = buf.split_whitespace();
        ($(w.next().unwrap().parse::<$t>().unwrap()),*)
    }};
}

trait IteratorExt: Iterator + Sized {
    fn vec(self) -> Vec<Self::Item> {
        self.collect()
    }
}

impl<T: Iterator> IteratorExt for T {}

#[allow(unused)]
macro_rules! debug {
    ($($arg:expr),*) => {
        #[cfg(debug_assertions)]
        {
            let entries = &[
                $((
                    &stringify!($arg) as &Debug,
                    &($arg) as &Debug,
                )),*
            ];
            eprintln!("{:?}", DebugMap(entries));
        }
    };
}

#[allow(unused)]
struct DebugMap<'a>(&'a [(&'a Debug, &'a Debug)]);

impl<'a> Debug for DebugMap<'a> {
    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        let mut m = fmt.debug_map();
        for &(key, value) in self.0.iter() {
            m.entry(key, value);
        }
        m.finish()
    }
}

// -----------------------------------------------
// Polyfill
// -----------------------------------------------

#[allow(unused)]
macro_rules! eprintln {
    ($($arg:expr),*) => { _eprintln(format_args!($($arg),*)) }
}

fn _eprintln(args: fmt::Arguments) {
    let err = std::io::stderr();
    let mut err = err.lock();
    err.write_fmt(args).unwrap();
    err.write(b"\n").unwrap();
}

// -----------------------------------------------
// Solution
// -----------------------------------------------

pub fn main() {
    return;
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_ok() {
        assert_eq!(7, 1 + 2 * 3);
    }
}
<commit_msg>Rename DebugMap to MyDebugMap to avoid confusion<commit_after>#![allow(unused_imports)]
#![allow(non_snake_case)]

use std::cmp::{max, min, Ordering};
use std::collections::*;
use std::fmt::{Debug, Formatter};
use std::io::*;
use std::ops::*;
use std::*;

// -----------------------------------------------
// Framework
// -----------------------------------------------

#[allow(unused)]
fn rl() -> String {
    let mut buf = String::new();
    io::stdin().read_line(&mut buf).unwrap();
    buf.trim_right().to_owned()
}

#[allow(unused_macros)]
macro_rules! read {
    ([$t:ty] ; $n:expr) =>
        ((0..$n).map(|_| read!([$t])).collect::<Vec<_>>());
    ($($t:ty),+ ; $n:expr) =>
        ((0..$n).map(|_| read!($($t),+)).collect::<Vec<_>>());
    ([$t:ty]) =>
        (rl().split_whitespace().map(|w| w.parse().unwrap()).collect::<Vec<$t>>());
    ($t:ty) =>
        (rl().parse::<$t>().unwrap());
    ($($t:ty),*) => {{
        let buf = rl();
        let mut w = buf.split_whitespace();
        ($(w.next().unwrap().parse::<$t>().unwrap()),*)
    }};
}

trait IteratorExt: Iterator + Sized {
    fn vec(self) -> Vec<Self::Item> {
        self.collect()
    }
}

impl<T: Iterator> IteratorExt for T {}

#[allow(unused)]
macro_rules! debug {
    ($($arg:expr),*) => {
        #[cfg(debug_assertions)]
        {
            let entries = &[
                $((
                    &stringify!($arg) as &Debug,
                    &($arg) as &Debug,
                )),*
            ];
            eprintln!("{:?}", MyDebugMap(entries));
        }
    };
}

#[allow(unused)]
struct MyDebugMap<'a>(&'a [(&'a Debug, &'a Debug)]);

impl<'a> Debug for MyDebugMap<'a> {
    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        let mut m = fmt.debug_map();
        for &(key, value) in self.0.iter() {
            m.entry(key, value);
        }
        m.finish()
    }
}

// -----------------------------------------------
// Polyfill
// -----------------------------------------------

#[allow(unused)]
macro_rules! eprintln {
    ($($arg:expr),*) => { _eprintln(format_args!($($arg),*)) }
}

fn _eprintln(args: fmt::Arguments) {
    let err = std::io::stderr();
    let mut err = err.lock();
    err.write_fmt(args).unwrap();
    err.write(b"\n").unwrap();
}

// -----------------------------------------------
// Solution
// -----------------------------------------------

pub fn main() {
    return;
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_ok() {
        assert_eq!(7, 1 + 2 * 3);
    }
}
<|endoftext|>