<commit_before>extern crate gl;
extern crate glfw;
extern crate time;

use gl::types::*;
use glfw::{Context, OpenGlProfileHint, WindowHint, WindowMode};
use std::mem;

macro_rules! gl_str {
    ($string_literal:expr) => (concat!($string_literal, '\0').as_bytes().as_ptr() as *const GLchar)
}

const VERTEX_SHADER_SOURCE: &'static str = "
    #version 150

    in vec2 position;
    in vec3 color;

    out vec3 Color;

    void main() {
        Color = color;
        gl_Position = vec4(position, 0.0, 1.0);
    }
";

const FRAGMENT_SHADER_SOURCE: &'static str = "
    #version 150

    in vec3 Color;

    out vec4 out_color;

    void main() {
        out_color = vec4(Color, 1.0);
    }
";

#[derive(Copy, Clone, Debug, PartialEq)]
#[repr(C, packed)]
struct Vertex {
    // Position.
    x: GLfloat, y: GLfloat,

    // Color.
    r: GLfloat, g: GLfloat, b: GLfloat,
}

static VERTICES: [Vertex; 4] = [
    Vertex { x: -0.5, y:  0.5, r: 1.0, g: 0.0, b: 0.0 }, // Top-left
    Vertex { x:  0.5, y:  0.5, r: 0.0, g: 1.0, b: 0.0 }, // Top-right
    Vertex { x:  0.5, y: -0.5, r: 0.0, g: 0.0, b: 1.0 }, // Bottom-right
    Vertex { x: -0.5, y: -0.5, r: 1.0, g: 1.0, b: 1.0 }, // Bottom-left
];

static ELEMENTS: [GLuint; 6] = [
    0, 1, 2, // Top-right triangle
    2, 3, 0, // Bottom-left triangle
];

unsafe fn compile_shader(shader_type: GLenum, source: &str) -> Result<GLuint, String> {
    let shader = gl::CreateShader(shader_type);
    let source_ptr = source.as_bytes().as_ptr() as *const GLchar;
    let source_len = source.len() as GLint;
    gl::ShaderSource(shader, 1, &source_ptr, &source_len);
    gl::CompileShader(shader);

    let mut status = gl::FALSE as GLint;
    gl::GetShaderiv(shader, gl::COMPILE_STATUS, &mut status);

    if status == gl::TRUE as GLint {
        Ok(shader)
    } else {
        let mut log_len = 0;
        gl::GetShaderiv(shader, gl::INFO_LOG_LENGTH, &mut log_len);
        if log_len == 0 { return Err(String::new()) }

        let mut buf = Vec::with_capacity(log_len as usize);
        buf.set_len(log_len as usize - 1); // Subtract 1 to ignore the trailing null.
        gl::GetShaderInfoLog(shader, log_len, std::ptr::null_mut(),
        buf.as_mut_ptr() as *mut GLchar);

        Err(String::from_utf8_lossy(&buf).into_owned())
    }
}

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

    glfw.window_hint(WindowHint::ContextVersion(3, 2));
    glfw.window_hint(WindowHint::OpenGlProfile(OpenGlProfileHint::Core));
    glfw.window_hint(WindowHint::OpenGlForwardCompat(true));
    glfw.window_hint(WindowHint::Resizable(false));

    let (mut window, events) = glfw.create_window(800, 600, "OpenGL", WindowMode::Windowed)
        .expect("Failed to create GLFW window.");

    // Listen for keyboard events on this window.
    window.set_key_polling(true);

    // Make this window's OpenGL context the current context. This must be done before calling
    // `gl::load_with`.
    window.make_current();

    // Load OpenGL function pointers.
    gl::load_with(|symbol| window.get_proc_address(symbol));

    let vertex_shader;
    let fragment_shader;
    let shader_program;
    let mut vao = 0;
    let mut vbo = 0;
    let mut ebo = 0;

    unsafe {
        // Create a vertex array object.
        gl::GenVertexArrays(1, &mut vao);
        gl::BindVertexArray(vao);

        // Create a vertex buffer object and copy the vertex data to it.
        gl::GenBuffers(1, &mut vbo);
        gl::BindBuffer(gl::ARRAY_BUFFER, vbo);
        gl::BufferData(gl::ARRAY_BUFFER,
                       mem::size_of_val(&VERTICES) as GLsizeiptr,
                       VERTICES.as_ptr() as *const GLvoid,
                       gl::STATIC_DRAW);

        // Create an element buffer object and copy the element data to it.
        gl::GenBuffers(1, &mut ebo);
        gl::BindBuffer(gl::ELEMENT_ARRAY_BUFFER, ebo);
        gl::BufferData(gl::ELEMENT_ARRAY_BUFFER,
                       mem::size_of_val(&ELEMENTS) as GLsizeiptr,
                       ELEMENTS.as_ptr() as *const GLvoid,
                       gl::STATIC_DRAW);

        // Compile the vertex and fragment shaders.
        vertex_shader = compile_shader(gl::VERTEX_SHADER, VERTEX_SHADER_SOURCE).unwrap();
        fragment_shader = compile_shader(gl::FRAGMENT_SHADER, FRAGMENT_SHADER_SOURCE).unwrap();

        // Link the vertex and fragment shaders into a shader program.
        shader_program = gl::CreateProgram();
        gl::AttachShader(shader_program, vertex_shader);
        gl::AttachShader(shader_program, fragment_shader);
        gl::BindFragDataLocation(shader_program, 0, gl_str!("out_color"));
        gl::LinkProgram(shader_program);
        gl::UseProgram(shader_program);

        // Specify the layout of the vertex data.
        let position_attrib = gl::GetAttribLocation(shader_program, gl_str!("position"));
        gl::EnableVertexAttribArray(position_attrib as GLuint);
        gl::VertexAttribPointer(position_attrib as GLuint, 2, gl::FLOAT, gl::FALSE,
                                mem::size_of::<Vertex>() as GLint, std::ptr::null());

        let position_attrib = gl::GetAttribLocation(shader_program, gl_str!("color"));
        gl::EnableVertexAttribArray(position_attrib as GLuint);
        gl::VertexAttribPointer(position_attrib as GLuint, 3, gl::FLOAT, gl::FALSE,
                                mem::size_of::<Vertex>() as GLint,
                                std::ptr::null().offset(2 * mem::size_of::<GLfloat>() as isize));
    }

    while !window.should_close() {
        glfw.poll_events();
        for (_, event) in glfw::flush_messages(&events) {
            handle_window_event(&mut window, event);
        }

        unsafe {
            // Clear the screen to black.
            gl::ClearColor(0.0, 0.0, 0.0, 1.0);
            gl::Clear(gl::COLOR_BUFFER_BIT);

            // Draw the triangles described by the elements array.
            gl::DrawElements(gl::TRIANGLES, ELEMENTS.len() as GLint, gl::UNSIGNED_INT,
                             std::ptr::null());
        }

        window.swap_buffers();
    }

    unsafe {
        gl::DeleteProgram(shader_program);
        gl::DeleteShader(fragment_shader);
        gl::DeleteShader(vertex_shader);
        gl::DeleteBuffers(1, &vbo);
        gl::DeleteVertexArrays(1, &vao);
    }
}

fn handle_window_event(window: &mut glfw::Window, event: glfw::WindowEvent) {
    use glfw::{Action, Key, WindowEvent};

    match event {
        WindowEvent::Key(Key::Escape, _, Action::Press, _) => {
            window.set_should_close(true);
        },
        _ => {},
    }
}
<commit_msg>Simplify some code.<commit_after>extern crate gl;
extern crate glfw;
extern crate time;

use gl::types::*;
use glfw::{Context, OpenGlProfileHint, WindowHint, WindowMode};
use std::mem;
use std::ptr;

macro_rules! gl_str {
    ($string_literal:expr) => (concat!($string_literal, '\0').as_bytes().as_ptr() as *const GLchar)
}

const VERTEX_SHADER_SOURCE: &'static str = "
    #version 150

    in vec2 position;
    in vec3 color;

    out vec3 Color;

    void main() {
        Color = color;
        gl_Position = vec4(position, 0.0, 1.0);
    }
";

const FRAGMENT_SHADER_SOURCE: &'static str = "
    #version 150

    in vec3 Color;

    out vec4 out_color;

    void main() {
        out_color = vec4(Color, 1.0);
    }
";

#[derive(Copy, Clone, Debug, PartialEq)]
#[repr(C, packed)]
struct Vertex {
    // Position.
    x: GLfloat, y: GLfloat,

    // Color.
    r: GLfloat, g: GLfloat, b: GLfloat,
}

static VERTICES: [Vertex; 4] = [
    Vertex { x: -0.5, y:  0.5, r: 1.0, g: 0.0, b: 0.0 }, // Top-left
    Vertex { x:  0.5, y:  0.5, r: 0.0, g: 1.0, b: 0.0 }, // Top-right
    Vertex { x:  0.5, y: -0.5, r: 0.0, g: 0.0, b: 1.0 }, // Bottom-right
    Vertex { x: -0.5, y: -0.5, r: 1.0, g: 1.0, b: 1.0 }, // Bottom-left
];

static ELEMENTS: [GLuint; 6] = [
    0, 1, 2, // Top-right triangle
    2, 3, 0, // Bottom-left triangle
];

unsafe fn compile_shader(shader_type: GLenum, source: &str) -> Result<GLuint, String> {
    let shader = gl::CreateShader(shader_type);
    let source_ptr = source.as_bytes().as_ptr() as *const GLchar;
    let source_len = source.len() as GLint;
    gl::ShaderSource(shader, 1, &source_ptr, &source_len);
    gl::CompileShader(shader);

    let mut status = gl::FALSE as GLint;
    gl::GetShaderiv(shader, gl::COMPILE_STATUS, &mut status);

    if status == gl::TRUE as GLint {
        Ok(shader)
    } else {
        let mut log_len = 0;
        gl::GetShaderiv(shader, gl::INFO_LOG_LENGTH, &mut log_len);
        if log_len == 0 { return Err(String::new()) }

        let mut buf = Vec::with_capacity(log_len as usize);
        buf.set_len(log_len as usize - 1); // Subtract 1 to ignore the trailing null.
        gl::GetShaderInfoLog(shader, log_len, ptr::null_mut(), buf.as_mut_ptr() as *mut GLchar);

        Err(String::from_utf8_lossy(&buf).into_owned())
    }
}

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

    glfw.window_hint(WindowHint::ContextVersion(3, 2));
    glfw.window_hint(WindowHint::OpenGlProfile(OpenGlProfileHint::Core));
    glfw.window_hint(WindowHint::OpenGlForwardCompat(true));
    glfw.window_hint(WindowHint::Resizable(false));

    let (mut window, events) = glfw.create_window(800, 600, "OpenGL", WindowMode::Windowed)
        .expect("Failed to create GLFW window.");

    // Listen for keyboard events on this window.
    window.set_key_polling(true);

    // Make this window's OpenGL context the current context. This must be done before calling
    // `gl::load_with`.
    window.make_current();

    // Load OpenGL function pointers.
    gl::load_with(|symbol| window.get_proc_address(symbol));

    let vertex_shader;
    let fragment_shader;
    let shader_program;
    let mut vao = 0;
    let mut vbo = 0;
    let mut ebo = 0;

    unsafe {
        // Create a vertex array object.
        gl::GenVertexArrays(1, &mut vao);
        gl::BindVertexArray(vao);

        // Create a vertex buffer object and copy the vertex data to it.
        gl::GenBuffers(1, &mut vbo);
        gl::BindBuffer(gl::ARRAY_BUFFER, vbo);
        gl::BufferData(gl::ARRAY_BUFFER,
                       mem::size_of_val(&VERTICES) as GLsizeiptr,
                       VERTICES.as_ptr() as *const GLvoid,
                       gl::STATIC_DRAW);

        // Create an element buffer object and copy the element data to it.
        gl::GenBuffers(1, &mut ebo);
        gl::BindBuffer(gl::ELEMENT_ARRAY_BUFFER, ebo);
        gl::BufferData(gl::ELEMENT_ARRAY_BUFFER,
                       mem::size_of_val(&ELEMENTS) as GLsizeiptr,
                       ELEMENTS.as_ptr() as *const GLvoid,
                       gl::STATIC_DRAW);

        // Compile the vertex and fragment shaders.
        vertex_shader = compile_shader(gl::VERTEX_SHADER, VERTEX_SHADER_SOURCE).unwrap();
        fragment_shader = compile_shader(gl::FRAGMENT_SHADER, FRAGMENT_SHADER_SOURCE).unwrap();

        // Link the vertex and fragment shaders into a shader program.
        shader_program = gl::CreateProgram();
        gl::AttachShader(shader_program, vertex_shader);
        gl::AttachShader(shader_program, fragment_shader);
        gl::BindFragDataLocation(shader_program, 0, gl_str!("out_color"));
        gl::LinkProgram(shader_program);
        gl::UseProgram(shader_program);

        // Specify the layout of the vertex data.
        let position_attrib = gl::GetAttribLocation(shader_program, gl_str!("position"));
        gl::EnableVertexAttribArray(position_attrib as GLuint);
        gl::VertexAttribPointer(position_attrib as GLuint, 2, gl::FLOAT, gl::FALSE,
                                mem::size_of::<Vertex>() as GLint, ptr::null());

        let position_attrib = gl::GetAttribLocation(shader_program, gl_str!("color"));
        gl::EnableVertexAttribArray(position_attrib as GLuint);
        gl::VertexAttribPointer(position_attrib as GLuint, 3, gl::FLOAT, gl::FALSE,
                                mem::size_of::<Vertex>() as GLint,
                                (2 * mem::size_of::<GLfloat>()) as *const GLvoid);
    }

    while !window.should_close() {
        glfw.poll_events();
        for (_, event) in glfw::flush_messages(&events) {
            handle_window_event(&mut window, event);
        }

        unsafe {
            // Clear the screen to black.
            gl::ClearColor(0.0, 0.0, 0.0, 1.0);
            gl::Clear(gl::COLOR_BUFFER_BIT);

            // Draw the triangles described by the elements array.
            gl::DrawElements(gl::TRIANGLES, ELEMENTS.len() as GLint, gl::UNSIGNED_INT,
                             ptr::null());
        }

        window.swap_buffers();
    }

    unsafe {
        gl::DeleteProgram(shader_program);
        gl::DeleteShader(fragment_shader);
        gl::DeleteShader(vertex_shader);
        gl::DeleteBuffers(1, &vbo);
        gl::DeleteVertexArrays(1, &vao);
    }
}

fn handle_window_event(window: &mut glfw::Window, event: glfw::WindowEvent) {
    use glfw::{Action, Key, WindowEvent};

    match event {
        WindowEvent::Key(Key::Escape, _, Action::Press, _) => {
            window.set_should_close(true);
        },
        _ => {},
    }
}
<|endoftext|>


<commit_before>import core::*;

// -*- rust -*-
use std;
import std::rand;
import str;

#[test]
fn test() {
    let r1: rand::rng = rand::mk_rng();
    log r1.next();
    log r1.next();
    {
        let r2 = rand::mk_rng();
        log r1.next();
        log r2.next();
        log r1.next();
        log r1.next();
        log r2.next();
        log r2.next();
        log r1.next();
        log r1.next();
        log r1.next();
        log r2.next();
        log r2.next();
        log r2.next();
    }
    log r1.next();
    log r1.next();
}

#[test]
fn genstr() {
    let r: rand::rng = rand::mk_rng();
    log r.gen_str(10u);
    log r.gen_str(10u);
    log r.gen_str(10u);
    assert(str::char_len(r.gen_str(10u)) == 10u);
    assert(str::char_len(r.gen_str(16u)) == 16u);
}
<commit_msg>Register snapshots and switch logging over to use of log_full or #error / #debug.<commit_after>import core::*;

// -*- rust -*-
use std;
import std::rand;
import str;

#[test]
fn test() {
    let r1: rand::rng = rand::mk_rng();
    log_full(core::debug, r1.next());
    log_full(core::debug, r1.next());
    {
        let r2 = rand::mk_rng();
        log_full(core::debug, r1.next());
        log_full(core::debug, r2.next());
        log_full(core::debug, r1.next());
        log_full(core::debug, r1.next());
        log_full(core::debug, r2.next());
        log_full(core::debug, r2.next());
        log_full(core::debug, r1.next());
        log_full(core::debug, r1.next());
        log_full(core::debug, r1.next());
        log_full(core::debug, r2.next());
        log_full(core::debug, r2.next());
        log_full(core::debug, r2.next());
    }
    log_full(core::debug, r1.next());
    log_full(core::debug, r1.next());
}

#[test]
fn genstr() {
    let r: rand::rng = rand::mk_rng();
    log_full(core::debug, r.gen_str(10u));
    log_full(core::debug, r.gen_str(10u));
    log_full(core::debug, r.gen_str(10u));
    assert(str::char_len(r.gen_str(10u)) == 10u);
    assert(str::char_len(r.gen_str(16u)) == 16u);
}
<|endoftext|>


<commit_before>use hdr_histogram::simple_hdr_histogram::*;

#[derive(Debug)]
pub struct HistogramIterationValue {
    value_iterated_to: u64,
    value_iterated_from: u64,
    count_at_value_iterated_to: u64,
    count_added_in_this_iteration_step: u64,
    total_count_to_this_value: u64,
    total_value_to_this_value: u64,
    percentile: f64,
    percentile_level_iterated_to: f64,
    integer_to_double_value_conversion_ratio: f64,
}

impl Default for HistogramIterationValue {
    fn default() -> HistogramIterationValue {
        HistogramIterationValue {
            value_iterated_to: 0,
            value_iterated_from: 0,
            count_at_value_iterated_to: 0,
            count_added_in_this_iteration_step: 0,
            total_count_to_this_value: 0,
            total_value_to_this_value: 0,
            percentile: 0.0,
            percentile_level_iterated_to: 0.0,
            integer_to_double_value_conversion_ratio: 0.0,
        }
    }
}

impl HistogramIterationValue {
    fn reset(mut self) {
        self = HistogramIterationValue { ..Default::default() };
    }
}

#[derive(Debug)]
pub struct BaseHistogramIterator<T: HistogramCount> {
    histogram: SimpleHdrHistogram<T>,
    saved_histogram_total_raw_count: u64,
    current_index: usize,
    current_value_at_index: u64,
    next_value_at_index: u64,
    prev_value_iterated_to: u64,
    total_count_to_prev_index: u64,
    total_count_to_current_index: u64,
    total_value_to_current_index: u64,
    array_total_count: u64,
    count_at_this_value: T,
    fresh_sub_bucket: bool,
    current_iteration_value: HistogramIterationValue,
    integer_to_double_value_conversion_ratio: u64,
}

impl<T: HistogramCount> BaseHistogramIterator<T> {
    fn reset_iterator(mut self, histogram: SimpleHdrHistogram<T>) {
        self.histogram = histogram;
        self.saved_histogram_total_raw_count = self.histogram.get_count();
        self.array_total_count = self.histogram.get_count();
        self.integer_to_double_value_conversion_ratio = 0; //TODO should be self.histogram.integer_to_double_value_conversion_ratio
        self.current_index = 0;
        self.current_value_at_index = 0;
        self.next_value_at_index = 1 << self.histogram.get_unit_magnitude();
        self.prev_value_iterated_to = 0;
        self.total_count_to_prev_index = 0;
        self.total_count_to_current_index = 0;
        self.total_value_to_current_index = 0;
        self.count_at_this_value = T::zero();
        self.fresh_sub_bucket = true;
        self.current_iteration_value.reset();
    }
    fn exhausted_sub_buckets(&self) -> bool {
        self.current_index >= 1000 //TODO should be self.histogram.get_counts_array_length()
    }
}

impl <T: HistogramCount> Iterator for BaseHistogramIterator<T> {
    type Item = HistogramIterationValue;
    fn next(&mut self) -> Option<Self::Item> {
        //combine Java's hasNext() and next()
        //first check if has next
        if self.histogram.get_count() != self.saved_histogram_total_raw_count {
            //in Java, this threw a ConcurrentModificationException
            return None
        }
        if self.total_count_to_current_index >= self.array_total_count {
            //this means hasNext() returns false
            return None
        }

        while ! self.exhausted_sub_buckets() {
            self.count_at_this_value = match self.histogram.get_count_at_index(self.current_index) {
                Ok(val) => val,
                Err(err) => T::zero()
            };
        }

        None

    }
}

#[derive(Debug)]
pub struct RecordedValuesIterator {
    //TODO
    visited_index: u32,
}

impl Iterator for RecordedValuesIterator {
    type Item = HistogramIterationValue;
    fn next(&mut self) -> Option<Self::Item> {
        //TODO
        None
    }
}<commit_msg>iterator next complete<commit_after>use hdr_histogram::simple_hdr_histogram::*;

#[derive(Debug)]
#[derive(Clone)]
pub struct HistogramIterationValue {
    value_iterated_to: u64,
    value_iterated_from: u64,
    count_at_value_iterated_to: u64,
    count_added_in_this_iteration_step: u64,
    total_count_to_this_value: u64,
    total_value_to_this_value: u64,
    percentile: f64,
    percentile_level_iterated_to: f64,
    integer_to_double_value_conversion_ratio: f64,
}

impl Default for HistogramIterationValue {
    fn default() -> HistogramIterationValue {
        HistogramIterationValue {
            value_iterated_to: 0,
            value_iterated_from: 0,
            count_at_value_iterated_to: 0,
            count_added_in_this_iteration_step: 0,
            total_count_to_this_value: 0,
            total_value_to_this_value: 0,
            percentile: 0.0,
            percentile_level_iterated_to: 0.0,
            integer_to_double_value_conversion_ratio: 0.0,
        }
    }
}

impl HistogramIterationValue {
    fn reset(mut self) {
        self = HistogramIterationValue { ..Default::default() };
    }
    fn set(&self, value_iterated_to: u64,
    value_iterated_from: u64,
    count_at_value_iterated_to: u64,
    count_added_in_this_iteration_step: u64,
    total_count_to_this_value: u64,
    total_value_to_this_value: u64,
    percentile: f64,
    percentile_level_iterated_to: f64,
    integer_to_double_value_conversion_ratio: f64) {

    }
}

#[derive(Debug)]
pub struct BaseHistogramIterator<T: HistogramCount> {
    histogram: SimpleHdrHistogram<T>,
    saved_histogram_total_raw_count: u64,
    current_index: usize,
    current_value_at_index: u64,
    next_value_at_index: u64,
    prev_value_iterated_to: u64,
    total_count_to_prev_index: u64,
    total_count_to_current_index: u64,
    total_value_to_current_index: u64,
    array_total_count: u64,
    count_at_this_value: T,
    fresh_sub_bucket: bool,
    current_iteration_value: HistogramIterationValue,
    integer_to_double_value_conversion_ratio: f64,
    visited_index: i32,
}

impl<T: HistogramCount> BaseHistogramIterator<T> {
    fn reset_iterator(mut self, histogram: SimpleHdrHistogram<T>) {
        self.histogram = histogram;
        self.saved_histogram_total_raw_count = self.histogram.get_count();
        self.array_total_count = self.histogram.get_count();
        self.integer_to_double_value_conversion_ratio = 0.0; //TODO should be self.histogram.integer_to_double_value_conversion_ratio
        self.current_index = 0;
        self.current_value_at_index = 0;
        self.next_value_at_index = 1 << self.histogram.get_unit_magnitude();
        self.prev_value_iterated_to = 0;
        self.total_count_to_prev_index = 0;
        self.total_count_to_current_index = 0;
        self.total_value_to_current_index = 0;
        self.count_at_this_value = T::zero();
        self.fresh_sub_bucket = true;
        self.visited_index = -1;
        self.current_iteration_value.reset();
    }
    fn exhausted_sub_buckets(&self) -> bool {
        self.current_index >= 1000 //TODO should be self.histogram.get_counts_array_length()
    }

    pub fn reached_iter_level(&self) -> bool {
        let current_count = match self.histogram.get_count_at_index(self.current_index) {
            Err(err) => 0,
            Ok(the_count) => match the_count.to_u64() {
                None => 0,
                Some(the_val) => the_val
            }
        };
        (current_count != 0) && (self.visited_index != self.current_index as i32)
    }

    pub fn get_value_iterated_to(&self) -> u64 {
        self.histogram.highest_equivalent_value(self.current_value_at_index)
    }

    pub fn get_percentile_iterated_to(&self) -> f64 {
        (100.0 * self.total_count_to_current_index as f64) / self.array_total_count as f64
    }

    pub fn increment_iteration_level(&mut self) {
        self.visited_index = self.current_index as i32;
    }

    pub fn increment_sub_bucket(&mut self) {
        self.fresh_sub_bucket = true;
        self.current_index += 1;
        self.current_value_at_index = self.histogram.value_from_index(self.current_index);
        self.next_value_at_index = self.histogram.value_from_index(self.current_index + 1);
    }
}

impl <T: HistogramCount> Iterator for BaseHistogramIterator<T> {
    type Item = HistogramIterationValue;
    fn next(&mut self) -> Option<Self::Item> {
        //combine Java's hasNext() and next()
        //first check if has next
        if self.histogram.get_count() != self.saved_histogram_total_raw_count {
            //in Java, this threw a ConcurrentModificationException
            return None
        }
        if self.total_count_to_current_index >= self.array_total_count {
            //this means hasNext() returns false
            return None
        }

        while ! self.exhausted_sub_buckets() {
            self.count_at_this_value = match self.histogram.get_count_at_index(self.current_index) {
                Ok(val) => val,
                Err(err) => T::zero()
            };
            if self.fresh_sub_bucket {
                let count_u64 = match self.count_at_this_value.to_u64() {
                    None => 0,
                    Some(the_long) => the_long
                };
                self.total_count_to_current_index += count_u64;
                let highest_eq_val = self.histogram.highest_equivalent_value(self.current_value_at_index);
                self.total_value_to_current_index += count_u64 * highest_eq_val;
                self.fresh_sub_bucket = false;
                if self.reached_iter_level() {
                    let value_iterated_to = self.get_value_iterated_to();
                    self.current_iteration_value.set(
                        value_iterated_to,
                        self.prev_value_iterated_to,
                        match self.count_at_this_value.to_u64() {
                            None => 0,
                            Some(the_count) => the_count
                        },
                        (self.total_count_to_current_index - self.total_count_to_prev_index),
                        self.total_count_to_current_index,
                        self.total_value_to_current_index,
                        ((100.0 * self.total_count_to_current_index as f64) / self.array_total_count as f64),
                        self.get_percentile_iterated_to(),
                        self.integer_to_double_value_conversion_ratio);
                    self.prev_value_iterated_to = value_iterated_to;
                    self.total_count_to_prev_index = self.total_count_to_current_index;
                    self.increment_iteration_level();

                    if self.histogram.get_count() != self.saved_histogram_total_raw_count {
                        //TODO this is bad
                    }

                    return Some(self.current_iteration_value.clone())
                }
                self.increment_sub_bucket();
            }
        }
        None
    }
}

#[derive(Debug)]
pub struct RecordedValuesIterator {
    //TODO
    visited_index: u32,
}

impl Iterator for RecordedValuesIterator {
    type Item = HistogramIterationValue;
    fn next(&mut self) -> Option<Self::Item> {
        //TODO
        None
    }
}<|endoftext|>


<commit_before>//! Reader and writer for the refFlat format.
//!
//! The refFlat format is a transcript-oriented format in which each
//! transcript is denoted in a single line. It is used most prominently
//! by the [picard suite tools](https://broadinstitute.github.io/picard/)
//!
//! A minimum specification of the columns can be found here:
//! https://genome.ucsc.edu/goldenPath/gbdDescriptionsOld.html#RefFlat

use std::cmp::{max, min};
use std::collections::HashMap;
use std::convert::AsRef;
use std::io;
use std::fs;
use std::path::Path;
use std::str::FromStr;

use csv;
use itertools::{GroupBy, Itertools};

use feature::FeatureError;
use {Coord, Gene, GBuilder, Strand, Transcript, TBuilder, Error};

pub type RefFlatRow = (String, String, String, char, u64, u64, u64, u64, usize, String, String);

pub struct RefFlatRecord {
    pub gene_id: String,
    pub transcript_name: String,
    pub seq_name: String,
    pub strand_char: char,
    pub trx_start: u64,
    pub trx_end: u64,
    pub coding_start: u64,
    pub coding_end: u64,
    pub num_exons: usize,
    pub exon_starts: String,
    pub exon_ends: String,
}

impl RefFlatRecord {
    pub fn new(row: RefFlatRow) -> RefFlatRecord {
        RefFlatRecord {
            gene_id: row.0,
            transcript_name: row.1,
            seq_name: row.2,
            strand_char: row.3,
            trx_start: row.4,
            trx_end: row.5,
            coding_start: row.6,
            coding_end: row.7,
            num_exons: row.8,
            exon_starts: row.9,
            exon_ends: row.10,
        }
    }

    pub fn to_transcript(self) -> Result<Transcript, Error> {

        let exon_coords = self.zip_raw_exon_coords();
        if exon_coords.len() != self.num_exons {
            return Err(Error::RefFlat(
                "number of exon and exon coordinates mismatch"));
        }

        let strand = Strand::from_char(&self.strand_char)
            .map_err(FeatureError::from)
            .map_err(Error::from)?;

        let coding_coord =
            if self.coding_start != self.coding_end {
                Some((self.coding_start, self.coding_end))
            } else {
                None
            };

        let mut attribs = HashMap::new();
        attribs.insert("gene_id".to_owned(), self.gene_id);
        TBuilder::new(self.seq_name, self.trx_start, self.trx_end)
            .id(self.transcript_name)
            .strand(strand)
            .coords(exon_coords, coding_coord)
            .coding_incl_stop(true)
            .attributes(attribs)
            .build()
            .map_err(Error::from)
    }

    #[inline]
    fn zip_raw_exon_coords(&self) -> Vec<Coord<u64>> {
        let exon_starts = self.exon_starts
            .split(',').filter_map(|item| u64::from_str(item).ok());
        let exon_ends = self.exon_ends
            .split(',').filter_map(|item| u64::from_str(item).ok());
        exon_starts.zip(exon_ends).collect()
    }
}

pub struct Reader<R: io::Read> {
    inner: csv::Reader<R>,
}

impl<R: io::Read> Reader<R> {

    pub fn from_reader(in_reader: R) -> Reader<R> {
        Reader {
            inner: csv::Reader::from_reader(in_reader)
                .delimiter(b'\t')
                .has_headers(false)
        }
    }

    pub fn records<'a>(&'a mut self) -> RefFlatRecords<'a, R> {
        RefFlatRecords {
            inner: self.inner.decode()
        }
    }

    pub fn transcripts<'a>(&'a mut self) -> RefFlatTranscripts<'a, R> {
        RefFlatTranscripts {
            inner: self.records()
        }
    }

    pub fn genes<'a>(&'a mut self) -> RefFlatGenes<'a, R> {
        RefFlatGenes {
            inner: self.records().group_by(groupf),
        }
    }
}

impl Reader<fs::File> {
    pub fn from_file<P: AsRef<Path>>(path: P) -> io::Result<Self> {
        fs::File::open(path).map(Reader::from_reader)
    }
}

pub struct RefFlatRecords<'a, R: 'a> where R: io::Read {
    inner: csv::DecodedRecords<'a, R, RefFlatRow>,
}

impl<'a, R> Iterator for RefFlatRecords<'a, R> where R: io::Read {

    type Item = Result<RefFlatRecord, Error>;

    fn next(&mut self) -> Option<Result<RefFlatRecord, Error>> {
        self.inner.next()
            .map(|row| {
                row.or_else(|err| Err(Error::from(err)))
                    .map(RefFlatRecord::new)
            })
    }
}

pub struct RefFlatTranscripts<'a, R: 'a> where R: io::Read {
    inner: RefFlatRecords<'a, R>,
}

impl<'a, R> Iterator for RefFlatTranscripts<'a, R> where R: io::Read {

    type Item = Result<Transcript, Error>;

    fn next(&mut self) -> Option<Result<Transcript, Error>> {
        self.inner.next()
            .map(|record| record.and_then(|rec| rec.to_transcript()))
    }
}

pub struct RefFlatGenes<'a, R: 'a> where R: io::Read, {
    inner: GroupBy<GroupKey, RefFlatRecords<'a, R>, GroupFunc>,
}

impl<'a, R> Iterator for RefFlatGenes<'a, R> where R: io::Read {

    type Item = Result<Gene, Error>;

    fn next(&mut self) -> Option<Result<Gene, Error>> {
        self.inner.into_iter()
            .map(|(okey, records)| {
                match okey {
                    Some((gid, seq_name, strand_char)) => {
                        let mut transcripts = HashMap::new();
                        let (mut gene_start, mut gene_end) = (u64::max_value(), u64::min_value());
                        for record in records {
                            let transcript = record.and_then(|rec| rec.to_transcript())?;
                            gene_start = min(gene_start, transcript.interval().start);
                            gene_end = max(gene_end, transcript.interval().end);
                            let tid = transcript.id.clone()
                                .ok_or(Error::RefFlat("transcript does not have ID"))?;
                            transcripts.insert(tid, transcript);
                        }
                        GBuilder::new(seq_name, gene_start, gene_end)
                            .id(gid)
                            .strand_char(strand_char)
                            .transcripts(transcripts)
                            .transcript_coding_incl_stop(true)
                            .build()
                    },
                    None => Err(records.filter_map(|x| x.err()).next().unwrap())
                }
            }).next()
    }
}

type GroupKey = Option<(String, String, char)>;

type GroupFunc = fn(&Result<RefFlatRecord, Error>) -> GroupKey;

fn groupf(result: &Result<RefFlatRecord, Error>) -> GroupKey {
    result.as_ref().ok()
        .map(|ref res| (res.gene_id.clone(), res.seq_name.clone(), res.strand_char.clone()))
}
<commit_msg>Add tests for RefFlat reader<commit_after>//! Reader and writer for the refFlat format.
//!
//! The refFlat format is a transcript-oriented format in which each
//! transcript is denoted in a single line. It is used most prominently
//! by the [picard suite tools](https://broadinstitute.github.io/picard/)
//!
//! A minimum specification of the columns can be found here:
//! https://genome.ucsc.edu/goldenPath/gbdDescriptionsOld.html#RefFlat

use std::cmp::{max, min};
use std::collections::HashMap;
use std::convert::AsRef;
use std::io;
use std::fs;
use std::path::Path;
use std::str::FromStr;

use csv;
use itertools::{GroupBy, Itertools};

use feature::FeatureError;
use {Coord, Gene, GBuilder, Strand, Transcript, TBuilder, Error};

pub type RefFlatRow = (String, String, String, char, u64, u64, u64, u64, usize, String, String);

pub struct RefFlatRecord {
    pub gene_id: String,
    pub transcript_name: String,
    pub seq_name: String,
    pub strand_char: char,
    pub trx_start: u64,
    pub trx_end: u64,
    pub coding_start: u64,
    pub coding_end: u64,
    pub num_exons: usize,
    pub exon_starts: String,
    pub exon_ends: String,
}

impl RefFlatRecord {
    pub fn new(row: RefFlatRow) -> RefFlatRecord {
        RefFlatRecord {
            gene_id: row.0,
            transcript_name: row.1,
            seq_name: row.2,
            strand_char: row.3,
            trx_start: row.4,
            trx_end: row.5,
            coding_start: row.6,
            coding_end: row.7,
            num_exons: row.8,
            exon_starts: row.9,
            exon_ends: row.10,
        }
    }

    pub fn to_transcript(self) -> Result<Transcript, Error> {

        let exon_coords = self.zip_raw_exon_coords();
        if exon_coords.len() != self.num_exons {
            return Err(Error::RefFlat(
                "number of exon and exon coordinates mismatch"));
        }

        let strand = Strand::from_char(&self.strand_char)
            .map_err(FeatureError::from)
            .map_err(Error::from)?;

        let coding_coord =
            if self.coding_start != self.coding_end {
                Some((self.coding_start, self.coding_end))
            } else {
                None
            };

        let mut attribs = HashMap::new();
        attribs.insert("gene_id".to_owned(), self.gene_id);
        TBuilder::new(self.seq_name, self.trx_start, self.trx_end)
            .id(self.transcript_name)
            .strand(strand)
            .coords(exon_coords, coding_coord)
            .coding_incl_stop(true)
            .attributes(attribs)
            .build()
            .map_err(Error::from)
    }

    #[inline]
    fn zip_raw_exon_coords(&self) -> Vec<Coord<u64>> {
        let exon_starts = self.exon_starts
            .split(',').filter_map(|item| u64::from_str(item).ok());
        let exon_ends = self.exon_ends
            .split(',').filter_map(|item| u64::from_str(item).ok());
        exon_starts.zip(exon_ends).collect()
    }
}

pub struct Reader<R: io::Read> {
    inner: csv::Reader<R>,
}

impl<R: io::Read> Reader<R> {

    pub fn from_reader(in_reader: R) -> Reader<R> {
        Reader {
            inner: csv::Reader::from_reader(in_reader)
                .delimiter(b'\t')
                .has_headers(false)
        }
    }

    pub fn records<'a>(&'a mut self) -> RefFlatRecords<'a, R> {
        RefFlatRecords {
            inner: self.inner.decode()
        }
    }

    pub fn transcripts<'a>(&'a mut self) -> RefFlatTranscripts<'a, R> {
        RefFlatTranscripts {
            inner: self.records()
        }
    }

    pub fn genes<'a>(&'a mut self) -> RefFlatGenes<'a, R> {
        RefFlatGenes {
            inner: self.records().group_by(groupf),
        }
    }
}

impl Reader<fs::File> {
    pub fn from_file<P: AsRef<Path>>(path: P) -> io::Result<Self> {
        fs::File::open(path).map(Reader::from_reader)
    }
}

pub struct RefFlatRecords<'a, R: 'a> where R: io::Read {
    inner: csv::DecodedRecords<'a, R, RefFlatRow>,
}

impl<'a, R> Iterator for RefFlatRecords<'a, R> where R: io::Read {

    type Item = Result<RefFlatRecord, Error>;

    fn next(&mut self) -> Option<Result<RefFlatRecord, Error>> {
        self.inner.next()
            .map(|row| {
                row.or_else(|err| Err(Error::from(err)))
                    .map(RefFlatRecord::new)
            })
    }
}

pub struct RefFlatTranscripts<'a, R: 'a> where R: io::Read {
    inner: RefFlatRecords<'a, R>,
}

impl<'a, R> Iterator for RefFlatTranscripts<'a, R> where R: io::Read {

    type Item = Result<Transcript, Error>;

    fn next(&mut self) -> Option<Result<Transcript, Error>> {
        self.inner.next()
            .map(|record| record.and_then(|rec| rec.to_transcript()))
    }
}

pub struct RefFlatGenes<'a, R: 'a> where R: io::Read, {
    inner: GroupBy<GroupKey, RefFlatRecords<'a, R>, GroupFunc>,
}

impl<'a, R> Iterator for RefFlatGenes<'a, R> where R: io::Read {

    type Item = Result<Gene, Error>;

    fn next(&mut self) -> Option<Result<Gene, Error>> {
        self.inner.into_iter()
            .map(|(okey, records)| {
                match okey {
                    Some((gid, seq_name, strand_char)) => {
                        let mut transcripts = HashMap::new();
                        let (mut gene_start, mut gene_end) = (u64::max_value(), u64::min_value());
                        for record in records {
                            let transcript = record.and_then(|rec| rec.to_transcript())?;
                            gene_start = min(gene_start, transcript.interval().start);
                            gene_end = max(gene_end, transcript.interval().end);
                            let tid = transcript.id.clone()
                                .ok_or(Error::RefFlat("transcript does not have ID"))?;
                            transcripts.insert(tid, transcript);
                        }
                        GBuilder::new(seq_name, gene_start, gene_end)
                            .id(gid)
                            .strand_char(strand_char)
                            .transcripts(transcripts)
                            .transcript_coding_incl_stop(true)
                            .build()
                    },
                    None => Err(records.filter_map(|x| x.err()).next().unwrap())
                }
            }).next()
    }
}

type GroupKey = Option<(String, String, char)>;

type GroupFunc = fn(&Result<RefFlatRecord, Error>) -> GroupKey;

fn groupf(result: &Result<RefFlatRecord, Error>) -> GroupKey {
    result.as_ref().ok()
        .map(|ref res| (res.gene_id.clone(), res.seq_name.clone(), res.strand_char.clone()))
}

#[cfg(test)]
mod test {

    use super::*;

    fn next_rec<'a, R>(rr: &mut RefFlatRecords<'a, R>) -> RefFlatRecord where R: io::Read {
        rr.next().expect("a refflat record result").expect("a refflat record")
    }

    fn next_trx<'a, R>(rt: &mut RefFlatTranscripts<'a, R>) -> Transcript where R: io::Read {
        rt.next().expect("a transcript result").expect("a transcript")
    }

    fn next_gx<'a, R>(rg: &mut RefFlatGenes<'a, R>) -> Gene where R: io::Read {
        rg.next().expect("a gene result").expect("a gene")
    }

    const REFFLAT_SINGLE_ROW_NO_CDS: &'static [u8] =  b"DDX11L1\tNR_046018\tchr1\t+\t11873\t14409\t14409\t14409\t3\t11873,12612,13220,\t12227,12721,14409,";

    #[test]
    fn records_single_row_no_cds() {
        let mut reader = Reader::from_reader(REFFLAT_SINGLE_ROW_NO_CDS);
        let mut records = reader.records();

        let rec1 = next_rec(&mut records);
        assert_eq!(rec1.gene_id, "DDX11L1".to_owned());

        assert!(records.next().is_none());
    }

    #[test]
    fn transcripts_single_row_no_cds() {
        let mut reader = Reader::from_reader(REFFLAT_SINGLE_ROW_NO_CDS);
        let mut transcripts = reader.transcripts();

        let trx1 = next_trx(&mut transcripts);
        assert_eq!(trx1.id, Some("NR_046018".to_owned()));

        assert!(transcripts.next().is_none());
    }

    #[test]
    fn genes_single_row_no_cds() {
        let mut reader = Reader::from_reader(REFFLAT_SINGLE_ROW_NO_CDS);
        let mut genes = reader.genes();

        let gx1 = next_gx(&mut genes);
        assert_eq!(gx1.id, Some("DDX11L1".to_owned()));

        assert!(genes.next().is_none());
    }

    const REFFLAT_MULT_ROWS_NO_CDS: &'static [u8] =  b"DDX11L1\tNR_046018\tchr1\t+\t11873\t14409\t14409\t14409\t3\t11873,12612,13220,\t12227,12721,14409,
MIR570\tNR_030296\tchr3\t+\t195699400\t195699497\t195699497\t195699497\t1\t195699400,\t195699497,";

    #[test]
    fn records_mult_rows_no_cds() {
        let mut reader = Reader::from_reader(REFFLAT_MULT_ROWS_NO_CDS);
        let mut records = reader.records();

        let rec1 = next_rec(&mut records);
        assert_eq!(rec1.gene_id, "DDX11L1".to_owned());

        let rec2 = next_rec(&mut records);
        assert_eq!(rec2.gene_id, "MIR570".to_owned());

        assert!(records.next().is_none());
    }

    #[test]
    fn transcripts_mult_rows_no_cds() {
        let mut reader = Reader::from_reader(REFFLAT_MULT_ROWS_NO_CDS);
        let mut transcripts = reader.transcripts();

        let trx1 = next_trx(&mut transcripts);
        assert_eq!(trx1.id, Some("NR_046018".to_owned()));

        let trx2 = next_trx(&mut transcripts);
        assert_eq!(trx2.id, Some("NR_030296".to_owned()));

        assert!(transcripts.next().is_none());
    }

    #[test]
    fn genes_mult_rows_no_cds() {
        let mut reader = Reader::from_reader(REFFLAT_MULT_ROWS_NO_CDS);
        let mut genes = reader.genes();

        let gx1 = next_gx(&mut genes);
        assert_eq!(gx1.id, Some("DDX11L1".to_owned()));

        let gx2 = next_gx(&mut genes);
        assert_eq!(gx2.id, Some("MIR570".to_owned()));

        assert!(genes.next().is_none());
    }

    const REFFLAT_MULT_ROWS_MULT_GENES_WITH_CDS: &'static [u8] = b"TNFRSF14\tNM_001297605\tchr1\t+\t2556364\t2565622\t2556664\t2562868\t7\t2556364,2557725,2558342,2559822,2560623,2562864,2563147,\t2556733,2557834,2558468,2559978,2560714,2562896,2565622,
TNFRSF14\tNM_003820\tchr1\t+\t2556364\t2565622\t2556664\t2563273\t8\t2556364,2557725,2558342,2559822,2560623,2561672,2562864,2563147,\t2556733,2557834,2558468,2559978,2560714,2561815,2562896,2565622,
SMIM12\tNM_001164824\tchr1\t-\t34850361\t34859045\t34855698\t34855977\t3\t34850361,34856555,34858839,\t34855982,34856739,34859045,
SMIM12\tNM_001164825\tchr1\t-\t34850361\t34859737\t34855698\t34855977\t2\t34850361,34859454,\t34855982,34859737,
SMIM12\tNM_138428\tchr1\t-\t34850361\t34859816\t34855698\t34855977\t2\t34850361,34859676,\t34855982,34859816,";

    #[test]
    fn records_mult_rows_mult_genes_with_cds() {
        let mut reader = Reader::from_reader(REFFLAT_MULT_ROWS_MULT_GENES_WITH_CDS);
        let mut records = reader.records();

        let rec1 = next_rec(&mut records);
        assert_eq!(rec1.transcript_name, "NM_001297605".to_owned());

        let _rec2 = next_rec(&mut records);
        let _rec3 = next_rec(&mut records);
        let _rec4 = next_rec(&mut records);

        let rec5 = next_rec(&mut records);
        assert_eq!(rec5.transcript_name, "NM_138428".to_owned());

        assert!(records.next().is_none());
    }

    #[test]
    fn transcripts_mult_rows_mult_genes_with_cds() {
        let mut reader = Reader::from_reader(REFFLAT_MULT_ROWS_MULT_GENES_WITH_CDS);
        let mut transcripts = reader.transcripts();

        let trx1 = next_trx(&mut transcripts);
        assert_eq!(trx1.id, Some("NM_001297605".to_owned()));

        let _trx2 = next_trx(&mut transcripts);
        let _trx3 = next_trx(&mut transcripts);
        let _trx4 = next_trx(&mut transcripts);

        let trx5 = next_trx(&mut transcripts);
        assert_eq!(trx5.id, Some("NM_138428".to_owned()));

        assert!(transcripts.next().is_none());
    }

    #[test]
    fn genes_mult_rows_mult_genes_with_cds() {
        let mut reader = Reader::from_reader(REFFLAT_MULT_ROWS_MULT_GENES_WITH_CDS);
        let mut genes = reader.genes();

        let gx1 = next_gx(&mut genes);
        assert_eq!(gx1.id, Some("TNFRSF14".to_owned()));

        let gx2 = next_gx(&mut genes);
        assert_eq!(gx2.id, Some("SMIM12".to_owned()));

        assert!(genes.next().is_none());
    }
}
<|endoftext|>


<commit_before>//! `mbe` (short for Macro By Example) crate contains code for handling
//! `macro_rules` macros. It uses `TokenTree` (from `ra_tt` package) as the
//! interface, although it contains some code to bridge `SyntaxNode`s and
//! `TokenTree`s as well!

mod parser;
mod mbe_expander;
mod syntax_bridge;
mod tt_iter;
mod subtree_source;

pub use tt::{Delimiter, Punct};

use crate::{
    parser::{parse_pattern, Op},
    tt_iter::TtIter,
};

#[derive(Debug, PartialEq, Eq)]
pub enum ParseError {
    Expected(String),
    RepetitionEmtpyTokenTree,
}

#[derive(Debug, PartialEq, Eq, Clone)]
pub enum ExpandError {
    NoMatchingRule,
    UnexpectedToken,
    BindingError(String),
    ConversionError,
    InvalidRepeat,
    ProcMacroError(tt::ExpansionError),
}

impl From<tt::ExpansionError> for ExpandError {
    fn from(it: tt::ExpansionError) -> Self {
        ExpandError::ProcMacroError(it)
    }
}

pub use crate::syntax_bridge::{
    ast_to_token_tree, parse_to_token_tree, syntax_node_to_token_tree, token_tree_to_syntax_node,
    TokenMap,
};

/// This struct contains AST for a single `macro_rules` definition. What might
/// be very confusing is that AST has almost exactly the same shape as
/// `tt::TokenTree`, but there's a crucial difference: in macro rules, `$ident`
/// and `$()*` have special meaning (see `Var` and `Repeat` data structures)
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct MacroRules {
    rules: Vec<Rule>,
    /// Highest id of the token we have in TokenMap
    shift: Shift,
}

#[derive(Clone, Debug, PartialEq, Eq)]
struct Rule {
    lhs: tt::Subtree,
    rhs: tt::Subtree,
}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
struct Shift(u32);

impl Shift {
    fn new(tt: &tt::Subtree) -> Shift {
        // Note that TokenId is started from zero,
        // We have to add 1 to prevent duplication.
        let value = max_id(tt).map_or(0, |it| it + 1);
        return Shift(value);

        // Find the max token id inside a subtree
        fn max_id(subtree: &tt::Subtree) -> Option<u32> {
            subtree
                .token_trees
                .iter()
                .filter_map(|tt| match tt {
                    tt::TokenTree::Subtree(subtree) => {
                        let tree_id = max_id(subtree);
                        match subtree.delimiter {
                            Some(it) if it.id != tt::TokenId::unspecified() => {
                                Some(tree_id.map_or(it.id.0, |t| t.max(it.id.0)))
                            }
                            _ => tree_id,
                        }
                    }
                    tt::TokenTree::Leaf(tt::Leaf::Ident(ident))
                        if ident.id != tt::TokenId::unspecified() =>
                    {
                        Some(ident.id.0)
                    }
                    _ => None,
                })
                .max()
        }
    }

    /// Shift given TokenTree token id
    fn shift_all(self, tt: &mut tt::Subtree) {
        for t in tt.token_trees.iter_mut() {
            match t {
                tt::TokenTree::Leaf(leaf) => match leaf {
                    tt::Leaf::Ident(ident) => ident.id = self.shift(ident.id),
                    tt::Leaf::Punct(punct) => punct.id = self.shift(punct.id),
                    tt::Leaf::Literal(lit) => lit.id = self.shift(lit.id),
                },
                tt::TokenTree::Subtree(tt) => {
                    if let Some(it) = tt.delimiter.as_mut() {
                        it.id = self.shift(it.id);
                    };
                    self.shift_all(tt)
                }
            }
        }
    }

    fn shift(self, id: tt::TokenId) -> tt::TokenId {
        if id == tt::TokenId::unspecified() {
            return id;
        }
        tt::TokenId(id.0 + self.0)
    }

    fn unshift(self, id: tt::TokenId) -> Option<tt::TokenId> {
        id.0.checked_sub(self.0).map(tt::TokenId)
    }
}

#[derive(Debug, Eq, PartialEq)]
pub enum Origin {
    Def,
    Call,
}

impl MacroRules {
    pub fn parse(tt: &tt::Subtree) -> Result<MacroRules, ParseError> {
        // Note: this parsing can be implemented using mbe machinery itself, by
        // matching against `$($lhs:tt => $rhs:tt);*` pattern, but implementing
        // manually seems easier.
        let mut src = TtIter::new(tt);
        let mut rules = Vec::new();
        while src.len() > 0 {
            let rule = Rule::parse(&mut src)?;
            rules.push(rule);
            if let Err(()) = src.expect_char(';') {
                if src.len() > 0 {
                    return Err(ParseError::Expected("expected `:`".to_string()));
                }
                break;
            }
        }

        for rule in rules.iter() {
            validate(&rule.lhs)?;
        }

        Ok(MacroRules { rules, shift: Shift::new(tt) })
    }

    pub fn expand(&self, tt: &tt::Subtree) -> ExpandResult<tt::Subtree> {
        // apply shift
        let mut tt = tt.clone();
        self.shift.shift_all(&mut tt);
        mbe_expander::expand(self, &tt)
    }

    pub fn map_id_down(&self, id: tt::TokenId) -> tt::TokenId {
        self.shift.shift(id)
    }

    pub fn map_id_up(&self, id: tt::TokenId) -> (tt::TokenId, Origin) {
        match self.shift.unshift(id) {
            Some(id) => (id, Origin::Call),
            None => (id, Origin::Def),
        }
    }
}

impl Rule {
    fn parse(src: &mut TtIter) -> Result<Rule, ParseError> {
        let mut lhs = src
            .expect_subtree()
            .map_err(|()| ParseError::Expected("expected subtree".to_string()))?
            .clone();
        lhs.delimiter = None;
        src.expect_char('=').map_err(|()| ParseError::Expected("expected `=`".to_string()))?;
        src.expect_char('>').map_err(|()| ParseError::Expected("expected `>`".to_string()))?;
        let mut rhs = src
            .expect_subtree()
            .map_err(|()| ParseError::Expected("expected subtree".to_string()))?
            .clone();
        rhs.delimiter = None;
        Ok(crate::Rule { lhs, rhs })
    }
}

fn to_parse_error(e: ExpandError) -> ParseError {
    let msg = match e {
        ExpandError::InvalidRepeat => "invalid repeat".to_string(),
        _ => "invalid macro definition".to_string(),
    };
    ParseError::Expected(msg)
}

fn validate(pattern: &tt::Subtree) -> Result<(), ParseError> {
    for op in parse_pattern(pattern) {
        let op = op.map_err(to_parse_error)?;

        match op {
            Op::TokenTree(tt::TokenTree::Subtree(subtree)) => validate(subtree)?,
            Op::Repeat { subtree, separator, .. } => {
                // Checks that no repetition which could match an empty token
                // https://github.com/rust-lang/rust/blob/a58b1ed44f5e06976de2bdc4d7dc81c36a96934f/src/librustc_expand/mbe/macro_rules.rs#L558

                if separator.is_none() {
                    if parse_pattern(subtree).all(|child_op| {
                        match child_op.map_err(to_parse_error) {
                            Ok(Op::Var { kind, .. }) => {
                                // vis is optional
                                if kind.map_or(false, |it| it == "vis") {
                                    return true;
                                }
                            }
                            Ok(Op::Repeat { kind, .. }) => {
                                return matches!(
                                    kind,
                                    parser::RepeatKind::ZeroOrMore | parser::RepeatKind::ZeroOrOne
                                )
                            }
                            _ => {}
                        }
                        false
                    }) {
                        return Err(ParseError::RepetitionEmtpyTokenTree);
                    }
                }
                validate(subtree)?
            }
            _ => (),
        }
    }
    Ok(())
}

#[derive(Debug)]
pub struct ExpandResult<T>(pub T, pub Option<ExpandError>);

impl<T> ExpandResult<T> {
    pub fn ok(t: T) -> ExpandResult<T> {
        ExpandResult(t, None)
    }

    pub fn only_err(err: ExpandError) -> ExpandResult<T>
    where
        T: Default,
    {
        ExpandResult(Default::default(), Some(err))
    }

    pub fn map<U>(self, f: impl FnOnce(T) -> U) -> ExpandResult<U> {
        ExpandResult(f(self.0), self.1)
    }

    pub fn result(self) -> Result<T, ExpandError> {
        self.1.map(Err).unwrap_or(Ok(self.0))
    }
}

impl<T: Default> From<Result<T, ExpandError>> for ExpandResult<T> {
    fn from(result: Result<T, ExpandError>) -> ExpandResult<T> {
        result
            .map_or_else(|e| ExpandResult(Default::default(), Some(e)), |it| ExpandResult(it, None))
    }
}

#[cfg(test)]
mod tests;
<commit_msg>Minor<commit_after>//! `mbe` (short for Macro By Example) crate contains code for handling
//! `macro_rules` macros. It uses `TokenTree` (from `ra_tt` package) as the
//! interface, although it contains some code to bridge `SyntaxNode`s and
//! `TokenTree`s as well!

mod parser;
mod mbe_expander;
mod syntax_bridge;
mod tt_iter;
mod subtree_source;

#[cfg(test)]
mod tests;

pub use tt::{Delimiter, Punct};

use crate::{
    parser::{parse_pattern, Op},
    tt_iter::TtIter,
};

#[derive(Debug, PartialEq, Eq)]
pub enum ParseError {
    Expected(String),
    RepetitionEmtpyTokenTree,
}

#[derive(Debug, PartialEq, Eq, Clone)]
pub enum ExpandError {
    NoMatchingRule,
    UnexpectedToken,
    BindingError(String),
    ConversionError,
    InvalidRepeat,
    ProcMacroError(tt::ExpansionError),
}

impl From<tt::ExpansionError> for ExpandError {
    fn from(it: tt::ExpansionError) -> Self {
        ExpandError::ProcMacroError(it)
    }
}

pub use crate::syntax_bridge::{
    ast_to_token_tree, parse_to_token_tree, syntax_node_to_token_tree, token_tree_to_syntax_node,
    TokenMap,
};

/// This struct contains AST for a single `macro_rules` definition. What might
/// be very confusing is that AST has almost exactly the same shape as
/// `tt::TokenTree`, but there's a crucial difference: in macro rules, `$ident`
/// and `$()*` have special meaning (see `Var` and `Repeat` data structures)
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct MacroRules {
    rules: Vec<Rule>,
    /// Highest id of the token we have in TokenMap
    shift: Shift,
}

#[derive(Clone, Debug, PartialEq, Eq)]
struct Rule {
    lhs: tt::Subtree,
    rhs: tt::Subtree,
}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
struct Shift(u32);

impl Shift {
    fn new(tt: &tt::Subtree) -> Shift {
        // Note that TokenId is started from zero,
        // We have to add 1 to prevent duplication.
        let value = max_id(tt).map_or(0, |it| it + 1);
        return Shift(value);

        // Find the max token id inside a subtree
        fn max_id(subtree: &tt::Subtree) -> Option<u32> {
            subtree
                .token_trees
                .iter()
                .filter_map(|tt| match tt {
                    tt::TokenTree::Subtree(subtree) => {
                        let tree_id = max_id(subtree);
                        match subtree.delimiter {
                            Some(it) if it.id != tt::TokenId::unspecified() => {
                                Some(tree_id.map_or(it.id.0, |t| t.max(it.id.0)))
                            }
                            _ => tree_id,
                        }
                    }
                    tt::TokenTree::Leaf(tt::Leaf::Ident(ident))
                        if ident.id != tt::TokenId::unspecified() =>
                    {
                        Some(ident.id.0)
                    }
                    _ => None,
                })
                .max()
        }
    }

    /// Shift given TokenTree token id
    fn shift_all(self, tt: &mut tt::Subtree) {
        for t in tt.token_trees.iter_mut() {
            match t {
                tt::TokenTree::Leaf(leaf) => match leaf {
                    tt::Leaf::Ident(ident) => ident.id = self.shift(ident.id),
                    tt::Leaf::Punct(punct) => punct.id = self.shift(punct.id),
                    tt::Leaf::Literal(lit) => lit.id = self.shift(lit.id),
                },
                tt::TokenTree::Subtree(tt) => {
                    if let Some(it) = tt.delimiter.as_mut() {
                        it.id = self.shift(it.id);
                    };
                    self.shift_all(tt)
                }
            }
        }
    }

    fn shift(self, id: tt::TokenId) -> tt::TokenId {
        if id == tt::TokenId::unspecified() {
            return id;
        }
        tt::TokenId(id.0 + self.0)
    }

    fn unshift(self, id: tt::TokenId) -> Option<tt::TokenId> {
        id.0.checked_sub(self.0).map(tt::TokenId)
    }
}

#[derive(Debug, Eq, PartialEq)]
pub enum Origin {
    Def,
    Call,
}

impl MacroRules {
    pub fn parse(tt: &tt::Subtree) -> Result<MacroRules, ParseError> {
        // Note: this parsing can be implemented using mbe machinery itself, by
        // matching against `$($lhs:tt => $rhs:tt);*` pattern, but implementing
        // manually seems easier.
        let mut src = TtIter::new(tt);
        let mut rules = Vec::new();
        while src.len() > 0 {
            let rule = Rule::parse(&mut src)?;
            rules.push(rule);
            if let Err(()) = src.expect_char(';') {
                if src.len() > 0 {
                    return Err(ParseError::Expected("expected `:`".to_string()));
                }
                break;
            }
        }

        for rule in rules.iter() {
            validate(&rule.lhs)?;
        }

        Ok(MacroRules { rules, shift: Shift::new(tt) })
    }

    pub fn expand(&self, tt: &tt::Subtree) -> ExpandResult<tt::Subtree> {
        // apply shift
        let mut tt = tt.clone();
        self.shift.shift_all(&mut tt);
        mbe_expander::expand(self, &tt)
    }

    pub fn map_id_down(&self, id: tt::TokenId) -> tt::TokenId {
        self.shift.shift(id)
    }

    pub fn map_id_up(&self, id: tt::TokenId) -> (tt::TokenId, Origin) {
        match self.shift.unshift(id) {
            Some(id) => (id, Origin::Call),
            None => (id, Origin::Def),
        }
    }
}

impl Rule {
    fn parse(src: &mut TtIter) -> Result<Rule, ParseError> {
        let mut lhs = src
            .expect_subtree()
            .map_err(|()| ParseError::Expected("expected subtree".to_string()))?
            .clone();
        lhs.delimiter = None;
        src.expect_char('=').map_err(|()| ParseError::Expected("expected `=`".to_string()))?;
        src.expect_char('>').map_err(|()| ParseError::Expected("expected `>`".to_string()))?;
        let mut rhs = src
            .expect_subtree()
            .map_err(|()| ParseError::Expected("expected subtree".to_string()))?
            .clone();
        rhs.delimiter = None;
        Ok(crate::Rule { lhs, rhs })
    }
}

fn to_parse_error(e: ExpandError) -> ParseError {
    let msg = match e {
        ExpandError::InvalidRepeat => "invalid repeat".to_string(),
        _ => "invalid macro definition".to_string(),
    };
    ParseError::Expected(msg)
}

fn validate(pattern: &tt::Subtree) -> Result<(), ParseError> {
    for op in parse_pattern(pattern) {
        let op = op.map_err(to_parse_error)?;

        match op {
            Op::TokenTree(tt::TokenTree::Subtree(subtree)) => validate(subtree)?,
            Op::Repeat { subtree, separator, .. } => {
                // Checks that no repetition which could match an empty token
                // https://github.com/rust-lang/rust/blob/a58b1ed44f5e06976de2bdc4d7dc81c36a96934f/src/librustc_expand/mbe/macro_rules.rs#L558

                if separator.is_none() {
                    if parse_pattern(subtree).all(|child_op| {
                        match child_op.map_err(to_parse_error) {
                            Ok(Op::Var { kind, .. }) => {
                                // vis is optional
                                if kind.map_or(false, |it| it == "vis") {
                                    return true;
                                }
                            }
                            Ok(Op::Repeat { kind, .. }) => {
                                return matches!(
                                    kind,
                                    parser::RepeatKind::ZeroOrMore | parser::RepeatKind::ZeroOrOne
                                )
                            }
                            _ => {}
                        }
                        false
                    }) {
                        return Err(ParseError::RepetitionEmtpyTokenTree);
                    }
                }
                validate(subtree)?
            }
            _ => (),
        }
    }
    Ok(())
}

#[derive(Debug)]
pub struct ExpandResult<T>(pub T, pub Option<ExpandError>);

impl<T> ExpandResult<T> {
    pub fn ok(t: T) -> ExpandResult<T> {
        ExpandResult(t, None)
    }

    pub fn only_err(err: ExpandError) -> ExpandResult<T>
    where
        T: Default,
    {
        ExpandResult(Default::default(), Some(err))
    }

    pub fn map<U>(self, f: impl FnOnce(T) -> U) -> ExpandResult<U> {
        ExpandResult(f(self.0), self.1)
    }

    pub fn result(self) -> Result<T, ExpandError> {
        self.1.map(Err).unwrap_or(Ok(self.0))
    }
}

impl<T: Default> From<Result<T, ExpandError>> for ExpandResult<T> {
    fn from(result: Result<T, ExpandError>) -> ExpandResult<T> {
        result
            .map_or_else(|e| ExpandResult(Default::default(), Some(e)), |it| ExpandResult(it, None))
    }
}
<|endoftext|>


<commit_before>// Copyright © 2017-2018 Mozilla Foundation
//
// This program is made available under an ISC-style license.  See the
// accompanying file LICENSE for details.

#[macro_export]
macro_rules! cubeb_log_internal {
    ($level: expr, $msg: expr) => {
        #[allow(unused_unsafe)]
        unsafe {
            if $level <= $crate::ffi::g_cubeb_log_level.into() {
                cubeb_log_internal!(__INTERNAL__ $msg);
            }
        }
    };
    ($level: expr, $fmt: expr, $($arg: expr),+) => {
        #[allow(unused_unsafe)]
        unsafe {
            if $level <= $crate::ffi::g_cubeb_log_level.into() {
                cubeb_log_internal!(__INTERNAL__ format!($fmt, $($arg),*));
            }
        }
    };
    (__INTERNAL__ $msg: expr) => {
        if let Some(log_callback) = $crate::ffi::g_cubeb_log_callback {
            use std::io::Write;

            let mut buf = [0 as u8; 1024];
            let filename = std::path::Path::new(file!())
                .file_name()
                .unwrap()
                .to_str()
                .unwrap();
            // +2 for ':', +1 for ' ', and +1 for converting line value to number of digits
            let len = filename.len() + ((line!() as f32).log10() as usize) + $msg.len() + 4;
            assert!(len < buf.len(), "log is too long!");
            write!(&mut buf[..], "{}:{}: {}", filename, line!(), $msg).unwrap();
            buf[len] = 0;
            let cstr = unsafe { std::ffi::CStr::from_bytes_with_nul_unchecked(&buf[..len + 1]) };
            log_callback(cstr.as_ptr());
        }
    }
}

#[macro_export]
macro_rules! cubeb_logv {
    ($msg: expr) => (cubeb_log_internal!($crate::LogLevel::Verbose, $msg));
    ($fmt: expr, $($arg: expr),+) => (cubeb_log_internal!($crate::LogLevel::Verbose, $fmt, $($arg),*));
}

#[macro_export]
macro_rules! cubeb_log {
    ($msg: expr) => (cubeb_log_internal!($crate::LogLevel::Normal, $msg));
    ($fmt: expr, $($arg: expr),+) => (cubeb_log_internal!($crate::LogLevel::Normal, $fmt, $($arg),*));
}

#[cfg(test)]
mod tests {
    #[test]
    fn test_normal_logging() {
        cubeb_log!("This is log at normal level");
        cubeb_log!("{} Formatted log", 1);
        cubeb_log!("{} Formatted {} log {}", 1, 2, 3);
    }

    #[test]
    fn test_verbose_logging() {
        cubeb_logv!("This is a log at verbose level");
        cubeb_logv!("{} Formatted log", 1);
        cubeb_logv!("{} Formatted {} log {}", 1, 2, 3);
    }
}
<commit_msg>Add newline character in buffer<commit_after>// Copyright © 2017-2018 Mozilla Foundation
//
// This program is made available under an ISC-style license.  See the
// accompanying file LICENSE for details.

#[macro_export]
macro_rules! cubeb_log_internal {
    ($level: expr, $msg: expr) => {
        #[allow(unused_unsafe)]
        unsafe {
            if $level <= $crate::ffi::g_cubeb_log_level.into() {
                cubeb_log_internal!(__INTERNAL__ $msg);
            }
        }
    };
    ($level: expr, $fmt: expr, $($arg: expr),+) => {
        #[allow(unused_unsafe)]
        unsafe {
            if $level <= $crate::ffi::g_cubeb_log_level.into() {
                cubeb_log_internal!(__INTERNAL__ format!($fmt, $($arg),*));
            }
        }
    };
    (__INTERNAL__ $msg: expr) => {
        if let Some(log_callback) = $crate::ffi::g_cubeb_log_callback {
            use std::io::Write;

            let mut buf = [0 as u8; 1024];
            let filename = std::path::Path::new(file!())
                .file_name()
                .unwrap()
                .to_str()
                .unwrap();
            // 2 for ':', 1 for ' ', 1 for '\n', and 1 for converting `line!()` to number of digits
            let len = filename.len() + ((line!() as f32).log10() as usize) + $msg.len() + 5;
            assert!(len < buf.len(), "log is too long!");
            write!(&mut buf[..], "{}:{}: {}\n", filename, line!(), $msg).unwrap();
            buf[len] = 0;
            let cstr = unsafe { std::ffi::CStr::from_bytes_with_nul_unchecked(&buf[..len + 1]) };
            log_callback(cstr.as_ptr());
        }
    }
}

#[macro_export]
macro_rules! cubeb_logv {
    ($msg: expr) => (cubeb_log_internal!($crate::LogLevel::Verbose, $msg));
    ($fmt: expr, $($arg: expr),+) => (cubeb_log_internal!($crate::LogLevel::Verbose, $fmt, $($arg),*));
}

#[macro_export]
macro_rules! cubeb_log {
    ($msg: expr) => (cubeb_log_internal!($crate::LogLevel::Normal, $msg));
    ($fmt: expr, $($arg: expr),+) => (cubeb_log_internal!($crate::LogLevel::Normal, $fmt, $($arg),*));
}

#[cfg(test)]
mod tests {
    #[test]
    fn test_normal_logging() {
        cubeb_log!("This is log at normal level");
        cubeb_log!("{} Formatted log", 1);
        cubeb_log!("{} Formatted {} log {}", 1, 2, 3);
    }

    #[test]
    fn test_verbose_logging() {
        cubeb_logv!("This is a log at verbose level");
        cubeb_logv!("{} Formatted log", 1);
        cubeb_logv!("{} Formatted {} log {}", 1, 2, 3);
    }
}
<|endoftext|>


<commit_before>use super::{CatResult, FdReadable, InputHandle};

use nix::unistd;
use std::os::unix::io::{AsRawFd, RawFd};

use uucore::pipes::{pipe, splice, splice_exact};

const BUF_SIZE: usize = 1024 * 16;

/// This function is called from `write_fast()` on Linux and Android. The
/// function `splice()` is used to move data between two file descriptors
/// without copying between kernel and user spaces. This results in a large
/// speedup.
///
/// The `bool` in the result value indicates if we need to fall back to normal
/// copying or not. False means we don't have to.
#[inline]
pub(super) fn write_fast_using_splice<R: FdReadable>(
    handle: &mut InputHandle<R>,
    write_fd: &impl AsRawFd,
) -> CatResult<bool> {
    let (pipe_rd, pipe_wr) = pipe()?;

    loop {
        match splice(&handle.reader, &pipe_wr, BUF_SIZE) {
            Ok(n) => {
                if n == 0 {
                    return Ok(false);
                }
                if splice_exact(&pipe_rd, write_fd, n).is_err() {
                    // If the first splice manages to copy to the intermediate
                    // pipe, but the second splice to stdout fails for some reason
                    // we can recover by copying the data that we have from the
                    // intermediate pipe to stdout using normal read/write. Then
                    // we tell the caller to fall back.
                    copy_exact(pipe_rd.as_raw_fd(), write_fd.as_raw_fd(), n)?;
                    return Ok(true);
                }
            }
            Err(_) => {
                return Ok(true);
            }
        }
    }
}

/// Caller must ensure that `num_bytes <= BUF_SIZE`, otherwise this function
/// will panic. The way we use this function in `write_fast_using_splice`
/// above is safe because `splice` is set to write at most `BUF_SIZE` to the
/// pipe.
#[inline]
fn copy_exact(read_fd: RawFd, write_fd: RawFd, num_bytes: usize) -> nix::Result<()> {
    let mut left = num_bytes;
    let mut buf = [0; BUF_SIZE];
    loop {
        let read = unistd::read(read_fd, &mut buf[..left])?;
        let written = unistd::write(write_fd, &buf[..read])?;
        left -= written;
        if left == 0 {
            break;
        }
    }
    Ok(())
}
<commit_msg>cat: Do not assume complete writes<commit_after>use super::{CatResult, FdReadable, InputHandle};

use nix::unistd;
use std::os::unix::io::{AsRawFd, RawFd};

use uucore::pipes::{pipe, splice, splice_exact};

const BUF_SIZE: usize = 1024 * 16;

/// This function is called from `write_fast()` on Linux and Android. The
/// function `splice()` is used to move data between two file descriptors
/// without copying between kernel and user spaces. This results in a large
/// speedup.
///
/// The `bool` in the result value indicates if we need to fall back to normal
/// copying or not. False means we don't have to.
#[inline]
pub(super) fn write_fast_using_splice<R: FdReadable>(
    handle: &mut InputHandle<R>,
    write_fd: &impl AsRawFd,
) -> CatResult<bool> {
    let (pipe_rd, pipe_wr) = pipe()?;

    loop {
        match splice(&handle.reader, &pipe_wr, BUF_SIZE) {
            Ok(n) => {
                if n == 0 {
                    return Ok(false);
                }
                if splice_exact(&pipe_rd, write_fd, n).is_err() {
                    // If the first splice manages to copy to the intermediate
                    // pipe, but the second splice to stdout fails for some reason
                    // we can recover by copying the data that we have from the
                    // intermediate pipe to stdout using normal read/write. Then
                    // we tell the caller to fall back.
                    copy_exact(pipe_rd.as_raw_fd(), write_fd.as_raw_fd(), n)?;
                    return Ok(true);
                }
            }
            Err(_) => {
                return Ok(true);
            }
        }
    }
}

/// Move exactly `num_bytes` bytes from `read_fd` to `write_fd`.
///
/// Panics if not enough bytes can be read.
fn copy_exact(read_fd: RawFd, write_fd: RawFd, num_bytes: usize) -> nix::Result<()> {
    let mut left = num_bytes;
    let mut buf = [0; BUF_SIZE];
    while left > 0 {
        let read = unistd::read(read_fd, &mut buf)?;
        assert_ne!(read, 0, "unexpected end of pipe");
        let mut written = 0;
        while written < read {
            match unistd::write(write_fd, &buf[written..read])? {
                0 => panic!(),
                n => written += n,
            }
        }
        left -= read;
    }
    Ok(())
}
<|endoftext|>


<commit_before>use super::swarm::Swarm;
use super::messaging::{Message, Actor, Individual, Packet, Recipient};
use super::inbox::Inbox;
use super::type_registry::TypeRegistry;
use std::intrinsics::{type_id, type_name};

pub static mut THE_SYSTEM: *mut ActorSystem = 0 as *mut ActorSystem;

#[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub struct ID {
    pub type_id: u16,
    pub version: u8,
    pub instance_id: u32
}

impl ID {
    pub fn invalid() -> ID {ID {type_id: u16::max_value(), version: u8::max_value(), instance_id: 0}}

    pub fn individual(individual_type_id: usize) -> ID {
        ID {type_id: individual_type_id as u16, version: 0, instance_id: 0}
    }

    pub fn broadcast(type_id: usize) -> ID {
        ID {type_id: type_id as u16, version: 0, instance_id: u32::max_value()}
    }

    pub fn instance(type_id: usize, instance_id_and_version: (usize, usize)) -> ID {
        ID {type_id: type_id as u16, version: instance_id_and_version.1 as u8, instance_id: instance_id_and_version.0 as u32}
    }

    pub fn is_broadcast(&self) -> bool {
        self.instance_id == u32::max_value()
    }

    pub fn swarm(type_id: usize) -> ID {
        ID {type_id: type_id as u16, version: 0, instance_id: u32::max_value() - 1}
    }

    pub fn is_swarm(&self) -> bool {
        self.instance_id == u32::max_value() - 1
    }
}

impl Default for ID {
    fn default() -> Self {
        ID::invalid()
    }
}

impl ::std::fmt::Debug for ID {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        write!(f, "ID {}_{}_{}", self.type_id, self.version, self.instance_id)
    }
}

impl<M: Message> ::std::ops::Shl<M> for ID {
    type Output = ();

    fn shl(self, rhs: M) {
        unsafe {(*THE_SYSTEM).send(self, rhs);}
    }
}

const MAX_RECIPIENT_TYPES : usize = 1024;
const MAX_MESSAGE_TYPES_PER_RECIPIENT: usize = 32;

#[derive(Clone)]
struct InboxMap {
    length: usize,
    entries: [Option<(u64, *mut u8)>; MAX_MESSAGE_TYPES_PER_RECIPIENT]
}

impl InboxMap {
    fn new() -> InboxMap {
        InboxMap{length: 0, entries: [None; MAX_MESSAGE_TYPES_PER_RECIPIENT]}
    }

    fn add_new<M: Message>(&mut self, pointer: *mut Inbox<M>) {
        let message_type_id = unsafe{type_id::<M>()};
        let entry_is_for_id = |entry: &&Option<(u64, *mut u8)>| {
            entry.is_some() && entry.unwrap().0 == message_type_id
        };
        assert!(self.entries.iter().find(entry_is_for_id).is_none());
        self.entries[self.length] = Some((message_type_id, pointer as *mut u8));
        self.length += 1;
    }

    fn get<M: Message>(&self) -> Option<*mut Inbox<M>> {
        let message_type_id = unsafe{type_id::<M>()};
        for entry in &self.entries {if let Some((id, pointer)) = *entry {
            if id == message_type_id {return Some(pointer as *mut Inbox<M>)}
        }}
        None
    }
}

pub struct ActorSystem {
    routing: [Option<InboxMap>; MAX_RECIPIENT_TYPES],
    recipient_registry: TypeRegistry,
    individuals: [Option<*mut u8>; MAX_RECIPIENT_TYPES],
    update_callbacks: Vec<Box<Fn()>>,
    clear_callbacks: Vec<Box<Fn()>>,
}

macro_rules! make_array {
    ($n:expr, $constructor:expr) => {{
        let mut items: [_; $n] = ::std::mem::uninitialized();
        for (i, place) in items.iter_mut().enumerate() {
            ::std::ptr::write(place, $constructor(i));
        }
        items
    }}
}

impl ActorSystem {
    pub fn new() -> ActorSystem {
        ActorSystem {
            routing: unsafe{make_array!(MAX_RECIPIENT_TYPES, |_| None)},
            recipient_registry: TypeRegistry::new(),
            individuals: [None; MAX_RECIPIENT_TYPES],
            update_callbacks: Vec::new(),
            clear_callbacks: Vec::new()
        }
    }

    pub fn add_individual<I: Individual>(&mut self, individual: I) {
        let recipient_id = self.recipient_registry.register_new::<I>();
        assert!(self.routing[recipient_id].is_none());
        self.routing[recipient_id] = Some(InboxMap::new());
        self.individuals[recipient_id] = Some(Box::into_raw(Box::new(individual)) as *mut u8);
    }

    pub fn add_inbox<M: Message, I: Individual + Recipient<M>> (&mut self) {
        self.add_inbox_helper::<M, I>(true);
    }

    pub fn add_unclearable_inbox<M: Message, I: Individual + Recipient<M>> (&mut self) {
        self.add_inbox_helper::<M, I>(false);
    }

    fn add_inbox_helper<M: Message, I: Individual + Recipient<M>> (&mut self, clearable: bool) {
        let inbox = Inbox::<M>::new();
        let recipient_id = self.recipient_registry.get::<I>();
        let inbox_ptr = self.store_inbox(inbox, recipient_id);
        let individual_ptr = self.individuals[recipient_id].unwrap() as *mut I;
        self.update_callbacks.push(Box::new(move || {
            unsafe {
                let mut n_packets = 0;
                for packet in (*inbox_ptr).empty() {
                    (*individual_ptr).receive_packet(packet);
                    n_packets += 1;
                }
                if n_packets > 100 {
                    println!("Processed {} {} Messages for {}",
                        n_packets,
                        type_name::<M>(),
                        type_name::<I>());
                }
            }
        }));
        if clearable {
            self.clear_callbacks.push(Box::new(move || {
                unsafe {
                    for _packet in (*inbox_ptr).empty() {
                    }
                }
            }));
        }
    }

    pub fn individual_id<I: Individual>(&mut self) -> ID {
        ID::individual(self.recipient_registry.get::<I>())
    }

    pub fn broadcast_id<A: Actor>(&mut self) -> ID {
        ID::broadcast(self.recipient_registry.get::<Swarm<A>>())
    }

    pub fn instance_id<A: Actor>(&mut self, instance_id_and_version: (usize, usize)) -> ID {
        ID::instance(self.recipient_registry.get::<Swarm<A>>(), instance_id_and_version)
    }

    fn store_inbox<M: Message>(&mut self, inbox: Inbox<M>, recipient_type_id: usize) -> *mut Inbox<M> {
        let inbox_ptr = Box::into_raw(Box::new(inbox));
        // TODO: deallocate inbox at the end of times
        self.routing[recipient_type_id].as_mut().unwrap().add_new(inbox_ptr);
        inbox_ptr
    }

    pub fn inbox_for<M: Message>(&mut self, packet: &Packet<M>) -> &mut Inbox<M> {
        if let Some(inbox_ptr) = self.routing[packet.recipient_id.type_id as usize].as_ref()
            .expect("Recipient not found")
            .get::<M>() {
                unsafe{&mut *inbox_ptr}
        } else {
            panic!("Inbox for {} not found for {}",
                unsafe{type_name::<M>()},
                self.recipient_registry.get_name(packet.recipient_id.type_id as usize))
        }
    }

    fn send<M: Message>(&mut self, recipient: ID, message: M) {
        let packet = Packet{
            recipient_id: recipient,
            message: message
        };
        self.inbox_for(&packet).put(packet);
    }

    pub fn process_messages(&mut self) {
        for callback in &self.update_callbacks {
            callback();
        }
    }

    pub fn clear_all_clearable_messages(&mut self) {
        for callback in &self.clear_callbacks {
            callback();
        }
    }

    pub fn process_all_messages(&mut self) {
        for _i in 0..1000 {
            self.process_messages();
        }
    }
}

impl Default for ActorSystem {
    fn default() -> Self {
        Self::new()
    }
}<commit_msg>Removed high-volume debug prints<commit_after>use super::swarm::Swarm;
use super::messaging::{Message, Actor, Individual, Packet, Recipient};
use super::inbox::Inbox;
use super::type_registry::TypeRegistry;
use std::intrinsics::{type_id, type_name};

pub static mut THE_SYSTEM: *mut ActorSystem = 0 as *mut ActorSystem;

#[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub struct ID {
    pub type_id: u16,
    pub version: u8,
    pub instance_id: u32
}

impl ID {
    pub fn invalid() -> ID {ID {type_id: u16::max_value(), version: u8::max_value(), instance_id: 0}}

    pub fn individual(individual_type_id: usize) -> ID {
        ID {type_id: individual_type_id as u16, version: 0, instance_id: 0}
    }

    pub fn broadcast(type_id: usize) -> ID {
        ID {type_id: type_id as u16, version: 0, instance_id: u32::max_value()}
    }

    pub fn instance(type_id: usize, instance_id_and_version: (usize, usize)) -> ID {
        ID {type_id: type_id as u16, version: instance_id_and_version.1 as u8, instance_id: instance_id_and_version.0 as u32}
    }

    pub fn is_broadcast(&self) -> bool {
        self.instance_id == u32::max_value()
    }

    pub fn swarm(type_id: usize) -> ID {
        ID {type_id: type_id as u16, version: 0, instance_id: u32::max_value() - 1}
    }

    pub fn is_swarm(&self) -> bool {
        self.instance_id == u32::max_value() - 1
    }
}

impl Default for ID {
    fn default() -> Self {
        ID::invalid()
    }
}

impl ::std::fmt::Debug for ID {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        write!(f, "ID {}_{}_{}", self.type_id, self.version, self.instance_id)
    }
}

impl<M: Message> ::std::ops::Shl<M> for ID {
    type Output = ();

    fn shl(self, rhs: M) {
        unsafe {(*THE_SYSTEM).send(self, rhs);}
    }
}

const MAX_RECIPIENT_TYPES : usize = 1024;
const MAX_MESSAGE_TYPES_PER_RECIPIENT: usize = 32;

#[derive(Clone)]
struct InboxMap {
    length: usize,
    entries: [Option<(u64, *mut u8)>; MAX_MESSAGE_TYPES_PER_RECIPIENT]
}

impl InboxMap {
    fn new() -> InboxMap {
        InboxMap{length: 0, entries: [None; MAX_MESSAGE_TYPES_PER_RECIPIENT]}
    }

    fn add_new<M: Message>(&mut self, pointer: *mut Inbox<M>) {
        let message_type_id = unsafe{type_id::<M>()};
        let entry_is_for_id = |entry: &&Option<(u64, *mut u8)>| {
            entry.is_some() && entry.unwrap().0 == message_type_id
        };
        assert!(self.entries.iter().find(entry_is_for_id).is_none());
        self.entries[self.length] = Some((message_type_id, pointer as *mut u8));
        self.length += 1;
    }

    fn get<M: Message>(&self) -> Option<*mut Inbox<M>> {
        let message_type_id = unsafe{type_id::<M>()};
        for entry in &self.entries {if let Some((id, pointer)) = *entry {
            if id == message_type_id {return Some(pointer as *mut Inbox<M>)}
        }}
        None
    }
}

pub struct ActorSystem {
    routing: [Option<InboxMap>; MAX_RECIPIENT_TYPES],
    recipient_registry: TypeRegistry,
    individuals: [Option<*mut u8>; MAX_RECIPIENT_TYPES],
    update_callbacks: Vec<Box<Fn()>>,
    clear_callbacks: Vec<Box<Fn()>>,
}

macro_rules! make_array {
    ($n:expr, $constructor:expr) => {{
        let mut items: [_; $n] = ::std::mem::uninitialized();
        for (i, place) in items.iter_mut().enumerate() {
            ::std::ptr::write(place, $constructor(i));
        }
        items
    }}
}

impl ActorSystem {
    pub fn new() -> ActorSystem {
        ActorSystem {
            routing: unsafe{make_array!(MAX_RECIPIENT_TYPES, |_| None)},
            recipient_registry: TypeRegistry::new(),
            individuals: [None; MAX_RECIPIENT_TYPES],
            update_callbacks: Vec::new(),
            clear_callbacks: Vec::new()
        }
    }

    pub fn add_individual<I: Individual>(&mut self, individual: I) {
        let recipient_id = self.recipient_registry.register_new::<I>();
        assert!(self.routing[recipient_id].is_none());
        self.routing[recipient_id] = Some(InboxMap::new());
        self.individuals[recipient_id] = Some(Box::into_raw(Box::new(individual)) as *mut u8);
    }

    pub fn add_inbox<M: Message, I: Individual + Recipient<M>> (&mut self) {
        self.add_inbox_helper::<M, I>(true);
    }

    pub fn add_unclearable_inbox<M: Message, I: Individual + Recipient<M>> (&mut self) {
        self.add_inbox_helper::<M, I>(false);
    }

    fn add_inbox_helper<M: Message, I: Individual + Recipient<M>> (&mut self, clearable: bool) {
        let inbox = Inbox::<M>::new();
        let recipient_id = self.recipient_registry.get::<I>();
        let inbox_ptr = self.store_inbox(inbox, recipient_id);
        let individual_ptr = self.individuals[recipient_id].unwrap() as *mut I;
        self.update_callbacks.push(Box::new(move || {
            unsafe {
                for packet in (*inbox_ptr).empty() {
                    (*individual_ptr).receive_packet(packet);
                }
            }
        }));
        if clearable {
            self.clear_callbacks.push(Box::new(move || {
                unsafe {
                    for _packet in (*inbox_ptr).empty() {
                    }
                }
            }));
        }
    }

    pub fn individual_id<I: Individual>(&mut self) -> ID {
        ID::individual(self.recipient_registry.get::<I>())
    }

    pub fn broadcast_id<A: Actor>(&mut self) -> ID {
        ID::broadcast(self.recipient_registry.get::<Swarm<A>>())
    }

    pub fn instance_id<A: Actor>(&mut self, instance_id_and_version: (usize, usize)) -> ID {
        ID::instance(self.recipient_registry.get::<Swarm<A>>(), instance_id_and_version)
    }

    fn store_inbox<M: Message>(&mut self, inbox: Inbox<M>, recipient_type_id: usize) -> *mut Inbox<M> {
        let inbox_ptr = Box::into_raw(Box::new(inbox));
        // TODO: deallocate inbox at the end of times
        self.routing[recipient_type_id].as_mut().unwrap().add_new(inbox_ptr);
        inbox_ptr
    }

    pub fn inbox_for<M: Message>(&mut self, packet: &Packet<M>) -> &mut Inbox<M> {
        if let Some(inbox_ptr) = self.routing[packet.recipient_id.type_id as usize].as_ref()
            .expect("Recipient not found")
            .get::<M>() {
                unsafe{&mut *inbox_ptr}
        } else {
            panic!("Inbox for {} not found for {}",
                unsafe{type_name::<M>()},
                self.recipient_registry.get_name(packet.recipient_id.type_id as usize))
        }
    }

    fn send<M: Message>(&mut self, recipient: ID, message: M) {
        let packet = Packet{
            recipient_id: recipient,
            message: message
        };
        self.inbox_for(&packet).put(packet);
    }

    pub fn process_messages(&mut self) {
        for callback in &self.update_callbacks {
            callback();
        }
    }

    pub fn clear_all_clearable_messages(&mut self) {
        for callback in &self.clear_callbacks {
            callback();
        }
    }

    pub fn process_all_messages(&mut self) {
        for _i in 0..1000 {
            self.process_messages();
        }
    }
}

impl Default for ActorSystem {
    fn default() -> Self {
        Self::new()
    }
}<|endoftext|>