<commit_before>
//! Immediate mode gui. See [`ui::Ui`](struct.Ui.html) for more info.

use std::mem;
use gl;
use gl::types::*;
use std::ops::Range;
use std::collections::HashMap;
use std::fmt::Write;
use cable_math::Vec2;

use color::Color;
use font::{Font, CachedFont};
use input::{InputManager, State};
use matrix_stack::MatrixStack;
use shader::{Shader, ShaderPrototype};
use buffer::{Vertex, VertexBuffer, PrimitiveMode, BufferUsage};

const FONT_SIZE: f32 = 14.0;

/// A struct for using a imediate mode gui.
pub struct Ui {
    pub style: Style,

    mat_stack: MatrixStack,
    font: CachedFont,
    shader: Shader,
    draw_data: Vec<Vert>,
    draw_vbo: VertexBuffer<Vert>,

    caret: Vec2<f32>,
    caret_start: Vec2<f32>,
    line_size: f32,
    line_dir: LineDir,
    held: Option<Id>,

    internal_format_string: String,
    slider_map: HashMap<Id, f32>,

    // Input state
    mouse_pos: Vec2<f32>,
    mouse_state: State,
}

impl Ui {
    /// Creates a new imediate mode gui system with the given font. Note that the font will be
    /// copied internally, so you can pass a reference to a font you are using elsewhere in your
    /// program.
    pub fn new(font: &Font) -> Ui {
        Ui {
            style: Default::default(),

            mat_stack: MatrixStack::new(),
            font: CachedFont::from_font(font.clone()),
            shader: build_shader(),
            draw_data: Vec::with_capacity(500),
            draw_vbo: VertexBuffer::with_capacity(PrimitiveMode::Triangles, BufferUsage::DynamicDraw, 500),

            caret: Vec2::zero(),
            caret_start: Vec2::zero(),
            line_size: 0.0,
            line_dir: LineDir::Vertical,
            held: None,

            internal_format_string: String::new(),
            slider_map: HashMap::new(),

            mouse_pos: Vec2::zero(),
            mouse_state: State::Up,
        }
    }

    /// Updates this imgui system. This should be called once per frame, before using any of the
    /// gui creation functions.
    pub fn update(&mut self, input: &InputManager, window_size: Vec2<u32>) {
        self.mat_stack.ortho(0.0, window_size.x as f32, 0.0, window_size.y as f32, -1.0, 1.0);

        self.mouse_pos = input.mouse_pos();
        self.mouse_state = input.mouse_key(0);

        if self.mouse_state.up() && !self.mouse_state.released() {
            self.held = None;
        }

        self.caret = Vec2::zero();
    }

    /// Shows all components added since the last call to `draw`. This function update the matrix
    /// buffers and binds new shaders. No special opengl state is required to be set when calling
    /// this function. Note that this function does not necessarily reset the state it changes.
    pub fn draw(&mut self) {
        self.mat_stack.update_buffer();

        self.draw_vbo.clear();
        self.draw_vbo.put(0, &self.draw_data);
        self.draw_data.clear();

        self.shader.bind();
        self.draw_vbo.draw();
        self.font.draw();
    }

    /// Moves the internal caret to the given position. Consecutive items will be inserted at
    /// the caret.
    pub fn set_caret(&mut self, pos: Vec2<f32>, line_dir: LineDir) {
        self.caret = pos;
        self.caret_start = pos;
        self.line_dir = line_dir;
        self.line_size = 0.0;
    }

    /// Advances the caret to the next line. The direction of a line depends on the line direction
    /// set by [`set_caret`].
    ///
    /// [`set_caret`]: struct.Ui.html#method.set_caret
    pub fn next_line(&mut self) {
        match self.line_dir {
            LineDir::Horizontal => {
                self.caret.y += self.line_size + self.style.line_spacing;
                self.caret.x = self.caret_start.x;
                self.line_size = 0.0;
            },
            LineDir::Vertical => {
                self.caret.x += self.line_size + self.style.line_spacing;
                self.caret.y = self.caret_start.y;
                self.line_size = 0.0;
            },
        }
    }

    fn advance_caret(&mut self, comp_width: f32, comp_height: f32) {
        match self.line_dir {
            LineDir::Horizontal => {
                self.caret.x += comp_width + self.style.line_spacing;
                self.line_size = f32::max(comp_height, self.line_size);
            },
            LineDir::Vertical => {
                self.caret.y += comp_height + self.style.line_spacing;
                self.line_size = f32::max(comp_width, self.line_size);
            },
        }
    }

    fn default_height(&self) -> f32 {
        self.font.font().line_height(FONT_SIZE) + self.style.internal_padding.y
    }

    /// Shows a new button with the given text at the given location. Returns true if the button
    /// was pressed. Note that this function needs to be called every frame you want to see the
    /// button.
    pub fn button(&mut self, text: &str) -> bool {
        let id = Id::from_str(text, CompType::Button);

        let width = self.font.font().width(text, FONT_SIZE) + self.style.internal_padding.x;
        let height = self.default_height();
        let pos = self.caret;
        self.advance_caret(width, height);

        let text_start = self.style.internal_padding.y/2.0 - self.font.font().descent(FONT_SIZE);

        let hovered = self.mouse_pos.x > pos.x && self.mouse_pos.y > pos.y &&
                      self.mouse_pos.x < pos.x + width && self.mouse_pos.y < pos.y + height;
        if hovered && self.mouse_state.pressed() {
            self.held = Some(id);
        }

        let color = if self.held == Some(id) {
            self.style.hold_color
        } else if hovered {
            self.style.hover_color
        } else {
            self.style.base_color
        };
        quad(&mut self.draw_data, pos, Vec2::new(width, height), color);
        self.font.cache(text, FONT_SIZE, pos + Vec2::new(self.style.internal_padding.x/2.0, height - text_start));

        self.held == Some(id) && hovered && self.mouse_state.released()
    }

    // TODO: Maybe make this generic over different number types
    pub fn slider(&mut self, text: &str, range: Range<f32>) -> f32 {
        let id = Id::from_str(text, CompType::Slider);
        let mut value = *self.slider_map.entry(id).or_insert((range.start + range.end) / 2.0);

        let width = self.style.default_comp_width;
        let height = self.default_height();
        let pos = self.caret;
        self.advance_caret(width, height);

        let hovered = self.mouse_pos.x > pos.x && self.mouse_pos.y > pos.y &&
                      self.mouse_pos.x < pos.x + width && self.mouse_pos.y < pos.y + height;
        if hovered && self.mouse_state.pressed() {
            self.held = Some(id);
        }

        let slider_size = {
            let size = height - self.style.internal_padding.y;
            Vec2::new(size, size)
        };
        let slider_pos = {
            let norm_value = (value - range.start) / (range.end - range.start);
            let slide_distance = width - self.style.internal_padding.x - slider_size.x;
            pos + Vec2::new(self.style.internal_padding.x/2.0 + norm_value*slide_distance, self.style.internal_padding.y/2.0)
        };

        self.internal_format_string.clear();
        write!(self.internal_format_string, "{}: {:.*}", text, 2, value).unwrap();

        let text_pos = {
            let text_width = self.font.font().width(&self.internal_format_string, FONT_SIZE);
            let text_v_offset = self.style.internal_padding.y/2.0 - self.font.font().descent(FONT_SIZE);
            pos + Vec2::new(width/2.0 - text_width/2.0, height - text_v_offset)
        };

        if self.held == Some(id) {
            value = (self.mouse_pos.x - pos.x - self.style.internal_padding.x/2.0 - slider_size.x/2.0) /
                    (width - self.style.internal_padding.x - slider_size.x);
            if value > 1.0 { value = 1.0 }
            if value < 0.0 { value = 0.0 }
            value = range.start + value*(range.end - range.start);

            self.slider_map.insert(id, value);
        }

        // Main bar
        let color = if hovered { self.style.hover_color } else { self.style.base_color };
        quad(&mut self.draw_data, pos, Vec2::new(width, height), color);
        self.font.cache(&self.internal_format_string, FONT_SIZE, text_pos);
        // Slidy thing
        let color = if self.held == Some(id) { self.style.top_hold_color } else { self.style.top_color };
        quad(&mut self.draw_data, slider_pos, slider_size, color);

        value
    }
}

#[derive(Clone, Debug)]
pub struct Style {
    pub base_color: Color,
    pub hover_color: Color,
    pub hold_color: Color,
    pub top_color: Color,
    pub top_hold_color: Color,

    pub internal_padding: Vec2<f32>,
    pub line_spacing: f32,
    pub default_comp_width: f32,
}
impl Default for Style {
    fn default() -> Style {
        Style {
            base_color:      Color::hex("4c4665"),
            hover_color:     Color::hex("575074"),
            hold_color:      Color::hex("413c56"),
            top_color:       Color::hex("403147"),
            top_hold_color:  Color::hex("2a2738"),

            internal_padding: Vec2::new(10.0, 6.0),
            line_spacing: 5.0,
            default_comp_width: 150.0,
        }
    }
}

pub enum LineDir {
    /// Components are layed out below each other
    Vertical,
    /// Components are layed out side by side
    Horizontal,
}

#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
struct Id(u64, CompType);
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
enum CompType {
    Button,
    Slider,
}

impl Id {
    fn from_str(text: &str, ty: CompType) -> Id {
        use std::collections::hash_map::DefaultHasher;
        use std::hash::{Hasher, Hash};

        let mut hasher = DefaultHasher::new();
        text.hash(&mut hasher);
        let id = hasher.finish();

        Id(id, ty)
    }
}

#[derive(Debug)]
#[repr(C)]
struct Vert {
    pos: Vec2<f32>,
    color: Color,
}

fn quad(buf: &mut Vec<Vert>, pos: Vec2<f32>, size: Vec2<f32>, color: Color){
    let min = pos;
    let max = pos + size;

    buf.push(Vert { pos: Vec2::new(min.x, min.y), color: color });
    buf.push(Vert { pos: Vec2::new(max.x, min.y), color: color });
    buf.push(Vert { pos: Vec2::new(max.x, max.y), color: color });

    buf.push(Vert { pos: Vec2::new(min.x, min.y), color: color });
    buf.push(Vert { pos: Vec2::new(max.x, max.y), color: color });
    buf.push(Vert { pos: Vec2::new(min.x, max.y), color: color });
}

// We cannot use the custom derive from within this crate
impl Vertex for Vert {
    fn bytes_per_vertex() -> usize { mem::size_of::<Vert>() }
    fn setup_attrib_pointers() {
        let stride = <Vert as Vertex>::bytes_per_vertex();
        let mut offset = 0;
        unsafe {
            gl::EnableVertexAttribArray(0);
            gl::VertexAttribPointer(0, 2, gl::FLOAT,
                                    false as GLboolean,
                                    stride as GLsizei, offset as *const GLvoid);
            offset += mem::size_of::<Vec2<f32>>();

            gl::EnableVertexAttribArray(1);
            gl::VertexAttribPointer(1, 4, gl::FLOAT,
                                    false as GLboolean,
                                    stride as GLsizei, offset as *const GLvoid);
        }
    }
    // Not used, we manualy declare inputs in the shader
    fn gen_shader_input_decl() -> String { String::new() }
}

const VERT_SRC: &'static str = "
    #version 330 core

    layout(location = 0) in vec2 pos;
    layout(location = 1) in vec4 color;

    out vec4 vert_col;

    // Matrix block is inserted automatically

    void main() {
        gl_Position = mvp * vec4(pos, 0.0, 1.0);
        vert_col = color;
    }
";
const FRAG_SRC: &'static str = "
    #version 330 core

    in vec4 vert_col;
    out vec4 color;

    void main() {
        color = vert_col;
    }
";

fn build_shader() -> Shader {
    let mut proto = ShaderPrototype::new_prototype(VERT_SRC, "", FRAG_SRC);
    proto.bind_to_matrix_storage();
    match proto.build() {
        Ok(shader) => shader,
        Err(err) => {
            println!("{}", err); // Print the error properly
            panic!();
        }
    }
}

<commit_msg>Some cleanup in imgui code<commit_after>
//! Immediate mode gui. See [`ui::Ui`](struct.Ui.html) for more info.

use std::mem;
use gl;
use gl::types::*;
use std::ops::Range;
use std::collections::HashMap;
use std::fmt::Write;
use cable_math::Vec2;

use color::Color;
use font::{Font, CachedFont};
use input::{InputManager, State};
use matrix_stack::MatrixStack;
use shader::{Shader, ShaderPrototype};
use buffer::{Vertex, VertexBuffer, PrimitiveMode, BufferUsage};

const FONT_SIZE: f32 = 14.0;

/// A struct for using a imediate mode gui.
pub struct Ui {
    pub style: Style,

    mat_stack: MatrixStack,
    font: CachedFont,
    shader: Shader,
    draw_data: Vec<Vert>,
    draw_vbo: VertexBuffer<Vert>,

    caret: Vec2<f32>,
    caret_start: Vec2<f32>,
    line_size: f32,
    line_dir: LineDir,
    held: Option<Id>,

    internal_fmt_string: String,
    slider_map: HashMap<Id, f32>,

    // Input state
    mouse_pos: Vec2<f32>,
    mouse_state: State,
}

impl Ui {
    /// Creates a new imediate mode gui system with the given font. Note that the font will be
    /// copied internally, so you can pass a reference to a font you are using elsewhere in your
    /// program.
    pub fn new(font: &Font) -> Ui {
        Ui {
            style: Default::default(),

            mat_stack: MatrixStack::new(),
            font: CachedFont::from_font(font.clone()),
            shader: build_shader(),
            draw_data: Vec::with_capacity(500),
            draw_vbo: VertexBuffer::with_capacity(PrimitiveMode::Triangles, BufferUsage::DynamicDraw, 500),

            caret: Vec2::zero(),
            caret_start: Vec2::zero(),
            line_size: 0.0,
            line_dir: LineDir::Vertical,
            held: None,

            internal_fmt_string: String::new(),
            slider_map: HashMap::new(),

            mouse_pos: Vec2::zero(),
            mouse_state: State::Up,
        }
    }

    /// Updates this imgui system. This should be called once per frame, before using any of the
    /// gui creation functions.
    pub fn update(&mut self, input: &InputManager, window_size: Vec2<u32>) {
        self.mat_stack.ortho(0.0, window_size.x as f32, 0.0, window_size.y as f32, -1.0, 1.0);

        self.mouse_pos = input.mouse_pos();
        self.mouse_state = input.mouse_key(0);

        if self.mouse_state.up() && !self.mouse_state.released() {
            self.held = None;
        }

        self.caret = Vec2::zero();
    }

    /// Shows all components added since the last call to `draw`. This function update the matrix
    /// buffers and binds new shaders. No special opengl state is required to be set when calling
    /// this function. Note that this function does not necessarily reset the state it changes.
    pub fn draw(&mut self) {
        self.mat_stack.update_buffer();

        self.draw_vbo.clear();
        self.draw_vbo.put(0, &self.draw_data);
        self.draw_data.clear();

        self.shader.bind();
        self.draw_vbo.draw();
        self.font.draw();
    }

    /// Moves the internal caret to the given position. Consecutive items will be inserted at
    /// the caret.
    pub fn set_caret(&mut self, pos: Vec2<f32>, line_dir: LineDir) {
        self.caret = pos;
        self.caret_start = pos;
        self.line_dir = line_dir;
        self.line_size = 0.0;
    }

    /// Advances the caret to the next line. The direction of a line depends on the line direction
    /// set by [`set_caret`].
    ///
    /// [`set_caret`]: struct.Ui.html#method.set_caret
    pub fn next_line(&mut self) {
        match self.line_dir {
            LineDir::Horizontal => {
                self.caret.y += self.line_size + self.style.line_spacing;
                self.caret.x = self.caret_start.x;
                self.line_size = 0.0;
            },
            LineDir::Vertical => {
                self.caret.x += self.line_size + self.style.line_spacing;
                self.caret.y = self.caret_start.y;
                self.line_size = 0.0;
            },
        }
    }

    /// Shows a new button with the given text at the given location. Returns true if the button
    /// was pressed. Note that this function needs to be called every frame you want to see the
    /// button.
    pub fn button(&mut self, text: &str) -> bool {
        let id = Id::from_str(text, CompType::Button);

        let width = self.font.font().width(text, FONT_SIZE) + self.style.internal_padding.x;
        let height = self.default_height();
        let pos = self.caret;
        self.advance_caret(width, height);

        let hovered = self.mouse_pos.x > pos.x && self.mouse_pos.y > pos.y &&
                      self.mouse_pos.x < pos.x + width && self.mouse_pos.y < pos.y + height;
        if hovered && self.mouse_state.pressed() {
            self.held = Some(id);
        }

        let color = if self.held == Some(id) {
            self.style.hold_color
        } else if hovered {
            self.style.hover_color
        } else {
            self.style.base_color
        };
        self.draw_comp(pos, width, height, color, text, Alignment::Left);

        self.held == Some(id) && hovered && self.mouse_state.released()
    }

    /// Creates a new slider that allows selecting values from the given range
    pub fn slider(&mut self, text: &str, range: Range<f32>) -> f32 {
        let id = Id::from_str(text, CompType::Slider);
        let mut value = *self.slider_map.entry(id).or_insert((range.start + range.end) / 2.0);

        let width = self.style.default_comp_width;
        let height = self.default_height();
        let pos = self.caret;
        self.advance_caret(width, height);

        let hovered = self.mouse_pos.x > pos.x && self.mouse_pos.y > pos.y &&
                      self.mouse_pos.x < pos.x + width && self.mouse_pos.y < pos.y + height;
        if hovered && self.mouse_state.pressed() {
            self.held = Some(id);
        }

        let slider_size = {
            let size = height - self.style.internal_padding.y;
            Vec2::new(size, size)
        };
        let slider_pos = {
            let norm_value = (value - range.start) / (range.end - range.start);
            let slide_distance = width - self.style.internal_padding.x - slider_size.x;
            pos + Vec2::new(self.style.internal_padding.x/2.0 + norm_value*slide_distance, self.style.internal_padding.y/2.0)
        };

        self.internal_fmt_string.clear();
        write!(self.internal_fmt_string, "{}: {:.*}", text, 2, value).unwrap();

        if self.held == Some(id) {
            value = (self.mouse_pos.x - pos.x - self.style.internal_padding.x/2.0 - slider_size.x/2.0) /
                    (width - self.style.internal_padding.x - slider_size.x);
            if value > 1.0 { value = 1.0 }
            if value < 0.0 { value = 0.0 }
            value = range.start + value*(range.end - range.start);

            self.slider_map.insert(id, value);
        }

        // Main bar
        let color = if hovered { self.style.hover_color } else { self.style.base_color };
        let text = &self.internal_fmt_string.clone();
        self.draw_comp(pos, width, height, color, text, Alignment::Center);
        // Slidy thing
        let color = if self.held == Some(id) { self.style.top_hold_color } else { self.style.top_color };
        quad(&mut self.draw_data, slider_pos, slider_size, color);

        value
    }

    fn draw_comp(&mut self, pos: Vec2<f32>, width: f32, height: f32, color: Color, text: &str, alignment: Alignment) {
        quad(&mut self.draw_data, pos, Vec2::new(width, height), color);
        match alignment {
            Alignment::Left => {
                let text_start = self.style.internal_padding.y/2.0 - self.font.font().descent(FONT_SIZE);
                self.font.cache(text, FONT_SIZE, pos + Vec2::new(self.style.internal_padding.x/2.0, height - text_start));
            },
            Alignment::Right => {
                let text_pos = {
                    let text_width = self.font.font().width(&self.internal_fmt_string, FONT_SIZE);
                    let text_v_offset = self.style.internal_padding.y/2.0 - self.font.font().descent(FONT_SIZE);
                    pos + Vec2::new(width - self.style.internal_padding.x/2.0 - text_width, height - text_v_offset)
                };
                self.font.cache(text, FONT_SIZE, text_pos);
            },
            Alignment::Center => {
                let text_pos = {
                    let text_width = self.font.font().width(&self.internal_fmt_string, FONT_SIZE);
                    let text_v_offset = self.style.internal_padding.y/2.0 - self.font.font().descent(FONT_SIZE);
                    pos + Vec2::new(width/2.0 - text_width/2.0, height - text_v_offset)
                };
                self.font.cache(text, FONT_SIZE, text_pos);
            },
        }
    }

    fn advance_caret(&mut self, comp_width: f32, comp_height: f32) {
        match self.line_dir {
            LineDir::Horizontal => {
                self.caret.x += comp_width + self.style.line_spacing;
                self.line_size = f32::max(comp_height, self.line_size);
            },
            LineDir::Vertical => {
                self.caret.y += comp_height + self.style.line_spacing;
                self.line_size = f32::max(comp_width, self.line_size);
            },
        }
    }

    fn default_height(&self) -> f32 {
        self.font.font().line_height(FONT_SIZE) + self.style.internal_padding.y
    }
}

#[derive(Clone, Debug)]
pub struct Style {
    pub base_color: Color,
    pub hover_color: Color,
    pub hold_color: Color,
    pub top_color: Color,
    pub top_hold_color: Color,

    pub internal_padding: Vec2<f32>,
    pub line_spacing: f32,
    pub default_comp_width: f32,
}
impl Default for Style {
    fn default() -> Style {
        Style {
            base_color:      Color::hex("4c4665"),
            hover_color:     Color::hex("575074"),
            hold_color:      Color::hex("413c56"),
            top_color:       Color::hex("403147"),
            top_hold_color:  Color::hex("2a2738"),

            internal_padding: Vec2::new(10.0, 6.0),
            line_spacing: 5.0,
            default_comp_width: 150.0,
        }
    }
}

pub enum LineDir {
    /// Components are layed out below each other
    Vertical,
    /// Components are layed out side by side
    Horizontal,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
enum Alignment {
    Left, Center, Right,
}

#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
struct Id(u64, CompType);
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
enum CompType {
    Button,
    Slider,
}

impl Id {
    fn from_str(text: &str, ty: CompType) -> Id {
        use std::collections::hash_map::DefaultHasher;
        use std::hash::{Hasher, Hash};

        let mut hasher = DefaultHasher::new();
        text.hash(&mut hasher);
        let id = hasher.finish();

        Id(id, ty)
    }
}

#[derive(Debug)]
#[repr(C)]
struct Vert {
    pos: Vec2<f32>,
    color: Color,
}

fn quad(buf: &mut Vec<Vert>, pos: Vec2<f32>, size: Vec2<f32>, color: Color){
    let min = pos;
    let max = pos + size;

    buf.push(Vert { pos: Vec2::new(min.x, min.y), color: color });
    buf.push(Vert { pos: Vec2::new(max.x, min.y), color: color });
    buf.push(Vert { pos: Vec2::new(max.x, max.y), color: color });

    buf.push(Vert { pos: Vec2::new(min.x, min.y), color: color });
    buf.push(Vert { pos: Vec2::new(max.x, max.y), color: color });
    buf.push(Vert { pos: Vec2::new(min.x, max.y), color: color });
}

// We cannot use the custom derive from within this crate
impl Vertex for Vert {
    fn bytes_per_vertex() -> usize { mem::size_of::<Vert>() }
    fn setup_attrib_pointers() {
        let stride = <Vert as Vertex>::bytes_per_vertex();
        let mut offset = 0;
        unsafe {
            gl::EnableVertexAttribArray(0);
            gl::VertexAttribPointer(0, 2, gl::FLOAT,
                                    false as GLboolean,
                                    stride as GLsizei, offset as *const GLvoid);
            offset += mem::size_of::<Vec2<f32>>();

            gl::EnableVertexAttribArray(1);
            gl::VertexAttribPointer(1, 4, gl::FLOAT,
                                    false as GLboolean,
                                    stride as GLsizei, offset as *const GLvoid);
        }
    }
    // Not used, we manualy declare inputs in the shader
    fn gen_shader_input_decl() -> String { String::new() }
}

const VERT_SRC: &'static str = "
    #version 330 core

    layout(location = 0) in vec2 pos;
    layout(location = 1) in vec4 color;

    out vec4 vert_col;

    // Matrix block is inserted automatically

    void main() {
        gl_Position = mvp * vec4(pos, 0.0, 1.0);
        vert_col = color;
    }
";
const FRAG_SRC: &'static str = "
    #version 330 core

    in vec4 vert_col;
    out vec4 color;

    void main() {
        color = vert_col;
    }
";

fn build_shader() -> Shader {
    let mut proto = ShaderPrototype::new_prototype(VERT_SRC, "", FRAG_SRC);
    proto.bind_to_matrix_storage();
    match proto.build() {
        Ok(shader) => shader,
        Err(err) => {
            println!("{}", err); // Print the error properly
            panic!();
        }
    }
}

<|endoftext|>


<commit_before>use std::io;
use std::io::Read;
use command::Command;

type Cell = u8;

pub struct VM {
    pub cells: [Cell; 30_000],
    pub data_pointer: usize,
}

impl VM {
    pub fn new() -> VM {
        VM { cells: [0; 30_000], data_pointer: 0 }
    }

    pub fn output(&self) {
        print!("{}", self.cells[self.data_pointer] as char);
    }

    pub fn input(&mut self) {
        match io::stdin().bytes().next() {
            Some(res) => match res {
                Ok(value) => self.cells[self.data_pointer] = value,
                Err(error) => panic!(error),
            },
            None => {}
        }
        println!("");
    }

    pub fn increment(&mut self) {
        self.cells[self.data_pointer] = self.cells[self.data_pointer].checked_add(1).unwrap_or(0);
    }

    pub fn decrement(&mut self) {
        self.cells[self.data_pointer] = self.cells[self.data_pointer]
            .checked_sub(1)
            .unwrap_or(Cell::max_value());
    }

    pub fn right_shift(&mut self) {
        self.data_pointer += 1;
    }

    pub fn left_shift(&mut self) {
        self.data_pointer -= 1;
    }

    pub fn apply(&mut self, command: Command) {
        match command {
            Command::Output => self.output(),
            Command::Input => self.input(),
            Command::Increment => self.increment(),
            Command::Decrement => self.decrement(),
            Command::RightShift => self.right_shift(),
            Command::LeftShift => self.left_shift(),
            _ => {},
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn test_new() {
        let vm = VM::new();
        assert!(vm.cells[0] == 0);
        assert!(vm.cells[30_000 - 1] == 0);
        assert!(vm.cells[0] == 0);
    }

    #[test]
    fn test_increment() {
        let mut vm = VM::new();
        vm.increment();
        assert!(vm.cells[0] == 1);
    }
}
<commit_msg>Add unit test for VM.decrement()<commit_after>use std::io;
use std::io::Read;
use command::Command;

type Cell = u8;

pub struct VM {
    pub cells: [Cell; 30_000],
    pub data_pointer: usize,
}

impl VM {
    pub fn new() -> VM {
        VM { cells: [0; 30_000], data_pointer: 0 }
    }

    pub fn output(&self) {
        print!("{}", self.cells[self.data_pointer] as char);
    }

    pub fn input(&mut self) {
        match io::stdin().bytes().next() {
            Some(res) => match res {
                Ok(value) => self.cells[self.data_pointer] = value,
                Err(error) => panic!(error),
            },
            None => {}
        }
        println!("");
    }

    pub fn increment(&mut self) {
        self.cells[self.data_pointer] = self.cells[self.data_pointer].checked_add(1).unwrap_or(0);
    }

    pub fn decrement(&mut self) {
        self.cells[self.data_pointer] = self.cells[self.data_pointer]
            .checked_sub(1)
            .unwrap_or(Cell::max_value());
    }

    pub fn right_shift(&mut self) {
        self.data_pointer += 1;
    }

    pub fn left_shift(&mut self) {
        self.data_pointer -= 1;
    }

    pub fn apply(&mut self, command: Command) {
        match command {
            Command::Output => self.output(),
            Command::Input => self.input(),
            Command::Increment => self.increment(),
            Command::Decrement => self.decrement(),
            Command::RightShift => self.right_shift(),
            Command::LeftShift => self.left_shift(),
            _ => {},
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn test_new() {
        let vm = VM::new();
        assert!(vm.cells[0] == 0);
        assert!(vm.cells[30_000 - 1] == 0);
        assert!(vm.cells[0] == 0);
    }

    #[test]
    fn test_increment() {
        let mut vm = VM::new();
        vm.increment();
        assert!(vm.cells[0] == 1);
    }

    #[test]
    fn test_decrement() {
        const STARTING_VALUE: u8 = 2;

        let mut vm = VM::new();
        vm.cells[0] = STARTING_VALUE;
        vm.decrement();
        assert!(vm.cells[0] == STARTING_VALUE - 1);
    }
}
<|endoftext|>


<commit_before>//! `Connections` node and its children.

use parser::binary::{Parser, ParserSource, Attributes};
use loader::binary::simple::{Result, Error};

/// `Connections` node.
#[derive(Debug, Clone, PartialEq)]
pub struct Connections(pub Vec<Connection>);

impl Connections {
    /// Loads node contents from the parser.
    pub fn load<R: ParserSource, P: Parser<R>>(mut parser: P) -> Result<Self> {
        let mut connections = Vec::new();

        loop {
            let attrs = try_get_node_attrs!(parser, ConnectionAttrs::load);
            connections.push(Connection::load(parser.subtree_parser(), attrs)?);
        }
        Ok(Connections(connections))
    }
}

/// Attributes read from a `C` node.
struct ConnectionAttrs {
    pub child_id: i64,
    pub parent_id: i64,
    pub property: Option<String>,
    pub child_is_prop: bool,
    pub parent_is_prop: bool,
}

impl ConnectionAttrs {
    /// Loads attributes.
    pub fn load<R: ParserSource>(name: &str, mut attrs: Attributes<R>) -> Result<Self> {
        use parser::binary::utils::AttributeValues;

        if name == "C" {
            let (ty, child_id, parent_id) =
                <(String, i64, i64)>::from_attributes(&mut attrs)?
                    .ok_or_else(|| Error::InvalidAttribute("C".to_owned()))?;
            let (child_is_prop, parent_is_prop) = match ty.as_str() {
                "OO" => (false, false),
                "OP" => (false, true),
                "PO" => (true, false),
                "PP" => (true, true),
                _ => return Err(Error::InvalidAttribute("C".to_owned())),
            };
            let property = if attrs.rest_attributes() > 0 {
                Some(String::from_attributes(&mut attrs)?
                    .ok_or_else(|| Error::InvalidAttribute("C".to_owned()))?)
            } else {
                None
            };
            Ok(ConnectionAttrs {
                child_id: child_id,
                parent_id: parent_id,
                property: property,
                child_is_prop: child_is_prop,
                parent_is_prop: parent_is_prop,
            })
        } else {
            Err(Error::UnexpectedNode(name.to_owned()))
        }
    }
}

/// `C` node.
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Connection {
    /// Object ID of the child object.
    pub child: i64,
    /// Object ID of the parent object.
    pub parent: i64,
    /// Property of the connection.
    pub property: Option<String>,
    /// `true` if the child is property.
    pub child_is_prop: bool,
    /// `true` if the parent is property.
    pub parent_is_prop: bool,
}

impl Connection {
    /// Loads node contents from the parser.
    fn load<R: ParserSource, P: Parser<R>>(mut parser: P, attrs: ConnectionAttrs) -> Result<Self> {
        parser.skip_current_node()?;
        Ok(Connection {
            child: attrs.child_id,
            parent: attrs.parent_id,
            property: attrs.property,
            child_is_prop: attrs.child_is_prop,
            parent_is_prop: attrs.parent_is_prop,
        })
    }
}
<commit_msg>Rename fields of `Connection{,s}`<commit_after>//! `Connections` node and its children.

use parser::binary::{Parser, ParserSource, Attributes};
use loader::binary::simple::{Result, Error};

/// `Connections` node.
#[derive(Debug, Clone, PartialEq)]
pub struct Connections(pub Vec<Connection>);

impl Connections {
    /// Loads node contents from the parser.
    pub fn load<R: ParserSource, P: Parser<R>>(mut parser: P) -> Result<Self> {
        let mut connections = Vec::new();

        loop {
            let attrs = try_get_node_attrs!(parser, ConnectionAttrs::load);
            connections.push(Connection::load(parser.subtree_parser(), attrs)?);
        }
        Ok(Connections(connections))
    }
}

/// Attributes read from a `C` node.
struct ConnectionAttrs {
    pub source_id: i64,
    pub destination_id: i64,
    pub property: Option<String>,
    pub source_is_prop: bool,
    pub destination_is_prop: bool,
}

impl ConnectionAttrs {
    /// Loads attributes.
    pub fn load<R: ParserSource>(name: &str, mut attrs: Attributes<R>) -> Result<Self> {
        use parser::binary::utils::AttributeValues;

        if name == "C" {
            let (ty, source_id, destination_id) =
                <(String, i64, i64)>::from_attributes(&mut attrs)?
                    .ok_or_else(|| Error::InvalidAttribute("C".to_owned()))?;
            let (source_is_prop, destination_is_prop) = match ty.as_str() {
                "OO" => (false, false),
                "OP" => (false, true),
                "PO" => (true, false),
                "PP" => (true, true),
                _ => return Err(Error::InvalidAttribute("C".to_owned())),
            };
            let property = if attrs.rest_attributes() > 0 {
                Some(String::from_attributes(&mut attrs)?
                         .ok_or_else(|| Error::InvalidAttribute("C".to_owned()))?)
            } else {
                None
            };
            Ok(ConnectionAttrs {
                   source_id: source_id,
                   destination_id: destination_id,
                   property: property,
                   source_is_prop: source_is_prop,
                   destination_is_prop: destination_is_prop,
               })
        } else {
            Err(Error::UnexpectedNode(name.to_owned()))
        }
    }
}

/// `C` node.
///
/// Note that "the child node will be a **source object** of the parent node", and "the parent node
/// will be the **destination object** of the child node".
/// See [FBX 2017 Developer Help:
/// Connections](http://help.autodesk.com/view/FBX/2017/ENU/?guid=__files_GUID_BB63A93A_7663_4256_B060_8EA35CB0FF3A_htm)
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Connection {
    /// Object ID of the source object.
    pub source: i64,
    /// Object ID of the destination object.
    pub destination: i64,
    /// Property of the connection.
    pub property: Option<String>,
    /// `true` if the source is property.
    pub source_is_prop: bool,
    /// `true` if the destination is property.
    pub destination_is_prop: bool,
}

impl Connection {
    /// Loads node contents from the parser.
    fn load<R: ParserSource, P: Parser<R>>(mut parser: P, attrs: ConnectionAttrs) -> Result<Self> {
        parser.skip_current_node()?;
        Ok(Connection {
               source: attrs.source_id,
               destination: attrs.destination_id,
               property: attrs.property,
               source_is_prop: attrs.source_is_prop,
               destination_is_prop: attrs.destination_is_prop,
           })
    }
}
<|endoftext|>


<commit_before>#[cfg(feature = "multipart")]
use super::multipart::Form;
/// dox
use bytes::Bytes;
use js_sys::{Array, Uint8Array};
use std::fmt;
use wasm_bindgen::JsValue;

/// The body of a `Request`.
///
/// In most cases, this is not needed directly, as the
/// [`RequestBuilder.body`][builder] method uses `Into<Body>`, which allows
/// passing many things (like a string or vector of bytes).
///
/// [builder]: ./struct.RequestBuilder.html#method.body
pub struct Body {
    inner: Inner,
}

enum Inner {
    Bytes(Bytes),
    #[cfg(feature = "multipart")]
    Multipart(Form),
}

impl Body {
    /// Returns a reference to the internal data of the `Body`.
    ///
    /// `None` is returned, if the underlying data is a multipart form.
    #[inline]
    pub fn as_bytes(&self) -> Option<&[u8]> {
        match &self.inner {
            Inner::Bytes(bytes) => Some(bytes.as_ref()),
            #[cfg(feature = "multipart")]
            Inner::Multipart(_) => None,
        }
    }
    pub(crate) fn to_js_value(&self) -> crate::Result<JsValue> {
        match &self.inner {
            Inner::Bytes(body_bytes) => {
                let body_bytes: &[u8] = body_bytes.as_ref();
                let body_uint8_array: Uint8Array = body_bytes.into();
                let body_array = Array::from(&body_uint8_array);
                let js_value: &JsValue = body_array.as_ref();
                Ok(js_value.to_owned())
            }
            #[cfg(feature = "multipart")]
            Inner::Multipart(form) => {
                let form_data = form.to_form_data()?;
                let js_value: &JsValue = form_data.as_ref();
                Ok(js_value.to_owned())
            }
        }
    }

    #[inline]
    #[cfg(feature = "multipart")]
    pub(crate) fn from_form(f: Form) -> Body {
        Self {
            inner: Inner::Multipart(f),
        }
    }

    pub(crate) fn is_empty(&self) -> bool {
        match &self.inner {
            Inner::Bytes(bytes) => bytes.is_empty(),
            #[cfg(feature = "multipart")]
            Inner::Multipart(form) => form.is_empty(),
        }
    }

    pub(crate) fn try_clone(&self) -> Option<Body> {
        match &self.inner {
            Inner::Bytes(bytes) => Some(Self {
                inner: Inner::Bytes(bytes.clone()),
            }),
            #[cfg(feature = "multipart")]
            Inner::Multipart(_) => None,
        }
    }
}

impl From<Bytes> for Body {
    #[inline]
    fn from(bytes: Bytes) -> Body {
        Body {
            inner: Inner::Bytes(bytes),
        }
    }
}

impl From<Vec<u8>> for Body {
    #[inline]
    fn from(vec: Vec<u8>) -> Body {
        Body {
            inner: Inner::Bytes(vec.into()),
        }
    }
}

impl From<&'static [u8]> for Body {
    #[inline]
    fn from(s: &'static [u8]) -> Body {
        Body {
            inner: Inner::Bytes(Bytes::from_static(s)),
        }
    }
}

impl From<String> for Body {
    #[inline]
    fn from(s: String) -> Body {
        Body {
            inner: Inner::Bytes(s.into()),
        }
    }
}

impl From<&'static str> for Body {
    #[inline]
    fn from(s: &'static str) -> Body {
        s.as_bytes().into()
    }
}

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

#[cfg(test)]
mod tests {
    use js_sys::{Array, Uint8Array};
    use wasm_bindgen::{prelude::*, JsValue};
    use wasm_bindgen_test::*;

    wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser);

    #[wasm_bindgen]
    extern "C" {
        // Use `js_namespace` here to bind `console.log(..)` instead of just
        // `log(..)`
        #[wasm_bindgen(js_namespace = console)]
        fn log(s: String);
    }

    #[wasm_bindgen_test]
    async fn test_body() {
        use crate::Body;

        let body = Body::from("TEST");
        assert_eq!([84, 69, 83, 84], body.as_bytes().unwrap());
    }

    #[wasm_bindgen_test]
    async fn test_body_js() {
        use crate::Body;

        let body = Body::from("TEST");

        let arr = [84u8, 69, 83, 84];
        let u8_arr: Uint8Array = arr.as_ref().into();
        let expected = JsValue::from(Array::from(&u8_arr));

        // ty JS -.-
        assert_eq!(
            format!("{:#?}", expected),
            format!(
                "{:#?}",
                body.to_js_value()
                    .expect("could not convert body to JsValue")
            )
        );
    }
}
<commit_msg>wasm: don't send request body as plain uint8 array (#1358)<commit_after>#[cfg(feature = "multipart")]
use super::multipart::Form;
/// dox
use bytes::Bytes;
use js_sys::{Uint8Array};
use std::fmt;
use wasm_bindgen::JsValue;

/// The body of a `Request`.
///
/// In most cases, this is not needed directly, as the
/// [`RequestBuilder.body`][builder] method uses `Into<Body>`, which allows
/// passing many things (like a string or vector of bytes).
///
/// [builder]: ./struct.RequestBuilder.html#method.body
pub struct Body {
    inner: Inner,
}

enum Inner {
    Bytes(Bytes),
    #[cfg(feature = "multipart")]
    Multipart(Form),
}

impl Body {
    /// Returns a reference to the internal data of the `Body`.
    ///
    /// `None` is returned, if the underlying data is a multipart form.
    #[inline]
    pub fn as_bytes(&self) -> Option<&[u8]> {
        match &self.inner {
            Inner::Bytes(bytes) => Some(bytes.as_ref()),
            #[cfg(feature = "multipart")]
            Inner::Multipart(_) => None,
        }
    }
    pub(crate) fn to_js_value(&self) -> crate::Result<JsValue> {
        match &self.inner {
            Inner::Bytes(body_bytes) => {
                let body_bytes: &[u8] = body_bytes.as_ref();
                let body_uint8_array: Uint8Array = body_bytes.into();
                let js_value: &JsValue = body_uint8_array.as_ref();
                Ok(js_value.to_owned())
            }
            #[cfg(feature = "multipart")]
            Inner::Multipart(form) => {
                let form_data = form.to_form_data()?;
                let js_value: &JsValue = form_data.as_ref();
                Ok(js_value.to_owned())
            }
        }
    }

    #[inline]
    #[cfg(feature = "multipart")]
    pub(crate) fn from_form(f: Form) -> Body {
        Self {
            inner: Inner::Multipart(f),
        }
    }

    pub(crate) fn is_empty(&self) -> bool {
        match &self.inner {
            Inner::Bytes(bytes) => bytes.is_empty(),
            #[cfg(feature = "multipart")]
            Inner::Multipart(form) => form.is_empty(),
        }
    }

    pub(crate) fn try_clone(&self) -> Option<Body> {
        match &self.inner {
            Inner::Bytes(bytes) => Some(Self {
                inner: Inner::Bytes(bytes.clone()),
            }),
            #[cfg(feature = "multipart")]
            Inner::Multipart(_) => None,
        }
    }
}

impl From<Bytes> for Body {
    #[inline]
    fn from(bytes: Bytes) -> Body {
        Body {
            inner: Inner::Bytes(bytes),
        }
    }
}

impl From<Vec<u8>> for Body {
    #[inline]
    fn from(vec: Vec<u8>) -> Body {
        Body {
            inner: Inner::Bytes(vec.into()),
        }
    }
}

impl From<&'static [u8]> for Body {
    #[inline]
    fn from(s: &'static [u8]) -> Body {
        Body {
            inner: Inner::Bytes(Bytes::from_static(s)),
        }
    }
}

impl From<String> for Body {
    #[inline]
    fn from(s: String) -> Body {
        Body {
            inner: Inner::Bytes(s.into()),
        }
    }
}

impl From<&'static str> for Body {
    #[inline]
    fn from(s: &'static str) -> Body {
        s.as_bytes().into()
    }
}

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

#[cfg(test)]
mod tests {
    // use js_sys::{Array, Uint8Array};
    use wasm_bindgen::{prelude::*};
    use wasm_bindgen_test::*;

    wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser);

    #[wasm_bindgen]
    extern "C" {
        // Use `js_namespace` here to bind `console.log(..)` instead of just
        // `log(..)`
        #[wasm_bindgen(js_namespace = console)]
        fn log(s: String);
    }

    #[wasm_bindgen_test]
    async fn test_body() {
        use crate::Body;

        let body = Body::from("TEST");
        assert_eq!([84, 69, 83, 84], body.as_bytes().unwrap());
    }

    #[wasm_bindgen_test]
    async fn test_body_js() {
        use crate::Body;

        let body_value = "TEST";
        let body = Body::from(body_value);

        let mut init = web_sys::RequestInit::new();
        init.method("POST");
        init.body(Some(body.to_js_value().expect("could not convert body to JsValue").as_ref()));

        let js_req = web_sys::Request::new_with_str_and_init("", &init).expect("could not create JS request");
        let text_promise = js_req.text().expect("could not get text promise");
        let text = crate::wasm::promise::<JsValue>(text_promise).await.expect("could not get request body as text");

        assert_eq!(text.as_string().expect("text is not a string"), body_value);
    }
}
<|endoftext|>


<commit_before>//! Contains the word lists for the password generator.
//!
//! Custom word lists can be made by creating a struct / enum and implementing the `WordList`
//! trait.

/// The trait that all word lists must implement.
pub trait WordList {
    /// Get all the words in the word list which are within the minimum and maximum length
    fn get_words(&self, min_len: u8, max_len: u8) -> Vec<&String>;
}

/// Generate the word list. Currently only loads the simple english dictionary. This is loaded
/// at compile time. Returns a list of words.
pub struct SimpleEnglish(Vec<String>);

impl SimpleEnglish {
    /// Creates a new `SimpleEnglish` word list that can be used to generate passwords.
    ///
    /// ```
    /// let word_list = SimpleEnglish::new();
    /// // The word list has words!
    /// assert!(word_list.num_words() != 0);
    /// ```
    pub fn new() -> SimpleEnglish {
        let dict_simple_en = include_str!("dictionaries/simple_en.txt");

        // TODO: More efficient parsing of the dictionaries
        let words: Vec<&str> = dict_simple_en.split('\n').collect();
        let words: Vec<String> = words.iter()
                                      .filter(|&a| a.trim().len() > 0).map(|a| a.to_string()).collect();

        return SimpleEnglish(words);
    }
}

impl WordList for SimpleEnglish {
    fn get_words(&self, min_len: u8, max_len: u8) -> Vec<&String> {
        let &SimpleEnglish(ref words) = self;
        return words.iter().filter(|&a| a.len() >= min_len as usize && a.len() <= max_len as usize).collect();
    }
}
<commit_msg>Fix the documentation tests<commit_after>//! Contains the word lists for the password generator.
//!
//! Custom word lists can be made by creating a struct / enum and implementing the `WordList`
//! trait.

/// The trait that all word lists must implement.
pub trait WordList {
    /// Get all the words in the word list which are within the minimum and maximum length
    fn get_words(&self, min_len: u8, max_len: u8) -> Vec<&String>;
}

/// Generate the word list. Currently only loads the simple english dictionary. This is loaded
/// at compile time. Returns a list of words.
pub struct SimpleEnglish(Vec<String>);

impl SimpleEnglish {
    /// Creates a new `SimpleEnglish` word list that can be used to generate passwords.
    ///
    /// ```
    /// use xkcd_pass::word_list::SimpleEnglish;
    ///
    /// let word_list = SimpleEnglish::new();
    /// ```
    pub fn new() -> SimpleEnglish {
        let dict_simple_en = include_str!("dictionaries/simple_en.txt");

        // TODO: More efficient parsing of the dictionaries
        let words: Vec<&str> = dict_simple_en.split('\n').collect();
        let words: Vec<String> = words.iter()
                                      .filter(|&a| a.trim().len() > 0).map(|a| a.to_string()).collect();

        return SimpleEnglish(words);
    }
}

impl WordList for SimpleEnglish {
    fn get_words(&self, min_len: u8, max_len: u8) -> Vec<&String> {
        let &SimpleEnglish(ref words) = self;
        return words.iter().filter(|&a| a.len() >= min_len as usize && a.len() <= max_len as usize).collect();
    }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/. */

extern crate js;
extern crate libc;

use std::ffi::CStr;
use std::ptr;
use std::str;

use js::{JSCLASS_RESERVED_SLOTS_MASK,JSCLASS_RESERVED_SLOTS_SHIFT,JSCLASS_GLOBAL_SLOT_COUNT,JSCLASS_IS_GLOBAL};
use js::jsapi::_Z24JS_GlobalObjectTraceHookP8JSTracerP8JSObject;
use js::jsapi::{CallArgs,CompartmentOptions,OnNewGlobalHookOption,Rooted,Value};
use js::jsapi::{JS_DefineFunction,JS_Init,JS_NewGlobalObject,JS_EncodeStringToUTF8,JS_ReportError};
use js::jsapi::{JSAutoCompartment,JSAutoRequest,JSContext,JSClass};
use js::jsval::UndefinedValue;
use js::rust::Runtime;

static CLASS: &'static JSClass = &JSClass {
    name: b"test\0" as *const u8 as *const libc::c_char,
    flags: JSCLASS_IS_GLOBAL | ((JSCLASS_GLOBAL_SLOT_COUNT & JSCLASS_RESERVED_SLOTS_MASK) << JSCLASS_RESERVED_SLOTS_SHIFT),
    addProperty: None,
    delProperty: None,
    getProperty: None,
    setProperty: None,
    enumerate: None,
    resolve: None,
    convert: None,
    finalize: None,
    call: None,
    hasInstance: None,
    construct: None,
    trace: Some(_Z24JS_GlobalObjectTraceHookP8JSTracerP8JSObject),
    reserved: [0 as *mut _; 25]
};

fn main() {
    unsafe {
        JS_Init();
    }
    let runtime = Runtime::new();
    let context = runtime.cx();

    unsafe {
        let h_option = OnNewGlobalHookOption::FireOnNewGlobalHook;
        let c_option = CompartmentOptions::default();
        let _ar = JSAutoRequest::new(context);
        let global = JS_NewGlobalObject(context, CLASS, ptr::null_mut(), h_option, &c_option);
        let global_root = Rooted::new(context, global);
        let global = global_root.handle();
        let _ac = JSAutoCompartment::new(context, global.get());
        JS_DefineFunction(context, global, b"puts\0".as_ptr() as *const libc::c_char, Some(puts), 1, 0);
        let javascript = "puts('Test Iñtërnâtiônàlizætiøn ┬─┬ノ( º _ ºノ) ');".to_string();
        let _ = runtime.evaluate_script(global, javascript, "test.js".to_string(), 0);
    }
}

unsafe extern "C" fn puts(context: *mut JSContext, argc: u32, vp: *mut Value) -> u8 {
    let args = CallArgs::from_vp(vp, argc);

    if args.argc_ != 1 {
        JS_ReportError(context, b"puts() requires exactly 1 argument\0".as_ptr() as *const libc::c_char);
        return 0;
    }

    let arg = args.get(0);
    let js = js::rust::ToString(context, arg);
    let message_root = Rooted::new(context, js);
    let message = JS_EncodeStringToUTF8(context, message_root.handle());
    let message = CStr::from_ptr(message);
    println!("{}", str::from_utf8(message.to_bytes()).unwrap());

    args.rval().set(UndefinedValue());
    return 1;
}
<commit_msg>Check the result of JS_DefineFunction in the example.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/. */

extern crate js;
extern crate libc;

use std::ffi::CStr;
use std::ptr;
use std::str;

use js::{JSCLASS_RESERVED_SLOTS_MASK,JSCLASS_RESERVED_SLOTS_SHIFT,JSCLASS_GLOBAL_SLOT_COUNT,JSCLASS_IS_GLOBAL};
use js::jsapi::_Z24JS_GlobalObjectTraceHookP8JSTracerP8JSObject;
use js::jsapi::{CallArgs,CompartmentOptions,OnNewGlobalHookOption,Rooted,Value};
use js::jsapi::{JS_DefineFunction,JS_Init,JS_NewGlobalObject,JS_EncodeStringToUTF8,JS_ReportError};
use js::jsapi::{JSAutoCompartment,JSAutoRequest,JSContext,JSClass};
use js::jsval::UndefinedValue;
use js::rust::Runtime;

static CLASS: &'static JSClass = &JSClass {
    name: b"test\0" as *const u8 as *const libc::c_char,
    flags: JSCLASS_IS_GLOBAL | ((JSCLASS_GLOBAL_SLOT_COUNT & JSCLASS_RESERVED_SLOTS_MASK) << JSCLASS_RESERVED_SLOTS_SHIFT),
    addProperty: None,
    delProperty: None,
    getProperty: None,
    setProperty: None,
    enumerate: None,
    resolve: None,
    convert: None,
    finalize: None,
    call: None,
    hasInstance: None,
    construct: None,
    trace: Some(_Z24JS_GlobalObjectTraceHookP8JSTracerP8JSObject),
    reserved: [0 as *mut _; 25]
};

fn main() {
    unsafe {
        JS_Init();
    }
    let runtime = Runtime::new();
    let context = runtime.cx();

    unsafe {
        let h_option = OnNewGlobalHookOption::FireOnNewGlobalHook;
        let c_option = CompartmentOptions::default();
        let _ar = JSAutoRequest::new(context);
        let global = JS_NewGlobalObject(context, CLASS, ptr::null_mut(), h_option, &c_option);
        let global_root = Rooted::new(context, global);
        let global = global_root.handle();
        let _ac = JSAutoCompartment::new(context, global.get());
        let function = JS_DefineFunction(context, global, b"puts\0".as_ptr() as *const libc::c_char,
                                         Some(puts), 1, 0);
        assert!(!function.is_null());
        let javascript = "puts('Test Iñtërnâtiônàlizætiøn ┬─┬ノ( º _ ºノ) ');".to_string();
        let _ = runtime.evaluate_script(global, javascript, "test.js".to_string(), 0);
    }
}

unsafe extern "C" fn puts(context: *mut JSContext, argc: u32, vp: *mut Value) -> u8 {
    let args = CallArgs::from_vp(vp, argc);

    if args.argc_ != 1 {
        JS_ReportError(context, b"puts() requires exactly 1 argument\0".as_ptr() as *const libc::c_char);
        return 0;
    }

    let arg = args.get(0);
    let js = js::rust::ToString(context, arg);
    let message_root = Rooted::new(context, js);
    let message = JS_EncodeStringToUTF8(context, message_root.handle());
    let message = CStr::from_ptr(message);
    println!("{}", str::from_utf8(message.to_bytes()).unwrap());

    args.rval().set(UndefinedValue());
    return 1;
}
<|endoftext|>


<commit_before>// Copyright 2016 Amanieu d'Antras
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

//! This library exposes a low-level API for creating your own efficient
//! synchronization primitives.
//!
//! # The parking lot
//!
//! To keep synchronization primitives small, all thread queuing and suspending
//! functionality is offloaded to the *parking lot*. The idea behind this is
//! based on the Webkit [`WTF::ParkingLot`]
//! (https://webkit.org/blog/6161/locking-in-webkit/) class, which essentially
//! consists of a hash table mapping of lock addresses to queues of parked
//! (sleeping) threads. The Webkit parking lot was itself inspired by Linux
//! [futexes](http://man7.org/linux/man-pages/man2/futex.2.html), but it is more
//! powerful since it allows invoking callbacks while holding a queue lock.
//!
//! There are two main operations that can be performed on the parking lot:
//!  - *Parking* refers to suspending the thread while simultaneously enqueuing it
//! on a queue keyed by some address.
//! - *Unparking* refers to dequeuing a thread rom a queue keyed by some address
//! and resuming it.
//!
//! See the documentation of the individual functions for more details.
//!
//! # Building custom synchronization primitives
//!
//! Building custom synchronization primitives is very simple since the parking
//! lot takes care of all the hard parts for you. A simple example for a
//! custom primitive would be to integrate a `Mutex` inside another data type.
//! Since a mutex only requires 2 bits, it can share space with other data.
//! For example, one could create an `ArcMutex` type that combines the atomic
//! reference count and the two mutex bits in the same atomic word.

#![warn(missing_docs)]
#![cfg_attr(feature = "nightly", feature(const_fn))]
#![cfg_attr(feature = "nightly", feature(integer_atomics))]
#![cfg_attr(feature = "nightly", feature(asm))]

extern crate smallvec;
extern crate rand;

#[cfg(unix)]
extern crate libc;

#[cfg(windows)]
extern crate winapi;
#[cfg(windows)]
extern crate kernel32;

#[cfg(all(feature = "nightly", target_os = "linux"))]
#[path = "thread_parker/linux.rs"]
mod thread_parker;
#[cfg(all(unix, not(all(feature = "nightly", target_os = "linux"))))]
#[path = "thread_parker/unix.rs"]
mod thread_parker;
#[cfg(windows)]
#[path = "thread_parker/windows.rs"]
mod thread_parker;
#[cfg(not(any(windows, unix)))]
#[path = "thread_parker/generic.rs"]
mod thread_parker;

#[cfg(not(feature = "nightly"))]
mod stable;

mod util;
mod spinwait;
mod word_lock;
mod parking_lot;

pub use parking_lot::{UnparkResult, RequeueOp, UnparkToken, ParkToken, FilterOp};
pub use parking_lot::{DEFAULT_UNPARK_TOKEN, DEFAULT_PARK_TOKEN};
pub use parking_lot::{park, unpark_one, unpark_all, unpark_requeue, unpark_filter};
pub use spinwait::SpinWait;
<commit_msg>Fix typo in `parking_lot` docs<commit_after>// Copyright 2016 Amanieu d'Antras
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

//! This library exposes a low-level API for creating your own efficient
//! synchronization primitives.
//!
//! # The parking lot
//!
//! To keep synchronization primitives small, all thread queuing and suspending
//! functionality is offloaded to the *parking lot*. The idea behind this is
//! based on the Webkit [`WTF::ParkingLot`]
//! (https://webkit.org/blog/6161/locking-in-webkit/) class, which essentially
//! consists of a hash table mapping of lock addresses to queues of parked
//! (sleeping) threads. The Webkit parking lot was itself inspired by Linux
//! [futexes](http://man7.org/linux/man-pages/man2/futex.2.html), but it is more
//! powerful since it allows invoking callbacks while holding a queue lock.
//!
//! There are two main operations that can be performed on the parking lot:
//!  - *Parking* refers to suspending the thread while simultaneously enqueuing it
//! on a queue keyed by some address.
//! - *Unparking* refers to dequeuing a thread from a queue keyed by some address
//! and resuming it.
//!
//! See the documentation of the individual functions for more details.
//!
//! # Building custom synchronization primitives
//!
//! Building custom synchronization primitives is very simple since the parking
//! lot takes care of all the hard parts for you. A simple example for a
//! custom primitive would be to integrate a `Mutex` inside another data type.
//! Since a mutex only requires 2 bits, it can share space with other data.
//! For example, one could create an `ArcMutex` type that combines the atomic
//! reference count and the two mutex bits in the same atomic word.

#![warn(missing_docs)]
#![cfg_attr(feature = "nightly", feature(const_fn))]
#![cfg_attr(feature = "nightly", feature(integer_atomics))]
#![cfg_attr(feature = "nightly", feature(asm))]

extern crate smallvec;
extern crate rand;

#[cfg(unix)]
extern crate libc;

#[cfg(windows)]
extern crate winapi;
#[cfg(windows)]
extern crate kernel32;

#[cfg(all(feature = "nightly", target_os = "linux"))]
#[path = "thread_parker/linux.rs"]
mod thread_parker;
#[cfg(all(unix, not(all(feature = "nightly", target_os = "linux"))))]
#[path = "thread_parker/unix.rs"]
mod thread_parker;
#[cfg(windows)]
#[path = "thread_parker/windows.rs"]
mod thread_parker;
#[cfg(not(any(windows, unix)))]
#[path = "thread_parker/generic.rs"]
mod thread_parker;

#[cfg(not(feature = "nightly"))]
mod stable;

mod util;
mod spinwait;
mod word_lock;
mod parking_lot;

pub use parking_lot::{UnparkResult, RequeueOp, UnparkToken, ParkToken, FilterOp};
pub use parking_lot::{DEFAULT_UNPARK_TOKEN, DEFAULT_PARK_TOKEN};
pub use parking_lot::{park, unpark_one, unpark_all, unpark_requeue, unpark_filter};
pub use spinwait::SpinWait;
<|endoftext|>


<commit_before>//! Interval tree, a data structure for efficiently storing and searching intervals.
//!
//! This implementation is based on the sorted array version as described/given in
//! https://github.com/lh3/cgranges / https://github.com/lh3/cgranges/blob/master/cpp/IITree.h
//!
//! It uses the same conventions as `crate::data_structures::interval_tree::IntervalTree`.
//! Note that if you do not use the `ArrayBackedIntervalTree::from_iter` constructor, you have to call `index(&mut self)`
//! first before `find()`-ing overlaps.
//!
//! # Example
//! ```
//! use bio::data_structures::interval_tree::ArrayBackedIntervalTree;
//! use bio::utils::Interval;
//!
//! let mut tree = ArrayBackedIntervalTree::new();
//! tree.insert(12..34, 0);
//! tree.insert(0..23, 1);
//! tree.insert(34..56, 2);
//! // since we did at least one manual insert, we have to index the tree
//! tree.index();
//! let i1 = &tree.find(22..25)[0];
//! assert_eq!(i1.interval().start(), 0);
//! assert_eq!(i1.interval().end(), 23);
//! assert_eq!(i1.data(), 1);
//!
//! let tree = ArrayBackedIntervalTree::from_iter(vec![(12..34, 0), (0..23, 1), (34..56, 2)]);
//! // no call to `index` needed here, since that happens in `from_iter` already
//! let i2 = &tree.find(22..25)[1];
//! assert_eq!(i1.interval().start(), 12);
//! assert_eq!(i1.interval().end(), 34);
//! assert_eq!(i1.data(), 0);
//!
//! ```
//!

use crate::utils::Interval;
use std::cmp::min;

/// A `find` query on the interval tree does not directly return references to the intervals in the
/// tree but wraps the fields `interval` and `data` in an `Entry`.
#[derive(PartialEq, Eq, Debug, Clone)]
struct InternalEntry<N: Ord + Clone + Copy, D> {
    data: D,
    interval: Interval<N>,
    max: N,
}

/// A `find` query on the interval tree does not directly return references to the nodes in the tree, but
/// wraps the fields `interval` and `data` in an `Entry`.
#[derive(PartialEq, Eq, Debug, Clone)]
pub struct Entry<'a, N: Ord + Clone, D> {
    data: &'a D,
    interval: &'a Interval<N>,
}

impl<'a, N: Ord + Clone + 'a, D: 'a> Entry<'a, N, D> {
    /// Get a reference to the data for this entry
    pub fn data(&self) -> &'a D {
        self.data
    }

    /// Get a reference to the interval for this entry
    pub fn interval(&self) -> &'a Interval<N> {
        self.interval
    }
}

impl<N: Ord + Clone + Copy, D> Default for ArrayBackedIntervalTree<N, D> {
    fn default() -> Self {
        ArrayBackedIntervalTree {
            entries: vec![],
            max_level: 0,
            indexed: false,
        }
    }
}

pub struct ArrayBackedIntervalTree<N: Ord + Clone + Copy, D> {
    entries: Vec<InternalEntry<N, D>>,
    max_level: usize,
    indexed: bool,
}

impl<N: Ord + Clone + Copy, D: Clone> ArrayBackedIntervalTree<N, D> {
    pub fn new() -> Self {
        Default::default()
    }

    pub fn from_iter<I: Iterator<Item = (V, D)>, V>(iter: I) -> Self
    where
        V: Into<Interval<N>>,
    {
        let mut tree = Self::new();
        iter.for_each(|(interval, data)| tree.insert(interval, data));
        tree.index();
        tree
    }

    pub fn insert<I: Into<Interval<N>>>(&mut self, interval: I, data: D) {
        let interval = interval.into();
        let max = interval.end;
        self.entries.push(InternalEntry {
            interval,
            data,
            max,
        });
        self.indexed = false;
    }

    pub fn index(&mut self) {
        if !self.indexed {
            self.entries.sort_by_key(|e| e.interval.start);
            self.index_core();
            self.indexed = true;
        }
    }

    fn index_core(&mut self) {
        let a = &mut self.entries;
        if a.is_empty() {
            return;
        }

        let n = a.len();
        let mut last_i = 0;
        let mut last_value = a[0].max;
        (0..n).step_by(2).for_each(|i| {
            last_i = i;
            a[i].max = a[i].interval.end;
            last_value = a[i].max;
        });
        let mut k = 1;
        while (1 << k) < n {
            // process internal nodes in the bottom-up order
            let x = 1 << (k - 1);
            let i0 = (x << 1) - 1; // i0 is the first node
            let step = x << 2;
            for i in (i0..n).step_by(step) {
                // traverse all nodes at level k
                let end_left = a[i - x].max; // max value of the left child
                let end_right = if i + x < n { a[i + x].max } else { last_value }; // max value of the right child
                let end = max3(a[i].interval.end, end_left, end_right);
                a[i].max = end;
            }
            last_i = if (last_i >> k & 1) > 0 {
                last_i - x
            } else {
                last_i + x
            };
            if last_i < n && a[last_i].max > last_value {
                last_value = a[last_i].max
            }
            k += 1;
        }
        self.max_level = k - 1;
    }

    /// Find overlapping intervals in the index.
    /// Returns a vector of entries, consisting of the interval and its associated data.
    ///
    /// # Arguments
    ///
    /// * `interval` - The interval for which overlaps are to be found in the index. Can also be a `Range`.
    ///
    /// # Panics
    ///
    /// Panics if this `IITree` instance has not been indexed yet.
    pub fn find<I: Into<Interval<N>>>(&self, interval: I) -> Vec<Entry<N, D>> {
        let mut buf = Vec::with_capacity(512);
        self.find_into(interval, &mut buf);
        buf
    }

    /// Find overlapping intervals in the index
    ///
    /// # Arguments
    ///
    /// * `interval` - The interval for which overlaps are to be found in the index. Can also be a `Range`.
    /// * `results` - A reusable buffer vector for storing the results.
    ///
    /// # Panics
    ///
    /// Panics if this `IITree` instance has not been indexed yet.
    pub fn find_into<'b, 'a: 'b, I: Into<Interval<N>>>(
        &'a self,
        interval: I,
        results: &'b mut Vec<Entry<'a, N, D>>,
    ) {
        if !self.indexed {
            panic!("This IITree has not been indexed yet. Call `index()` first.")
        }

        let interval = interval.into();
        let (start, end) = (interval.start, interval.end);
        let n = self.entries.len() as usize;
        let a = &self.entries;
        results.clear();
        let mut stack = [StackCell::empty(); 64];
        // push the root; this is a top down traversal
        stack[0].k = self.max_level;
        stack[0].x = (1 << self.max_level) - 1;
        stack[0].w = false;
        let mut t = 1;
        while t > 0 {
            t -= 1;
            let StackCell { k, x, w } = stack[t];
            if k <= 3 {
                // we are in a small subtree; traverse every node in this subtree
                let i0 = x >> k << k;
                let i1 = min(i0 + (1 << (k + 1)) - 1, n);
                for i in i0..i1 {
                    if a[i].interval.start >= end {
                        break;
                    }
                    if start < a[i].interval.end {
                        // if overlap, append to `results`
                        results.push(Entry {
                            interval: &self.entries[i].interval,
                            data: &self.entries[i].data,
                        });
                    }
                }
            } else if !w {
                // if left child not processed
                let y = x - (1 << (k - 1)); // the left child of x; NB: y may be out of range (i.e. y>=n)
                stack[t].k = k;
                stack[t].x = x;
                stack[t].w = true; // re-add node x, but mark the left child having been processed
                t += 1;
                if y >= n || a[y].max > start {
                    // push the left child if y is out of range or may overlap with the query
                    stack[t].k = k - 1;
                    stack[t].x = y;
                    stack[t].w = false;
                    t += 1;
                }
            } else if x < n && a[x].interval.start < end {
                // need to push the right child
                if start < a[x].interval.end {
                    results.push(Entry {
                        interval: &self.entries[x].interval,
                        data: &self.entries[x].data,
                    });
                }
                stack[t].k = k - 1;
                stack[t].x = x + (1 << (k - 1));
                stack[t].w = false;
                t += 1;
            }
        }
    }
}

fn max3<T: Ord>(a: T, b: T, c: T) -> T {
    a.max(b.max(c))
}

#[derive(Clone, Copy)]
struct StackCell {
    // node
    x: usize,
    // level
    k: usize,
    // false if left child hasn't been processed
    w: bool,
}

impl StackCell {
    fn empty() -> Self {
        Self {
            x: 0,
            k: 0,
            w: false,
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::data_structures::interval_tree::ArrayBackedIntervalTree;

    #[test]
    fn test_example() {
        let mut tree = ArrayBackedIntervalTree::new();
        tree.insert(12..34, 0);
        tree.insert(0..23, 1);
        tree.insert(34..56, 2);
        tree.index();
        let overlap = tree.find(22..25);

        let e1 = Entry {
            interval: &(0..23).into(),
            data: &1,
        };
        let e2 = Entry {
            interval: &(12..34).into(),
            data: &0,
        };
        let expected = vec![e1, e2];
        assert_eq!(overlap, expected);
    }
}
<commit_msg>fix doctest for ArrayBackedIntervalTree (#298)<commit_after>//! Interval tree, a data structure for efficiently storing and searching intervals.
//!
//! This implementation is based on the sorted array version as described/given in
//! https://github.com/lh3/cgranges / https://github.com/lh3/cgranges/blob/master/cpp/IITree.h
//!
//! It uses the same conventions as `crate::data_structures::interval_tree::IntervalTree`.
//! Note that if you do not use the `ArrayBackedIntervalTree::from_iter` constructor, you have to call `index(&mut self)`
//! first before `find()`-ing overlaps.
//!
//! # Example
//! ```
//! use bio::data_structures::interval_tree::ArrayBackedIntervalTree;
//! use bio::utils::Interval;
//!
//! let mut tree = ArrayBackedIntervalTree::new();
//! tree.insert(12..34, 0);
//! tree.insert(0..23, 1);
//! tree.insert(34..56, 2);
//! // since we did at least one manual insert, we have to index the tree
//! tree.index();
//! let i1 = &tree.find(22..25)[0];
//! assert_eq!(i1.interval().start, 0);
//! assert_eq!(i1.interval().end, 23);
//! assert_eq!(i1.data(), 1);
//!
//! let tree = ArrayBackedIntervalTree::from_iter(&vec![(12..34, 0), (0..23, 1), (34..56, 2)]);
//! // no call to `index` needed here, since that happens in `from_iter` already
//! let i2 = &tree.find(22..25)[1];
//! assert_eq!(i1.interval().start, 12);
//! assert_eq!(i1.interval().end, 34);
//! assert_eq!(i1.data(), 0);
//!
//! ```
//!

use crate::utils::Interval;
use std::cmp::min;

/// A `find` query on the interval tree does not directly return references to the intervals in the
/// tree but wraps the fields `interval` and `data` in an `Entry`.
#[derive(PartialEq, Eq, Debug, Clone)]
struct InternalEntry<N: Ord + Clone + Copy, D> {
    data: D,
    interval: Interval<N>,
    max: N,
}

/// A `find` query on the interval tree does not directly return references to the nodes in the tree, but
/// wraps the fields `interval` and `data` in an `Entry`.
#[derive(PartialEq, Eq, Debug, Clone)]
pub struct Entry<'a, N: Ord + Clone, D> {
    data: &'a D,
    interval: &'a Interval<N>,
}

impl<'a, N: Ord + Clone + 'a, D: 'a> Entry<'a, N, D> {
    /// Get a reference to the data for this entry
    pub fn data(&self) -> &'a D {
        self.data
    }

    /// Get a reference to the interval for this entry
    pub fn interval(&self) -> &'a Interval<N> {
        self.interval
    }
}

impl<N: Ord + Clone + Copy, D> Default for ArrayBackedIntervalTree<N, D> {
    fn default() -> Self {
        ArrayBackedIntervalTree {
            entries: vec![],
            max_level: 0,
            indexed: false,
        }
    }
}

pub struct ArrayBackedIntervalTree<N: Ord + Clone + Copy, D> {
    entries: Vec<InternalEntry<N, D>>,
    max_level: usize,
    indexed: bool,
}

impl<N: Ord + Clone + Copy, D: Clone> ArrayBackedIntervalTree<N, D> {
    pub fn new() -> Self {
        Default::default()
    }

    pub fn from_iter<I: Iterator<Item = (V, D)>, V>(iter: I) -> Self
    where
        V: Into<Interval<N>>,
    {
        let mut tree = Self::new();
        iter.for_each(|(interval, data)| tree.insert(interval, data));
        tree.index();
        tree
    }

    pub fn insert<I: Into<Interval<N>>>(&mut self, interval: I, data: D) {
        let interval = interval.into();
        let max = interval.end;
        self.entries.push(InternalEntry {
            interval,
            data,
            max,
        });
        self.indexed = false;
    }

    pub fn index(&mut self) {
        if !self.indexed {
            self.entries.sort_by_key(|e| e.interval.start);
            self.index_core();
            self.indexed = true;
        }
    }

    fn index_core(&mut self) {
        let a = &mut self.entries;
        if a.is_empty() {
            return;
        }

        let n = a.len();
        let mut last_i = 0;
        let mut last_value = a[0].max;
        (0..n).step_by(2).for_each(|i| {
            last_i = i;
            a[i].max = a[i].interval.end;
            last_value = a[i].max;
        });
        let mut k = 1;
        while (1 << k) < n {
            // process internal nodes in the bottom-up order
            let x = 1 << (k - 1);
            let i0 = (x << 1) - 1; // i0 is the first node
            let step = x << 2;
            for i in (i0..n).step_by(step) {
                // traverse all nodes at level k
                let end_left = a[i - x].max; // max value of the left child
                let end_right = if i + x < n { a[i + x].max } else { last_value }; // max value of the right child
                let end = max3(a[i].interval.end, end_left, end_right);
                a[i].max = end;
            }
            last_i = if (last_i >> k & 1) > 0 {
                last_i - x
            } else {
                last_i + x
            };
            if last_i < n && a[last_i].max > last_value {
                last_value = a[last_i].max
            }
            k += 1;
        }
        self.max_level = k - 1;
    }

    /// Find overlapping intervals in the index.
    /// Returns a vector of entries, consisting of the interval and its associated data.
    ///
    /// # Arguments
    ///
    /// * `interval` - The interval for which overlaps are to be found in the index. Can also be a `Range`.
    ///
    /// # Panics
    ///
    /// Panics if this `IITree` instance has not been indexed yet.
    pub fn find<I: Into<Interval<N>>>(&self, interval: I) -> Vec<Entry<N, D>> {
        let mut buf = Vec::with_capacity(512);
        self.find_into(interval, &mut buf);
        buf
    }

    /// Find overlapping intervals in the index
    ///
    /// # Arguments
    ///
    /// * `interval` - The interval for which overlaps are to be found in the index. Can also be a `Range`.
    /// * `results` - A reusable buffer vector for storing the results.
    ///
    /// # Panics
    ///
    /// Panics if this `IITree` instance has not been indexed yet.
    pub fn find_into<'b, 'a: 'b, I: Into<Interval<N>>>(
        &'a self,
        interval: I,
        results: &'b mut Vec<Entry<'a, N, D>>,
    ) {
        if !self.indexed {
            panic!("This IITree has not been indexed yet. Call `index()` first.")
        }

        let interval = interval.into();
        let (start, end) = (interval.start, interval.end);
        let n = self.entries.len() as usize;
        let a = &self.entries;
        results.clear();
        let mut stack = [StackCell::empty(); 64];
        // push the root; this is a top down traversal
        stack[0].k = self.max_level;
        stack[0].x = (1 << self.max_level) - 1;
        stack[0].w = false;
        let mut t = 1;
        while t > 0 {
            t -= 1;
            let StackCell { k, x, w } = stack[t];
            if k <= 3 {
                // we are in a small subtree; traverse every node in this subtree
                let i0 = x >> k << k;
                let i1 = min(i0 + (1 << (k + 1)) - 1, n);
                for i in i0..i1 {
                    if a[i].interval.start >= end {
                        break;
                    }
                    if start < a[i].interval.end {
                        // if overlap, append to `results`
                        results.push(Entry {
                            interval: &self.entries[i].interval,
                            data: &self.entries[i].data,
                        });
                    }
                }
            } else if !w {
                // if left child not processed
                let y = x - (1 << (k - 1)); // the left child of x; NB: y may be out of range (i.e. y>=n)
                stack[t].k = k;
                stack[t].x = x;
                stack[t].w = true; // re-add node x, but mark the left child having been processed
                t += 1;
                if y >= n || a[y].max > start {
                    // push the left child if y is out of range or may overlap with the query
                    stack[t].k = k - 1;
                    stack[t].x = y;
                    stack[t].w = false;
                    t += 1;
                }
            } else if x < n && a[x].interval.start < end {
                // need to push the right child
                if start < a[x].interval.end {
                    results.push(Entry {
                        interval: &self.entries[x].interval,
                        data: &self.entries[x].data,
                    });
                }
                stack[t].k = k - 1;
                stack[t].x = x + (1 << (k - 1));
                stack[t].w = false;
                t += 1;
            }
        }
    }
}

fn max3<T: Ord>(a: T, b: T, c: T) -> T {
    a.max(b.max(c))
}

#[derive(Clone, Copy)]
struct StackCell {
    // node
    x: usize,
    // level
    k: usize,
    // false if left child hasn't been processed
    w: bool,
}

impl StackCell {
    fn empty() -> Self {
        Self {
            x: 0,
            k: 0,
            w: false,
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::data_structures::interval_tree::ArrayBackedIntervalTree;

    #[test]
    fn test_example() {
        let mut tree = ArrayBackedIntervalTree::new();
        tree.insert(12..34, 0);
        tree.insert(0..23, 1);
        tree.insert(34..56, 2);
        tree.index();
        let overlap = tree.find(22..25);

        let e1 = Entry {
            interval: &(0..23).into(),
            data: &1,
        };
        let e2 = Entry {
            interval: &(12..34).into(),
            data: &0,
        };
        let expected = vec![e1, e2];
        assert_eq!(overlap, expected);
    }
}
<|endoftext|>


<commit_before>use tool::*;

///
/// Represents a tooling environment, which enables tools to be retrieved by name.
///
/// Environments make it possible to use tools without needing to know where the
/// precise implementation is located. Environments also provide a way to perform
/// dependency injection in other tools.
///
pub trait Environment : Send {
    ///
    /// Retrieves a tool using a JSON interface by name
    ///
    fn get_json_tool(&self, name: &str) -> Result<Box<Tool>, RetrieveToolError>;
}

///
/// The reason an environment retrieve failed
///
#[derive(Copy, Clone, Debug)]
pub enum RetrieveFailReason {
    /// Reason not listed in this enum
    Generic,

    /// A tool could not be found
    NotFound,
}

///
/// Represents an error that occurred during a request to retrieve a tool
///
#[derive(Debug)]
pub struct RetrieveToolError {
    /// The reason the failure occurred
    reason: RetrieveFailReason,

    /// A human-readable message associated with this error
    msg: String
}

impl RetrieveToolError {
    ///
    /// Creates a new error
    ///
    pub fn new(message: &str) -> RetrieveToolError {
        RetrieveToolError { reason: RetrieveFailReason::Generic, msg: String::from(message) }
    }

    ///
    /// Creates a 'tool not found' error
    ///
    pub fn not_found() -> RetrieveToolError {
        RetrieveToolError { reason: RetrieveFailReason::NotFound, msg: String::from("Tool not found") }
    }

    ///
    /// Retrieves the message for an error
    ///
    pub fn message<'a>(&'a self) -> &'a str {
        &self.msg
    }

    ///
    /// Retrieves the reason attached to this failure
    ///
    pub fn reason(&self) -> RetrieveFailReason {
        self.reason
    }
}
<commit_msg>Make Environments Send+Sync<commit_after>use tool::*;

///
/// Represents a tooling environment, which enables tools to be retrieved by name.
///
/// Environments make it possible to use tools without needing to know where the
/// precise implementation is located. Environments also provide a way to perform
/// dependency injection in other tools.
///
pub trait Environment : Send+Sync {
    ///
    /// Retrieves a tool using a JSON interface by name
    ///
    fn get_json_tool(&self, name: &str) -> Result<Box<Tool>, RetrieveToolError>;
}

///
/// The reason an environment retrieve failed
///
#[derive(Copy, Clone, Debug)]
pub enum RetrieveFailReason {
    /// Reason not listed in this enum
    Generic,

    /// A tool could not be found
    NotFound,
}

///
/// Represents an error that occurred during a request to retrieve a tool
///
#[derive(Debug)]
pub struct RetrieveToolError {
    /// The reason the failure occurred
    reason: RetrieveFailReason,

    /// A human-readable message associated with this error
    msg: String
}

impl RetrieveToolError {
    ///
    /// Creates a new error
    ///
    pub fn new(message: &str) -> RetrieveToolError {
        RetrieveToolError { reason: RetrieveFailReason::Generic, msg: String::from(message) }
    }

    ///
    /// Creates a 'tool not found' error
    ///
    pub fn not_found() -> RetrieveToolError {
        RetrieveToolError { reason: RetrieveFailReason::NotFound, msg: String::from("Tool not found") }
    }

    ///
    /// Retrieves the message for an error
    ///
    pub fn message<'a>(&'a self) -> &'a str {
        &self.msg
    }

    ///
    /// Retrieves the reason attached to this failure
    ///
    pub fn reason(&self) -> RetrieveFailReason {
        self.reason
    }
}
<|endoftext|>