<commit_before>extern crate byteorder;
extern crate tempfile;
#[macro_use]
extern crate wayland_client;
#[macro_use]
extern crate wlroots;

use std::thread;
use std::time::Duration;

use wlroots::{matrix_mul, matrix_rotate, matrix_scale, matrix_translate, Area, Compositor,
              CompositorBuilder, CursorBuilder, InputManagerHandler, Keyboard, KeyboardHandler,
              Origin, Output, OutputBuilder, OutputBuilderResult, OutputHandler, OutputLayout,
              OutputManagerHandler, Pointer, PointerHandler, Renderer, Size, Surface,
              WlShellHandler, WlShellManagerHandler, WlShellSurface, WlShellSurfaceHandle,
              XCursorTheme};
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,
    shells: Vec<WlShellSurfaceHandle>
}

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

compositor_data!(State);

struct WlShellHandlerEx;
struct WlShellManager;

impl WlShellHandler for WlShellHandlerEx {}
impl WlShellManagerHandler for WlShellManager {
    fn new_surface(&mut self,
                   compositor: &mut Compositor,
                   shell: &mut WlShellSurface,
                   _: &mut Surface)
                   -> Option<Box<WlShellHandler>> {
        let state: &mut State = compositor.into();
        state.shells.push(shell.weak_reference());
        Some(Box::new(WlShellHandlerEx))
    }
}

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 cursor = &mut state.layout.cursors()[0];
        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()
            }
            // TODO This is a dumb way to compare these values
            else if key_event.key_state() as u32 == 1 {
                thread::spawn(move || {
                    use byteorder::{NativeEndian, WriteBytesExt};
                    use std::cmp::min;
                    use std::io::Write;
                    use std::os::unix::io::AsRawFd;
                    use wayland_client::EnvHandler;
                    use wayland_client::protocol::{wl_compositor, wl_pointer, wl_seat, wl_shell,
                                                   wl_shell_surface, wl_shm};

                    wayland_env!(WaylandEnv,
                                 compositor: wl_compositor::WlCompositor,
                                 seat: wl_seat::WlSeat,
                                 shell: wl_shell::WlShell,
                                 shm: wl_shm::WlShm);

                    fn pointer_impl() -> wl_pointer::Implementation<()> {
                        wl_pointer::Implementation {
                            enter: |_, _, _pointer, _serial, _surface, x, y| {
                                println!("Pointer entered surface at ({},{}).", x, y);
                            },
                            leave: |_, _, _pointer, _serial, _surface| {
                                println!("Pointer left surface.");
                            },
                            motion: |_, _, _pointer, _time, x, y| {
                                println!("Pointer moved to ({},{}).", x, y);
                            },
                            button: |_, _, _pointer, _serial, _time, button, state| {
                                println!(
                                    "Button {} ({}) was {:?}.",
                                    match button {
                                        272 => "Left",
                                        273 => "Right",
                                        274 => "Middle",
                                        _ => "Unknown",
                                    },
                                    button,
                                    state
                                );
                            },
                            axis: |_, _, _, _, _, _| { /* not used in this example */ },
                            frame: |_, _, _| { /* not used in this example */ },
                            axis_source: |_, _, _, _| { /* not used in this example */ },
                            axis_discrete: |_, _, _, _, _| { /* not used in this example */ },
                            axis_stop: |_, _, _, _, _| { /* not used in this example */ },
                        }
                    }

                    fn shell_surface_impl() -> wl_shell_surface::Implementation<()> {
                        wl_shell_surface::Implementation { ping: |_, _, shell_surface, serial| {
                                                               shell_surface.pong(serial);
                                                           },
                                                           configure: |_, _, _, _, _, _| {
                                                               /* not used in this example */
                                                           },
                                                           popup_done: |_, _, _| {
                                                               /* not used in this example */
                                                           } }
                    }

                    let (display, mut event_queue) = match wayland_client::default_connect() {
                        Ok(ret) => ret,
                        Err(e) => panic!("Cannot connect to wayland server: {:?}", e)
                    };

                    let registry = display.get_registry();

                    let env_token = EnvHandler::<WaylandEnv>::init(&mut event_queue, &registry);

                    event_queue.sync_roundtrip().unwrap();

                    // buffer (and window) width and height
                    let buf_x: u32 = 320;
                    let buf_y: u32 = 240;

                    // create a tempfile to write the conents of the window on
                    let mut tmp = tempfile::tempfile().ok()
                                                      .expect("Unable to create a tempfile.");
                    // write the contents to it, lets put a nice color gradient
                    for i in 0..(buf_x * buf_y) {
                        let x = (i % buf_x) as u32;
                        let y = (i / buf_x) as u32;
                        let r: u32 =
                            min(((buf_x - x) * 0xFF) / buf_x, ((buf_y - y) * 0xFF) / buf_y);
                        let g: u32 = min((x * 0xFF) / buf_x, ((buf_y - y) * 0xFF) / buf_y);
                        let b: u32 = min(((buf_x - x) * 0xFF) / buf_x, (y * 0xFF) / buf_y);
                        let _ =
                            tmp.write_u32::<NativeEndian>((0xFF << 24) + (r << 16) + (g << 8) + b);
                    }
                    let _ = tmp.flush();

                    // retrieve the env
                    let env = event_queue.state().get(&env_token).clone_inner().unwrap();

                    // prepare the wayland surface
                    let surface = env.compositor.create_surface();
                    let shell_surface = env.shell.get_shell_surface(&surface);

                    let pool = env.shm.create_pool(tmp.as_raw_fd(), (buf_x * buf_y * 4) as i32);
                    // match a buffer on the part we wrote on
                    let buffer = pool.create_buffer(
                        0,
                        buf_x as i32,
                        buf_y as i32,
                        (buf_x * 4) as i32,
                        wl_shm::Format::Argb8888,
                    ).expect("The pool cannot be already dead");

                    // make our surface as a toplevel one
                    shell_surface.set_toplevel();
                    // attach the buffer to it
                    surface.attach(Some(&buffer), 0, 0);
                    // commit
                    surface.commit();

                    let pointer = env.seat.get_pointer()
                                     .expect("Seat cannot be already destroyed.");

                    event_queue.register(&shell_surface, shell_surface_impl(), ());
                    event_queue.register(&pointer, pointer_impl(), ());

                    loop {
                        display.flush().unwrap();
                        event_queue.dispatch().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.cursors()[0].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 renderer = compositor.renderer
                                 .as_mut()
                                 .expect("Compositor was not loaded with a renderer");
        let state: &mut State = compositor.data.downcast_mut().unwrap();
        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().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");

    layout.attach_cursor(cursor);
    let compositor = CompositorBuilder::new().gles2(true)
                                             .build_auto(State::new(xcursor_theme, layout),
                                                         Some(Box::new(InputManager)),
                                                         Some(Box::new(OutputManager)),
                                                         Some(Box::new(WlShellManager)));
    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>Fix wl_shell_test so it works again w/ seat<commit_after>extern crate byteorder;
extern crate tempfile;
#[macro_use]
extern crate wayland_client;
#[macro_use]
extern crate wlroots;

use std::thread;
use std::time::Duration;

use wlroots::{matrix_mul, matrix_rotate, matrix_scale, matrix_translate, Area, Compositor,
              CompositorBuilder, CursorBuilder, InputManagerHandler, Keyboard, KeyboardHandler,
              Origin, Output, OutputBuilder, OutputBuilderResult, OutputHandler, OutputLayout,
              OutputManagerHandler, Pointer, PointerHandler, Renderer, Seat, SeatHandler, Size,
              Surface, WlShellHandler, WlShellManagerHandler, WlShellSurface,
              WlShellSurfaceHandle, XCursorTheme};
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,
    shells: Vec<WlShellSurfaceHandle>,
    seat: Option<Seat>
}

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

compositor_data!(State);

struct SeatHandlerEx;

impl SeatHandler for SeatHandlerEx {
    // TODO
}

struct WlShellHandlerEx;
struct WlShellManager;

impl WlShellHandler for WlShellHandlerEx {}
impl WlShellManagerHandler for WlShellManager {
    fn new_surface(&mut self,
                   compositor: &mut Compositor,
                   shell: &mut WlShellSurface,
                   _: &mut Surface)
                   -> Option<Box<WlShellHandler>> {
        let state: &mut State = compositor.into();
        state.shells.push(shell.weak_reference());
        Some(Box::new(WlShellHandlerEx))
    }
}

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 cursor = &mut state.layout.cursors()[0];
        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()
            }
            // TODO This is a dumb way to compare these values
            else if key_event.key_state() as u32 == 1 {
                thread::spawn(move || {
                    use byteorder::{NativeEndian, WriteBytesExt};
                    use std::cmp::min;
                    use std::io::Write;
                    use std::os::unix::io::AsRawFd;
                    use wayland_client::EnvHandler;
                    use wayland_client::protocol::{wl_compositor, wl_pointer, wl_seat, wl_shell,
                                                   wl_shell_surface, wl_shm};

                    wayland_env!(WaylandEnv,
                                 compositor: wl_compositor::WlCompositor,
                                 seat: wl_seat::WlSeat,
                                 shell: wl_shell::WlShell,
                                 shm: wl_shm::WlShm);

                    fn pointer_impl() -> wl_pointer::Implementation<()> {
                        wl_pointer::Implementation {
                            enter: |_, _, _pointer, _serial, _surface, x, y| {
                                println!("Pointer entered surface at ({},{}).", x, y);
                            },
                            leave: |_, _, _pointer, _serial, _surface| {
                                println!("Pointer left surface.");
                            },
                            motion: |_, _, _pointer, _time, x, y| {
                                println!("Pointer moved to ({},{}).", x, y);
                            },
                            button: |_, _, _pointer, _serial, _time, button, state| {
                                println!(
                                    "Button {} ({}) was {:?}.",
                                    match button {
                                        272 => "Left",
                                        273 => "Right",
                                        274 => "Middle",
                                        _ => "Unknown",
                                    },
                                    button,
                                    state
                                );
                            },
                            axis: |_, _, _, _, _, _| { /* not used in this example */ },
                            frame: |_, _, _| { /* not used in this example */ },
                            axis_source: |_, _, _, _| { /* not used in this example */ },
                            axis_discrete: |_, _, _, _, _| { /* not used in this example */ },
                            axis_stop: |_, _, _, _, _| { /* not used in this example */ },
                        }
                    }

                    fn shell_surface_impl() -> wl_shell_surface::Implementation<()> {
                        wl_shell_surface::Implementation { ping: |_, _, shell_surface, serial| {
                                                               shell_surface.pong(serial);
                                                           },
                                                           configure: |_, _, _, _, _, _| {
                                                               /* not used in this example */
                                                           },
                                                           popup_done: |_, _, _| {
                                                               /* not used in this example */
                                                           } }
                    }

                    let (display, mut event_queue) = match wayland_client::default_connect() {
                        Ok(ret) => ret,
                        Err(e) => panic!("Cannot connect to wayland server: {:?}", e)
                    };

                    let registry = display.get_registry();

                    let env_token = EnvHandler::<WaylandEnv>::init(&mut event_queue, &registry);

                    event_queue.sync_roundtrip().unwrap();

                    // buffer (and window) width and height
                    let buf_x: u32 = 320;
                    let buf_y: u32 = 240;

                    // create a tempfile to write the conents of the window on
                    let mut tmp = tempfile::tempfile().ok()
                                                      .expect("Unable to create a tempfile.");
                    // write the contents to it, lets put a nice color gradient
                    for i in 0..(buf_x * buf_y) {
                        let x = (i % buf_x) as u32;
                        let y = (i / buf_x) as u32;
                        let r: u32 =
                            min(((buf_x - x) * 0xFF) / buf_x, ((buf_y - y) * 0xFF) / buf_y);
                        let g: u32 = min((x * 0xFF) / buf_x, ((buf_y - y) * 0xFF) / buf_y);
                        let b: u32 = min(((buf_x - x) * 0xFF) / buf_x, (y * 0xFF) / buf_y);
                        let _ =
                            tmp.write_u32::<NativeEndian>((0xFF << 24) + (r << 16) + (g << 8) + b);
                    }
                    let _ = tmp.flush();

                    // retrieve the env
                    let env = event_queue.state().get(&env_token).clone_inner().unwrap();

                    // prepare the wayland surface
                    let surface = env.compositor.create_surface();
                    let shell_surface = env.shell.get_shell_surface(&surface);

                    let pool = env.shm.create_pool(tmp.as_raw_fd(), (buf_x * buf_y * 4) as i32);
                    // match a buffer on the part we wrote on
                    let buffer = pool.create_buffer(
                        0,
                        buf_x as i32,
                        buf_y as i32,
                        (buf_x * 4) as i32,
                        wl_shm::Format::Argb8888,
                    ).expect("The pool cannot be already dead");

                    // make our surface as a toplevel one
                    shell_surface.set_toplevel();
                    // attach the buffer to it
                    surface.attach(Some(&buffer), 0, 0);
                    // commit
                    surface.commit();

                    let pointer = env.seat.get_pointer()
                                     .expect("Seat cannot be already destroyed.");

                    event_queue.register(&shell_surface, shell_surface_impl(), ());
                    event_queue.register(&pointer, pointer_impl(), ());

                    loop {
                        display.flush().unwrap();
                        event_queue.dispatch().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.cursors()[0].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 renderer = compositor.renderer
                                 .as_mut()
                                 .expect("Compositor was not loaded with a renderer");
        let state: &mut State = compositor.data.downcast_mut().unwrap();
        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().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");

    layout.attach_cursor(cursor);
    let mut compositor = CompositorBuilder::new().gles2(true)
                                                 .build_auto(State::new(xcursor_theme, layout),
                                                             Some(Box::new(InputManager)),
                                                             Some(Box::new(OutputManager)),
                                                             Some(Box::new(WlShellManager)));
    let seat = Seat::new(&mut compositor, "Main Seat".into(), Box::new(SeatHandlerEx))
        .expect("Could not allocate the global seat");
    {
        let state: &mut State = (&mut compositor).into();
        state.seat = Some(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 {ErrorCode, IndyHandle};

use std::ffi::CString;
use std::time::Duration;

use utils::callbacks::ClosureHandler;
use utils::results::ResultHandler;

use ffi::pairwise;
use ffi::{ResponseEmptyCB,
          ResponseStringCB,
          ResponseBoolCB};

pub struct Pairwise {}

impl Pairwise {
    pub fn does_exist(wallet_handle: IndyHandle, their_did: &str) -> Result<bool, ErrorCode> {
        let (receiver, command_handle, cb) = ClosureHandler::cb_ec_bool();

        let err = Pairwise::_does_exist(command_handle, wallet_handle, their_did, cb);

        ResultHandler::one(err, receiver)
    }

    /// * `timeout` - the maximum time this function waits for a response
    pub fn does_exist_timeout(wallet_handle: IndyHandle, their_did: &str, timeout: Duration) -> Result<bool, ErrorCode> {
        let (receiver, command_handle, cb) = ClosureHandler::cb_ec_bool();

        let err = Pairwise::_does_exist(command_handle, wallet_handle, their_did, cb);

        ResultHandler::one_timeout(err, receiver, timeout)
    }

    /// * `closure` - the closure that is called when finished
    ///
    /// # Returns
    /// * `errorcode` - errorcode from calling ffi function. The closure receives the return result
    pub fn does_exist_async<F: 'static>(wallet_handle: IndyHandle, their_did: &str, closure: F) -> ErrorCode where F: FnMut(ErrorCode, bool) + Send {
        let (command_handle, cb) = ClosureHandler::convert_cb_ec_bool(Box::new(closure));

        Pairwise::_does_exist(command_handle, wallet_handle, their_did, cb)
    }

    fn _does_exist(command_handle: IndyHandle, wallet_handle: IndyHandle, their_did: &str, cb: Option<ResponseBoolCB>) -> ErrorCode {
        let their_did = c_str!(their_did);

        ErrorCode::from(unsafe {
            pairwise::indy_is_pairwise_exists(command_handle, wallet_handle, their_did.as_ptr(), cb)
        })
    }

    pub fn create(wallet_handle: IndyHandle, their_did: &str, my_did: &str, metadata: Option<&str>) -> Result<(), ErrorCode> {
        let (receiver, command_handle, cb) = ClosureHandler::cb_ec();

        let err = Pairwise::_create(command_handle, wallet_handle, their_did, my_did, metadata, cb);

        ResultHandler::empty(err, receiver)
    }

    /// * `timeout` - the maximum time this function waits for a response
    pub fn create_timeout(wallet_handle: IndyHandle, their_did: &str, my_did: &str, metadata: Option<&str>, timeout: Duration) -> Result<(), ErrorCode> {
        let (receiver, command_handle, cb) = ClosureHandler::cb_ec();

        let err = Pairwise::_create(command_handle, wallet_handle, their_did, my_did, metadata, cb);

        ResultHandler::empty_timeout(err, receiver, timeout)
    }

    /// * `closure` - the closure that is called when finished
    ///
    /// # Returns
    /// * `errorcode` - errorcode from calling ffi function. The closure receives the return result
    pub fn create_async<F: 'static>(wallet_handle: IndyHandle, their_did: &str, my_did: &str, metadata: Option<&str>, closure: F) -> ErrorCode where F: FnMut(ErrorCode) + Send {
        let (command_handle, cb) = ClosureHandler::convert_cb_ec(Box::new(closure));

        Pairwise::_create(command_handle, wallet_handle, their_did, my_did, metadata, cb)
    }

    fn _create(command_handle: IndyHandle, wallet_handle: IndyHandle, their_did: &str, my_did: &str, metadata: Option<&str>, cb: Option<ResponseEmptyCB>) -> ErrorCode {
        let their_did = c_str!(their_did);
        let my_did = c_str!(my_did);
        let metadata_str = opt_c_str!(metadata);

        ErrorCode::from(unsafe {
            pairwise::indy_create_pairwise(command_handle, wallet_handle, their_did.as_ptr(), my_did.as_ptr(), opt_c_ptr!(metadata, metadata_str), cb)
        })
    }

    pub fn list(wallet_handle: IndyHandle) -> Result<String, ErrorCode> {
        let (receiver, command_handle, cb) = ClosureHandler::cb_ec_string();

        let err = Pairwise::_list(command_handle, wallet_handle, cb);

        ResultHandler::one(err, receiver)
    }

    /// * `timeout` - the maximum time this function waits for a response
    pub fn list_timeout(wallet_handle: IndyHandle, timeout: Duration) -> Result<String, ErrorCode> {
        let (receiver, command_handle, cb) = ClosureHandler::cb_ec_string();

        let err = Pairwise::_list(command_handle, wallet_handle, cb);

        ResultHandler::one_timeout(err, receiver, timeout)
    }

    /// * `closure` - the closure that is called when finished
    ///
    /// # Returns
    /// * `errorcode` - errorcode from calling ffi function. The closure receives the return result
    pub fn list_async<F: 'static>(wallet_handle: IndyHandle, closure: F) -> ErrorCode where F: FnMut(ErrorCode, String) + Send {
        let (command_handle, cb) = ClosureHandler::convert_cb_ec_string(Box::new(closure));

        Pairwise::_list(command_handle, wallet_handle, cb)
    }

    fn _list(command_handle: IndyHandle, wallet_handle: IndyHandle, cb: Option<ResponseStringCB>) -> ErrorCode {
        ErrorCode::from(unsafe {
            pairwise::indy_list_pairwise(command_handle, wallet_handle, cb)
        })
    }

    pub fn get(wallet_handle: IndyHandle, their_did: &str) -> Result<String, ErrorCode> {
        let (receiver, command_handle, cb) = ClosureHandler::cb_ec_string();

        let err = Pairwise::_get(command_handle, wallet_handle, their_did, cb);

        ResultHandler::one(err, receiver)
    }

    /// * `timeout` - the maximum time this function waits for a response
    pub fn get_timeout(wallet_handle: IndyHandle, their_did: &str, timeout: Duration) -> Result<String, ErrorCode> {
        let (receiver, command_handle, cb) = ClosureHandler::cb_ec_string();

        let err = Pairwise::_get(command_handle, wallet_handle, their_did, cb);

        ResultHandler::one_timeout(err, receiver, timeout)
    }

    /// * `closure` - the closure that is called when finished
    ///
    /// # Returns
    /// * `errorcode` - errorcode from calling ffi function. The closure receives the return result
    pub fn get_async<F: 'static>(wallet_handle: IndyHandle, their_did: &str, closure: F) -> ErrorCode where F: FnMut(ErrorCode, String) + Send {
        let (command_handle, cb) = ClosureHandler::convert_cb_ec_string(Box::new(closure));

        Pairwise::_get(command_handle, wallet_handle, their_did, cb)
    }

    fn _get(command_handle: IndyHandle, wallet_handle: IndyHandle, their_did: &str, cb: Option<ResponseStringCB>) -> ErrorCode {
        let their_did = c_str!(their_did);

        ErrorCode::from(unsafe {
            pairwise::indy_get_pairwise(command_handle, wallet_handle, their_did.as_ptr(), cb)
        })
    }

    pub fn set_metadata(wallet_handle: IndyHandle, their_did: &str, metadata: Option<&str>) -> Result<(), ErrorCode> {
        let (receiver, command_handle, cb) = ClosureHandler::cb_ec();

        let err = Pairwise::_set_metadata(command_handle, wallet_handle, their_did, metadata, cb);

        ResultHandler::empty(err, receiver)
    }

    /// * `timeout` - the maximum time this function waits for a response
    pub fn set_metadata_timeout(wallet_handle: IndyHandle, their_did: &str, metadata: Option<&str>, timeout: Duration) -> Result<(), ErrorCode> {
        let (receiver, command_handle, cb) = ClosureHandler::cb_ec();

        let err = Pairwise::_set_metadata(command_handle, wallet_handle, their_did, metadata, cb);

        ResultHandler::empty_timeout(err, receiver, timeout)
    }

    /// * `closure` - the closure that is called when finished
    ///
    /// # Returns
    /// * `errorcode` - errorcode from calling ffi function. The closure receives the return result
    pub fn set_metadata_async<F: 'static>(wallet_handle: IndyHandle, their_did: &str, metadata: Option<&str>, closure: F) -> ErrorCode where F: FnMut(ErrorCode) + Send {
        let (command_handle, cb) = ClosureHandler::convert_cb_ec(Box::new(closure));

        Pairwise::_set_metadata(command_handle, wallet_handle, their_did, metadata, cb)
    }

    fn _set_metadata(command_handle: IndyHandle, wallet_handle: IndyHandle, their_did: &str, metadata: Option<&str>, cb: Option<ResponseEmptyCB>) -> ErrorCode {
        let their_did = c_str!(their_did);
        let metadata_str = opt_c_str!(metadata);

        ErrorCode::from(unsafe {
            pairwise::indy_set_pairwise_metadata(command_handle, wallet_handle, their_did.as_ptr(), opt_c_ptr!(metadata, metadata_str), cb)
        })
    }
}
<commit_msg>Fix bug<commit_after>use {ErrorCode, IndyHandle};

use std::ffi::CString;
use std::time::Duration;
use std::ptr::null;

use utils::callbacks::ClosureHandler;
use utils::results::ResultHandler;

use ffi::pairwise;
use ffi::{ResponseEmptyCB,
          ResponseStringCB,
          ResponseBoolCB};

pub struct Pairwise {}

impl Pairwise {
    pub fn does_exist(wallet_handle: IndyHandle, their_did: &str) -> Result<bool, ErrorCode> {
        let (receiver, command_handle, cb) = ClosureHandler::cb_ec_bool();

        let err = Pairwise::_does_exist(command_handle, wallet_handle, their_did, cb);

        ResultHandler::one(err, receiver)
    }

    /// * `timeout` - the maximum time this function waits for a response
    pub fn does_exist_timeout(wallet_handle: IndyHandle, their_did: &str, timeout: Duration) -> Result<bool, ErrorCode> {
        let (receiver, command_handle, cb) = ClosureHandler::cb_ec_bool();

        let err = Pairwise::_does_exist(command_handle, wallet_handle, their_did, cb);

        ResultHandler::one_timeout(err, receiver, timeout)
    }

    /// * `closure` - the closure that is called when finished
    ///
    /// # Returns
    /// * `errorcode` - errorcode from calling ffi function. The closure receives the return result
    pub fn does_exist_async<F: 'static>(wallet_handle: IndyHandle, their_did: &str, closure: F) -> ErrorCode where F: FnMut(ErrorCode, bool) + Send {
        let (command_handle, cb) = ClosureHandler::convert_cb_ec_bool(Box::new(closure));

        Pairwise::_does_exist(command_handle, wallet_handle, their_did, cb)
    }

    fn _does_exist(command_handle: IndyHandle, wallet_handle: IndyHandle, their_did: &str, cb: Option<ResponseBoolCB>) -> ErrorCode {
        let their_did = c_str!(their_did);

        ErrorCode::from(unsafe {
            pairwise::indy_is_pairwise_exists(command_handle, wallet_handle, their_did.as_ptr(), cb)
        })
    }

    pub fn create(wallet_handle: IndyHandle, their_did: &str, my_did: &str, metadata: Option<&str>) -> Result<(), ErrorCode> {
        let (receiver, command_handle, cb) = ClosureHandler::cb_ec();

        let err = Pairwise::_create(command_handle, wallet_handle, their_did, my_did, metadata, cb);

        ResultHandler::empty(err, receiver)
    }

    /// * `timeout` - the maximum time this function waits for a response
    pub fn create_timeout(wallet_handle: IndyHandle, their_did: &str, my_did: &str, metadata: Option<&str>, timeout: Duration) -> Result<(), ErrorCode> {
        let (receiver, command_handle, cb) = ClosureHandler::cb_ec();

        let err = Pairwise::_create(command_handle, wallet_handle, their_did, my_did, metadata, cb);

        ResultHandler::empty_timeout(err, receiver, timeout)
    }

    /// * `closure` - the closure that is called when finished
    ///
    /// # Returns
    /// * `errorcode` - errorcode from calling ffi function. The closure receives the return result
    pub fn create_async<F: 'static>(wallet_handle: IndyHandle, their_did: &str, my_did: &str, metadata: Option<&str>, closure: F) -> ErrorCode where F: FnMut(ErrorCode) + Send {
        let (command_handle, cb) = ClosureHandler::convert_cb_ec(Box::new(closure));

        Pairwise::_create(command_handle, wallet_handle, their_did, my_did, metadata, cb)
    }

    fn _create(command_handle: IndyHandle, wallet_handle: IndyHandle, their_did: &str, my_did: &str, metadata: Option<&str>, cb: Option<ResponseEmptyCB>) -> ErrorCode {
        let their_did = c_str!(their_did);
        let my_did = c_str!(my_did);
        let metadata_str = opt_c_str!(metadata);

        ErrorCode::from(unsafe {
            pairwise::indy_create_pairwise(command_handle, wallet_handle, their_did.as_ptr(), my_did.as_ptr(), opt_c_ptr!(metadata, metadata_str), cb)
        })
    }

    pub fn list(wallet_handle: IndyHandle) -> Result<String, ErrorCode> {
        let (receiver, command_handle, cb) = ClosureHandler::cb_ec_string();

        let err = Pairwise::_list(command_handle, wallet_handle, cb);

        ResultHandler::one(err, receiver)
    }

    /// * `timeout` - the maximum time this function waits for a response
    pub fn list_timeout(wallet_handle: IndyHandle, timeout: Duration) -> Result<String, ErrorCode> {
        let (receiver, command_handle, cb) = ClosureHandler::cb_ec_string();

        let err = Pairwise::_list(command_handle, wallet_handle, cb);

        ResultHandler::one_timeout(err, receiver, timeout)
    }

    /// * `closure` - the closure that is called when finished
    ///
    /// # Returns
    /// * `errorcode` - errorcode from calling ffi function. The closure receives the return result
    pub fn list_async<F: 'static>(wallet_handle: IndyHandle, closure: F) -> ErrorCode where F: FnMut(ErrorCode, String) + Send {
        let (command_handle, cb) = ClosureHandler::convert_cb_ec_string(Box::new(closure));

        Pairwise::_list(command_handle, wallet_handle, cb)
    }

    fn _list(command_handle: IndyHandle, wallet_handle: IndyHandle, cb: Option<ResponseStringCB>) -> ErrorCode {
        ErrorCode::from(unsafe {
            pairwise::indy_list_pairwise(command_handle, wallet_handle, cb)
        })
    }

    pub fn get(wallet_handle: IndyHandle, their_did: &str) -> Result<String, ErrorCode> {
        let (receiver, command_handle, cb) = ClosureHandler::cb_ec_string();

        let err = Pairwise::_get(command_handle, wallet_handle, their_did, cb);

        ResultHandler::one(err, receiver)
    }

    /// * `timeout` - the maximum time this function waits for a response
    pub fn get_timeout(wallet_handle: IndyHandle, their_did: &str, timeout: Duration) -> Result<String, ErrorCode> {
        let (receiver, command_handle, cb) = ClosureHandler::cb_ec_string();

        let err = Pairwise::_get(command_handle, wallet_handle, their_did, cb);

        ResultHandler::one_timeout(err, receiver, timeout)
    }

    /// * `closure` - the closure that is called when finished
    ///
    /// # Returns
    /// * `errorcode` - errorcode from calling ffi function. The closure receives the return result
    pub fn get_async<F: 'static>(wallet_handle: IndyHandle, their_did: &str, closure: F) -> ErrorCode where F: FnMut(ErrorCode, String) + Send {
        let (command_handle, cb) = ClosureHandler::convert_cb_ec_string(Box::new(closure));

        Pairwise::_get(command_handle, wallet_handle, their_did, cb)
    }

    fn _get(command_handle: IndyHandle, wallet_handle: IndyHandle, their_did: &str, cb: Option<ResponseStringCB>) -> ErrorCode {
        let their_did = c_str!(their_did);

        ErrorCode::from(unsafe {
            pairwise::indy_get_pairwise(command_handle, wallet_handle, their_did.as_ptr(), cb)
        })
    }

    pub fn set_metadata(wallet_handle: IndyHandle, their_did: &str, metadata: Option<&str>) -> Result<(), ErrorCode> {
        let (receiver, command_handle, cb) = ClosureHandler::cb_ec();

        let err = Pairwise::_set_metadata(command_handle, wallet_handle, their_did, metadata, cb);

        ResultHandler::empty(err, receiver)
    }

    /// * `timeout` - the maximum time this function waits for a response
    pub fn set_metadata_timeout(wallet_handle: IndyHandle, their_did: &str, metadata: Option<&str>, timeout: Duration) -> Result<(), ErrorCode> {
        let (receiver, command_handle, cb) = ClosureHandler::cb_ec();

        let err = Pairwise::_set_metadata(command_handle, wallet_handle, their_did, metadata, cb);

        ResultHandler::empty_timeout(err, receiver, timeout)
    }

    /// * `closure` - the closure that is called when finished
    ///
    /// # Returns
    /// * `errorcode` - errorcode from calling ffi function. The closure receives the return result
    pub fn set_metadata_async<F: 'static>(wallet_handle: IndyHandle, their_did: &str, metadata: Option<&str>, closure: F) -> ErrorCode where F: FnMut(ErrorCode) + Send {
        let (command_handle, cb) = ClosureHandler::convert_cb_ec(Box::new(closure));

        Pairwise::_set_metadata(command_handle, wallet_handle, their_did, metadata, cb)
    }

    fn _set_metadata(command_handle: IndyHandle, wallet_handle: IndyHandle, their_did: &str, metadata: Option<&str>, cb: Option<ResponseEmptyCB>) -> ErrorCode {
        let their_did = c_str!(their_did);
        let metadata_str = opt_c_str!(metadata);

        ErrorCode::from(unsafe {
            pairwise::indy_set_pairwise_metadata(command_handle, wallet_handle, their_did.as_ptr(), opt_c_ptr!(metadata, metadata_str), cb)
        })
    }
}
<|endoftext|>


<commit_before>use helpers::*;
use basename;
use chop_basename;
use cleanpath_aggressive;
use cleanpath_conservative;
use dirname;
use extname;
use plus;
use relative_path_from;
use debug;
use helpers::TryFrom;
use pathname_sys::null_byte_check;

use ruru;
use ruru::{
  RString,
  Boolean,
  Array,
  AnyObject,
  NilClass,
  Object,
  Class,
  VerifiedObject,
  Exception as Exc,
  AnyException as Exception
};
use ruru::types::{Value, ValueType};
use std::path::{MAIN_SEPARATOR,Path};
use std::fs;

type MaybeArray = Result<ruru::Array, ruru::result::Error>;
type MaybeString = Result<ruru::RString, ruru::result::Error>;
type MaybeBoolean = Result<ruru::Boolean, ruru::result::Error>;

pub struct Pathname {
  value: Value
}

impl Pathname {
  pub fn new(path: &str) -> Pathname {
    let mut instance = Class::from_existing("Pathname").allocate();
    instance.instance_variable_set("@path", RString::new(path).to_any_object());

    Pathname { value: instance.value() }
  }

  pub fn new_checked(path: AnyObject) -> Result<Pathname, Exception> {
    let pth: Value = if Class::from_existing("String").case_equals(&path) {
      path.value()
    } else if path.respond_to("to_path") {
      path.send("to_path", None).value()
    } else {
      return Err(
        Exception::new(
          "ArgumentError",
          Some("The type for the argument provided to Pathname.new was invalid.")
        )
      )
    };

    if null_byte_check(path.value()) {
      return Err( Exception::new("ArgumentError", Some("pathname contains null byte")) )
    }

    // if it crashes then dup the path string here before assigning to @path
    let mut instance = Class::from_existing("Pathname").allocate();
    instance.instance_variable_set("@path", RString::from(pth).to_any_object());

    Ok(Pathname { value: instance.value() })
  }

  pub fn to_any_object(&self) -> AnyObject {
    AnyObject::from(self.value())
  }
}

impl From<Value> for Pathname {
  fn from(value: Value) -> Self {
    Pathname { value: value }
  }
}

impl TryFrom<AnyObject> for Pathname {
  type Error = debug::RubyDebugInfo;
  fn try_from(obj: AnyObject) -> Result<Pathname, Self::Error> {
    if Class::from_existing("String").case_equals(&obj) {
      Ok(Pathname::new(&RString::from(obj.value()).to_string()))
    } else if Class::from_existing("Pathname").case_equals(&obj) {
      Ok(Pathname::from(obj.value()))
    } else if obj.respond_to("to_path") {
      Ok(Pathname::from(obj.send("to_path", None).value()))
    } else {
      Err(Self::Error::from(obj))
    }
  }
}

impl Object for Pathname {
  #[inline]
  fn value(&self) -> Value {
    self.value
  }
}

impl VerifiedObject for Pathname {
  fn is_correct_type<T: Object>(object: &T) -> bool {
    object.value().ty() == ValueType::Class &&
      Class::from_existing("Pathname").case_equals(object)
  }

  fn error_message() -> &'static str {
    "Error converting to Pathname"
  }
}

pub fn pn_add_trailing_separator(pth: MaybeString) -> RString {
  let p = pth.ok().unwrap();
  let x = format!("{}{}", p.to_str(), "a");
  match x.rsplit_terminator(MAIN_SEPARATOR).next() {
    Some("a") => p,
    _ => RString::new(format!("{}{}", p.to_str(), MAIN_SEPARATOR).as_str())
  }
}

pub fn pn_is_absolute(pth: MaybeString) -> Boolean {
  Boolean::new(match pth.ok().unwrap_or(RString::new("")).to_str().chars().next() {
    Some(c) => c == MAIN_SEPARATOR,
    None => false
  })
}

// pub fn pn_ascend(){}

pub fn pn_basename(pth: MaybeString, ext: MaybeString) -> RString {
  RString::new(
    basename::basename(
      pth.ok().unwrap_or(RString::new("")).to_str(),
      ext.ok().unwrap_or(RString::new("")).to_str()
    )
  )
}

pub fn pn_children(pth: MaybeString, with_dir: MaybeBoolean) -> AnyObject {
  let val = pth.ok().unwrap_or(RString::new("."));
  let val = val.to_str();

  if let Ok(entries) = fs::read_dir(val) {
    let mut with_directory = with_dir.ok().unwrap_or(Boolean::new(true)).to_bool();
    if val == "." {
      with_directory = false;
    }

    let mut arr = Array::new();
    for entry in entries {
      if with_directory {
        match entry {
          Ok(v) => { arr.push(RString::new(v.path().to_str().unwrap())); },
          _ => {}
        };
      } else {
        match entry {
          Ok(v) => { arr.push(RString::new(v.file_name().to_str().unwrap())); },
          _ => {}
        };
      }
    }

    arr.to_any_object()
  } else {
    // TODO: When ruru exceptions are available switch the exception logic
    // from the Ruby side to the Rust side
    NilClass::new().to_any_object()
  }
}

pub fn pn_children_compat(pth: MaybeString, with_dir: MaybeBoolean) -> AnyObject {
  let val = pth.ok().unwrap_or(RString::new("."));
  let val = val.to_str();

  if let Ok(entries) = fs::read_dir(val) {
    let mut with_directory = with_dir.ok().unwrap_or(Boolean::new(true)).to_bool();
    if val == "." {
      with_directory = false;
    }

    let mut arr = Array::new();
    for entry in entries {
      if with_directory {
        if let Ok(v) = entry {
          arr.push(Pathname::new(v.path().to_str().unwrap()));
        };
      } else {
        if let Ok(v) = entry {
          arr.push(Pathname::new(v.file_name().to_str().unwrap()));
        };
      }
    }

    arr.to_any_object()
  } else {
    // TODO: When ruru exceptions are available switch the exception logic
    // from the Ruby side to the Rust side
    NilClass::new().to_any_object()
  }
}

pub fn pn_chop_basename(pth: MaybeString) -> Array {
  let mut arr = Array::with_capacity(2);
  let pth = pth.ok().unwrap_or(RString::new(""));
  let results = chop_basename::chop_basename(pth.to_str());
  match results {
    Some((dirname, basename)) => {
      arr.push(RString::new(&dirname[..]));
      arr.push(RString::new(&basename[..]));
      arr
    },
    None => arr
  }
}

// pub fn pn_cleanpath(pth: MaybeString){}

pub fn pn_cleanpath_aggressive(pth: MaybeString) -> RString {
  let path = cleanpath_aggressive::cleanpath_aggressive(
    pth.ok().unwrap_or(RString::new("")).to_str()
  );

  RString::new(&path)
}

pub fn pn_cleanpath_conservative(pth: MaybeString) -> RString {
  let path = cleanpath_conservative::cleanpath_conservative(
    pth.ok().unwrap_or(RString::new("")).to_str()
  );

  RString::new(&path)
}

pub fn pn_del_trailing_separator(pth: MaybeString) -> RString {
  if let &Ok(ref path) = &pth {
    let path = path.to_str();

    if !path.is_empty() {
      let path = path.trim_right_matches('/');

      if path.is_empty() {
        return RString::new("/");
      } else {
        return RString::new(path);
      }
    }
  } else {
    return RString::new("");
  }

  pth.unwrap()
}

// pub fn pn_descend(){}

pub fn pn_is_directory(pth: MaybeString) -> Boolean {
  Boolean::new(
    Path::new(
      pth.ok().unwrap_or(RString::new("")).to_str()
    ).is_dir()
  )
}

pub fn pn_dirname(pth: MaybeString) -> RString {
  RString::new(
    dirname::dirname(
      pth.ok().unwrap_or(RString::new("")).to_str()
    )
  )
}

// pub fn pn_each_child(){}

// pub fn pn_each_filename(pth: MaybeString) -> NilClass {
//   NilClass::new()
// }

pub fn pn_entries(pth: MaybeString) -> AnyObject {
  if let Ok(files) = fs::read_dir(pth.ok().unwrap_or(RString::new("")).to_str()) {
    let mut arr = Array::new();

    arr.push(RString::new("."));
    arr.push(RString::new(".."));

    for file in files {
      let file_name_str = file.unwrap().file_name().into_string().unwrap();
      arr.push(RString::new(&file_name_str[..]));
    }

    arr.to_any_object()
  } else {
    // TODO: When ruru exceptions are available switch the exception logic
    // from the Ruby side to the Rust side
    NilClass::new().to_any_object()
  }
}

pub fn pn_entries_compat(pth: MaybeString) -> AnyObject {
  if let Ok(files) = fs::read_dir(pth.ok().unwrap_or(RString::new("")).to_str()) {
    let mut arr = Array::new();

    arr.push(Pathname::new("."));
    arr.push(Pathname::new(".."));

    for file in files {
      let file_name_str = file.unwrap().file_name().into_string().unwrap();
      arr.push(Pathname::new(&file_name_str));
    }

    arr.to_any_object()
  } else {
    // TODO: When ruru exceptions are available switch the exception logic
    // from the Ruby side to the Rust side
    NilClass::new().to_any_object()
  }
}

pub fn pn_extname(pth: MaybeString) -> RString {
  RString::new(
    extname::extname(pth.ok().unwrap_or(RString::new("")).to_str())
  )
}

// pub fn pn_find(pth: MaybeString, ignore_error: Boolean){}

pub fn pn_has_trailing_separator(pth: MaybeString) -> Boolean {
  let v = pth.ok().unwrap_or(RString::new(""));
  match chop_basename::chop_basename(v.to_str()) {
    Some((a,b)) => {
      Boolean::new(a.len() + b.len() < v.to_str().len())
    },
    _ => Boolean::new(false)
  }
}

pub fn pn_join(args: MaybeArray) -> AnyObject {
  let mut args = args.unwrap();
  let path_self = anyobject_to_string(args.shift()).unwrap();
  let mut qty = args.length();
  if qty <= 0 {
    return Pathname::new(&path_self).to_any_object();
  }

  let mut result = String::new();

  loop {
    if qty == 0 { break; }

    let item = args.pop();
    result = plus::plus_paths(&anyobject_to_string(item).unwrap(), &result);
    if result.chars().next() == Some(MAIN_SEPARATOR) {
      return Pathname::new(&result).to_any_object()
    }

    qty -= 1;
  }

  let result = plus::plus_paths(&path_self, &result);

  Pathname::new(&result).to_any_object()
}

// pub fn pn_mkpath(pth: MaybeString) -> NilClass {
//   NilClass::new()
// }

// pub fn pn_is_mountpoint(pth: MaybeString){}

// pub fn pn_parent(pth: MaybeString){}

pub fn pn_plus(pth1: MaybeString, pth2: MaybeString) -> RString {
  RString::new(
    &plus::plus_paths(
      pth1.ok().unwrap_or(RString::new("")).to_str(),
      pth2.ok().unwrap_or(RString::new("")).to_str()
    )[..]
  )
}

// pub fn pn_prepend_prefix(prefix: MaybeString, relpath: MaybeString){}

pub fn pn_is_relative(pth: MaybeString) -> Boolean {
  Boolean::new(
    match pth.ok().unwrap_or(RString::new(&MAIN_SEPARATOR.to_string()[..])).to_str().chars().next() {
      Some(c) => c != MAIN_SEPARATOR,
      None => true
    }
  )
}

// pub fn pn_root(pth: MaybeString){}

// pub fn pn_split_names(pth: MaybeString){}

pub fn pn_relative_path_from(itself: MaybeString, base_directory: MaybeString) -> Result<Pathname, Exception> {
  relative_path_from::relative_path_from(itself, base_directory)
}

// pub fn pn_rmtree(pth: MaybeString) -> NilClass {
//   NilClass::new()
// }
//
<commit_msg>Simplify MaybeString to &str conversions<commit_after>use helpers::*;
use basename;
use chop_basename;
use cleanpath_aggressive;
use cleanpath_conservative;
use dirname;
use extname;
use plus;
use relative_path_from;
use debug;
use helpers::TryFrom;
use pathname_sys::null_byte_check;

use ruru;
use ruru::{
  RString,
  Boolean,
  Array,
  AnyObject,
  NilClass,
  Object,
  Class,
  VerifiedObject,
  Exception as Exc,
  AnyException as Exception
};
use ruru::types::{Value, ValueType};
use std::path::{MAIN_SEPARATOR,Path};
use std::fs;

type MaybeArray = Result<ruru::Array, ruru::result::Error>;
type MaybeString = Result<ruru::RString, ruru::result::Error>;
type MaybeBoolean = Result<ruru::Boolean, ruru::result::Error>;

pub struct Pathname {
  value: Value
}

impl Pathname {
  pub fn new(path: &str) -> Pathname {
    let mut instance = Class::from_existing("Pathname").allocate();
    instance.instance_variable_set("@path", RString::new(path).to_any_object());

    Pathname { value: instance.value() }
  }

  pub fn new_checked(path: AnyObject) -> Result<Pathname, Exception> {
    let pth: Value = if Class::from_existing("String").case_equals(&path) {
      path.value()
    } else if path.respond_to("to_path") {
      path.send("to_path", None).value()
    } else {
      return Err(
        Exception::new(
          "ArgumentError",
          Some("The type for the argument provided to Pathname.new was invalid.")
        )
      )
    };

    if null_byte_check(path.value()) {
      return Err( Exception::new("ArgumentError", Some("pathname contains null byte")) )
    }

    // if it crashes then dup the path string here before assigning to @path
    let mut instance = Class::from_existing("Pathname").allocate();
    instance.instance_variable_set("@path", RString::from(pth).to_any_object());

    Ok(Pathname { value: instance.value() })
  }

  pub fn to_any_object(&self) -> AnyObject {
    AnyObject::from(self.value())
  }
}

impl From<Value> for Pathname {
  fn from(value: Value) -> Self {
    Pathname { value: value }
  }
}

impl TryFrom<AnyObject> for Pathname {
  type Error = debug::RubyDebugInfo;
  fn try_from(obj: AnyObject) -> Result<Pathname, Self::Error> {
    if Class::from_existing("String").case_equals(&obj) {
      Ok(Pathname::new(&RString::from(obj.value()).to_string()))
    } else if Class::from_existing("Pathname").case_equals(&obj) {
      Ok(Pathname::from(obj.value()))
    } else if obj.respond_to("to_path") {
      Ok(Pathname::from(obj.send("to_path", None).value()))
    } else {
      Err(Self::Error::from(obj))
    }
  }
}

impl Object for Pathname {
  #[inline]
  fn value(&self) -> Value {
    self.value
  }
}

impl VerifiedObject for Pathname {
  fn is_correct_type<T: Object>(object: &T) -> bool {
    object.value().ty() == ValueType::Class &&
      Class::from_existing("Pathname").case_equals(object)
  }

  fn error_message() -> &'static str {
    "Error converting to Pathname"
  }
}

fn to_str(maybe_string: &MaybeString) -> &str {
  match maybe_string {
    &Ok(ref ruru_string) => ruru_string.to_str(),
    &Err(_) => "",
  }
}

pub fn pn_add_trailing_separator(pth: MaybeString) -> RString {
  let p = pth.ok().unwrap();
  let x = format!("{}{}", p.to_str(), "a");
  match x.rsplit_terminator(MAIN_SEPARATOR).next() {
    Some("a") => p,
    _ => RString::new(format!("{}{}", p.to_str(), MAIN_SEPARATOR).as_str())
  }
}

pub fn pn_is_absolute(pth: MaybeString) -> Boolean {
  Boolean::new(match to_str(&pth).chars().next() {
    Some(c) => c == MAIN_SEPARATOR,
    None => false
  })
}

// pub fn pn_ascend(){}

pub fn pn_basename(pth: MaybeString, ext: MaybeString) -> RString {
  RString::new(basename::basename(to_str(&pth), to_str(&ext)))
}

pub fn pn_children(pth: MaybeString, with_dir: MaybeBoolean) -> AnyObject {
  let val = pth.ok().unwrap_or(RString::new("."));
  let val = val.to_str();

  if let Ok(entries) = fs::read_dir(val) {
    let mut with_directory = with_dir.ok().unwrap_or(Boolean::new(true)).to_bool();
    if val == "." {
      with_directory = false;
    }

    let mut arr = Array::new();
    for entry in entries {
      if with_directory {
        match entry {
          Ok(v) => { arr.push(RString::new(v.path().to_str().unwrap())); },
          _ => {}
        };
      } else {
        match entry {
          Ok(v) => { arr.push(RString::new(v.file_name().to_str().unwrap())); },
          _ => {}
        };
      }
    }

    arr.to_any_object()
  } else {
    // TODO: When ruru exceptions are available switch the exception logic
    // from the Ruby side to the Rust side
    NilClass::new().to_any_object()
  }
}

pub fn pn_children_compat(pth: MaybeString, with_dir: MaybeBoolean) -> AnyObject {
  let val = to_str(&pth);

  if let Ok(entries) = fs::read_dir(val) {
    let mut with_directory = with_dir.ok().unwrap_or(Boolean::new(true)).to_bool();
    if val == "." {
      with_directory = false;
    }

    let mut arr = Array::new();
    for entry in entries {
      if with_directory {
        if let Ok(v) = entry {
          arr.push(Pathname::new(v.path().to_str().unwrap()));
        };
      } else {
        if let Ok(v) = entry {
          arr.push(Pathname::new(v.file_name().to_str().unwrap()));
        };
      }
    }

    arr.to_any_object()
  } else {
    // TODO: When ruru exceptions are available switch the exception logic
    // from the Ruby side to the Rust side
    NilClass::new().to_any_object()
  }
}

pub fn pn_chop_basename(pth: MaybeString) -> Array {
  let mut arr = Array::with_capacity(2);
  let results = chop_basename::chop_basename(to_str(&pth));
  match results {
    Some((dirname, basename)) => {
      arr.push(RString::new(&dirname[..]));
      arr.push(RString::new(&basename[..]));
      arr
    },
    None => arr
  }
}

// pub fn pn_cleanpath(pth: MaybeString){}

pub fn pn_cleanpath_aggressive(pth: MaybeString) -> RString {
  RString::new(&cleanpath_aggressive::cleanpath_aggressive(to_str(&pth)))
}

pub fn pn_cleanpath_conservative(pth: MaybeString) -> RString {
  RString::new(&cleanpath_conservative::cleanpath_conservative(to_str(&pth)))
}

pub fn pn_del_trailing_separator(pth: MaybeString) -> RString {
  if let &Ok(ref path) = &pth {
    let path = path.to_str();

    if !path.is_empty() {
      let path = path.trim_right_matches('/');

      if path.is_empty() {
        return RString::new("/");
      } else {
        return RString::new(path);
      }
    }
  } else {
    return RString::new("");
  }

  pth.unwrap()
}

// pub fn pn_descend(){}

pub fn pn_is_directory(pth: MaybeString) -> Boolean {
  Boolean::new(Path::new(to_str(&pth)).is_dir())
}

pub fn pn_dirname(pth: MaybeString) -> RString {
  RString::new(dirname::dirname(to_str(&pth)))
}

// pub fn pn_each_child(){}

// pub fn pn_each_filename(pth: MaybeString) -> NilClass {
//   NilClass::new()
// }

pub fn pn_entries(pth: MaybeString) -> AnyObject {
  if let Ok(files) = fs::read_dir(to_str(&pth)) {
    let mut arr = Array::new();

    arr.push(RString::new("."));
    arr.push(RString::new(".."));

    for file in files {
      let file_name_str = file.unwrap().file_name().into_string().unwrap();
      arr.push(RString::new(&file_name_str[..]));
    }

    arr.to_any_object()
  } else {
    // TODO: When ruru exceptions are available switch the exception logic
    // from the Ruby side to the Rust side
    NilClass::new().to_any_object()
  }
}

pub fn pn_entries_compat(pth: MaybeString) -> AnyObject {
  if let Ok(files) = fs::read_dir(to_str(&pth)) {
    let mut arr = Array::new();

    arr.push(Pathname::new("."));
    arr.push(Pathname::new(".."));

    for file in files {
      let file_name_str = file.unwrap().file_name().into_string().unwrap();
      arr.push(Pathname::new(&file_name_str));
    }

    arr.to_any_object()
  } else {
    // TODO: When ruru exceptions are available switch the exception logic
    // from the Ruby side to the Rust side
    NilClass::new().to_any_object()
  }
}

pub fn pn_extname(pth: MaybeString) -> RString {
  RString::new(extname::extname(to_str(&pth)))
}

// pub fn pn_find(pth: MaybeString, ignore_error: Boolean){}

pub fn pn_has_trailing_separator(pth: MaybeString) -> Boolean {
  let v = pth.ok().unwrap_or(RString::new(""));
  match chop_basename::chop_basename(v.to_str()) {
    Some((a,b)) => {
      Boolean::new(a.len() + b.len() < v.to_str().len())
    },
    _ => Boolean::new(false)
  }
}

pub fn pn_join(args: MaybeArray) -> AnyObject {
  let mut args = args.unwrap();
  let path_self = anyobject_to_string(args.shift()).unwrap();
  let mut qty = args.length();
  if qty <= 0 {
    return Pathname::new(&path_self).to_any_object();
  }

  let mut result = String::new();

  loop {
    if qty == 0 { break; }

    let item = args.pop();
    result = plus::plus_paths(&anyobject_to_string(item).unwrap(), &result);
    if result.chars().next() == Some(MAIN_SEPARATOR) {
      return Pathname::new(&result).to_any_object()
    }

    qty -= 1;
  }

  let result = plus::plus_paths(&path_self, &result);

  Pathname::new(&result).to_any_object()
}

// pub fn pn_mkpath(pth: MaybeString) -> NilClass {
//   NilClass::new()
// }

// pub fn pn_is_mountpoint(pth: MaybeString){}

// pub fn pn_parent(pth: MaybeString){}

pub fn pn_plus(pth1: MaybeString, pth2: MaybeString) -> RString {
  RString::new(
    &plus::plus_paths(
      pth1.ok().unwrap_or(RString::new("")).to_str(),
      pth2.ok().unwrap_or(RString::new("")).to_str()
    )[..]
  )
}

// pub fn pn_prepend_prefix(prefix: MaybeString, relpath: MaybeString){}

pub fn pn_is_relative(pth: MaybeString) -> Boolean {
  Boolean::new(
    match pth.ok().unwrap_or(RString::new(&MAIN_SEPARATOR.to_string()[..])).to_str().chars().next() {
      Some(c) => c != MAIN_SEPARATOR,
      None => true
    }
  )
}

// pub fn pn_root(pth: MaybeString){}

// pub fn pn_split_names(pth: MaybeString){}

pub fn pn_relative_path_from(itself: MaybeString, base_directory: MaybeString) -> Result<Pathname, Exception> {
  relative_path_from::relative_path_from(itself, base_directory)
}

// pub fn pn_rmtree(pth: MaybeString) -> NilClass {
//   NilClass::new()
// }
//
<|endoftext|>


<commit_before>// Copyright 2013 The rust-pcre authors.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

extern mod extra;
extern mod rustc;
extern mod rustpkg;

use extra::time;
use rustc::driver::driver::host_triple;
use rustpkg::api;
use std::from_str::{from_str};
use std::io::fs::{mkdir, File};
use std::io::buffered::BufferedReader;
use std::io;
use std::option::{Option};
use std::os;
use std::run;
use std::str;

struct Version {
    major: uint,
    minor: uint
}

impl Version {
    pub fn parse(version_str: &str) -> Option<Version> {
        let mut it = version_str.split('.');
        match (it.next().and_then(from_str::<uint>), it.next().and_then(from_str::<uint>)) {
            (Some(major), Some(minor)) => Some(Version { major: major, minor: minor }),
            _                          => None
        }
    }
}

impl ToStr for Version {
    fn to_str(&self) -> ~str {
        format!("{:u}.{:u}", self.major, self.minor)
    }
}

impl Ord for Version {
    fn lt(&self, other: &Version) -> bool {
        self.major < other.major || (self.major == other.major && self.minor < other.minor)
    }
}

fn cd(path: &Path) {
    if !os::change_dir(path) {
        fail!("Package script error: Failed to `cd` into `{}`", path.display());
    }
}

fn do_install(args: ~[~str]) {
    let sysroot_arg = args[1].clone();
    let sysroot_path = from_str(sysroot_arg).unwrap();

    let pcre_libs = match os::getenv("PCRE_LIBS") {
        None            => {
            let pcre_config_output = io::io_error::cond.trap(|e: io::IoError| {
                match e.kind {
                    io::FileNotFound => fail!("Package script error: Could not run `pcre-config` because no such executable is in the executable search PATH. Make sure that you have installed a dev package for libpcre and/or make sure that libpcre's bindir is added to your PATH (currently \"{}\").", os::getenv("PATH").unwrap_or(~"")),
                    _ => fail!("Package script error: Could not run `pcre-config`: {}", e.to_str())
                }
            }).inside(|| -> run::ProcessOutput {
                run::process_output("pcre-config", [~"--libs"]).expect("failed to exec `pcre-config`")
            });
            if !pcre_config_output.status.success() {
                fail!("Package script error: `pcre-config` failed");
            }
            let output_ptr = pcre_config_output.output.as_ptr();
            let output_len = pcre_config_output.output.len();
            let libs_str = unsafe { str::raw::from_buf_len(output_ptr, output_len) };
            os::setenv("PCRE_LIBS", libs_str);
            libs_str
        },
        Some(pcre_libs) => pcre_libs
    };
    // `pcre-config` adds a newline to the end, which we need to trim away because newlines
    // in link_args cause build issues.
    let trimmed_pcre_libs = pcre_libs.trim();
    debug!("PCRE_LIBS=\"{:s}\"", trimmed_pcre_libs);

    let workspace_path = os::getcwd();

    // Check the version
    let target_build_path = workspace_path.join("build").join(host_triple());
    if !target_build_path.exists() {
        if !io::result(|| mkdir(&target_build_path, 0x1FF)).is_ok() {
            fail!("Package script error: Failed to create target build directory `{}`", target_build_path.display());
        }
    }
    let out_path = target_build_path.join("pcre");
    if !out_path.exists() {
        if !io::result(|| mkdir(&out_path, 0x1FF)).is_ok() {
            fail!("Package script error: Failed to create output directory `{}`", out_path.display());
        }
    }

    let versioncheck_rs_path = out_path.join("versioncheck.rs");
    {
        let mut w = match File::create(&versioncheck_rs_path) {
            None    => fail!("Package script error: Failed to open `{}` for writing", versioncheck_rs_path.display()),
            Some(w) => w
        };
        write!(&mut w as &mut Writer, "\
\\#[feature(globs)];
\\#[feature(link_args)];
use std::c_str::\\{CString\\};
use std::libc::*;
use std::ptr;
use std::vec;

type options = c_int;
struct pcre;
struct pcre_extra;

\\#[link_args = \"{:s}\"]
extern \\{
    static pcre_free: extern \"C\" fn(ptr: *c_void);

    fn pcre_compile(pattern: *c_char, options: options, errptr: *mut *c_char, erroffset: *mut c_int, tableptr: *c_uchar) -> *pcre;
    fn pcre_exec(code: *pcre, extra: *pcre_extra, subject: *c_char, length: c_int, startoffset: c_int, options: options, ovector: *mut c_int, ovecsize: c_int) -> c_int;
    fn pcre_version() -> *c_char;
\\}

fn main () \\{
    unsafe \\{
        let version_cstring = CString::new(pcre_version(), false);
        let version_str = version_cstring.as_str().unwrap().to_owned();

        let pattern = \"^\\\\\\\\d+\\\\\\\\.\\\\\\\\d+\";
        pattern.with_c_str(|pattern_c_str| \\{
            let mut err: *c_char = ptr::null();
            let mut erroffset: c_int = 0;
            let code = pcre_compile(pattern_c_str, 0, &mut err, &mut erroffset, ptr::null());
            if ptr::is_null(code) \\{
                if ptr::is_null(code) \\{
                    let err_cstring = CString::new(err, false);
                    match err_cstring.as_str() \\{
                        None          => fail!(\"pcre_compile() failed at offset \\{\\}\", erroffset as uint),
                        Some(err_str) => fail!(\"pcre_compile() failed at offset \\{\\}: \\{\\}\", erroffset as uint, err_str)
                    \\}
                \\}
            \\}
            assert!(ptr::is_not_null(code));

            let ovecsize = 1 * 3;
            let mut ovector: ~[c_int] = vec::from_elem(ovecsize, 0 as c_int);
            version_str.with_c_str_unchecked(|version_c_str| \\{
                let rc = pcre_exec(code, ptr::null(), version_c_str, version_str.len() as c_int, 0, 0, ovector.as_mut_ptr(), ovecsize as c_int);
                if rc < 0 \\{
                    fail!(\"pcre_exec() failed\");
                \\}

                print(version_str.slice_to(ovector[1] as uint));
            \\});

            pcre_free(code as *c_void);
        \\});
    \\}
\\}
", trimmed_pcre_libs);
    }

    // Compile and run `versioncheck.rs`
    cd(&out_path);
    let rustc_run_output = run::process_output("rustc", [~"versioncheck.rs"]).expect("failed to exec `rustc`");
    if !rustc_run_output.status.success() {
        println(str::from_utf8(rustc_run_output.output));
        println(str::from_utf8(rustc_run_output.error));
        fail!("Package script error: `rustc versioncheck.rs` failed: {}", rustc_run_output.status);
    }
    let version_check_output = run::process_output("./versioncheck", []).expect("failed to exec `./versioncheck`");
    if !version_check_output.status.success() {
        println(str::from_utf8(version_check_output.output));
        println(str::from_utf8(version_check_output.error));
        fail!("versioncheck error: {}", version_check_output.status);
    }
    cd(&workspace_path);

    let output_ptr = version_check_output.output.as_ptr();
    let output_len = version_check_output.output.len();
    let output_str = unsafe { str::raw::from_buf_len(output_ptr, output_len) };

    // The "no debug symbols in executable" warning may be present in the output.
    // https://github.com/mozilla/rust/issues/3495
    let mut output_rsplit_iter = output_str.rsplit('\n');
    let version_str: ~str = match output_rsplit_iter.next() {
        None              => output_str.clone(),
        Some(version_str) => version_str.to_owned()
    };

    debug!("libpcre version {:s}", version_str);

    let min_required_version = Version::parse("8.20").unwrap();
    let pcre_version = match Version::parse(version_str) {
        None               => fail!("Package script error: Failed to parse version string '{}'", version_str),
        Some(pcre_version) => pcre_version
    };

    if pcre_version < min_required_version {
        fail!("Package script error: Found libpcre version {}, but at least version {} is required", version_str, min_required_version.to_str());
    }

    let src_path = workspace_path.join("src");

    // Output `src/pcre/detail/native.rs`
    let detail_src_path = src_path.join("pcre").join("detail");
    if !detail_src_path.exists() {
        fail!("Package script error: Source directory `{}` does not exist.", detail_src_path.display());
    }
    let native_rs_path = detail_src_path.join("native.rs");
    let native_rs_in_path = detail_src_path.join("native.rs.in");
    if !native_rs_in_path.exists() {
        fail!("Package script error: Source file `{}` does not exist.", native_rs_in_path.display());
    }
    {
        let r = match File::open(&native_rs_in_path) {
            None    => fail!("Package script error: Failed to open `{}` for reading", native_rs_in_path.display()),
            Some(r) => r
        };
        let mut w = match File::create(&native_rs_path) {
            None    => fail!("Package script error: Failed to open `{}` for writing", native_rs_path.display()),
            Some(w) => w
        };
        write!(&mut w as &mut Writer, "// -*- buffer-read-only: t -*-\n");
        write!(&mut w as &mut Writer, "// Generated by {:s} on {:s}\n", args[0], time::now().rfc822());

        let mut buffered_reader = BufferedReader::new(r);
        while !buffered_reader.eof() {
            let line = buffered_reader.read_line();
            if line.is_some() {
                let substituted_line = str::replace(line.unwrap(), "@PCRE_LIBS@", trimmed_pcre_libs);
                write!(&mut w as &mut Writer, "{:s}", substituted_line);
            }
        }
    }

    api::build_lib(sysroot_path, workspace_path, ~"pcre", rustpkg::version::ExactRevision(~"0.1"), from_str("mod.rs").unwrap());
}

fn do_configs(args: ~[~str]) {
    drop(args);
}

fn main() {
    let args = os::args();
    let args_len = args.len();

    if args_len < 2 {
        fail!("Package script requires a directory where rustc libraries live as the first argument");
    } else if args_len < 3 {
        fail!("Package script requires a command as the second argument");
    }

    if args[2] == ~"install" {
        do_install(args);
    } else if args[2] == ~"configs" {
        do_configs(args);
    } else {
        fail!("Package script error: Unsupported command `{}`", args[2]);
    }
}
<commit_msg>Update for eof() being removed from io::Reader<commit_after>// Copyright 2013 The rust-pcre authors.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

extern mod extra;
extern mod rustc;
extern mod rustpkg;

use extra::time;
use rustc::driver::driver::host_triple;
use rustpkg::api;
use std::from_str::{from_str};
use std::io::fs::{mkdir, File};
use std::io::buffered::BufferedReader;
use std::io;
use std::option::{Option};
use std::os;
use std::run;
use std::str;

struct Version {
    major: uint,
    minor: uint
}

impl Version {
    pub fn parse(version_str: &str) -> Option<Version> {
        let mut it = version_str.split('.');
        match (it.next().and_then(from_str::<uint>), it.next().and_then(from_str::<uint>)) {
            (Some(major), Some(minor)) => Some(Version { major: major, minor: minor }),
            _                          => None
        }
    }
}

impl ToStr for Version {
    fn to_str(&self) -> ~str {
        format!("{:u}.{:u}", self.major, self.minor)
    }
}

impl Ord for Version {
    fn lt(&self, other: &Version) -> bool {
        self.major < other.major || (self.major == other.major && self.minor < other.minor)
    }
}

fn cd(path: &Path) {
    if !os::change_dir(path) {
        fail!("Package script error: Failed to `cd` into `{}`", path.display());
    }
}

fn do_install(args: ~[~str]) {
    let sysroot_arg = args[1].clone();
    let sysroot_path = from_str(sysroot_arg).unwrap();

    let pcre_libs = match os::getenv("PCRE_LIBS") {
        None            => {
            let pcre_config_output = io::io_error::cond.trap(|e: io::IoError| {
                match e.kind {
                    io::FileNotFound => fail!("Package script error: Could not run `pcre-config` because no such executable is in the executable search PATH. Make sure that you have installed a dev package for libpcre and/or make sure that libpcre's bindir is added to your PATH (currently \"{}\").", os::getenv("PATH").unwrap_or(~"")),
                    _ => fail!("Package script error: Could not run `pcre-config`: {}", e.to_str())
                }
            }).inside(|| -> run::ProcessOutput {
                run::process_output("pcre-config", [~"--libs"]).expect("failed to exec `pcre-config`")
            });
            if !pcre_config_output.status.success() {
                fail!("Package script error: `pcre-config` failed");
            }
            let output_ptr = pcre_config_output.output.as_ptr();
            let output_len = pcre_config_output.output.len();
            let libs_str = unsafe { str::raw::from_buf_len(output_ptr, output_len) };
            os::setenv("PCRE_LIBS", libs_str);
            libs_str
        },
        Some(pcre_libs) => pcre_libs
    };
    // `pcre-config` adds a newline to the end, which we need to trim away because newlines
    // in link_args cause build issues.
    let trimmed_pcre_libs = pcre_libs.trim();
    debug!("PCRE_LIBS=\"{:s}\"", trimmed_pcre_libs);

    let workspace_path = os::getcwd();

    // Check the version
    let target_build_path = workspace_path.join("build").join(host_triple());
    if !target_build_path.exists() {
        if !io::result(|| mkdir(&target_build_path, 0x1FF)).is_ok() {
            fail!("Package script error: Failed to create target build directory `{}`", target_build_path.display());
        }
    }
    let out_path = target_build_path.join("pcre");
    if !out_path.exists() {
        if !io::result(|| mkdir(&out_path, 0x1FF)).is_ok() {
            fail!("Package script error: Failed to create output directory `{}`", out_path.display());
        }
    }

    let versioncheck_rs_path = out_path.join("versioncheck.rs");
    {
        let mut w = match File::create(&versioncheck_rs_path) {
            None    => fail!("Package script error: Failed to open `{}` for writing", versioncheck_rs_path.display()),
            Some(w) => w
        };
        write!(&mut w as &mut Writer, "\
\\#[feature(globs)];
\\#[feature(link_args)];
use std::c_str::\\{CString\\};
use std::libc::*;
use std::ptr;
use std::vec;

type options = c_int;
struct pcre;
struct pcre_extra;

\\#[link_args = \"{:s}\"]
extern \\{
    static pcre_free: extern \"C\" fn(ptr: *c_void);

    fn pcre_compile(pattern: *c_char, options: options, errptr: *mut *c_char, erroffset: *mut c_int, tableptr: *c_uchar) -> *pcre;
    fn pcre_exec(code: *pcre, extra: *pcre_extra, subject: *c_char, length: c_int, startoffset: c_int, options: options, ovector: *mut c_int, ovecsize: c_int) -> c_int;
    fn pcre_version() -> *c_char;
\\}

fn main () \\{
    unsafe \\{
        let version_cstring = CString::new(pcre_version(), false);
        let version_str = version_cstring.as_str().unwrap().to_owned();

        let pattern = \"^\\\\\\\\d+\\\\\\\\.\\\\\\\\d+\";
        pattern.with_c_str(|pattern_c_str| \\{
            let mut err: *c_char = ptr::null();
            let mut erroffset: c_int = 0;
            let code = pcre_compile(pattern_c_str, 0, &mut err, &mut erroffset, ptr::null());
            if ptr::is_null(code) \\{
                if ptr::is_null(code) \\{
                    let err_cstring = CString::new(err, false);
                    match err_cstring.as_str() \\{
                        None          => fail!(\"pcre_compile() failed at offset \\{\\}\", erroffset as uint),
                        Some(err_str) => fail!(\"pcre_compile() failed at offset \\{\\}: \\{\\}\", erroffset as uint, err_str)
                    \\}
                \\}
            \\}
            assert!(ptr::is_not_null(code));

            let ovecsize = 1 * 3;
            let mut ovector: ~[c_int] = vec::from_elem(ovecsize, 0 as c_int);
            version_str.with_c_str_unchecked(|version_c_str| \\{
                let rc = pcre_exec(code, ptr::null(), version_c_str, version_str.len() as c_int, 0, 0, ovector.as_mut_ptr(), ovecsize as c_int);
                if rc < 0 \\{
                    fail!(\"pcre_exec() failed\");
                \\}

                print(version_str.slice_to(ovector[1] as uint));
            \\});

            pcre_free(code as *c_void);
        \\});
    \\}
\\}
", trimmed_pcre_libs);
    }

    // Compile and run `versioncheck.rs`
    cd(&out_path);
    let rustc_run_output = run::process_output("rustc", [~"versioncheck.rs"]).expect("failed to exec `rustc`");
    if !rustc_run_output.status.success() {
        println(str::from_utf8(rustc_run_output.output));
        println(str::from_utf8(rustc_run_output.error));
        fail!("Package script error: `rustc versioncheck.rs` failed: {}", rustc_run_output.status);
    }
    let version_check_output = run::process_output("./versioncheck", []).expect("failed to exec `./versioncheck`");
    if !version_check_output.status.success() {
        println(str::from_utf8(version_check_output.output));
        println(str::from_utf8(version_check_output.error));
        fail!("versioncheck error: {}", version_check_output.status);
    }
    cd(&workspace_path);

    let output_ptr = version_check_output.output.as_ptr();
    let output_len = version_check_output.output.len();
    let output_str = unsafe { str::raw::from_buf_len(output_ptr, output_len) };

    // The "no debug symbols in executable" warning may be present in the output.
    // https://github.com/mozilla/rust/issues/3495
    let mut output_rsplit_iter = output_str.rsplit('\n');
    let version_str: ~str = match output_rsplit_iter.next() {
        None              => output_str.clone(),
        Some(version_str) => version_str.to_owned()
    };

    debug!("libpcre version {:s}", version_str);

    let min_required_version = Version::parse("8.20").unwrap();
    let pcre_version = match Version::parse(version_str) {
        None               => fail!("Package script error: Failed to parse version string '{}'", version_str),
        Some(pcre_version) => pcre_version
    };

    if pcre_version < min_required_version {
        fail!("Package script error: Found libpcre version {}, but at least version {} is required", version_str, min_required_version.to_str());
    }

    let src_path = workspace_path.join("src");

    // Output `src/pcre/detail/native.rs`
    let detail_src_path = src_path.join("pcre").join("detail");
    if !detail_src_path.exists() {
        fail!("Package script error: Source directory `{}` does not exist.", detail_src_path.display());
    }
    let native_rs_path = detail_src_path.join("native.rs");
    let native_rs_in_path = detail_src_path.join("native.rs.in");
    if !native_rs_in_path.exists() {
        fail!("Package script error: Source file `{}` does not exist.", native_rs_in_path.display());
    }
    {
        let r = match File::open(&native_rs_in_path) {
            None    => fail!("Package script error: Failed to open `{}` for reading", native_rs_in_path.display()),
            Some(r) => r
        };
        let mut w = match File::create(&native_rs_path) {
            None    => fail!("Package script error: Failed to open `{}` for writing", native_rs_path.display()),
            Some(w) => w
        };
        write!(&mut w as &mut Writer, "// -*- buffer-read-only: t -*-\n");
        write!(&mut w as &mut Writer, "// Generated by {:s} on {:s}\n", args[0], time::now().rfc822());

        let mut buffered_reader = BufferedReader::new(r);
        loop {
            match buffered_reader.read_line() {
                None => break,
                Some(line) => {
                    let substituted_line = str::replace(line, "@PCRE_LIBS@", trimmed_pcre_libs);
                    write!(&mut w as &mut Writer, "{:s}", substituted_line);
                }
            }
        }
    }

    api::build_lib(sysroot_path, workspace_path, ~"pcre", rustpkg::version::ExactRevision(~"0.1"), from_str("mod.rs").unwrap());
}

fn do_configs(args: ~[~str]) {
    drop(args);
}

fn main() {
    let args = os::args();
    let args_len = args.len();

    if args_len < 2 {
        fail!("Package script requires a directory where rustc libraries live as the first argument");
    } else if args_len < 3 {
        fail!("Package script requires a command as the second argument");
    }

    if args[2] == ~"install" {
        do_install(args);
    } else if args[2] == ~"configs" {
        do_configs(args);
    } else {
        fail!("Package script error: Unsupported command `{}`", args[2]);
    }
}
<|endoftext|>


<commit_before>extern crate rand;

use std::io;
use std::cmp::Ordering;
use rand::Rng;

fn main() {
    println!("Hello in my guessing game!");

    let secret_number = rand::thread_rng().gen_range(1, 101);

    println!("The secret number is: {}", secret_number);

    println!("Input your guess, please:");

    let mut guess = String::new();

    io::stdin().read_line(&mut guess)
        .expect("Failed to read line!");

    let guess: u32 = guess.trim().parse()
        .expect("It's not a valid number :(");

    println!("Your guess is: {}", guess);

    match guess.cmp(&secret_number) {
        Ordering::Less    => println!("Too low!"),
        Ordering::Greater => println!("Too big!"),
        Ordering::Equal   => println!("Great guess! You win!")
    }
}
<commit_msg>Add loop to allow multiple guesses<commit_after>extern crate rand;

use std::io;
use std::cmp::Ordering;
use rand::Rng;

fn main() {
    println!("Hello in my guessing game!");

    let secret_number = rand::thread_rng().gen_range(1, 101);

    println!("The secret number is: {}", secret_number);
    loop {
        println!("Input your guess, please:");

        let mut guess = String::new();

        io::stdin().read_line(&mut guess)
            .expect("Failed to read line!");

        let guess: u32 = guess.trim().parse()
            .expect("It's not a valid number :(");

        println!("Your guess is: {}", guess);

        match guess.cmp(&secret_number) {
            Ordering::Less => println!("Too low!"),
            Ordering::Greater => println!("Too big!"),
            Ordering::Equal => println!("Great guess! You win!")
        }
    }
}
<|endoftext|>