<commit_before>#[macro_use]
extern crate wlroots;

use std::process::Command;
use std::thread;
use std::time::Duration;

use wlroots::{matrix_mul, matrix_rotate, matrix_scale, matrix_translate, Area, Compositor,
              CompositorBuilder, CursorBuilder, CursorHandler, CursorId, InputManagerHandler,
              Keyboard, KeyboardHandler, Origin, Output, OutputBuilder, OutputBuilderResult,
              OutputHandler, OutputLayout, OutputManagerHandler, Pointer, PointerHandler,
              Renderer, Seat, SeatHandler, Size, Surface, XCursorTheme, XdgV6ShellHandler,
              XdgV6ShellManagerHandler, XdgV6ShellSurface, XdgV6ShellSurfaceHandle};
use wlroots::key_events::KeyEvent;
use wlroots::pointer_events::{AxisEvent, ButtonEvent, MotionEvent};
use wlroots::utils::{init_logging, L_DEBUG};
use wlroots::wlroots_sys::wlr_button_state::WLR_BUTTON_RELEASED;
use wlroots::xkbcommon::xkb::keysyms::KEY_Escape;

struct State {
    color: [f32; 4],
    default_color: [f32; 4],
    xcursor_theme: XCursorTheme,
    layout: OutputLayout,
    cursor_id: CursorId,
    shells: Vec<XdgV6ShellSurfaceHandle>
}

impl State {
    fn new(xcursor_theme: XCursorTheme, layout: OutputLayout, cursor_id: CursorId) -> Self {
        State { color: [0.25, 0.25, 0.25, 1.0],
                default_color: [0.25, 0.25, 0.25, 1.0],
                xcursor_theme,
                layout,
                cursor_id,
                shells: vec![] }
    }
}

compositor_data!(State);

struct SeatHandlerEx;

struct CursorEx;

impl CursorHandler for CursorEx {}

impl SeatHandler for SeatHandlerEx {
    // TODO
}

struct XdgV6ShellHandlerEx;
struct XdgV6ShellManager;

impl XdgV6ShellHandler for XdgV6ShellHandlerEx {}
impl XdgV6ShellManagerHandler for XdgV6ShellManager {
    fn new_surface(&mut self,
                   compositor: &mut Compositor,
                   shell: &mut XdgV6ShellSurface,
                   _: &mut Surface)
                   -> Option<Box<XdgV6ShellHandler>> {
        let state: &mut State = compositor.into();
        state.shells.push(shell.weak_reference());
        for (mut output, _) in state.layout.outputs() {
            output.run(|output| output.schedule_frame()).unwrap();
        }
        Some(Box::new(XdgV6ShellHandlerEx))
    }

    fn surface_destroyed(&mut self,
                         compositor: &mut Compositor,
                         shell: &mut XdgV6ShellSurface,
                         _: &mut Surface) {
        let state: &mut State = compositor.into();
        let weak = shell.weak_reference();
        if let Some(index) = state.shells.iter().position(|s| *s == weak) {
            state.shells.remove(index);
        }
    }
}

struct OutputManager;

struct ExOutput;

struct InputManager;

struct ExPointer;

struct ExKeyboardHandler;

impl OutputManagerHandler for OutputManager {
    fn output_added<'output>(&mut self,
                             compositor: &mut Compositor,
                             builder: OutputBuilder<'output>)
                             -> Option<OutputBuilderResult<'output>> {
        let result = builder.build_best_mode(ExOutput);
        let state: &mut State = compositor.into();
        let xcursor = state.xcursor_theme
                           .get_cursor("left_ptr".into())
                           .expect("Could not load left_ptr cursor");
        let image = &xcursor.images()[0];
        // TODO use output config if present instead of auto
        state.layout.add_auto(result.output);
        let mut cursor = state.layout.cursor(state.cursor_id).unwrap();
        cursor.set_cursor_image(image);
        let (x, y) = cursor.coords();
        // https://en.wikipedia.org/wiki/Mouse_warping
        cursor.warp(None, x, y);
        Some(result)
    }
}

impl KeyboardHandler for ExKeyboardHandler {
    fn on_key(&mut self, compositor: &mut Compositor, _: &mut Keyboard, key_event: &mut KeyEvent) {
        for key in key_event.pressed_keys() {
            if key == KEY_Escape {
                compositor.terminate()
            } else {
                thread::spawn(move || {
                                  Command::new("weston-terminal").output().unwrap();
                              });
            }
        }
    }
}

impl PointerHandler for ExPointer {
    fn on_motion(&mut self, compositor: &mut Compositor, _: &mut Pointer, event: &MotionEvent) {
        let state: &mut State = compositor.into();
        let (delta_x, delta_y) = event.delta();
        state.layout
             .cursor(state.cursor_id)
             .unwrap()
             .move_to(event.device(), delta_x, delta_y);
    }

    fn on_button(&mut self, compositor: &mut Compositor, _: &mut Pointer, event: &ButtonEvent) {
        let state: &mut State = compositor.into();
        if event.state() == WLR_BUTTON_RELEASED {
            state.color = state.default_color;
        } else {
            state.color = [0.25, 0.25, 0.25, 1.0];
            state.color[event.button() as usize % 3] = 1.0;
        }
    }

    fn on_axis(&mut self, compositor: &mut Compositor, _: &mut Pointer, event: &AxisEvent) {
        let state: &mut State = compositor.into();
        for color_byte in &mut state.default_color[..3] {
            *color_byte += if event.delta() > 0.0 { -0.05 } else { 0.05 };
            if *color_byte > 1.0 {
                *color_byte = 1.0
            }
            if *color_byte < 0.0 {
                *color_byte = 0.0
            }
        }
        state.color = state.default_color.clone()
    }
}

impl OutputHandler for ExOutput {
    fn on_frame(&mut self, compositor: &mut Compositor, output: &mut Output) {
        let state: &mut State = compositor.data.downcast_mut().unwrap();
        if state.shells.len() < 1 {
            return
        }
        let renderer = compositor.renderer
                                 .as_mut()
                                 .expect("Compositor was not loaded with a renderer");
        render_shells(state, &mut renderer.render(output));
    }
}

impl InputManagerHandler for InputManager {
    fn pointer_added(&mut self,
                     _: &mut Compositor,
                     _: &mut Pointer)
                     -> Option<Box<PointerHandler>> {
        Some(Box::new(ExPointer))
    }

    fn keyboard_added(&mut self,
                      _: &mut Compositor,
                      _: &mut Keyboard)
                      -> Option<Box<KeyboardHandler>> {
        Some(Box::new(ExKeyboardHandler))
    }
}

fn main() {
    init_logging(L_DEBUG, None);
    let cursor = CursorBuilder::new(Box::new(CursorEx)).expect("Could not create cursor");
    let xcursor_theme = XCursorTheme::load_theme(None, 16).expect("Could not load theme");
    let mut layout = OutputLayout::new().expect("Could not construct an output layout");

    let cursor_id = layout.attach_cursor(cursor);
    let mut compositor =
        CompositorBuilder::new().gles2(true)
                                .build_auto(State::new(xcursor_theme, layout, cursor_id),
                                            Some(Box::new(InputManager)),
                                            Some(Box::new(OutputManager)),
                                            None,
                                            Some(Box::new(XdgV6ShellManager)));
    Seat::create(&mut compositor, "Main Seat".into(), Box::new(SeatHandlerEx))
        .expect("Could not allocate the global seat");
    compositor.run();
}

/// Render the shells in the current compositor state on the given output.
fn render_shells(state: &mut State, renderer: &mut Renderer) {
    let shells = state.shells.clone();
    for mut shell in shells {
        shell.run(|shell| {
                      shell.surface()
                           .run(|surface| {
                                    let (width, height) = {
                                        let current_state = surface.current_state();
                                        (current_state.width() as i32,
                                        current_state.height() as i32)
                                    };
                                    let (render_width, render_height) =
                                        (width * renderer.output.scale() as i32,
                                        height * renderer.output.scale() as i32);
                                    // TODO Some value from something else?
                                    let (lx, ly) = (0.0, 0.0);
                                    let (mut ox, mut oy) = (lx, ly);
                                    state.layout
                                         .output_coords(renderer.output, &mut ox, &mut oy);
                                    ox *= renderer.output.scale() as f64;
                                    oy *= renderer.output.scale() as f64;
                                    let render_box = Area::new(Origin::new(lx as i32, ly as i32),
                                                               Size::new(render_width,
                                                                         render_height));
                                    if state.layout.intersects(renderer.output, render_box) {
                                        let mut matrix = [0.0; 16];
                                        let mut translate_center = [0.0; 16];
                                        matrix_translate(&mut translate_center,
                                                         (ox as i32 + render_width / 2) as f32,
                                                         (oy as i32 + render_height / 2) as f32,
                                                         0.0);
                                        let mut rotate = [0.0; 16];
                                        // TODO what is rotation
                                        let rotation = 0.0;
                                        matrix_rotate(&mut rotate, rotation);

                                        let mut translate_origin = [0.0; 16];
                                        matrix_translate(&mut translate_origin,
                                                         (-render_width / 2) as f32,
                                                         (-render_height / 2) as f32,
                                                         0.0);

                                        let mut scale = [0.0; 16];
                                        matrix_scale(&mut scale,
                                                     render_width as f32,
                                                     render_height as f32,
                                                     1.0);

                                        let mut transform = [0.0; 16];
                                        matrix_mul(&translate_center, &mut rotate, &mut transform);
                                        matrix_mul(&transform.clone(),
                                                   &mut translate_origin,
                                                   &mut transform);
                                        matrix_mul(&transform.clone(), &mut scale, &mut transform);

                                        // TODO Handle non transform normal on the output
                                        // if ... {}
                                        matrix_mul(&renderer.output.transform_matrix(),
                                                   &mut transform,
                                                   &mut matrix);
                                        renderer.render_with_matrix(&surface.texture(), &matrix);
                                        surface.send_frame_done(Duration::from_secs(1));
                                    }
                                })
                           .unwrap()
                  })
             .unwrap();
    }
}
<commit_msg>Fixed xdg_shell_v6_test to use new builder<commit_after>#[macro_use]
extern crate wlroots;

use std::process::Command;
use std::thread;
use std::time::Duration;

use wlroots::{matrix_mul, matrix_rotate, matrix_scale, matrix_translate, Area, Compositor,
              CompositorBuilder, CursorBuilder, CursorHandler, CursorId, InputManagerHandler,
              Keyboard, KeyboardHandler, Origin, Output, OutputBuilder, OutputBuilderResult,
              OutputHandler, OutputLayout, OutputManagerHandler, Pointer, PointerHandler,
              Renderer, Seat, SeatHandler, Size, Surface, XCursorTheme, XdgV6ShellHandler,
              XdgV6ShellManagerHandler, XdgV6ShellSurface, XdgV6ShellSurfaceHandle};
use wlroots::key_events::KeyEvent;
use wlroots::pointer_events::{AxisEvent, ButtonEvent, MotionEvent};
use wlroots::utils::{init_logging, L_DEBUG};
use wlroots::wlroots_sys::wlr_button_state::WLR_BUTTON_RELEASED;
use wlroots::xkbcommon::xkb::keysyms::KEY_Escape;

struct State {
    color: [f32; 4],
    default_color: [f32; 4],
    xcursor_theme: XCursorTheme,
    layout: OutputLayout,
    cursor_id: CursorId,
    shells: Vec<XdgV6ShellSurfaceHandle>
}

impl State {
    fn new(xcursor_theme: XCursorTheme, layout: OutputLayout, cursor_id: CursorId) -> Self {
        State { color: [0.25, 0.25, 0.25, 1.0],
                default_color: [0.25, 0.25, 0.25, 1.0],
                xcursor_theme,
                layout,
                cursor_id,
                shells: vec![] }
    }
}

compositor_data!(State);

struct SeatHandlerEx;

struct CursorEx;

impl CursorHandler for CursorEx {}

impl SeatHandler for SeatHandlerEx {
    // TODO
}

struct XdgV6ShellHandlerEx;
struct XdgV6ShellManager;

impl XdgV6ShellHandler for XdgV6ShellHandlerEx {}
impl XdgV6ShellManagerHandler for XdgV6ShellManager {
    fn new_surface(&mut self,
                   compositor: &mut Compositor,
                   shell: &mut XdgV6ShellSurface,
                   _: &mut Surface)
                   -> Option<Box<XdgV6ShellHandler>> {
        let state: &mut State = compositor.into();
        state.shells.push(shell.weak_reference());
        for (mut output, _) in state.layout.outputs() {
            output.run(|output| output.schedule_frame()).unwrap();
        }
        Some(Box::new(XdgV6ShellHandlerEx))
    }

    fn surface_destroyed(&mut self,
                         compositor: &mut Compositor,
                         shell: &mut XdgV6ShellSurface,
                         _: &mut Surface) {
        let state: &mut State = compositor.into();
        let weak = shell.weak_reference();
        if let Some(index) = state.shells.iter().position(|s| *s == weak) {
            state.shells.remove(index);
        }
    }
}

struct OutputManager;

struct ExOutput;

struct InputManager;

struct ExPointer;

struct ExKeyboardHandler;

impl OutputManagerHandler for OutputManager {
    fn output_added<'output>(&mut self,
                             compositor: &mut Compositor,
                             builder: OutputBuilder<'output>)
                             -> Option<OutputBuilderResult<'output>> {
        let result = builder.build_best_mode(ExOutput);
        let state: &mut State = compositor.into();
        let xcursor = state.xcursor_theme
                           .get_cursor("left_ptr".into())
                           .expect("Could not load left_ptr cursor");
        let image = &xcursor.images()[0];
        // TODO use output config if present instead of auto
        state.layout.add_auto(result.output);
        let mut cursor = state.layout.cursor(state.cursor_id).unwrap();
        cursor.set_cursor_image(image);
        let (x, y) = cursor.coords();
        // https://en.wikipedia.org/wiki/Mouse_warping
        cursor.warp(None, x, y);
        Some(result)
    }
}

impl KeyboardHandler for ExKeyboardHandler {
    fn on_key(&mut self, compositor: &mut Compositor, _: &mut Keyboard, key_event: &mut KeyEvent) {
        for key in key_event.pressed_keys() {
            if key == KEY_Escape {
                compositor.terminate()
            } else {
                thread::spawn(move || {
                                  Command::new("weston-terminal").output().unwrap();
                              });
            }
        }
    }
}

impl PointerHandler for ExPointer {
    fn on_motion(&mut self, compositor: &mut Compositor, _: &mut Pointer, event: &MotionEvent) {
        let state: &mut State = compositor.into();
        let (delta_x, delta_y) = event.delta();
        state.layout
             .cursor(state.cursor_id)
             .unwrap()
             .move_to(event.device(), delta_x, delta_y);
    }

    fn on_button(&mut self, compositor: &mut Compositor, _: &mut Pointer, event: &ButtonEvent) {
        let state: &mut State = compositor.into();
        if event.state() == WLR_BUTTON_RELEASED {
            state.color = state.default_color;
        } else {
            state.color = [0.25, 0.25, 0.25, 1.0];
            state.color[event.button() as usize % 3] = 1.0;
        }
    }

    fn on_axis(&mut self, compositor: &mut Compositor, _: &mut Pointer, event: &AxisEvent) {
        let state: &mut State = compositor.into();
        for color_byte in &mut state.default_color[..3] {
            *color_byte += if event.delta() > 0.0 { -0.05 } else { 0.05 };
            if *color_byte > 1.0 {
                *color_byte = 1.0
            }
            if *color_byte < 0.0 {
                *color_byte = 0.0
            }
        }
        state.color = state.default_color.clone()
    }
}

impl OutputHandler for ExOutput {
    fn on_frame(&mut self, compositor: &mut Compositor, output: &mut Output) {
        let state: &mut State = compositor.data.downcast_mut().unwrap();
        if state.shells.len() < 1 {
            return
        }
        let renderer = compositor.renderer
                                 .as_mut()
                                 .expect("Compositor was not loaded with a renderer");
        render_shells(state, &mut renderer.render(output));
    }
}

impl InputManagerHandler for InputManager {
    fn pointer_added(&mut self,
                     _: &mut Compositor,
                     _: &mut Pointer)
                     -> Option<Box<PointerHandler>> {
        Some(Box::new(ExPointer))
    }

    fn keyboard_added(&mut self,
                      _: &mut Compositor,
                      _: &mut Keyboard)
                      -> Option<Box<KeyboardHandler>> {
        Some(Box::new(ExKeyboardHandler))
    }
}

fn main() {
    init_logging(L_DEBUG, None);
    let cursor = CursorBuilder::new(Box::new(CursorEx)).expect("Could not create cursor");
    let xcursor_theme = XCursorTheme::load_theme(None, 16).expect("Could not load theme");
    let mut layout = OutputLayout::new().expect("Could not construct an output layout");

    let cursor_id = layout.attach_cursor(cursor);
    let mut compositor =
        CompositorBuilder::new().gles2(true)
                                .input_manager(Box::new(InputManager))
                                .output_manager(Box::new(OutputManager))
                                .xdg_shell_v6_manager(Box::new(XdgV6ShellManager))
                                .build_auto(State::new(xcursor_theme, layout, cursor_id));
    Seat::create(&mut compositor, "Main Seat".into(), Box::new(SeatHandlerEx))
        .expect("Could not allocate the global seat");
    compositor.run();
}

/// Render the shells in the current compositor state on the given output.
fn render_shells(state: &mut State, renderer: &mut Renderer) {
    let shells = state.shells.clone();
    for mut shell in shells {
        shell.run(|shell| {
                      shell.surface()
                           .run(|surface| {
                                    let (width, height) = {
                                        let current_state = surface.current_state();
                                        (current_state.width() as i32,
                                        current_state.height() as i32)
                                    };
                                    let (render_width, render_height) =
                                        (width * renderer.output.scale() as i32,
                                        height * renderer.output.scale() as i32);
                                    // TODO Some value from something else?
                                    let (lx, ly) = (0.0, 0.0);
                                    let (mut ox, mut oy) = (lx, ly);
                                    state.layout
                                         .output_coords(renderer.output, &mut ox, &mut oy);
                                    ox *= renderer.output.scale() as f64;
                                    oy *= renderer.output.scale() as f64;
                                    let render_box = Area::new(Origin::new(lx as i32, ly as i32),
                                                               Size::new(render_width,
                                                                         render_height));
                                    if state.layout.intersects(renderer.output, render_box) {
                                        let mut matrix = [0.0; 16];
                                        let mut translate_center = [0.0; 16];
                                        matrix_translate(&mut translate_center,
                                                         (ox as i32 + render_width / 2) as f32,
                                                         (oy as i32 + render_height / 2) as f32,
                                                         0.0);
                                        let mut rotate = [0.0; 16];
                                        // TODO what is rotation
                                        let rotation = 0.0;
                                        matrix_rotate(&mut rotate, rotation);

                                        let mut translate_origin = [0.0; 16];
                                        matrix_translate(&mut translate_origin,
                                                         (-render_width / 2) as f32,
                                                         (-render_height / 2) as f32,
                                                         0.0);

                                        let mut scale = [0.0; 16];
                                        matrix_scale(&mut scale,
                                                     render_width as f32,
                                                     render_height as f32,
                                                     1.0);

                                        let mut transform = [0.0; 16];
                                        matrix_mul(&translate_center, &mut rotate, &mut transform);
                                        matrix_mul(&transform.clone(),
                                                   &mut translate_origin,
                                                   &mut transform);
                                        matrix_mul(&transform.clone(), &mut scale, &mut transform);

                                        // TODO Handle non transform normal on the output
                                        // if ... {}
                                        matrix_mul(&renderer.output.transform_matrix(),
                                                   &mut transform,
                                                   &mut matrix);
                                        renderer.render_with_matrix(&surface.texture(), &matrix);
                                        surface.send_frame_done(Duration::from_secs(1));
                                    }
                                })
                           .unwrap()
                  })
             .unwrap();
    }
}
<|endoftext|>


<commit_before>use std::num::FloatMath;
use linalg;
use linalg::Matrix4;
use linalg::Vector;
use linalg::Point;
use linalg::Normal;
use linalg::Ray;

/// Transform describes an affine transformation in 3D space
/// and stores both the transformation and its inverse
#[deriving(Show, Copy, PartialEq)]
pub struct Transform {
    pub mat: Matrix4,
    pub inv: Matrix4,
}

impl Transform {
    /// Construct the identity transformation
    pub fn identity() -> Transform {
        Transform {
            mat: Matrix4::identity(),
            inv: Matrix4::identity(),
        }
    }
    /// Construct a transform from an existing matrix
    pub fn from_mat(mat: &Matrix4) -> Transform {
        Transform { mat: *mat, inv: mat.inverse() }
    }
    /// Construct a transform from an existing matrix/inverse pair
    pub fn from_pair(mat: &Matrix4, inv: &Matrix4) -> Transform {
        Transform { mat: *mat, inv: *inv }
    }
    /// Construct a transformation matrix to translate by the vector
    pub fn translate(v: &Vector) -> Transform {
        Transform {
            mat: Matrix4::new([1f32, 0f32, 0f32, v.x,
                               0f32, 1f32, 0f32, v.y,
                               0f32, 0f32, 1f32, v.z,
                               0f32, 0f32, 0f32, 1f32]),
            inv: Matrix4::new([1f32, 0f32, 0f32, -v.x,
                               0f32, 1f32, 0f32, -v.y,
                               0f32, 0f32, 1f32, -v.z,
                               0f32, 0f32, 0f32, 1f32]),
        }
    }
    /// Construct a transform to scale x, y and z by the values in the vector
    pub fn scale(v: &Vector) -> Transform {
        Transform {
            mat: Matrix4::new([v.x, 0f32, 0f32, 0f32,
                               0f32, v.y, 0f32, 0f32,
                               0f32, 0f32, v.z, 0f32,
                               0f32, 0f32, 0f32, 1f32]),
            inv: Matrix4::new([1f32 / v.x, 0f32, 0f32, 0f32,
                               0f32, 1f32 / v.y, 0f32, 0f32,
                               0f32, 0f32, 1f32 / v.z, 0f32,
                               0f32, 0f32, 0f32, 1f32]),
        }
    }
    /// Construct a transform to rotate `deg` degrees about the x axis
    pub fn rotate_x(deg: f32) -> Transform {
        let r = linalg::radians(deg);
        let s = FloatMath::sin(r);
        let c = FloatMath::cos(r);
        let m = Matrix4::new([1f32, 0f32, 0f32, 0f32,
                              0f32, c, -s, 0f32,
                              0f32, s, c, 0f32,
                              0f32, 0f32, 0f32, 1f32]);
        Transform { mat: m, inv: m.transpose() }
    }
    /// Construct a transform to rotate `deg` degrees about the y axis
    pub fn rotate_y(deg: f32) -> Transform {
        let r = linalg::radians(deg);
        let s = FloatMath::sin(r);
        let c = FloatMath::cos(r);
        let m = Matrix4::new([c, 0f32, s, 0f32,
                              0f32, 1f32, 0f32, 0f32,
                              -s, 0f32, c, 0f32,
                              0f32, 0f32, 0f32, 1f32]);
        Transform { mat: m, inv: m.transpose() }
    }
    /// Construct a transform to rotate `deg` degrees about the z axis
    pub fn rotate_z(deg: f32) -> Transform {
        let r = linalg::radians(deg);
        let s = FloatMath::sin(r);
        let c = FloatMath::cos(r);
        let m = Matrix4::new([c, -s, 0f32, 0f32,
                              s, c, 0f32, 0f32,
                              0f32, 0f32, 1f32, 0f32,
                              0f32, 0f32, 0f32, 1f32]);
        Transform { mat: m, inv: m.transpose() }
    }
    /// Construct a transform to rotate about `axis` by `deg` degrees
    pub fn rotate(axis: &Vector, deg: f32) -> Transform {
        let a = axis.normalized();
        let r = linalg::radians(deg);
        let s = FloatMath::sin(r);
        let c = FloatMath::cos(r);
        let mut m = Matrix4::identity();
        *m.at_mut(0, 0) = a.x * a.x + (1f32 - a.x * a.x) * c;
        *m.at_mut(0, 1) = a.x * a.y * (1f32 - c) - a.z * s;
        *m.at_mut(0, 2) = a.x * a.z * (1f32 - c) + a.y * s;

        *m.at_mut(1, 0) = a.x * a.y * (1f32 - c) + a.z * s;
        *m.at_mut(1, 1) = a.y * a.y + (1f32 - a.y * a.y) * c;
        *m.at_mut(1, 2) = a.y * a.z * (1f32 - c) - a.x * s;

        *m.at_mut(2, 0) = a.x * a.z * (1f32 - c) - a.y * s;
        *m.at_mut(2, 1) = a.y * a.z * (1f32 - c) + a.x * s;
        *m.at_mut(2, 2) = a.z * a.z + (1f32 - a.z * a.z) * c;
        Transform { mat: m, inv: m.transpose() }
    }
    /// Construct the look at transform for a camera at `pos` looking at
    /// the point `center` oriented with up vector `up`
    pub fn look_at(pos: &Point, center: &Point, up: &Vector) -> Transform {
        let dir = (*center - *pos).normalized();
        let right = linalg::cross(&dir, up).normalized();
        let u = linalg::cross(&dir, &right).normalized();
        let mut m = Matrix4::identity();
        for i in range(0u, 3u) {
            *m.at_mut(i, 0) = right[i];
            *m.at_mut(i, 1) = u[i];
            *m.at_mut(i, 2) = dir[i];
            *m.at_mut(i, 3) = pos[i];
        }
        Transform { mat: m, inv: m.inverse() }
    }
    /// Construct a perspective transformation
    pub fn perspective(fovy: f32, near: f32, far: f32) -> Transform {
        let proj_div = Matrix4::new(
            [1f32, 0f32, 0f32, 0f32,
             0f32, 1f32, 0f32, 0f32,
             0f32, 0f32, far / (far - near), -far * near / (far - near),
             0f32, 0f32, 1f32, 0f32]);
        let inv_tan = 1f32 / FloatMath::tan(linalg::radians(fovy) / 2f32);
        Transform::scale(&Vector::new(inv_tan, inv_tan, 1f32))
            * Transform::from_mat(&proj_div)
    }
    /// Return the inverse of the transformation
    pub fn inverse(&self) -> Transform {
        Transform { mat: self.inv, inv: self.mat }
    }
}

impl Mul<Transform, Transform> for Transform {
    /// Compose two transformations
    fn mul(self, rhs: Transform) -> Transform {
        Transform { mat: self.mat * rhs.mat, inv: rhs.inv * self.inv }
    }
}

impl Mul<Point, Point> for Transform {
    /// Multiply the point by the transform to apply the transformation
    fn mul(self, p: Point) -> Point {
        let mut res = Point::broadcast(0f32);
        for i in range(0u, 3u) {
            res[i] = *self.mat.at(i, 0) * p.x + *self.mat.at(i, 1) * p.y
                + *self.mat.at(i, 2) * p.z + *self.mat.at(i, 3);
        }
        let w = *self.mat.at(3, 0) * p.x + *self.mat.at(3, 1) * p.y
            + *self.mat.at(3, 2) * p.z + *self.mat.at(3, 3);
        if w != 1f32 {
            res / w
        } else {
            res
        }
    }
}

impl Mul<Vector, Vector> for Transform {
    /// Multiply the vector by the transform to apply the transformation
    fn mul(self, v: Vector) -> Vector {
        let mut res = Vector::broadcast(0f32);
        for i in range(0u, 3u) {
            res[i] = *self.mat.at(i, 0) * v.x + *self.mat.at(i, 1) * v.y
                + *self.mat.at(i, 2) * v.z;
        }
        res
    }
}

impl Mul<Normal, Normal> for Transform {
    /// Multiply the normal by the transform to apply the transformation
    fn mul(self, n: Normal) -> Normal {
        let mut res = Normal::broadcast(0f32);
        for i in range(0u, 3u) {
            res[i] = *self.inv.at(0, i) * n.x + *self.inv.at(1, i) * n.y
                + *self.inv.at(2, i) * n.z;
        }
        res
    }
}

impl Mul<Ray, Ray> for Transform {
    /// Multiply the ray by the transform to apply the transformation
    fn mul(self, ray: Ray) -> Ray {
        let mut res = ray;
        res.o = self * res.o;
        res.d = self * res.d;
        res
    }
}

// Just test against multiplying by the identity matrix as a sanity baseline
#[test]
fn test_mult_sanity() {
    let t = Transform::identity();
    let p = Point::new(1f32, 2f32, 3f32);
    assert!(t * p == p);

    let v = Vector::new(1f32, 2f32, 3f32);
    assert!(t * v == v);

    let n = Normal::new(1f32, 2f32, 3f32);
    assert!(t * n == n);

    let r = Ray::new(&p, &v);
    assert!(t * r == r);
}

<commit_msg>Add some transform tests<commit_after>use std::num::FloatMath;
use linalg;
use linalg::Matrix4;
use linalg::Vector;
use linalg::Point;
use linalg::Normal;
use linalg::Ray;

/// Transform describes an affine transformation in 3D space
/// and stores both the transformation and its inverse
#[deriving(Show, Copy, PartialEq)]
pub struct Transform {
    pub mat: Matrix4,
    pub inv: Matrix4,
}

impl Transform {
    /// Construct the identity transformation
    pub fn identity() -> Transform {
        Transform {
            mat: Matrix4::identity(),
            inv: Matrix4::identity(),
        }
    }
    /// Construct a transform from an existing matrix
    pub fn from_mat(mat: &Matrix4) -> Transform {
        Transform { mat: *mat, inv: mat.inverse() }
    }
    /// Construct a transform from an existing matrix/inverse pair
    pub fn from_pair(mat: &Matrix4, inv: &Matrix4) -> Transform {
        Transform { mat: *mat, inv: *inv }
    }
    /// Construct a transformation matrix to translate by the vector
    pub fn translate(v: &Vector) -> Transform {
        Transform {
            mat: Matrix4::new([1f32, 0f32, 0f32, v.x,
                               0f32, 1f32, 0f32, v.y,
                               0f32, 0f32, 1f32, v.z,
                               0f32, 0f32, 0f32, 1f32]),
            inv: Matrix4::new([1f32, 0f32, 0f32, -v.x,
                               0f32, 1f32, 0f32, -v.y,
                               0f32, 0f32, 1f32, -v.z,
                               0f32, 0f32, 0f32, 1f32]),
        }
    }
    /// Construct a transform to scale x, y and z by the values in the vector
    pub fn scale(v: &Vector) -> Transform {
        Transform {
            mat: Matrix4::new([v.x, 0f32, 0f32, 0f32,
                               0f32, v.y, 0f32, 0f32,
                               0f32, 0f32, v.z, 0f32,
                               0f32, 0f32, 0f32, 1f32]),
            inv: Matrix4::new([1f32 / v.x, 0f32, 0f32, 0f32,
                               0f32, 1f32 / v.y, 0f32, 0f32,
                               0f32, 0f32, 1f32 / v.z, 0f32,
                               0f32, 0f32, 0f32, 1f32]),
        }
    }
    /// Construct a transform to rotate `deg` degrees about the x axis
    pub fn rotate_x(deg: f32) -> Transform {
        let r = linalg::radians(deg);
        let s = FloatMath::sin(r);
        let c = FloatMath::cos(r);
        let m = Matrix4::new([1f32, 0f32, 0f32, 0f32,
                              0f32, c, -s, 0f32,
                              0f32, s, c, 0f32,
                              0f32, 0f32, 0f32, 1f32]);
        Transform { mat: m, inv: m.transpose() }
    }
    /// Construct a transform to rotate `deg` degrees about the y axis
    pub fn rotate_y(deg: f32) -> Transform {
        let r = linalg::radians(deg);
        let s = FloatMath::sin(r);
        let c = FloatMath::cos(r);
        let m = Matrix4::new([c, 0f32, s, 0f32,
                              0f32, 1f32, 0f32, 0f32,
                              -s, 0f32, c, 0f32,
                              0f32, 0f32, 0f32, 1f32]);
        Transform { mat: m, inv: m.transpose() }
    }
    /// Construct a transform to rotate `deg` degrees about the z axis
    pub fn rotate_z(deg: f32) -> Transform {
        let r = linalg::radians(deg);
        let s = FloatMath::sin(r);
        let c = FloatMath::cos(r);
        let m = Matrix4::new([c, -s, 0f32, 0f32,
                              s, c, 0f32, 0f32,
                              0f32, 0f32, 1f32, 0f32,
                              0f32, 0f32, 0f32, 1f32]);
        Transform { mat: m, inv: m.transpose() }
    }
    /// Construct a transform to rotate about `axis` by `deg` degrees
    pub fn rotate(axis: &Vector, deg: f32) -> Transform {
        let a = axis.normalized();
        let r = linalg::radians(deg);
        let s = FloatMath::sin(r);
        let c = FloatMath::cos(r);
        let mut m = Matrix4::identity();
        *m.at_mut(0, 0) = a.x * a.x + (1f32 - a.x * a.x) * c;
        *m.at_mut(0, 1) = a.x * a.y * (1f32 - c) - a.z * s;
        *m.at_mut(0, 2) = a.x * a.z * (1f32 - c) + a.y * s;

        *m.at_mut(1, 0) = a.x * a.y * (1f32 - c) + a.z * s;
        *m.at_mut(1, 1) = a.y * a.y + (1f32 - a.y * a.y) * c;
        *m.at_mut(1, 2) = a.y * a.z * (1f32 - c) - a.x * s;

        *m.at_mut(2, 0) = a.x * a.z * (1f32 - c) - a.y * s;
        *m.at_mut(2, 1) = a.y * a.z * (1f32 - c) + a.x * s;
        *m.at_mut(2, 2) = a.z * a.z + (1f32 - a.z * a.z) * c;
        Transform { mat: m, inv: m.transpose() }
    }
    /// Construct the look at transform for a camera at `pos` looking at
    /// the point `center` oriented with up vector `up`
    pub fn look_at(pos: &Point, center: &Point, up: &Vector) -> Transform {
        let dir = (*center - *pos).normalized();
        let right = linalg::cross(&dir, up).normalized();
        let u = linalg::cross(&dir, &right).normalized();
        let mut m = Matrix4::identity();
        for i in range(0u, 3u) {
            *m.at_mut(i, 0) = right[i];
            *m.at_mut(i, 1) = u[i];
            *m.at_mut(i, 2) = dir[i];
            *m.at_mut(i, 3) = pos[i];
        }
        Transform { mat: m, inv: m.inverse() }
    }
    /// Construct a perspective transformation
    pub fn perspective(fovy: f32, near: f32, far: f32) -> Transform {
        let proj_div = Matrix4::new(
            [1f32, 0f32, 0f32, 0f32,
             0f32, 1f32, 0f32, 0f32,
             0f32, 0f32, far / (far - near), -far * near / (far - near),
             0f32, 0f32, 1f32, 0f32]);
        let inv_tan = 1f32 / FloatMath::tan(linalg::radians(fovy) / 2f32);
        Transform::scale(&Vector::new(inv_tan, inv_tan, 1f32))
            * Transform::from_mat(&proj_div)
    }
    /// Return the inverse of the transformation
    pub fn inverse(&self) -> Transform {
        Transform { mat: self.inv, inv: self.mat }
    }
}

impl Mul<Transform, Transform> for Transform {
    /// Compose two transformations
    fn mul(self, rhs: Transform) -> Transform {
        Transform { mat: self.mat * rhs.mat, inv: rhs.inv * self.inv }
    }
}

impl Mul<Point, Point> for Transform {
    /// Multiply the point by the transform to apply the transformation
    fn mul(self, p: Point) -> Point {
        let mut res = Point::broadcast(0f32);
        for i in range(0u, 3u) {
            res[i] = *self.mat.at(i, 0) * p.x + *self.mat.at(i, 1) * p.y
                + *self.mat.at(i, 2) * p.z + *self.mat.at(i, 3);
        }
        let w = *self.mat.at(3, 0) * p.x + *self.mat.at(3, 1) * p.y
            + *self.mat.at(3, 2) * p.z + *self.mat.at(3, 3);
        if w != 1f32 {
            res / w
        } else {
            res
        }
    }
}

impl Mul<Vector, Vector> for Transform {
    /// Multiply the vector by the transform to apply the transformation
    fn mul(self, v: Vector) -> Vector {
        let mut res = Vector::broadcast(0f32);
        for i in range(0u, 3u) {
            res[i] = *self.mat.at(i, 0) * v.x + *self.mat.at(i, 1) * v.y
                + *self.mat.at(i, 2) * v.z;
        }
        res
    }
}

impl Mul<Normal, Normal> for Transform {
    /// Multiply the normal by the transform to apply the transformation
    fn mul(self, n: Normal) -> Normal {
        let mut res = Normal::broadcast(0f32);
        for i in range(0u, 3u) {
            res[i] = *self.inv.at(0, i) * n.x + *self.inv.at(1, i) * n.y
                + *self.inv.at(2, i) * n.z;
        }
        res
    }
}

impl Mul<Ray, Ray> for Transform {
    /// Multiply the ray by the transform to apply the transformation
    fn mul(self, ray: Ray) -> Ray {
        let mut res = ray;
        res.o = self * res.o;
        res.d = self * res.d;
        res
    }
}

// Just test against multiplying by the identity matrix as a sanity baseline
#[test]
fn test_mult_sanity() {
    let t = Transform::identity();
    let p = Point::new(1f32, 2f32, 3f32);
    let v = Vector::new(1f32, 2f32, 3f32);
    let n = Normal::new(1f32, 2f32, 3f32);
    assert_eq!(t * p, p);
    assert_eq!(t * v, v);
    assert_eq!(t * n, n);
}
#[test]
fn test_translate() {
    let t = Transform::translate(&Vector::new(1f32, 2f32, 3f32));
    let p = Point::new(1f32, 2f32, -1f32);
    let v = Vector::new(1f32, 0f32, 1f32);
    let n = Normal::new(1f32, 0f32, 1f32);
    assert_eq!(t * p, p + Vector::new(1f32, 2f32, 3f32));
    assert_eq!(t * v, v);
    assert_eq!(t * n, n);
}
#[test]
fn test_scale() {
    let t = Transform::scale(&Vector::new(0.5f32, 0.1f32, 2f32));
    let p = Point::new(10f32, 20f32, 30f32);
    let v = Vector::new(10f32, 20f32, 30f32);
    let n = Normal::new(1f32, 2f32, 10f32);
    assert_eq!(t * p, Point::new(p.x * 0.5f32, p.y * 0.1f32, p.z * 2f32));
    assert_eq!(t * v, v * Vector::new(0.5f32, 0.1f32, 2f32));
    assert_eq!(t * n, n * Normal::new(2f32, 10f32, 0.5f32));
}
#[test]
fn test_rotate_x() {
    let t = Transform::rotate_x(90f32);
    let p = t * Point::new(0f32, 1f32, 0f32);
    let v = t * Vector::new(0f32, 1f32, 0f32);
    let n = t * Normal::new(0f32, 1f32, 0f32);
    // Need to now deal with some floating annoyances in these tests
    assert_eq!(p.x, 0f32);
    assert_eq!(FloatMath::abs_sub(p.y, 0f32), 0f32);
    assert_eq!(p.z, 1f32);

    assert_eq!(v.x, 0f32);
    assert_eq!(FloatMath::abs_sub(v.y, 0f32), 0f32);
    assert_eq!(v.z, 1f32);

    assert_eq!(n.x, 0f32);
    assert_eq!(FloatMath::abs_sub(n.y, 0f32), 0f32);
    assert_eq!(n.z, 1f32);
}
#[test]
fn test_rotate_y() {
    let t = Transform::rotate_y(-90f32);
    let p = t * Point::new(1f32, 0f32, 0f32);
    let v = t * Vector::new(1f32, 0f32, 0f32);
    let n = t * Normal::new(1f32, 0f32, 0f32);
    // Need to now deal with some floating annoyances in these tests
    assert_eq!(FloatMath::abs_sub(p.x, 0f32), 0f32);
    assert_eq!(p.y, 0f32);
    assert_eq!(p.z, 1f32);

    assert_eq!(FloatMath::abs_sub(v.x, 0f32), 0f32);
    assert_eq!(v.y, 0f32);
    assert_eq!(v.z, 1f32);

    assert_eq!(FloatMath::abs_sub(n.x, 0f32), 0f32);
    assert_eq!(n.y, 0f32);
    assert_eq!(n.z, 1f32);
}
#[test]
fn test_rotate_z() {
    let t = Transform::rotate_z(90f32);
    let p = t * Point::new(1f32, 0f32, 0f32);
    let v = t * Vector::new(1f32, 0f32, 0f32);
    let n = t * Normal::new(1f32, 0f32, 0f32);
    // Need to now deal with some floating annoyances in these tests
    assert_eq!(FloatMath::abs_sub(p.x, 0f32), 0f32);
    assert_eq!(p.y, 1f32);
    assert_eq!(p.z, 0f32);

    assert_eq!(FloatMath::abs_sub(v.x, 0f32), 0f32);
    assert_eq!(v.y, 1f32);
    assert_eq!(v.z, 0f32);

    assert_eq!(FloatMath::abs_sub(n.x, 0f32), 0f32);
    assert_eq!(n.y, 1f32);
    assert_eq!(n.z, 0f32);
}
#[test]
fn test_rotate() {
    assert_eq!(Transform::rotate(&Vector::new(1f32, 0f32, 0f32), 32f32),
                Transform::rotate_x(32f32));
    assert_eq!(Transform::rotate(&Vector::new(0f32, 1f32, 0f32), 104f32),
                Transform::rotate_y(104f32));
    assert_eq!(Transform::rotate(&Vector::new(0f32, 0f32, 1f32), 243f32),
                Transform::rotate_z(243f32));
}

<|endoftext|>


<commit_before>//! This module contains the implementation for an in-memory DICOM object.

use std::collections::HashMap;
use std::marker::PhantomData;
use std::path::Path;
use std::fs::File;
use std::io::BufReader;
use meta::DicomMetaTable;

use super::DicomObject;
use data::{DataElement, Header, Tag};
use data::value::DicomValue;
use dictionary::{DataDictionary, DictionaryEntry, StandardDataDictionary, get_standard_dictionary};
use error::{Error, Result};
use object::pixeldata::PixelData;

/** A DICOM sequence that is fully contained in memory.
 */
#[derive(Debug, Clone)]
pub struct InMemSequence<D> {
    tag: Tag,
    objects: Vec<InMemDicomObject<D>>,
}

/** A DICOM object that is fully contained in memory.
 */
#[derive(Debug, Clone)]
pub struct InMemDicomObject<D> {
    entries: HashMap<Tag, DataElement>,
    dict: D,
}

impl<'s, D> PartialEq for InMemDicomObject<D> {
    // This implementation ignores the data dictionary.
    fn eq(&self, other: &Self) -> bool {
        self.entries == other.entries
    }
}

impl<'s, D: 's> DicomObject for &'s InMemDicomObject<D>
    where D: DataDictionary
{
    type Element = &'s DataElement;
    type Sequence = InMemSequence<D>;

    fn get_element(&self, tag: Tag) -> Result<Self::Element> {
        (**self).get_element(tag)
    }

    fn get_element_by_name(&self, name: &str) -> Result<Self::Element> {
        (**self).get_element_by_name(name)
    }

    fn get_pixel_data<PV, PD: PixelData<PV>>(&self) -> Result<PD> {
        (**self).get_pixel_data()
    }
}

impl InMemDicomObject<&'static StandardDataDictionary> {
    /// Create a new empty DICOM object.
    pub fn create_empty() -> Self {
        InMemDicomObject {
            entries: HashMap::new(),
            dict: get_standard_dictionary(),
        }
    }

    /// Create a DICOM object by reading from a file.
    pub fn from_file<P: AsRef<Path>>(path: P) -> Result<Self> {
        Self::from_file_with_dict(path, get_standard_dictionary())
    }
}

impl<D> InMemDicomObject<D>
    where D: DataDictionary
{
    /// Create a new empty object, using the given dictionary
    /// for name lookup.
    pub fn new_empty_with_dict(dict: D) -> Self {
        InMemDicomObject {
            entries: HashMap::new(),
            dict: dict,
        }
    }

    /// Create a DICOM object by reading from a file.
    pub fn from_file_with_dict<P: AsRef<Path>>(path: P, dict: D) -> Result<Self> {
        let mut file = BufReader::new(File::open(path)?);

        // read metadata header
        let meta = DicomMetaTable::from_readseek_stream(&mut file)?;
        // TODO feed data to object

        // TODO read rest of data according to metadata, feed it to object

        unimplemented!()
    }

    fn lookup_name(&self, name: &str) -> Result<Tag> {
        self.dict
            .get_by_name(name)
            .ok_or(Error::NoSuchAttributeName)
            .map(|e| e.tag())
    }

    /// Insert a data element to the object.
    pub fn put(&mut self, elt: DataElement) {
        self.entries.insert(elt.tag(), elt);
    }

    fn get_element(&self, tag: Tag) -> Result<&DataElement> {
        self.entries
            .get(&tag)
            .ok_or(Error::NoSuchDataElement)
    }

    fn get_element_by_name(&self, name: &str) -> Result<&DataElement> {
        let tag = self.lookup_name(name)?;
        self.get_element(tag)
    }

    fn get_pixel_data<PV, PD: PixelData<PV>>(&self) -> Result<PD> {
        unimplemented!()
    }
}

#[cfg(test)]
mod tests {

    use super::*;
    use object::DicomObject;
    use data::VR;

    #[test]
    fn inmem_object_write() {
        let mut obj1 = InMemDicomObject::create_empty();
        let mut obj2 = InMemDicomObject::create_empty();
        assert_eq!(obj1, obj2);
        let empty_patient_name = DataElement::empty(Tag(0x0010, 0x0010), VR::PN);
        obj1.put(empty_patient_name.clone());
        assert_ne!(obj1, obj2);
        obj2.put(empty_patient_name.clone());
        assert_eq!(obj1, obj2);
    }

    #[test]
    fn inmem_object_get() {
        let another_patient_name = DataElement::new(Tag(0x0010, 0x0010),
                                                    VR::PN,
                                                    DicomValue::Str("Doe^John".to_string()));
        let mut obj = InMemDicomObject::create_empty();
        obj.put(another_patient_name.clone());
        let elem1 = (&obj).get_element(Tag(0x0010, 0x0010)).unwrap();
        assert_eq!(elem1, &another_patient_name);
    }

    #[test]
    fn inmem_object_get_by_name() {
        let another_patient_name = DataElement::new(Tag(0x0010, 0x0010),
                                                    VR::PN,
                                                    DicomValue::Str("Doe^John".to_string()));
        let mut obj = InMemDicomObject::create_empty();
        obj.put(another_patient_name.clone());
        let elem1 = (&obj).get_element_by_name("PatientName").unwrap();
        assert_eq!(elem1, &another_patient_name);
    }
}
<commit_msg>Take of unnecessary ref-wrapping<commit_after>//! This module contains the implementation for an in-memory DICOM object.

use std::collections::HashMap;
use std::marker::PhantomData;
use std::path::Path;
use std::fs::File;
use std::io::BufReader;
use meta::DicomMetaTable;

use super::DicomObject;
use data::{DataElement, Header, Tag};
use data::value::DicomValue;
use dictionary::{DataDictionary, DictionaryEntry, StandardDataDictionary, get_standard_dictionary};
use error::{Error, Result};
use object::pixeldata::PixelData;

/** A DICOM sequence that is fully contained in memory.
 */
#[derive(Debug, Clone)]
pub struct InMemSequence<D> {
    tag: Tag,
    objects: Vec<InMemDicomObject<D>>,
}

/** A DICOM object that is fully contained in memory.
 */
#[derive(Debug, Clone)]
pub struct InMemDicomObject<D> {
    entries: HashMap<Tag, DataElement>,
    dict: D,
}

impl<'s, D> PartialEq for InMemDicomObject<D> {
    // This implementation ignores the data dictionary.
    fn eq(&self, other: &Self) -> bool {
        self.entries == other.entries
    }
}

impl<'s, D: 's> DicomObject for &'s InMemDicomObject<D>
    where D: DataDictionary
{
    type Element = &'s DataElement;
    type Sequence = InMemSequence<D>;

    fn get_element(&self, tag: Tag) -> Result<Self::Element> {
        (**self).get_element(tag)
    }

    fn get_element_by_name(&self, name: &str) -> Result<Self::Element> {
        (**self).get_element_by_name(name)
    }

    fn get_pixel_data<PV, PD: PixelData<PV>>(&self) -> Result<PD> {
        (**self).get_pixel_data()
    }
}

impl InMemDicomObject<&'static StandardDataDictionary> {
    /// Create a new empty DICOM object.
    pub fn create_empty() -> Self {
        InMemDicomObject {
            entries: HashMap::new(),
            dict: get_standard_dictionary(),
        }
    }

    /// Create a DICOM object by reading from a file.
    pub fn from_file<P: AsRef<Path>>(path: P) -> Result<Self> {
        Self::from_file_with_dict(path, get_standard_dictionary())
    }
}

impl<D> InMemDicomObject<D>
    where D: DataDictionary
{
    /// Create a new empty object, using the given dictionary
    /// for name lookup.
    pub fn new_empty_with_dict(dict: D) -> Self {
        InMemDicomObject {
            entries: HashMap::new(),
            dict: dict,
        }
    }

    /// Create a DICOM object by reading from a file.
    pub fn from_file_with_dict<P: AsRef<Path>>(path: P, dict: D) -> Result<Self> {
        let mut file = BufReader::new(File::open(path)?);

        // read metadata header
        let meta = DicomMetaTable::from_readseek_stream(&mut file)?;
        // TODO feed data to object

        // TODO read rest of data according to metadata, feed it to object

        unimplemented!()
    }

    fn lookup_name(&self, name: &str) -> Result<Tag> {
        self.dict
            .get_by_name(name)
            .ok_or(Error::NoSuchAttributeName)
            .map(|e| e.tag())
    }

    /// Insert a data element to the object.
    pub fn put(&mut self, elt: DataElement) {
        self.entries.insert(elt.tag(), elt);
    }

    fn get_element(&self, tag: Tag) -> Result<&DataElement> {
        self.entries
            .get(&tag)
            .ok_or(Error::NoSuchDataElement)
    }

    fn get_element_by_name(&self, name: &str) -> Result<&DataElement> {
        let tag = self.lookup_name(name)?;
        self.get_element(tag)
    }

    fn get_pixel_data<PV, PD: PixelData<PV>>(&self) -> Result<PD> {
        unimplemented!()
    }
}

#[cfg(test)]
mod tests {

    use super::*;
    use object::DicomObject;
    use data::VR;

    #[test]
    fn inmem_object_write() {
        let mut obj1 = InMemDicomObject::create_empty();
        let mut obj2 = InMemDicomObject::create_empty();
        assert_eq!(obj1, obj2);
        let empty_patient_name = DataElement::empty(Tag(0x0010, 0x0010), VR::PN);
        obj1.put(empty_patient_name.clone());
        assert_ne!(obj1, obj2);
        obj2.put(empty_patient_name.clone());
        assert_eq!(obj1, obj2);
    }

    #[test]
    fn inmem_object_get() {
        let another_patient_name = DataElement::new(Tag(0x0010, 0x0010),
                                                    VR::PN,
                                                    DicomValue::Str("Doe^John".to_string()));
        let mut obj = InMemDicomObject::create_empty();
        obj.put(another_patient_name.clone());
        let elem1 = obj.get_element(Tag(0x0010, 0x0010)).unwrap();
        assert_eq!(elem1, &another_patient_name);
    }

    #[test]
    fn inmem_object_get_by_name() {
        let another_patient_name = DataElement::new(Tag(0x0010, 0x0010),
                                                    VR::PN,
                                                    DicomValue::Str("Doe^John".to_string()));
        let mut obj = InMemDicomObject::create_empty();
        obj.put(another_patient_name.clone());
        let elem1 = obj.get_element_by_name("PatientName").unwrap();
        assert_eq!(elem1, &another_patient_name);
    }
}
<|endoftext|>


<commit_before>use libc::{c_char, c_double, c_int, size_t};

#[cfg(target_arch="x86_64")]
#[path="ucontext_x86_64.rs"]
mod ucontext;

// This almost certainly needs to be made specific to just x86 (and
// add cases for the other processors).
#[cfg(not(target_arch="x86_64"))]
#[path="ucontext_generic.rs"]
mod ucontext;

// These almost certainly need to be replaced with something that is
// target/platform specific.
mod sigset;
mod sigstack;

#[cfg(target_arch="x86_64")]
const UNW_TDEP_CURSOR_LEN: usize = 127;

#[cfg(target_arch="x86_64")]
type unw_word_t = usize;

#[repr(C)]
pub struct unw_cursor_t {
    opaque: [unw_word_t; UNW_TDEP_CURSOR_LEN],
}

type unw_context_t = ucontext::ucontext_t;
type unw_regnum_t = c_int;

#[cfg(target_arch="x86_64")]
type unw_fpreg_t = c_double;

extern {
    fn unw_getcontext(ucp: *mut unw_context_t);
    fn unw_init_local(c: *mut unw_cursor_t, ctxt: *mut unw_context_t);
    // fn unw_init_remote(c: *mut unw_cursor_t, as: unw_addr_space_t, arg: *mut c_void);
    fn unw_step(cp: *mut unw_cursor_t);
    fn unw_get_reg(cp: *mut unw_cursor_t, reg: unw_regnum_t, valp: *mut unw_word_t);
    fn unw_get_fpreg(cp: *mut unw_cursor_t, reg: unw_regnum_t, valp: *mut unw_fpreg_t);
    fn unw_resume(cp: *mut unw_cursor_t);

    // fn unw_create_addr_space(ap: *mut unw_accessors_t, byteorder: c_int);
    // fn unw_destroy_addr_space(as: unw_addr_space_t);
    // fn unw_get_accessors(as: unw_addr_space_t) -> *mut unw_accessors_t;
    // fn unw_flush_cache(as: unw_addr_space, lo: unw_word_t, hi: unw_word_t);
    // fn unw_set_caching_policy(as: unw_addr_space, policy: unw_caching_policy_t) -> c_int;

    fn unw_regname(regnum: unw_regnum_t) -> *const c_char;
    // fn unw_get_proc_info(cp: *mut unw_cursor_t, pip: *mut unw_proc_info_t);
    // fn unw_get_save_loc(cp: *mut unw_cursor_t, _int: c_int, loc: *mut unw_save_loc_t);
    fn unw_is_fpreg(r: unw_regnum_t) -> c_int;
    fn unw_is_signal_frame(cp: *mut unw_cursor_t) -> c_int;
    fn unw_get_proc_name(cp: *mut unw_cursor_t, bufp: *mut c_char, len: size_t, offp: *mut unw_word_t) -> c_int;

    // fn _U_dyn_register(di: *mut unw_dyn_info_t);
    // fn _U_dyn_cancel(di: *mut unw_dyn_info_t);
}
<commit_msg>Added other struct definitions I suspect needed for local unwinding.<commit_after>use libc::{c_char, c_double, c_int, c_void, size_t};

#[cfg(target_arch="x86_64")]
#[path="ucontext_x86_64.rs"]
mod ucontext;

// This almost certainly needs to be made specific to just x86 (and
// add cases for the other processors).
#[cfg(not(target_arch="x86_64"))]
#[path="ucontext_generic.rs"]
mod ucontext;

// These almost certainly need to be replaced with something that is
// target/platform specific.
mod sigset;
mod sigstack;

#[cfg(target_arch="x86_64")]
const UNW_TDEP_CURSOR_LEN: usize = 127;

#[cfg(target_arch="x86_64")]
type unw_word_t = usize;

#[repr(C)]
pub struct unw_cursor_t {
    opaque: [unw_word_t; UNW_TDEP_CURSOR_LEN],
}

type unw_context_t = ucontext::ucontext_t;
type unw_regnum_t = c_int;

#[cfg(target_arch="x86_64")]
type unw_fpreg_t = c_double;

#[cfg(target_arch="x86_64")]
#[repr(C)]
struct unw_tdep_proc_info_t {

}

#[repr(C)]
struct unw_proc_info_t {
    start_ip: unw_word_t,
    end_ip: unw_word_t,
    lsda: unw_word_t,
    handler: unw_word_t,
    gp: unw_word_t,
    flags: unw_word_t,
    format: c_int,
    unwind_info_size: c_int,
    unwind_info: *mut c_void,
    extra: unw_tdep_proc_info_t,
}

#[repr(C)]
enum unw_save_loc_type_t {
    UNW_SLT_NONE,
    UNW_SLT_MEMORY,
    UNW_SLT_REG,
}

#[repr(C)]
struct unw_save_loc_t {
    type_: unw_save_loc_type_t,
    u: unw_word_t, // should be union { unw_word_t, unw_regnum_t }
    extra: unw_tdep_save_loc_t,
}

#[cfg(target_arch="x86_64")]
#[repr(C)]
struct unw_tdep_save_loc_t {

}

extern {
    fn unw_getcontext(ucp: *mut unw_context_t);
    fn unw_init_local(c: *mut unw_cursor_t, ctxt: *mut unw_context_t);
    fn unw_step(cp: *mut unw_cursor_t);
    fn unw_get_reg(cp: *mut unw_cursor_t, reg: unw_regnum_t, valp: *mut unw_word_t);
    fn unw_get_fpreg(cp: *mut unw_cursor_t, reg: unw_regnum_t, valp: *mut unw_fpreg_t);
    fn unw_resume(cp: *mut unw_cursor_t);

    // I think the methods below are solely used for "remote
    // unwinding", which is not immediately relevant to me, so I need
    // not worry about finding definition for `struct unw_addr_space`.

    // fn unw_init_remote(c: *mut unw_cursor_t, as: unw_addr_space_t, arg: *mut c_void);
    // fn unw_create_addr_space(ap: *mut unw_accessors_t, byteorder: c_int);
    // fn unw_destroy_addr_space(as: unw_addr_space_t);
    // fn unw_get_accessors(as: unw_addr_space_t) -> *mut unw_accessors_t;
    // fn unw_flush_cache(as: unw_addr_space, lo: unw_word_t, hi: unw_word_t);
    // fn unw_set_caching_policy(as: unw_addr_space, policy: unw_caching_policy_t) -> c_int;

    fn unw_regname(regnum: unw_regnum_t) -> *const c_char;
    fn unw_get_proc_info(cp: *mut unw_cursor_t, pip: *mut unw_proc_info_t);
    fn unw_get_save_loc(cp: *mut unw_cursor_t, _int: c_int, loc: *mut unw_save_loc_t);
    fn unw_is_fpreg(r: unw_regnum_t) -> c_int;
    fn unw_is_signal_frame(cp: *mut unw_cursor_t) -> c_int;
    fn unw_get_proc_name(cp: *mut unw_cursor_t, bufp: *mut c_char, len: size_t, offp: *mut unw_word_t) -> c_int;

    // fn _U_dyn_register(di: *mut unw_dyn_info_t);
    // fn _U_dyn_cancel(di: *mut unw_dyn_info_t);
}
<|endoftext|>


<commit_before>//! QuotientFilter implementation.
use std::collections::hash_map::DefaultHasher;
use std::hash::{BuildHasher, BuildHasherDefault, Hash, Hasher};

use filters::Filter;

/// Error that signals that the QuotientFilter is full.
#[derive(Debug)]
pub struct QuotientFilterFull;

/// TODO
/// Run: List of fingerprints with same quotient.
/// Cluster: set of runs
///
/// https://en.wikipedia.org/wiki/Quotient_filter
/// http://static.usenix.org/events/hotstorage11/tech/final_files/Bender.pdf
/// https://www.vldb.org/pvldb/vol5/p1627_michaelabender_vldb2012.pdf
#[derive(Debug)]
pub struct QuotientFilter<B = BuildHasherDefault<DefaultHasher>>
where
    B: BuildHasher + Clone + Eq,
{
    is_occupied: Vec<bool>,     // TODO: shrink
    is_continuation: Vec<bool>, // TODO: shrink
    is_shifted: Vec<bool>,      // TODO: shrink
    remainders: Vec<u64>,       // TODO: shrink
    bits_quotient: usize,
    bits_remainder: usize,
    buildhasher: B,
    n_elements: usize,
}

impl QuotientFilter {
    /// Create new quotient filter with:
    ///
    /// - `bits_quotient`: number of bits used for a quotient, aka `2^bits_quotient` slots will be
    ///   allocated
    /// - `bits_remainder`: number of bits used for the remainder, so every slot will require
    ///   `bits_remainder + 3` bits of storage
    ///
    /// and a default hasher.
    pub fn with_params(bits_quotient: usize, bits_remainder: usize) -> Self {
        let buildhasher = BuildHasherDefault::<DefaultHasher>::default();
        QuotientFilter::with_params_and_hash(bits_quotient, bits_remainder, buildhasher)
    }
}

impl<B> QuotientFilter<B>
where
    B: BuildHasher + Clone + Eq,
{
    /// Create new quotient filter with:
    ///
    /// - `bits_quotient`: number of bits used for a quotient, aka `2^bits_quotient` slots will be
    ///   allocated
    /// - `bits_remainder`: number of bits used for the remainder, so every slot will require
    ///   `bits_remainder + 3` bits of storage
    /// - `buildhasher`: hash implementation
    pub fn with_params_and_hash(
        bits_quotient: usize,
        bits_remainder: usize,
        buildhasher: B,
    ) -> Self {
        assert!(
            bits_remainder > 0,
            "bits_remainder ({}) must be greater than 0",
            bits_remainder,
        );
        assert!(
            bits_quotient > 0,
            "bits_quotient ({}) must be greater than 0",
            bits_quotient,
        );
        assert!(
            bits_remainder + bits_quotient <= 64,
            "bits_remainder ({}) + bits_quotient ({}) must be smaller or equal than 64",
            bits_remainder,
            bits_quotient,
        );

        let len = 1 << bits_quotient;
        Self {
            is_occupied: vec![false; len],
            is_continuation: vec![false; len],
            is_shifted: vec![false; len],
            remainders: vec![0; len],
            bits_quotient,
            bits_remainder,
            buildhasher,
            n_elements: 0,
        }
    }

    /// Number of bits used for addressing slots.
    pub fn bits_quotient(&self) -> usize {
        self.bits_quotient
    }

    /// Number of bits stored as fingeprint information.
    pub fn bits_remainder(&self) -> usize {
        self.bits_remainder
    }

    fn calc_quotient_remainder<T>(&self, obj: &T) -> (usize, u64)
    where
        T: Hash,
    {
        let mut hasher = self.buildhasher.build_hasher();
        obj.hash(&mut hasher);
        let fingerprint = hasher.finish();
        let bits_trash = 64 - self.bits_remainder - self.bits_quotient;
        let trash = if bits_trash > 0 {
            (fingerprint >> (64 - bits_trash)) << (64 - bits_trash)
        } else {
            0
        };
        let fingerprint_clean = fingerprint - trash;
        let quotient = fingerprint_clean >> self.bits_remainder;
        let remainder = fingerprint_clean - (quotient << self.bits_remainder);
        (quotient as usize, remainder)
    }

    fn decr(&self, pos: &mut usize) {
        *pos = if *pos == 0 {
            self.is_occupied.len() - 1
        } else {
            *pos - 1
        };
    }

    fn incr(&self, pos: &mut usize) {
        *pos = if *pos == self.is_occupied.len() - 1 {
            0
        } else {
            *pos + 1
        }
    }

    fn scan(&self, quotient: usize, remainder: u64, on_insert: bool) -> (bool, usize, bool, usize) {
        let run_exists = self.is_occupied[quotient];
        if (!run_exists) && (!on_insert) {
            // fast-path for query, since we don't need to find the correct position for the
            // insertion process
            return (run_exists, quotient, run_exists, quotient);
        }

        // walk back to find the beginning of the cluster
        let mut b = quotient;
        while self.is_shifted[b] {
            self.decr(&mut b);
        }

        // walk forward to find the actual start of the run
        let mut s = b;
        while b != quotient {
            // invariant: `s` poins to first slot of bucket `b`

            // skip all elements in the current run
            loop {
                self.incr(&mut s);
                if !self.is_continuation[s] {
                    break;
                }
            }

            // find the next occupied bucket
            loop {
                self.incr(&mut b);
                if self.is_occupied[b] || ((b == quotient) && on_insert) {
                    break;
                }
            }
        }
        // `s` now points to the first remainder in bucket at `quotient`

        // search of remainder within the run
        let start_of_run = s;
        if run_exists {
            loop {
                if self.remainders[s] == remainder {
                    return (run_exists, s, run_exists, start_of_run);
                }
                if self.remainders[s] > remainder {
                    // remainders are sorted within run
                    break;
                }
                self.incr(&mut s);
                if !self.is_continuation[s] {
                    break;
                }
            }
        }
        (false, s, run_exists, start_of_run)
    }
}

impl<B> Filter for QuotientFilter<B>
where
    B: BuildHasher + Clone + Eq,
{
    type InsertErr = QuotientFilterFull;

    fn clear(&mut self) {
        unimplemented!()
    }

    fn insert<T>(&mut self, t: &T) -> Result<(), Self::InsertErr>
    where
        T: Hash,
    {
        let (quotient, remainder) = self.calc_quotient_remainder(t);
        let (present, mut position, run_exists, start_of_run) =
            self.scan(quotient, remainder, true);

        // early exit if the element is already present
        if present {
            return Ok(());
        }
        // we need to insert the element into the filter

        // error out if there is no space left
        if self.n_elements == self.is_occupied.len() {
            return Err(QuotientFilterFull);
        }

        // set up swap chain
        let mut current_is_continuation =
            self.is_continuation[position] || (run_exists && (position == start_of_run));
        let mut current_remainder = self.remainders[position];
        let mut current_used = self.is_occupied[position] || self.is_shifted[position];

        // set current state
        self.remainders[position] = remainder;
        if position != start_of_run {
            // might be an append operation, ensure is_continuation and is_shifted are set
            self.is_continuation[position] = true;
        }
        if position != quotient {
            // not at canonical slot
            self.is_shifted[position] = true;
        }

        // run swap chain until nothing to do
        let start = position;
        while current_used {
            self.incr(&mut position);
            let next_is_continuation = self.is_continuation[position];
            let next_remainder = self.remainders[position];
            let next_used = self.is_occupied[position] || self.is_shifted[position];

            self.is_shifted[position] = true;
            self.is_continuation[position] = current_is_continuation;
            self.remainders[position] = current_remainder;

            current_is_continuation = next_is_continuation;
            current_remainder = next_remainder;
            current_used = next_used;

            if position == start {
                panic!("infinite loop detected");
            }
        }

        // mark canonical slot as occupied
        self.is_occupied[quotient] = true;

        // done
        self.n_elements += 1;
        Ok(())
    }

    fn is_empty(&self) -> bool {
        self.n_elements == 0
    }

    fn len(&self) -> usize {
        self.n_elements
    }

    fn query<T>(&self, obj: &T) -> bool
    where
        T: Hash,
    {
        let (quotient, remainder) = self.calc_quotient_remainder(obj);
        let (present, _position, _run_exists, _start_of_run) =
            self.scan(quotient, remainder, false);
        present
    }
}

#[cfg(test)]
mod tests {
    use super::QuotientFilter;
    use filters::Filter;

    #[test]
    #[should_panic(expected = "bits_quotient (0) must be greater than 0")]
    fn new_bits_quotient_0() {
        QuotientFilter::with_params(0, 16);
    }

    #[test]
    #[should_panic(expected = "bits_remainder (0) must be greater than 0")]
    fn new_bits_remainder_0() {
        QuotientFilter::with_params(3, 0);
    }

    #[test]
    #[should_panic(
        expected = "bits_remainder (5) + bits_quotient (60) must be smaller or equal than 64"
    )]
    fn new_too_many_bits() {
        QuotientFilter::with_params(60, 5);
    }

    #[test]
    fn new() {
        let qf = QuotientFilter::with_params(3, 16);
        assert!(qf.is_empty());
        assert_eq!(qf.len(), 0);
        assert!(!qf.query(&13));
        assert_eq!(qf.bits_quotient(), 3);
        assert_eq!(qf.bits_remainder(), 16);
    }

    #[test]
    fn insert() {
        let mut qf = QuotientFilter::with_params(3, 16);
        qf.insert(&13).unwrap();
        assert!(!qf.is_empty());
        assert_eq!(qf.len(), 1);
        assert!(qf.query(&13));
        assert!(!qf.query(&42));
    }

    #[test]
    fn double_insert() {
        let mut qf = QuotientFilter::with_params(3, 16);
        qf.insert(&13).unwrap();
        qf.insert(&13).unwrap();
        assert!(!qf.is_empty());
        assert_eq!(qf.len(), 1);
        assert!(qf.query(&13));
        assert!(!qf.query(&42));
    }

    #[test]
    fn full() {
        let mut qf = QuotientFilter::with_params(3, 16);
        for i in 0..8 {
            qf.insert(&i).unwrap();
            for j in 0..i {
                assert!(qf.query(&j), "Cannot find {} after inserting {}", j, i);
            }
        }
        assert!(qf.insert(&1000).is_err());
    }
}
<commit_msg>quotientfilter: bitpacking<commit_after>//! QuotientFilter implementation.
use std::collections::hash_map::DefaultHasher;
use std::hash::{BuildHasher, BuildHasherDefault, Hash, Hasher};
use std::mem::size_of;

use fixedbitset::FixedBitSet;
use succinct::{IntVec, IntVecMut, IntVector};

use filters::Filter;

/// Error that signals that the QuotientFilter is full.
#[derive(Debug)]
pub struct QuotientFilterFull;

/// TODO
/// Run: List of fingerprints with same quotient.
/// Cluster: set of runs
///
/// https://en.wikipedia.org/wiki/Quotient_filter
/// http://static.usenix.org/events/hotstorage11/tech/final_files/Bender.pdf
/// https://www.vldb.org/pvldb/vol5/p1627_michaelabender_vldb2012.pdf
#[derive(Debug)]
pub struct QuotientFilter<B = BuildHasherDefault<DefaultHasher>>
where
    B: BuildHasher + Clone + Eq,
{
    is_occupied: FixedBitSet,
    is_continuation: FixedBitSet,
    is_shifted: FixedBitSet,
    remainders: IntVector,
    bits_quotient: usize,
    bits_remainder: usize,
    buildhasher: B,
    n_elements: usize,
}

impl QuotientFilter {
    /// Create new quotient filter with:
    ///
    /// - `bits_quotient`: number of bits used for a quotient, aka `2^bits_quotient` slots will be
    ///   allocated
    /// - `bits_remainder`: number of bits used for the remainder, so every slot will require
    ///   `bits_remainder + 3` bits of storage
    ///
    /// and a default hasher.
    pub fn with_params(bits_quotient: usize, bits_remainder: usize) -> Self {
        let buildhasher = BuildHasherDefault::<DefaultHasher>::default();
        QuotientFilter::with_params_and_hash(bits_quotient, bits_remainder, buildhasher)
    }
}

impl<B> QuotientFilter<B>
where
    B: BuildHasher + Clone + Eq,
{
    /// Create new quotient filter with:
    ///
    /// - `bits_quotient`: number of bits used for a quotient, aka `2^bits_quotient` slots will be
    ///   allocated
    /// - `bits_remainder`: number of bits used for the remainder, so every slot will require
    ///   `bits_remainder + 3` bits of storage
    /// - `buildhasher`: hash implementation
    pub fn with_params_and_hash(
        bits_quotient: usize,
        bits_remainder: usize,
        buildhasher: B,
    ) -> Self {
        assert!(
            (bits_remainder > 0) && (bits_remainder <= size_of::<usize>() * 8),
            "bits_remainder ({}) must be greater than 0 and smaller or equal than {}",
            bits_remainder,
            size_of::<usize>() * 8,
        );
        assert!(
            bits_quotient > 0,
            "bits_quotient ({}) must be greater than 0",
            bits_quotient,
        );
        assert!(
            bits_remainder + bits_quotient <= 64,
            "bits_remainder ({}) + bits_quotient ({}) must be smaller or equal than 64",
            bits_remainder,
            bits_quotient,
        );

        let len = 1 << bits_quotient;
        Self {
            is_occupied: FixedBitSet::with_capacity(len),
            is_continuation: FixedBitSet::with_capacity(len),
            is_shifted: FixedBitSet::with_capacity(len),
            remainders: IntVector::with_fill(bits_remainder, len as u64, 0),
            bits_quotient,
            bits_remainder,
            buildhasher,
            n_elements: 0,
        }
    }

    /// Number of bits used for addressing slots.
    pub fn bits_quotient(&self) -> usize {
        self.bits_quotient
    }

    /// Number of bits stored as fingeprint information.
    pub fn bits_remainder(&self) -> usize {
        self.bits_remainder
    }

    fn calc_quotient_remainder<T>(&self, obj: &T) -> (usize, usize)
    where
        T: Hash,
    {
        let mut hasher = self.buildhasher.build_hasher();
        obj.hash(&mut hasher);
        let fingerprint = hasher.finish();
        let bits_trash = 64 - self.bits_remainder - self.bits_quotient;
        let trash = if bits_trash > 0 {
            (fingerprint >> (64 - bits_trash)) << (64 - bits_trash)
        } else {
            0
        };
        let fingerprint_clean = fingerprint - trash;
        let quotient = fingerprint_clean >> self.bits_remainder;
        let remainder = fingerprint_clean - (quotient << self.bits_remainder);
        (quotient as usize, remainder as usize)
    }

    fn decr(&self, pos: &mut usize) {
        *pos = if *pos == 0 {
            self.is_occupied.len() - 1
        } else {
            *pos - 1
        };
    }

    fn incr(&self, pos: &mut usize) {
        *pos = if *pos == self.is_occupied.len() - 1 {
            0
        } else {
            *pos + 1
        }
    }

    fn scan(
        &self,
        quotient: usize,
        remainder: usize,
        on_insert: bool,
    ) -> (bool, usize, bool, usize) {
        let run_exists = self.is_occupied[quotient];
        if (!run_exists) && (!on_insert) {
            // fast-path for query, since we don't need to find the correct position for the
            // insertion process
            return (run_exists, quotient, run_exists, quotient);
        }

        // walk back to find the beginning of the cluster
        let mut b = quotient;
        while self.is_shifted[b] {
            self.decr(&mut b);
        }

        // walk forward to find the actual start of the run
        let mut s = b;
        while b != quotient {
            // invariant: `s` poins to first slot of bucket `b`

            // skip all elements in the current run
            loop {
                self.incr(&mut s);
                if !self.is_continuation[s] {
                    break;
                }
            }

            // find the next occupied bucket
            loop {
                self.incr(&mut b);
                if self.is_occupied[b] || ((b == quotient) && on_insert) {
                    break;
                }
            }
        }
        // `s` now points to the first remainder in bucket at `quotient`

        // search of remainder within the run
        let start_of_run = s;
        if run_exists {
            loop {
                let r = self.remainders.get(s as u64);
                if r == remainder {
                    return (run_exists, s, run_exists, start_of_run);
                }
                if r > remainder {
                    // remainders are sorted within run
                    break;
                }
                self.incr(&mut s);
                if !self.is_continuation[s] {
                    break;
                }
            }
        }
        (false, s, run_exists, start_of_run)
    }
}

impl<B> Filter for QuotientFilter<B>
where
    B: BuildHasher + Clone + Eq,
{
    type InsertErr = QuotientFilterFull;

    fn clear(&mut self) {
        unimplemented!()
    }

    fn insert<T>(&mut self, t: &T) -> Result<(), Self::InsertErr>
    where
        T: Hash,
    {
        let (quotient, remainder) = self.calc_quotient_remainder(t);
        let (present, mut position, run_exists, start_of_run) =
            self.scan(quotient, remainder, true);

        // early exit if the element is already present
        if present {
            return Ok(());
        }
        // we need to insert the element into the filter

        // error out if there is no space left
        if self.n_elements == self.is_occupied.len() {
            return Err(QuotientFilterFull);
        }

        // set up swap chain
        let mut current_is_continuation =
            self.is_continuation[position] || (run_exists && (position == start_of_run));
        let mut current_remainder = self.remainders.get(position as u64);
        let mut current_used = self.is_occupied[position] || self.is_shifted[position];

        // set current state
        self.remainders.set(position as u64, remainder);
        if position != start_of_run {
            // might be an append operation, ensure is_continuation and is_shifted are set
            self.is_continuation.set(position, true);
        }
        if position != quotient {
            // not at canonical slot
            self.is_shifted.set(position, true);
        }

        // run swap chain until nothing to do
        let start = position;
        while current_used {
            self.incr(&mut position);
            let next_is_continuation = self.is_continuation[position];
            let next_remainder = self.remainders.get(position as u64);
            let next_used = self.is_occupied[position] || self.is_shifted[position];

            self.is_shifted.set(position, true);
            self.is_continuation.set(position, current_is_continuation);
            self.remainders.set(position as u64, current_remainder);

            current_is_continuation = next_is_continuation;
            current_remainder = next_remainder;
            current_used = next_used;

            if position == start {
                panic!("infinite loop detected");
            }
        }

        // mark canonical slot as occupied
        self.is_occupied.set(quotient, true);

        // done
        self.n_elements += 1;
        Ok(())
    }

    fn is_empty(&self) -> bool {
        self.n_elements == 0
    }

    fn len(&self) -> usize {
        self.n_elements
    }

    fn query<T>(&self, obj: &T) -> bool
    where
        T: Hash,
    {
        let (quotient, remainder) = self.calc_quotient_remainder(obj);
        let (present, _position, _run_exists, _start_of_run) =
            self.scan(quotient, remainder, false);
        present
    }
}

#[cfg(test)]
mod tests {
    use super::QuotientFilter;
    use filters::Filter;

    #[test]
    #[should_panic(expected = "bits_quotient (0) must be greater than 0")]
    fn new_bits_quotient_0() {
        QuotientFilter::with_params(0, 16);
    }

    #[cfg(target_pointer_width = "32")]
    #[test]
    #[should_panic(
        expected = "bits_remainder (0) must be greater than 0 and smaller or equal than 32"
    )]
    fn new_bits_remainder_0() {
        QuotientFilter::with_params(3, 0);
    }

    #[cfg(target_pointer_width = "64")]
    #[test]
    #[should_panic(
        expected = "bits_remainder (0) must be greater than 0 and smaller or equal than 64"
    )]
    fn new_bits_remainder_0() {
        QuotientFilter::with_params(3, 0);
    }

    #[cfg(target_pointer_width = "32")]
    #[test]
    #[should_panic(
        expected = "bits_remainder (33) must be greater than 0 and smaller or equal than 32"
    )]
    fn new_bits_remainder_too_large() {
        QuotientFilter::with_params(3, 33);
    }

    #[cfg(target_pointer_width = "64")]
    #[test]
    #[should_panic(
        expected = "bits_remainder (65) must be greater than 0 and smaller or equal than 64"
    )]
    fn new_bits_remainder_too_large() {
        QuotientFilter::with_params(3, 65);
    }

    #[test]
    #[should_panic(
        expected = "bits_remainder (5) + bits_quotient (60) must be smaller or equal than 64"
    )]
    fn new_too_many_bits() {
        QuotientFilter::with_params(60, 5);
    }

    #[test]
    fn new() {
        let qf = QuotientFilter::with_params(3, 16);
        assert!(qf.is_empty());
        assert_eq!(qf.len(), 0);
        assert!(!qf.query(&13));
        assert_eq!(qf.bits_quotient(), 3);
        assert_eq!(qf.bits_remainder(), 16);
    }

    #[test]
    fn insert() {
        let mut qf = QuotientFilter::with_params(3, 16);
        qf.insert(&13).unwrap();
        assert!(!qf.is_empty());
        assert_eq!(qf.len(), 1);
        assert!(qf.query(&13));
        assert!(!qf.query(&42));
    }

    #[test]
    fn double_insert() {
        let mut qf = QuotientFilter::with_params(3, 16);
        qf.insert(&13).unwrap();
        qf.insert(&13).unwrap();
        assert!(!qf.is_empty());
        assert_eq!(qf.len(), 1);
        assert!(qf.query(&13));
        assert!(!qf.query(&42));
    }

    #[test]
    fn full() {
        let mut qf = QuotientFilter::with_params(3, 16);
        for i in 0..8 {
            qf.insert(&i).unwrap();
            for j in 0..i {
                assert!(qf.query(&j), "Cannot find {} after inserting {}", j, i);
            }
        }
        assert!(qf.insert(&1000).is_err());
    }
}
<|endoftext|>


<commit_before>use protobuf_parse::ProtobufAbsPath;
use protobuf_parse::ProtobufRelPath;
use protobuf_parse::ProtobufRelPathRef;

use crate::compiler_plugin;
use crate::gen::code_writer::CodeWriter;
use crate::gen::paths::proto_path_to_rust_mod;

pub(crate) static WELL_KNOWN_TYPES_PROTO_FILE_NAMES: &[&str] = &[
    "any.proto",
    "api.proto",
    "duration.proto",
    "empty.proto",
    "field_mask.proto",
    "source_context.proto",
    "struct.proto",
    "timestamp.proto",
    "type.proto",
    "wrappers.proto",
];

pub(crate) static WELL_KNOWN_TYPES_PROTO_FILE_FULL_NAMES: &[&str] = &[
    "google/protobuf/any.proto",
    "google/protobuf/api.proto",
    "google/protobuf/duration.proto",
    "google/protobuf/empty.proto",
    "google/protobuf/field_mask.proto",
    "google/protobuf/source_context.proto",
    "google/protobuf/struct.proto",
    "google/protobuf/timestamp.proto",
    "google/protobuf/type.proto",
    "google/protobuf/wrappers.proto",
];

static NAMES: &'static [&'static str] = &[
    "Any",
    "Api",
    "BoolValue",
    "BytesValue",
    "DoubleValue",
    "Duration",
    "Empty",
    "Enum",
    "EnumValue",
    "Field",
    // TODO: dotted names
    "Field.Cardinality",
    "Field.Kind",
    "FieldMask",
    "FloatValue",
    "Int32Value",
    "Int64Value",
    "ListValue",
    "Method",
    "Mixin",
    "NullValue",
    "Option",
    "SourceContext",
    "StringValue",
    "Struct",
    "Syntax",
    "Timestamp",
    "Type",
    "UInt32Value",
    "UInt64Value",
    "Value",
];

fn is_well_known_type(name: &ProtobufRelPathRef) -> bool {
    NAMES.iter().any(|&n| n == format!("{}", name))
}

pub(crate) fn is_well_known_type_full(name: &ProtobufAbsPath) -> Option<ProtobufRelPath> {
    if let Some(rem) = name.remove_prefix(&ProtobufAbsPath::from(".google.protobuf")) {
        if is_well_known_type(rem) {
            Some(rem.to_owned())
        } else {
            None
        }
    } else {
        None
    }
}

pub(crate) fn gen_well_known_types_mod() -> compiler_plugin::GenResult {
    let v = CodeWriter::with_no_error(|w| {
        w.comment("This file is generated. Do not edit");
        w.comment("@generated");
        w.mod_doc("Generated code for \"well known types\"");
        w.mod_doc("");
        w.mod_doc("[This document](https://developers.google.com/protocol-buffers/docs/reference/google.protobuf) describes these types.");

        w.write_line("");
        w.write_line("#![allow(unused_attributes)]");
        w.write_line("#![cfg_attr(rustfmt, rustfmt::skip)]");

        w.write_line("");
        for m in WELL_KNOWN_TYPES_PROTO_FILE_NAMES {
            w.write_line(&format!("pub mod {};", proto_path_to_rust_mod(m)));
        }
    });

    compiler_plugin::GenResult {
        name: "well_known_types_mod.rs".to_string(),
        content: v.into_bytes(),
    }
}

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

    #[test]
    fn test_is_well_known_type_full() {
        assert_eq!(
            Some(ProtobufRelPath::from("BoolValue")),
            is_well_known_type_full(&ProtobufAbsPath::from(".google.protobuf.BoolValue"))
        );
        assert_eq!(
            None,
            is_well_known_type_full(&ProtobufAbsPath::from(".google.protobuf.Fgfg"))
        );
    }
}
<commit_msg>Outdated todo<commit_after>use protobuf_parse::ProtobufAbsPath;
use protobuf_parse::ProtobufRelPath;
use protobuf_parse::ProtobufRelPathRef;

use crate::compiler_plugin;
use crate::gen::code_writer::CodeWriter;
use crate::gen::paths::proto_path_to_rust_mod;

pub(crate) static WELL_KNOWN_TYPES_PROTO_FILE_NAMES: &[&str] = &[
    "any.proto",
    "api.proto",
    "duration.proto",
    "empty.proto",
    "field_mask.proto",
    "source_context.proto",
    "struct.proto",
    "timestamp.proto",
    "type.proto",
    "wrappers.proto",
];

pub(crate) static WELL_KNOWN_TYPES_PROTO_FILE_FULL_NAMES: &[&str] = &[
    "google/protobuf/any.proto",
    "google/protobuf/api.proto",
    "google/protobuf/duration.proto",
    "google/protobuf/empty.proto",
    "google/protobuf/field_mask.proto",
    "google/protobuf/source_context.proto",
    "google/protobuf/struct.proto",
    "google/protobuf/timestamp.proto",
    "google/protobuf/type.proto",
    "google/protobuf/wrappers.proto",
];

static NAMES: &'static [&'static str] = &[
    "Any",
    "Api",
    "BoolValue",
    "BytesValue",
    "DoubleValue",
    "Duration",
    "Empty",
    "Enum",
    "EnumValue",
    "Field",
    "Field.Cardinality",
    "Field.Kind",
    "FieldMask",
    "FloatValue",
    "Int32Value",
    "Int64Value",
    "ListValue",
    "Method",
    "Mixin",
    "NullValue",
    "Option",
    "SourceContext",
    "StringValue",
    "Struct",
    "Syntax",
    "Timestamp",
    "Type",
    "UInt32Value",
    "UInt64Value",
    "Value",
];

fn is_well_known_type(name: &ProtobufRelPathRef) -> bool {
    NAMES.iter().any(|&n| n == format!("{}", name))
}

pub(crate) fn is_well_known_type_full(name: &ProtobufAbsPath) -> Option<ProtobufRelPath> {
    if let Some(rem) = name.remove_prefix(&ProtobufAbsPath::from(".google.protobuf")) {
        if is_well_known_type(rem) {
            Some(rem.to_owned())
        } else {
            None
        }
    } else {
        None
    }
}

pub(crate) fn gen_well_known_types_mod() -> compiler_plugin::GenResult {
    let v = CodeWriter::with_no_error(|w| {
        w.comment("This file is generated. Do not edit");
        w.comment("@generated");
        w.mod_doc("Generated code for \"well known types\"");
        w.mod_doc("");
        w.mod_doc("[This document](https://developers.google.com/protocol-buffers/docs/reference/google.protobuf) describes these types.");

        w.write_line("");
        w.write_line("#![allow(unused_attributes)]");
        w.write_line("#![cfg_attr(rustfmt, rustfmt::skip)]");

        w.write_line("");
        for m in WELL_KNOWN_TYPES_PROTO_FILE_NAMES {
            w.write_line(&format!("pub mod {};", proto_path_to_rust_mod(m)));
        }
    });

    compiler_plugin::GenResult {
        name: "well_known_types_mod.rs".to_string(),
        content: v.into_bytes(),
    }
}

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

    #[test]
    fn test_is_well_known_type_full() {
        assert_eq!(
            Some(ProtobufRelPath::from("BoolValue")),
            is_well_known_type_full(&ProtobufAbsPath::from(".google.protobuf.BoolValue"))
        );
        assert_eq!(
            None,
            is_well_known_type_full(&ProtobufAbsPath::from(".google.protobuf.Fgfg"))
        );
    }
}
<|endoftext|>


<commit_before>use subframe;
use subframe::{Subframe, MAX_FIXED_ORDER, MAX_LPC_ORDER};

pub fn fixed_restore_signal(order: usize,
                            residual: &[i32],
                            output: &mut [i32]) {
  debug_assert!(order <= MAX_FIXED_ORDER);

  let polynomial = [ &[][..]
                   , &[1][..]
                   , &[-1, 2][..]
                   , &[1, -3, 3][..]
                   , &[-1, 4, -6, 4][..]
                   ];

  let coefficients = polynomial[order];

  for i in 0..residual.len() {
    let offset     = i + order;
    let prediction = coefficients.iter()
                      .zip(&output[i..offset])
                      .fold(0, |result, (coefficient, signal)|
                            result + coefficient * signal);

    output[offset] = residual[i] + prediction;
  }
}

pub fn lpc_restore_signal(quantization_level: i8,
                          coefficients: &[i32],
                          residual: &[i32],
                          output: &mut [i32]) {
  let order = coefficients.len();

  debug_assert!(order <= MAX_LPC_ORDER);

  for i in 0..residual.len() {
    let offset     = i + order;
    let prediction = coefficients.iter().rev()
                       .zip(&output[i..offset])
                       .fold(0, |result, (coefficient, signal)|
                             result + coefficient * signal);

    output[offset] = residual[i] + (prediction >> quantization_level);
  }
}

pub fn decode(subframe: &Subframe, output: &mut [i32]) {
  match subframe.data {
    subframe::Data::Constant(_)      => unimplemented!(),
    subframe::Data::Verbatim(_)      => unimplemented!(),
    subframe::Data::Fixed(ref fixed) => {
      let order = fixed.order as usize;

      for i in 0..order {
        output[i] = fixed.warmup[i];
      }

      fixed_restore_signal(order, &fixed.residual, output);
    }
    subframe::Data::LPC(ref lpc)     => {
      let order        = lpc.order as usize;
      let coefficients = &lpc.qlp_coefficients[0..order];

      for i in 0..order {
        output[i] = lpc.warmup[i];
      }

      lpc_restore_signal(lpc.quantization_level, coefficients, &lpc.residual,
                         output);
    }
  }

  if subframe.wasted_bits > 0 {
    for value in output {
      *value <<= subframe.wasted_bits;
    }
  }
}
<commit_msg>Add functionality for `Constant` subframe decoding<commit_after>use subframe;
use subframe::{Subframe, MAX_FIXED_ORDER, MAX_LPC_ORDER};

pub fn fixed_restore_signal(order: usize,
                            residual: &[i32],
                            output: &mut [i32]) {
  debug_assert!(order <= MAX_FIXED_ORDER);

  let polynomial = [ &[][..]
                   , &[1][..]
                   , &[-1, 2][..]
                   , &[1, -3, 3][..]
                   , &[-1, 4, -6, 4][..]
                   ];

  let coefficients = polynomial[order];

  for i in 0..residual.len() {
    let offset     = i + order;
    let prediction = coefficients.iter()
                      .zip(&output[i..offset])
                      .fold(0, |result, (coefficient, signal)|
                            result + coefficient * signal);

    output[offset] = residual[i] + prediction;
  }
}

pub fn lpc_restore_signal(quantization_level: i8,
                          coefficients: &[i32],
                          residual: &[i32],
                          output: &mut [i32]) {
  let order = coefficients.len();

  debug_assert!(order <= MAX_LPC_ORDER);

  for i in 0..residual.len() {
    let offset     = i + order;
    let prediction = coefficients.iter().rev()
                       .zip(&output[i..offset])
                       .fold(0, |result, (coefficient, signal)|
                             result + coefficient * signal);

    output[offset] = residual[i] + (prediction >> quantization_level);
  }
}

pub fn decode(subframe: &Subframe, output: &mut [i32]) {
  match subframe.data {
    subframe::Data::Constant(constant) => {
      for i in 0..output.len() {
        output[i] = constant
      }
    }
    subframe::Data::Verbatim(_)        => unimplemented!(),
    subframe::Data::Fixed(ref fixed)   => {
      let order = fixed.order as usize;

      for i in 0..order {
        output[i] = fixed.warmup[i];
      }

      fixed_restore_signal(order, &fixed.residual, output);
    }
    subframe::Data::LPC(ref lpc)       => {
      let order        = lpc.order as usize;
      let coefficients = &lpc.qlp_coefficients[0..order];

      for i in 0..order {
        output[i] = lpc.warmup[i];
      }

      lpc_restore_signal(lpc.quantization_level, coefficients, &lpc.residual,
                         output);
    }
  }

  if subframe.wasted_bits > 0 {
    for value in output {
      *value <<= subframe.wasted_bits;
    }
  }
}
<|endoftext|>


<commit_before>use std::prelude::v1::*;
use std::cell::Cell;
use std::fmt;

thread_local!(static ENTERED: Cell<bool> = Cell::new(false));

/// Represents an executor context.
///
/// For more details, see [`enter` documentation](::enter())
pub struct Enter {
    _a: ()
}

/// An error returned by `enter` if an execution scope has already been
/// entered.
#[derive(Debug)]
pub struct EnterError {
    _a: (),
}

/// Marks the current thread as being within the dynamic extent of an
/// executor.
///
/// Executor implementations should call this function before beginning to
/// execute any tasks. Doing so ensures that executors aren't accidentally
/// invoked in a nested fashion.
///
/// # Error
///
/// Returns an error if the current thread is already marked, in which case the
/// caller should panic with a tailored error message.
pub fn enter() -> Result<Enter, EnterError> {
    ENTERED.with(|c| {
        if c.get() {
            Err(EnterError { _a: () })
        } else {
            c.set(true);

            Ok(Enter { _a: () })
        }
    })
}

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

impl Drop for Enter {
    fn drop(&mut self) {
        ENTERED.with(|c| {
            assert!(c.get());
            c.set(false);
        });
    }
}
<commit_msg>Revise `enter` docs<commit_after>use std::prelude::v1::*;
use std::cell::Cell;
use std::fmt;

thread_local!(static ENTERED: Cell<bool> = Cell::new(false));

/// Represents an executor context.
///
/// For more details, see [`enter` documentation](::enter())
pub struct Enter {
    _a: ()
}

/// An error returned by `enter` if an execution scope has already been
/// entered.
#[derive(Debug)]
pub struct EnterError {
    _a: (),
}

/// Marks the current thread as being within the dynamic extent of an
/// executor.
///
/// Executor implementations should call this function before beginning to
/// execute a tasks, and drop the returned [`Enter`](Enter) value after
/// completing task execution:
///
/// ```rust
/// # extern crate futures;
/// # use futures::executor::enter;
///
/// # fn main() {
/// let enter = enter().expect("...");
/// /* run task */
/// drop(enter);
/// # }
/// ```
///
/// Doing so ensures that executors aren't
/// accidentally invoked in a nested fashion.
///
/// # Error
///
/// Returns an error if the current thread is already marked, in which case the
/// caller should panic with a tailored error message.
pub fn enter() -> Result<Enter, EnterError> {
    ENTERED.with(|c| {
        if c.get() {
            Err(EnterError { _a: () })
        } else {
            c.set(true);

            Ok(Enter { _a: () })
        }
    })
}

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

impl Drop for Enter {
    fn drop(&mut self) {
        ENTERED.with(|c| {
            assert!(c.get());
            c.set(false);
        });
    }
}
<|endoftext|>