<commit_before>// During tests, we disable the renderer and that causes a bunch of warnings that we just want
// to get rid of.
// See Cargo.toml for an explanation of this attribute
#![cfg_attr(any(feature = "test", test), allow(dead_code, unused_variables))]

use std::env;
use std::thread;
use std::process;
use std::sync::mpsc::{self, TryRecvError};

use piston_window::{
    PistonWindow,
    WindowSettings,
    G2d,
    context,
    clear,
    line,
    polygon,
};

use app::{TurtleApp, ReadOnly};
use extensions::ConvertScreenCoordinates;
use state::{Path, Polygon, Pen, TurtleState, DrawingState};
use query::DrawingCommand;
use event::{Event, from_piston_event};
use types::Point;
use color::{self, Color};
use server;

/// Setup the turtle window in advance
///
/// You must call this function at the beginning of `main()` if you do not create the
/// turtle immediately using [`Turtle::new()`].
///
/// It's a good idea to call this function before any other code runs in `main()`. Programs that
/// parse command line arguments or look at environment variables may **fail** to start if this
/// function is not called right at the beginning of the program. Programs that perform any
/// expensive computations may experience delayed start up problems unless they call this
/// function first.
///
/// The [`Turtle::new()`] method will call this function for you so that you don't need to worry
/// about this unless you are doing something before that.
///
/// # Example
/// ```rust,no_run
/// # #![allow(unused_variables, unused_mut)]
/// extern crate turtle;
/// use turtle::Turtle;
///
/// fn main() {
///     // Initializes the turtle renderer first so that there is less delay when a Turtle
///     // is created and so that there are no conflicts with command line arguments or
///     // environment variables.
///     // Not required if Turtle::new() is already at the top of main.
///     turtle::setup();
///
///     // Do all kinds of expensive work here...
///     // Feel free to check environment variables, command line arguments, etc.
///
///     // Create the turtle when you are ready
///     // Turtle::new() will also call setup(), but calling it twice doesn't matter
///     let mut turtle = Turtle::new();
///     // Do things with the turtle...
/// }
/// ```
///
/// [`Turtle::new()`]: struct.Turtle.html#method.new
pub fn setup() {
    // If this environment variable is present, this process is taken over so that no other
    // code runs after main(). This allows us to ship one executable that appears to
    // have two separate processes.
    // We run the renderer loop and then immediately exit.
    if env::var("RUN_TURTLE_CANVAS").unwrap_or_else(|_| "".to_owned()) == "true" {
        // This code MUST be run on the main thread.

        // Run the renderer process
        main();
        unreachable!("bug: renderer loop did not exit after finishing");
    }
}

/// Run the renderer process in the current thread
///
/// This function must run in the main thread ONLY
pub fn main() {
    let app = TurtleApp::new();
    let read_only = app.read_only();
    let (drawing_tx, drawing_rx) = mpsc::channel();
    let (events_tx, events_rx) = mpsc::channel();

    // The running channel is entirely for checking if the other thread is still active.
    // We need to check because while we can exit while that thread is still running, we want
    // any errors caused in that thread to be reported.
    let (running_tx, running_rx) = mpsc::channel();
    let handle = thread::spawn(move || {
        server::run(app, drawing_tx, events_rx, running_tx);
    });

    // Renderer MUST run on the main thread or else it will panic on MacOS
    #[cfg(not(any(feature = "test", test)))]
    Renderer::new().run(drawing_rx, events_tx, read_only);

    // Quit immediately when the window is closed

    // Check if an error has occurred on the thread
    match running_rx.try_recv() {
        Ok(_) => unreachable!("bug: running channel should always be empty"),
        // The thread was still running, exit normally
        Err(mpsc::TryRecvError::Empty) => process::exit(0),
        Err(mpsc::TryRecvError::Disconnected) => match handle.join() {
            Ok(_) => process::exit(0),
            // The other thread must have panicked
            Err(_) => process::exit(1),
        },
    }
}

#[derive(Debug)]
pub enum Drawing {
    Path(Path),
    Polygon(Polygon),
}

pub struct Renderer {
    drawings: Vec<Drawing>,
    /// Polygon that is currently in the process of being filled
    /// Removed when EndFill is sent
    fill_polygon: Option<(Vec<Path>, Polygon)>,
}

impl Renderer {
    pub fn new() -> Renderer {
        Self {
            drawings: Vec::new(),
            fill_polygon: None,
        }
    }

    pub fn run(
        &mut self,
        drawing_rx: mpsc::Receiver<DrawingCommand>,
        events_tx: mpsc::Sender<Event>,
        state: ReadOnly,
    ) {
        let mut window: PistonWindow = WindowSettings::new(
            "Turtle", [800, 600]
        ).exit_on_esc(true).build().unwrap();

        let mut center = [0.0, 0.0];

        'renderloop:
        while let Some(e) = window.next() {
            if let Some(event) = from_piston_event(&e, |pt| pt.to_local_coords(center)) {
                match events_tx.send(event) {
                    Ok(_) => {},
                    // Quit - the server thread must have quit
                    Err(_) => break,
                }
            }

            // Need to handle all of the queries we receive at once so that any lag caused by
            // how long rendering takes doesn't cause any problems
            loop {
                match drawing_rx.try_recv() {
                    Ok(cmd) => self.handle_drawing_command(cmd),
                    Err(TryRecvError::Empty) => break, // Do nothing
                    Err(TryRecvError::Disconnected) => break 'renderloop, // Quit
                }
            }

            window.draw_2d(&e, |c, g| {
                let view = c.get_view_size();
                let width = view[0] as f64;
                let height = view[1] as f64;
                center = [width * 0.5, height * 0.5];

                // We clone the relevant state before rendering so that the rendering thread
                // doesn't need to keep locking, waiting or making the main thread wait
                let drawing = state.drawing().clone();
                let temporary_path = state.temporary_path().clone();
                let turtle = state.turtle().clone();

                self.render(c, g, center, &drawing, &temporary_path, &turtle);
            });
        }
    }

    /// Handles a drawing command sent from the main thread
    fn handle_drawing_command(&mut self, command: DrawingCommand) {
        //NOTE: Do not pass the ReadOnly state to this function. By the time a DrawingCommand is
        // handled, that state may be completely out of date
        use self::DrawingCommand::*;
        match command {
            StorePath(path) => {
                if self.fill_polygon.is_some() {
                    let &mut (ref mut border, ref mut poly) = self.fill_polygon.as_mut().unwrap();
                    border.push(path.clone());

                    let Path {start, end, ..} = path;
                    if poly.vertices.last().map_or(true, |&v| v != start) {
                        poly.vertices.push(start);
                    }
                    poly.vertices.push(end);
                }
                else if path.pen.enabled {
                    self.drawings.push(Drawing::Path(path));
                }
            },
            BeginFill(fill_color) => {
                // Calling begin_fill multiple times is okay, it just won't do anything until
                // end_fill is called
                self.fill_polygon = self.fill_polygon.take().or_else(|| Some((Vec::new(), Polygon {
                    vertices: Vec::new(),
                    fill_color: fill_color,
                })));
            },
            // Calling end_fill multiple times is not a problem
            EndFill => if let Some((border, poly)) = self.fill_polygon.take() {
                // Always add the border over the filled polygon so the border is drawn on top
                self.drawings.push(Drawing::Polygon(poly));
                self.drawings.extend(border.into_iter().filter_map(|p| if p.pen.enabled {
                    Some(Drawing::Path(p))
                } else { None }));
            },
            Clear => {
                self.drawings.clear();
                // Because clear doesn't actually shorten the capacity of the vector
                // We don't want to leak memory by leaving this Vec at whatever its size was before
                self.drawings.shrink_to_fit();
                self.fill_polygon.take();
            }
        }
    }

    /// The main rendering route. Dispatches to other functions as needed.
    fn render(&self, c: context::Context, g: &mut G2d, center: Point,
        drawing: &DrawingState, temporary_path: &Option<Path>, turtle: &TurtleState) {
        let background = drawing.background;
        clear(background.into(), g);

        for drawing in &self.drawings {
            match *drawing {
                Drawing::Path(ref path) => self.render_path(c, g, center, path),
                Drawing::Polygon(ref poly) => self.render_polygon(c, g, center,
                    poly.fill_color, poly.vertices.iter()),
            }
        }

        if let Some(&(ref border, ref poly)) = self.fill_polygon.as_ref() {
            // If the temporary_path is not None, we need to add it to the polygon being
            // filled or else the polygon will fall one edge behind in the animation
            let extra = temporary_path.as_ref().map_or(Vec::new(), |&Path {start, end, ..}| {
                if poly.vertices.last().map_or(true, |&v| v != start) {
                    vec![start, end]
                }
                else {
                    vec![end]
                }
            });
            self.render_polygon(c, g, center, poly.fill_color,
                poly.vertices.iter().chain(extra.iter()));

            for path in border {
                if path.pen.enabled {
                    self.render_path(c, g, center, path);
                }
            }
        }

        if let Some(ref path) = *temporary_path {
            if path.pen.enabled {
                self.render_path(c, g, center, path);
            }
        }

        self.render_shell(c, g, center, turtle);
    }

    /// Render a path assuming that its pen is enabled
    fn render_path(&self, c: context::Context, g: &mut G2d, center: Point, path: &Path) {
        let &Path {start, end, ref pen} = path;
        let &Pen {thickness, color, enabled} = pen;
        debug_assert!(enabled, "bug: attempt to render path when pen was not enabled");

        let start = start.to_screen_coords(center);
        let end = end.to_screen_coords(center);

        line(color.into(), thickness,
            [start[0], start[1], end[0], end[1]],
            c.transform, g);
    }

    /// Render a polygon given its vertices
    fn render_polygon<'a, T: Iterator<Item=&'a Point>>(
        &self,
        c: context::Context,
        g: &mut G2d,
        center: Point,
        fill_color: Color,
        verts: T,
    ) {
        // Performance note: Why make this function generic instead of just taking Polygon?
        // Answer: render_polygon is called multiple times. It's called repeatedly in a loop, and
        // it is also called when drawing the current fill_polygon. Rather than moving the
        // code to *maybe* add the temporary_path to the rendered polygon into this method, we
        // avoid branching unnecessarily by allowing the repeated caller to do what is fast, then
        // doing the slow thing (checking if the path is None) only once when it is needed.
        //
        // We pass in the points as an Iterator so that they do not need to be collected into any
        // struct. This avoids an allocation that really isn't needed since these are all temporary
        // anyway. Everything is going to get copied anyway on the next line. No need to do it
        // twice.
        //
        // See the commit before this comment was added for the approach that would have required
        // branching in every iteration of the loop where render_polygon is called over and over
        // again.
        let verts = verts.map(|p| p.to_screen_coords(center)).collect::<Vec<_>>();
        polygon(fill_color.into(), &verts, c.transform, g);
    }

    /// Draw the turtle's shell
    fn render_shell(&self, c: context::Context, g: &mut G2d, center: Point,
        &TurtleState {position, heading, visible, ..}: &TurtleState) {
        // Calculate all the points on the shell by rotating the shell shape by the turtle's
        // heading and moving it to the turtle's position
        if !visible {
            return;
        }

        let cos = heading.cos();
        let sin = heading.sin();
        let turtle_x = position[0];
        let turtle_y = position[1];
        let shell: Vec<_> = [
            [0., 15.],
            [10., 0.],
            [0., -15.],
        ].into_iter().map(|pt| {
            // Rotate each point by the heading and add the current turtle position
            let x = cos * pt[0] - sin * pt[1] + turtle_x;
            let y = sin * pt[0] + cos * pt[1] + turtle_y;
            [x, y].to_screen_coords(center)
        }).collect();

        // Draw the turtle shell with its background first, then its border
        polygon(color::WHITE.into(), &shell, c.transform, g);
        for i in 0..shell.len() {
            let start = shell[i];
            let end = shell[(i + 1) % shell.len()];

            line(color::BLACK.into(), 1.,
            [start[0], start[1], end[0], end[1]],
            c.transform, g);
        }
    }
}
<commit_msg>Adding a check to make sure windows are only created on the main thread on all platforms<commit_after>// During tests, we disable the renderer and that causes a bunch of warnings that we just want
// to get rid of.
// See Cargo.toml for an explanation of this attribute
#![cfg_attr(any(feature = "test", test), allow(dead_code, unused_variables))]

use std::env;
use std::thread;
use std::process;
use std::sync::mpsc::{self, TryRecvError};

use piston_window::{
    PistonWindow,
    WindowSettings,
    G2d,
    context,
    clear,
    line,
    polygon,
};

use app::{TurtleApp, ReadOnly};
use extensions::ConvertScreenCoordinates;
use state::{Path, Polygon, Pen, TurtleState, DrawingState};
use query::DrawingCommand;
use event::{Event, from_piston_event};
use types::Point;
use color::{self, Color};
use server;

/// Setup the turtle window in advance
///
/// You must call this function at the beginning of `main()` if you do not create the
/// turtle immediately using [`Turtle::new()`].
///
/// It's a good idea to call this function before any other code runs in `main()`. Programs that
/// parse command line arguments or look at environment variables may **fail** to start if this
/// function is not called right at the beginning of the program. Programs that perform any
/// expensive computations may experience delayed start up problems unless they call this
/// function first.
///
/// The [`Turtle::new()`] method will call this function for you so that you don't need to worry
/// about this unless you are doing something before that.
///
/// # Example
/// ```rust,no_run
/// # #![allow(unused_variables, unused_mut)]
/// extern crate turtle;
/// use turtle::Turtle;
///
/// fn main() {
///     // Initializes the turtle renderer first so that there is less delay when a Turtle
///     // is created and so that there are no conflicts with command line arguments or
///     // environment variables.
///     // Not required if Turtle::new() is already at the top of main.
///     turtle::setup();
///
///     // Do all kinds of expensive work here...
///     // Feel free to check environment variables, command line arguments, etc.
///
///     // Create the turtle when you are ready
///     // Turtle::new() will also call setup(), but calling it twice doesn't matter
///     let mut turtle = Turtle::new();
///     // Do things with the turtle...
/// }
/// ```
///
/// [`Turtle::new()`]: struct.Turtle.html#method.new
pub fn setup() {
    // If this environment variable is present, this process is taken over so that no other
    // code runs after main(). This allows us to ship one executable that appears to
    // have two separate processes.
    // We run the renderer loop and then immediately exit.
    if env::var("RUN_TURTLE_CANVAS").unwrap_or_else(|_| "".to_owned()) == "true" {
        // This code MUST be run on the main thread.

        // Run the renderer process
        main();
        unreachable!("bug: renderer loop did not exit after finishing");
    }
}

/// Run the renderer process in the current thread
///
/// This function must run in the main thread ONLY
pub fn main() {
    let app = TurtleApp::new();
    let read_only = app.read_only();
    let (drawing_tx, drawing_rx) = mpsc::channel();
    let (events_tx, events_rx) = mpsc::channel();

    // The running channel is entirely for checking if the other thread is still active.
    // We need to check because while we can exit while that thread is still running, we want
    // any errors caused in that thread to be reported.
    let (running_tx, running_rx) = mpsc::channel();
    let handle = thread::spawn(move || {
        server::run(app, drawing_tx, events_rx, running_tx);
    });

    // Renderer MUST run on the main thread or else it will panic on MacOS
    #[cfg(not(any(feature = "test", test)))]
    Renderer::new().run(drawing_rx, events_tx, read_only);

    // Quit immediately when the window is closed

    // Check if an error has occurred on the thread
    match running_rx.try_recv() {
        Ok(_) => unreachable!("bug: running channel should always be empty"),
        // The thread was still running, exit normally
        Err(mpsc::TryRecvError::Empty) => process::exit(0),
        Err(mpsc::TryRecvError::Disconnected) => match handle.join() {
            Ok(_) => process::exit(0),
            // The other thread must have panicked
            Err(_) => process::exit(1),
        },
    }
}

#[derive(Debug)]
pub enum Drawing {
    Path(Path),
    Polygon(Polygon),
}

pub struct Renderer {
    drawings: Vec<Drawing>,
    /// Polygon that is currently in the process of being filled
    /// Removed when EndFill is sent
    fill_polygon: Option<(Vec<Path>, Polygon)>,
}

impl Renderer {
    pub fn new() -> Renderer {
        Self {
            drawings: Vec::new(),
            fill_polygon: None,
        }
    }

    pub fn run(
        &mut self,
        drawing_rx: mpsc::Receiver<DrawingCommand>,
        events_tx: mpsc::Sender<Event>,
        state: ReadOnly,
    ) {
        // This check isn't foolproof. Someone can always create a thread named "main".
        if thread::current().name().unwrap_or("") != "main" {
            // In order to maintain compatibility with MacOS, we need to make sure that windows are
            // only created on the main thread. We do this check on all platforms so that no one
            // can accidentally make a change that creates the window off of the main thread.
            unreachable!("bug: windows can only be created on the main thread");
        }
        let mut window: PistonWindow = WindowSettings::new(
            "Turtle", [800, 600]
        ).exit_on_esc(true).build().unwrap();

        let mut center = [0.0, 0.0];

        'renderloop:
        while let Some(e) = window.next() {
            if let Some(event) = from_piston_event(&e, |pt| pt.to_local_coords(center)) {
                match events_tx.send(event) {
                    Ok(_) => {},
                    // Quit - the server thread must have quit
                    Err(_) => break,
                }
            }

            // Need to handle all of the queries we receive at once so that any lag caused by
            // how long rendering takes doesn't cause any problems
            loop {
                match drawing_rx.try_recv() {
                    Ok(cmd) => self.handle_drawing_command(cmd),
                    Err(TryRecvError::Empty) => break, // Do nothing
                    Err(TryRecvError::Disconnected) => break 'renderloop, // Quit
                }
            }

            window.draw_2d(&e, |c, g| {
                let view = c.get_view_size();
                let width = view[0] as f64;
                let height = view[1] as f64;
                center = [width * 0.5, height * 0.5];

                // We clone the relevant state before rendering so that the rendering thread
                // doesn't need to keep locking, waiting or making the main thread wait
                let drawing = state.drawing().clone();
                let temporary_path = state.temporary_path().clone();
                let turtle = state.turtle().clone();

                self.render(c, g, center, &drawing, &temporary_path, &turtle);
            });
        }
    }

    /// Handles a drawing command sent from the main thread
    fn handle_drawing_command(&mut self, command: DrawingCommand) {
        //NOTE: Do not pass the ReadOnly state to this function. By the time a DrawingCommand is
        // handled, that state may be completely out of date
        use self::DrawingCommand::*;
        match command {
            StorePath(path) => {
                if self.fill_polygon.is_some() {
                    let &mut (ref mut border, ref mut poly) = self.fill_polygon.as_mut().unwrap();
                    border.push(path.clone());

                    let Path {start, end, ..} = path;
                    if poly.vertices.last().map_or(true, |&v| v != start) {
                        poly.vertices.push(start);
                    }
                    poly.vertices.push(end);
                }
                else if path.pen.enabled {
                    self.drawings.push(Drawing::Path(path));
                }
            },
            BeginFill(fill_color) => {
                // Calling begin_fill multiple times is okay, it just won't do anything until
                // end_fill is called
                self.fill_polygon = self.fill_polygon.take().or_else(|| Some((Vec::new(), Polygon {
                    vertices: Vec::new(),
                    fill_color: fill_color,
                })));
            },
            // Calling end_fill multiple times is not a problem
            EndFill => if let Some((border, poly)) = self.fill_polygon.take() {
                // Always add the border over the filled polygon so the border is drawn on top
                self.drawings.push(Drawing::Polygon(poly));
                self.drawings.extend(border.into_iter().filter_map(|p| if p.pen.enabled {
                    Some(Drawing::Path(p))
                } else { None }));
            },
            Clear => {
                self.drawings.clear();
                // Because clear doesn't actually shorten the capacity of the vector
                // We don't want to leak memory by leaving this Vec at whatever its size was before
                self.drawings.shrink_to_fit();
                self.fill_polygon.take();
            }
        }
    }

    /// The main rendering route. Dispatches to other functions as needed.
    fn render(&self, c: context::Context, g: &mut G2d, center: Point,
        drawing: &DrawingState, temporary_path: &Option<Path>, turtle: &TurtleState) {
        let background = drawing.background;
        clear(background.into(), g);

        for drawing in &self.drawings {
            match *drawing {
                Drawing::Path(ref path) => self.render_path(c, g, center, path),
                Drawing::Polygon(ref poly) => self.render_polygon(c, g, center,
                    poly.fill_color, poly.vertices.iter()),
            }
        }

        if let Some(&(ref border, ref poly)) = self.fill_polygon.as_ref() {
            // If the temporary_path is not None, we need to add it to the polygon being
            // filled or else the polygon will fall one edge behind in the animation
            let extra = temporary_path.as_ref().map_or(Vec::new(), |&Path {start, end, ..}| {
                if poly.vertices.last().map_or(true, |&v| v != start) {
                    vec![start, end]
                }
                else {
                    vec![end]
                }
            });
            self.render_polygon(c, g, center, poly.fill_color,
                poly.vertices.iter().chain(extra.iter()));

            for path in border {
                if path.pen.enabled {
                    self.render_path(c, g, center, path);
                }
            }
        }

        if let Some(ref path) = *temporary_path {
            if path.pen.enabled {
                self.render_path(c, g, center, path);
            }
        }

        self.render_shell(c, g, center, turtle);
    }

    /// Render a path assuming that its pen is enabled
    fn render_path(&self, c: context::Context, g: &mut G2d, center: Point, path: &Path) {
        let &Path {start, end, ref pen} = path;
        let &Pen {thickness, color, enabled} = pen;
        debug_assert!(enabled, "bug: attempt to render path when pen was not enabled");

        let start = start.to_screen_coords(center);
        let end = end.to_screen_coords(center);

        line(color.into(), thickness,
            [start[0], start[1], end[0], end[1]],
            c.transform, g);
    }

    /// Render a polygon given its vertices
    fn render_polygon<'a, T: Iterator<Item=&'a Point>>(
        &self,
        c: context::Context,
        g: &mut G2d,
        center: Point,
        fill_color: Color,
        verts: T,
    ) {
        // Performance note: Why make this function generic instead of just taking Polygon?
        // Answer: render_polygon is called multiple times. It's called repeatedly in a loop, and
        // it is also called when drawing the current fill_polygon. Rather than moving the
        // code to *maybe* add the temporary_path to the rendered polygon into this method, we
        // avoid branching unnecessarily by allowing the repeated caller to do what is fast, then
        // doing the slow thing (checking if the path is None) only once when it is needed.
        //
        // We pass in the points as an Iterator so that they do not need to be collected into any
        // struct. This avoids an allocation that really isn't needed since these are all temporary
        // anyway. Everything is going to get copied anyway on the next line. No need to do it
        // twice.
        //
        // See the commit before this comment was added for the approach that would have required
        // branching in every iteration of the loop where render_polygon is called over and over
        // again.
        let verts = verts.map(|p| p.to_screen_coords(center)).collect::<Vec<_>>();
        polygon(fill_color.into(), &verts, c.transform, g);
    }

    /// Draw the turtle's shell
    fn render_shell(&self, c: context::Context, g: &mut G2d, center: Point,
        &TurtleState {position, heading, visible, ..}: &TurtleState) {
        // Calculate all the points on the shell by rotating the shell shape by the turtle's
        // heading and moving it to the turtle's position
        if !visible {
            return;
        }

        let cos = heading.cos();
        let sin = heading.sin();
        let turtle_x = position[0];
        let turtle_y = position[1];
        let shell: Vec<_> = [
            [0., 15.],
            [10., 0.],
            [0., -15.],
        ].into_iter().map(|pt| {
            // Rotate each point by the heading and add the current turtle position
            let x = cos * pt[0] - sin * pt[1] + turtle_x;
            let y = sin * pt[0] + cos * pt[1] + turtle_y;
            [x, y].to_screen_coords(center)
        }).collect();

        // Draw the turtle shell with its background first, then its border
        polygon(color::WHITE.into(), &shell, c.transform, g);
        for i in 0..shell.len() {
            let start = shell[i];
            let end = shell[(i + 1) % shell.len()];

            line(color::BLACK.into(), 1.,
            [start[0], start[1], end[0], end[1]],
            c.transform, g);
        }
    }
}
<|endoftext|>


<commit_before>extern crate vulkano;
extern crate winit;

#[cfg(target_os = "macos")]
extern crate objc;
#[cfg(target_os = "macos")]
extern crate cocoa;
#[cfg(target_os = "macos")]
extern crate metal_rs as metal;

use std::error;
use std::fmt;
use std::ptr;
use std::sync::Arc;

use vulkano::instance::Instance;
use vulkano::instance::InstanceExtensions;
use vulkano::swapchain::Surface;
use vulkano::swapchain::SurfaceCreationError;
use winit::{EventsLoop, WindowBuilder};
use winit::CreationError as WindowCreationError;

#[cfg(target_os = "macos")]
use objc::runtime::{YES};
#[cfg(target_os = "macos")]
use cocoa::base::id as cocoa_id;
#[cfg(target_os = "macos")]
use cocoa::appkit::{NSWindow, NSView};
#[cfg(target_os = "macos")]
use metal::*;

use std::mem;

pub fn required_extensions() -> InstanceExtensions {
    let ideal = InstanceExtensions {
        khr_surface: true,
        khr_xlib_surface: true,
        khr_xcb_surface: true,
        khr_wayland_surface: true,
        khr_mir_surface: true,
        khr_android_surface: true,
        khr_win32_surface: true,
        mvk_ios_surface: true,
        mvk_macos_surface: true,
        ..InstanceExtensions::none()
    };

    match InstanceExtensions::supported_by_core() {
        Ok(supported) => supported.intersection(&ideal),
        Err(_) => InstanceExtensions::none()
    }
}

pub trait VkSurfaceBuild {
    fn build_vk_surface(self, events_loop: &EventsLoop, instance: Arc<Instance>) -> Result<Window, CreationError>;
}

impl VkSurfaceBuild for WindowBuilder {
    fn build_vk_surface(self, events_loop: &EventsLoop, instance: Arc<Instance>) -> Result<Window, CreationError> {
        let window = try!(self.build(events_loop));
        let surface = try!(unsafe { winit_to_surface(instance, &window) });

        Ok(Window {
            window: window,
            surface: surface,
        })
    }
}

pub struct Window {
    window: winit::Window,
    surface: Arc<Surface>,
}

impl Window {
    #[inline]
    pub fn window(&self) -> &winit::Window {
        &self.window
    }

    #[inline]
    pub fn surface(&self) -> &Arc<Surface> {
        &self.surface
    }
}

/// Error that can happen when creating a window.
#[derive(Debug)]
pub enum CreationError {
    /// Error when creating the surface.
    SurfaceCreationError(SurfaceCreationError),
    /// Error when creating the window.
    WindowCreationError(WindowCreationError),
}

impl error::Error for CreationError {
    #[inline]
    fn description(&self) -> &str {
        match *self {
            CreationError::SurfaceCreationError(_) => "error while creating the surface",
            CreationError::WindowCreationError(_) => "error while creating the window",
        }
    }

    #[inline]
    fn cause(&self) -> Option<&error::Error> {
        match *self {
            CreationError::SurfaceCreationError(ref err) => Some(err),
            CreationError::WindowCreationError(ref err) => Some(err),
        }
    }
}

impl fmt::Display for CreationError {
    #[inline]
    fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(fmt, "{}", error::Error::description(self))
    }
}

impl From<SurfaceCreationError> for CreationError {
    #[inline]
    fn from(err: SurfaceCreationError) -> CreationError {
        CreationError::SurfaceCreationError(err)
    }
}

impl From<WindowCreationError> for CreationError {
    #[inline]
    fn from(err: WindowCreationError) -> CreationError {
        CreationError::WindowCreationError(err)
    }
}

#[cfg(target_os = "android")]
unsafe fn winit_to_surface(instance: Arc<Instance>,
                           win: &winit::Window)
                           -> Result<Arc<Surface>, SurfaceCreationError> {
    use winit::os::android::WindowExt;
    Surface::from_anativewindow(instance, win.get_native_window())
}

#[cfg(all(unix, not(target_os = "android"), not(target_os = "macos")))]
unsafe fn winit_to_surface(instance: Arc<Instance>,
                           win: &winit::Window)
                           -> Result<Arc<Surface>, SurfaceCreationError> {
    use winit::os::unix::WindowExt;
    match (win.get_wayland_display(), win.get_wayland_surface()) {
        (Some(display), Some(surface)) => Surface::from_wayland(instance, display, surface),
        _ => {
            // No wayland display found, check if we can use xlib.
            // If not, we use xcb.
            if instance.loaded_extensions().khr_xlib_surface {
                Surface::from_xlib(instance,
                                   win.get_xlib_display().unwrap(),
                                   win.get_xlib_window().unwrap() as _)
            } else {
                Surface::from_xcb(instance,
                                   win.get_xcb_connection().unwrap(),
                                   win.get_xlib_window().unwrap() as _)
            }
        }
    }
}

#[cfg(target_os = "windows")]
unsafe fn winit_to_surface(instance: Arc<Instance>,
                           win: &winit::Window)
                           -> Result<Arc<Surface>, SurfaceCreationError> {
    use winit::os::windows::WindowExt;
    Surface::from_hwnd(instance,
                       ptr::null() as *const (), // FIXME
                       win.get_hwnd())
}

#[cfg(target_os = "macos")]
unsafe fn winit_to_surface(instance: Arc<Instance>, win: &winit::Window)
                           -> Result<Arc<Surface>, SurfaceCreationError>
{
    use winit::os::macos::WindowExt;

    unsafe {
        let wnd: cocoa_id = mem::transmute(win.get_nswindow());

        let layer = CAMetalLayer::new();

        layer.set_edge_antialiasing_mask(0);
        layer.set_presents_with_transaction(false);
        layer.remove_all_animations();

        let view = wnd.contentView();
        view.setWantsLayer(YES);
        view.setLayer(mem::transmute(layer.0));  // Bombs here with out of memory
    }

    Surface::from_macos_moltenvk(instance, win.get_nsview() as *const ())
}
<commit_msg>Fix actual type not being a reference<commit_after>extern crate vulkano;
extern crate winit;

#[cfg(target_os = "macos")]
extern crate objc;
#[cfg(target_os = "macos")]
extern crate cocoa;
#[cfg(target_os = "macos")]
extern crate metal_rs as metal;

use std::error;
use std::fmt;
use std::ptr;
use std::sync::Arc;

use vulkano::instance::Instance;
use vulkano::instance::InstanceExtensions;
use vulkano::swapchain::Surface;
use vulkano::swapchain::SurfaceCreationError;
use winit::{EventsLoop, WindowBuilder};
use winit::CreationError as WindowCreationError;

#[cfg(target_os = "macos")]
use objc::runtime::{YES};
#[cfg(target_os = "macos")]
use cocoa::base::id as cocoa_id;
#[cfg(target_os = "macos")]
use cocoa::appkit::{NSWindow, NSView};
#[cfg(target_os = "macos")]
use metal::*;

use std::mem;

pub fn required_extensions() -> InstanceExtensions {
    let ideal = InstanceExtensions {
        khr_surface: true,
        khr_xlib_surface: true,
        khr_xcb_surface: true,
        khr_wayland_surface: true,
        khr_mir_surface: true,
        khr_android_surface: true,
        khr_win32_surface: true,
        mvk_ios_surface: true,
        mvk_macos_surface: true,
        ..InstanceExtensions::none()
    };

    match InstanceExtensions::supported_by_core() {
        Ok(supported) => supported.intersection(&ideal),
        Err(_) => InstanceExtensions::none()
    }
}

pub trait VkSurfaceBuild {
    fn build_vk_surface(self, events_loop: &EventsLoop, instance: Arc<Instance>) -> Result<Window, CreationError>;
}

impl VkSurfaceBuild for WindowBuilder {
    fn build_vk_surface(self, events_loop: &EventsLoop, instance: Arc<Instance>) -> Result<Window, CreationError> {
        let window = try!(self.build(events_loop));
        let surface = try!(unsafe { winit_to_surface(instance, &window) });

        Ok(Window {
            window: window,
            surface: surface,
        })
    }
}

pub struct Window {
    window: winit::Window,
    surface: Arc<Surface>,
}

impl Window {
    #[inline]
    pub fn window(&self) -> &winit::Window {
        &self.window
    }

    #[inline]
    pub fn surface(&self) -> &Arc<Surface> {
        &self.surface
    }
}

/// Error that can happen when creating a window.
#[derive(Debug)]
pub enum CreationError {
    /// Error when creating the surface.
    SurfaceCreationError(SurfaceCreationError),
    /// Error when creating the window.
    WindowCreationError(WindowCreationError),
}

impl error::Error for CreationError {
    #[inline]
    fn description(&self) -> &str {
        match *self {
            CreationError::SurfaceCreationError(_) => "error while creating the surface",
            CreationError::WindowCreationError(_) => "error while creating the window",
        }
    }

    #[inline]
    fn cause(&self) -> Option<&error::Error> {
        match *self {
            CreationError::SurfaceCreationError(ref err) => Some(err),
            CreationError::WindowCreationError(ref err) => Some(err),
        }
    }
}

impl fmt::Display for CreationError {
    #[inline]
    fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(fmt, "{}", error::Error::description(self))
    }
}

impl From<SurfaceCreationError> for CreationError {
    #[inline]
    fn from(err: SurfaceCreationError) -> CreationError {
        CreationError::SurfaceCreationError(err)
    }
}

impl From<WindowCreationError> for CreationError {
    #[inline]
    fn from(err: WindowCreationError) -> CreationError {
        CreationError::WindowCreationError(err)
    }
}

#[cfg(target_os = "android")]
unsafe fn winit_to_surface(instance: Arc<Instance>,
                           win: &winit::Window)
                           -> Result<Arc<Surface>, SurfaceCreationError> {
    use winit::os::android::WindowExt;
    Surface::from_anativewindow(instance, win.get_native_window())
}

#[cfg(all(unix, not(target_os = "android"), not(target_os = "macos")))]
unsafe fn winit_to_surface(instance: Arc<Instance>,
                           win: &winit::Window)
                           -> Result<Arc<Surface>, SurfaceCreationError> {
    use winit::os::unix::WindowExt;
    match (win.get_wayland_display(), win.get_wayland_surface()) {
        (Some(display), Some(surface)) => Surface::from_wayland(instance, display, surface),
        _ => {
            // No wayland display found, check if we can use xlib.
            // If not, we use xcb.
            if instance.loaded_extensions().khr_xlib_surface {
                Surface::from_xlib(instance,
                                   win.get_xlib_display().unwrap(),
                                   win.get_xlib_window().unwrap() as _)
            } else {
                Surface::from_xcb(instance,
                                   win.get_xcb_connection().unwrap(),
                                   win.get_xlib_window().unwrap() as _)
            }
        }
    }
}

#[cfg(target_os = "windows")]
unsafe fn winit_to_surface(instance: Arc<Instance>,
                           win: &winit::Window)
                           -> Result<Arc<Surface>, SurfaceCreationError> {
    use winit::os::windows::WindowExt;
    Surface::from_hwnd(instance,
                       ptr::null() as *const (), // FIXME
                       win.get_hwnd())
}

#[cfg(target_os = "macos")]
unsafe fn winit_to_surface(instance: Arc<Instance>, win: &winit::Window)
                           -> Result<Arc<Surface>, SurfaceCreationError>
{
    use winit::os::macos::WindowExt;

    unsafe {
        let wnd: cocoa_id = mem::transmute(win.get_nswindow());

        let layer = CAMetalLayer::new();

        layer.set_edge_antialiasing_mask(0);
        layer.set_presents_with_transaction(false);
        layer.remove_all_animations();

        let view = wnd.contentView();
        view.setWantsLayer(YES);
        view.setLayer(mem::transmute(layer.0));  // Bombs here with out of memory
    }

    Surface::from_macos_moltenvk(&instance, win.get_nsview() as *const ())
}
<|endoftext|>


<commit_before>extern mod extra;

use extra::net::tcp;
use extra::net::ip;
use extra::uv;
use extra::arc::RWARC;
use std::{str, io, int, uint, task, comm};
use std::hashmap::HashMap;

fn main() {
    println("Started");
    let iotask = &uv::global_loop::get();
    let port = 6380;

    let data = ~HashMap::new::<~[u8], ~[u8]>();
    let dataARC = RWARC(data);

    let listen_res = do tcp::listen(ip::v4::parse_addr("127.0.0.1"), port, 1000, iotask,
        |_kill_ch| {
            // pass the kill_ch to your main loop or wherever you want
            // to be able to externally kill the server from
            println(fmt!("Server is listening on port %u", port));
        }
    ) |new_conn, kill_ch| {
        println("New client");

        let (port, channel) = comm::stream::<Option<tcp::TcpErrData>>();
        let localARC = dataARC.clone();

        do task::spawn_supervised {
            let accept_result = tcp::accept(new_conn);
            match accept_result {
                Err(accept_error) => {
                    io::stderr().write_line("Failed to accept connection");
                    channel.send(Some(accept_error));
                },
                Ok(sock) => {
                    let peer_addr = &sock.get_peer_addr();
                    println(fmt!("Client connected: %s on port %u", ip::format_addr(peer_addr), ip::get_port(peer_addr)));
                    channel.send(None);

                    let sockbuf = tcp::socket_buf(sock);
                    let crlf = bytes!("\r\n");
                    loop {
                        let parse_res = parse_args(sockbuf);
                        let mut response;
                        match parse_res {
                            Err(msg) => {
                                response = msg.as_bytes().to_owned();
                            },
                            Ok(args) => {
                                response = cmd_dispatcher(&localARC, args);
                            }
                        }
                        response.push_all(crlf);
                        sockbuf.write(response);
                    }
                }
            }
        };

        match port.recv() {
            // shut down listen()
            Some(err_data) => kill_ch.send(Some(err_data)),
            // wait for next connection
            None => ()
        }
    };

    if listen_res.is_err() {
        io::stderr().write_line(fmt!("Failed to bind address: %?", listen_res.get_err()));
    }
}

fn parse_args(buf: tcp::TcpSocketBuf) -> Result<~[~[u8]], ~str> {
    let first_char = buf.read_char();
    let has_arg_count = first_char == '*';
    let mut args = ~[];

    if has_arg_count {
        let mut arg_count;
        match uint::from_str(buf.read_until('\r'.to_ascii().to_byte(), false)) {
            Some(count) => {
                arg_count = count;
            },
            None => {
                return Err(~"Could not parse argument count as uint");
            }
        }

        // discard \n
        buf.read_byte();

        while arg_count > 0 {
            let chr = buf.read_char();
            let has_arg_len = chr == '$';
            if !has_arg_len {
                return Err(fmt!("No argument length found, expected $n, got %?", chr));
            }
            let arg_len;
            match uint::from_str(buf.read_until('\r'.to_ascii().to_byte(), false)) {
                Some(count) => {
                    arg_len = count;
                },
                None => {
                    return Err(~"Could not parse argument length as uint");
                }
            }
            // discard \n
            buf.read_byte();

            args.push(buf.read_bytes(arg_len));
            arg_count -= 1;

            // discard \r\n
            buf.read_bytes(2);
        }
    } else {
        let input = str::from_char(first_char);
        let input = input.append(buf.read_until('\r'.to_ascii().to_byte(), false));

        // discard \n
        buf.read_char();

        let words: ~[&str] = input.split_iter(' ').collect();
        args = words.map(|word| {
            word.as_bytes().to_owned()
        })
    }

    Ok(args)
}

fn cmd_dispatcher(arc: &RWARC<~HashMap<~[u8], ~[u8]>>, mut args: ~[~[u8]]) -> ~[u8] {
    let command = args[0].to_ascii().to_lower().into_str().to_owned();

    //println(fmt!("%s: %?", command, args));

    let mut output = ~[];
    if command == ~"get" {
        do arc.read() |data| {
            let res = data.find(&args[1]);
            if res.is_some() {
                let result = [~"$", res.unwrap().len().to_str(), ~"\r\n"].concat();
                output = result.as_bytes().to_owned();
                output.push_all(*res.unwrap());
            } else {
                output = bytes!("$-1").to_owned();
            }
        }
    } else if command == ~"set" {
        if (args.len() < 3) {
            output = bytes!("-ERR wrong number of arguments for 'set' command").to_owned();
        } else {
            do arc.write() |data| {
                args.truncate(3);
                let val = args.pop();
                let key = args.pop();
                data.insert(key, val);

                output = bytes!("+OK").to_owned();
            }
        }
    } else if command == ~"incr" || command == ~"decr" || command == ~"incrby" || command == ~"decrby" {
        let mut cur_val = 0;

        do arc.read() |data| {
            let res = data.find(&args[1]);

            if res.is_some() {
                match int::parse_bytes(*res.unwrap(), 10) {
                    Some(val) => {
                        cur_val = val;
                    },
                    None => {
                        output = bytes!("-ERR value is not an integer or out of range").to_owned();
                    }
                }
            }
        }

        let mut incr_by = 1;
        if command == ~"incrby" || command == ~"decrby" {
            args.truncate(3);
            match int::parse_bytes(args.pop(), 10) {
                Some(val) => {
                    incr_by = val;
                },
                None => {
                    output = bytes!("-ERR incrby argument is not an integer or out of range").to_owned();
                }
            }
        }
        if command == ~"decr" || command == ~"decrby" {
            incr_by = -incr_by;
        }

        if output.len() == 0 {
            do arc.write() |data| {
                args.truncate(2);
                let key = args.pop();
                let new_val = (cur_val + incr_by).to_str();
                let new_val = new_val.as_bytes().to_owned();
                output = bytes!(":").to_owned();
                output.push_all(new_val);
                data.insert(key, new_val);
            }
        }
    } else {
        let result = fmt!("-ERR unknown command '%s'", command);
        output = result.as_bytes().to_owned();
    }

    output
}
<commit_msg>Update to rust 0.8-dev<commit_after>extern mod extra;

use std::cell::Cell;
use std::rt::io::net::tcp::{TcpListener, TcpStream};
use std::rt::io::net::ip::Ipv4;
use std::rt::io::{Listener, Reader, ReaderUtil, Writer};
use extra::arc::RWArc;
use std::hashmap::HashMap;
use std::{uint, int, str};

fn main() {
    println("Started");

    let data = ~HashMap::new::<~[u8], ~[u8]>();
    let data_arc = RWArc::new(data);

    let port = 6380;
    let mut listener = TcpListener::bind(Ipv4(127, 0, 0, 1, port)).expect("Unable to bind to 127.0.0.1:6380");
    println(fmt!("Server is listening on %s", listener.socket_name().expect("").to_str()));

    loop {
        let stream = Cell::new(listener.accept());

        let local_arc = data_arc.clone();

        do std::task::spawn_supervised {
            let mut stream = stream.take().unwrap();
            println(fmt!("Client connected: %s", stream.peer_name().expect("").to_str()));

            let crlf = bytes!("\r\n");
            loop {
                let parse_res = parse_args(&mut stream);
                let mut response;
                match parse_res {
                    Err(msg) => {
                        response = msg.as_bytes().to_owned();
                    },
                    Ok(args) => {
                        response = cmd_dispatcher(&local_arc, args);
                    }
                }
                response.push_all(crlf);
                stream.write(response);
            }
        }
    }
}

fn read_byte(stream: &mut TcpStream) -> u8 {
    stream.read_byte().expect("")
}

fn read_bytes(stream: &mut TcpStream, len: uint) -> ~[u8] {
    let mut buffer = std::vec::with_capacity::<u8>(len);

    for i in range(0, len) {
        buffer[i] = stream.read_byte().expect("");
    }

    buffer
}

fn read_until(stream: &mut TcpStream, until: u8) -> ~[u8] {
    let mut buffer: ~[u8] = ~[];

    loop {
        let byte = stream.read_byte().expect("");
        if byte == until {
            break
        }
        buffer.push(byte);
    }

    buffer
}

static CR: u8 = '\r' as u8;
static STAR: u8 = '*' as u8;
static DOLLAR: u8 = '$' as u8;

fn parse_args(stream: &mut TcpStream) -> Result<~[~[u8]], ~str> {
    let first_byte = read_byte(stream);
    let mut args = ~[];

    if first_byte == STAR {
        let mut arg_count;
        match uint::parse_bytes(read_until(stream, CR), 10) {
            Some(count) => {
                arg_count = count;
            },
            None => {
                return Err(~"Could not parse argument count as uint");
            }
        }

        // discard \n
        read_byte(stream);

        for _ in range(0, arg_count) {
            let byte = read_byte(stream);
            if byte != DOLLAR {
                return Err(fmt!("No argument length found, expected $, got %?", byte));
            }
            let arg_len;
            match uint::parse_bytes(read_until(stream, CR), 10) {
                Some(count) => {
                    arg_len = count;
                },
                None => {
                    return Err(~"Could not parse argument length as uint");
                }
            }
            // discard \n
            read_byte(stream);

            args.push(stream.read_bytes(arg_len));

            // discard \r\n
            stream.read_bytes(2);
        }
    } else {
        let input = str::from_byte(first_byte);
        let input = input.append(str::from_bytes(read_until(stream, CR)));

        // discard \n
        stream.read_byte();

        let words: ~[&str] = input.split_iter(' ').collect();
        args = words.map(|word| {
            word.as_bytes().to_owned()
        })
    }

    Ok(args)
}

fn cmd_dispatcher(arc: &RWArc<~HashMap<~[u8], ~[u8]>>, mut args: ~[~[u8]]) -> ~[u8] {
    let command = args[0].to_ascii().to_lower().into_str().to_owned();

    //println(fmt!("%s: %?", command, args));

    let mut output = ~[];
    if command == ~"get" {
        do arc.read() |data| {
            let res = data.find(&args[1]);
            if res.is_some() {
                let result = [~"$", res.unwrap().len().to_str(), ~"\r\n"].concat();
                output = result.as_bytes().to_owned();
                output.push_all(*res.unwrap());
            } else {
                output = bytes!("$-1").to_owned();
            }
        }
    } else if command == ~"set" {
        if (args.len() < 3) {
            output = bytes!("-ERR wrong number of arguments for 'set' command").to_owned();
        } else {
            do arc.write() |data| {
                args.truncate(3);
                let val = args.pop();
                let key = args.pop();
                data.insert(key, val);

                output = bytes!("+OK").to_owned();
            }
        }
    } else if command == ~"incr" || command == ~"decr" || command == ~"incrby" || command == ~"decrby" {
        let mut cur_val = 0;

        do arc.read() |data| {
            let res = data.find(&args[1]);

            if res.is_some() {
                match int::parse_bytes(*res.unwrap(), 10) {
                    Some(val) => {
                        cur_val = val;
                    },
                    None => {
                        output = bytes!("-ERR value is not an integer or out of range").to_owned();
                    }
                }
            }
        }

        let mut incr_by = 1;
        if command == ~"incrby" || command == ~"decrby" {
            args.truncate(3);
            match int::parse_bytes(args.pop(), 10) {
                Some(val) => {
                    incr_by = val;
                },
                None => {
                    output = bytes!("-ERR incrby argument is not an integer or out of range").to_owned();
                }
            }
        }
        if command == ~"decr" || command == ~"decrby" {
            incr_by = -incr_by;
        }

        if output.len() == 0 {
            do arc.write() |data| {
                args.truncate(2);
                let key = args.pop();
                let new_val = (cur_val + incr_by).to_str();
                let new_val = new_val.as_bytes().to_owned();
                output = bytes!(":").to_owned();
                output.push_all(new_val);
                data.insert(key, new_val);
            }
        }
    } else {
        let result = fmt!("-ERR unknown command '%s'", command);
        output = result.as_bytes().to_owned();
    }

    output
}
<|endoftext|>


<commit_before>use std::env;
use std::path::PathBuf;

use imageparse::Image;
use imageparse::chd::ChdImage;

fn main() {
    env_logger::Builder::from_default_env()
        .format_timestamp(None)
        .filter_level(log::LevelFilter::Info)
        .init();

    if env::args().len() < 2 {
        println!("Testing tool that opens a CHD file with its parents recursively");
        println!("Usage: {} <CHD filename> (<list of possible CHD parents>)",
            env::current_exe().expect("Failed to get current exe name").file_name().unwrap().to_string_lossy());
        return;
    }

    let main_chd_path = PathBuf::from(env::args().nth(1).unwrap());
    let possible_parent_paths: Vec<PathBuf> = env::args().skip(2).map(|x| PathBuf::from(x)).collect();

    let chd = ChdImage::open_with_parent(main_chd_path, &possible_parent_paths);

    if let Ok(mut chd) = chd {
        println!("Successfully opened CHD!");
        println!("Tracks: {}", chd.num_tracks());

        let sha1s = chd.track_sha1s();

        if let Ok(ref sha1s) = sha1s {
            println!("SHA-1 hashes for tracks:");
            for (i, sha1) in sha1s.iter().enumerate() {
                print!("Track {}: ", i + 1);
                for x in sha1.iter() {
                    print!("{:x}", x);
                }
                println!("");
            }
        } else if let Err(e) = sha1s {
            println!("Error generating track SHA1s: {:?}", e);
        }

    } else if let Err(e) = chd {
        println!("Error opening CHD: {:?}", e);
    }

}<commit_msg>Fix printing the SHA-1 hashes in open_chd_with_parents example<commit_after>use std::env;
use std::path::PathBuf;

use imageparse::Image;
use imageparse::chd::ChdImage;

fn main() {
    env_logger::Builder::from_default_env()
        .format_timestamp(None)
        .filter_level(log::LevelFilter::Info)
        .init();

    if env::args().len() < 2 {
        println!("Testing tool that opens a CHD file with its parents recursively");
        println!("Usage: {} <CHD filename> (<list of possible CHD parents>)",
            env::current_exe().expect("Failed to get current exe name").file_name().unwrap().to_string_lossy());
        return;
    }

    let main_chd_path = PathBuf::from(env::args().nth(1).unwrap());
    let possible_parent_paths: Vec<PathBuf> = env::args().skip(2).map(|x| PathBuf::from(x)).collect();

    let chd = ChdImage::open_with_parent(main_chd_path, &possible_parent_paths);

    if let Ok(mut chd) = chd {
        println!("Successfully opened CHD!");
        println!("Tracks: {}", chd.num_tracks());

        let sha1s = chd.track_sha1s();

        if let Ok(ref sha1s) = sha1s {
            println!("SHA-1 hashes for tracks:");
            for (i, sha1) in sha1s.iter().enumerate() {
                print!("Track {}: ", i + 1);
                for x in sha1.iter() {
                    print!("{:02x}", x);
                }
                println!("");
            }
        } else if let Err(e) = sha1s {
            println!("Error generating track SHA1s: {:?}", e);
        }

    } else if let Err(e) = chd {
        println!("Error opening CHD: {:?}", e);
    }

}<|endoftext|>


<commit_before>
use core::mem;

pub mod i2c_v1;

use bsp;

#[derive(PartialEq)]
enum PeripheralState {
    StartBitSet,
    AddressSent,
    Transmitting(usize),
    Receiving(usize),
    Done(i32)
}

pub enum Step<'a> {
    Read(&'a mut [u8]),
    Write(&'a mut [u8]),
}

impl<'a> AsMut<[u8]> for Step<'a> {
    fn as_mut(&mut self) -> &mut [u8] {
        match *self {
            Step::Read(ref mut data) | Step::Write(ref mut data) => data,
        }
    }
}

impl<'a> AsRef<[u8]> for Step<'a> {
    fn as_ref(&self) -> &[u8] {
        match *self {
            Step::Read(ref data) | Step::Write(ref data) => data,
        }
    }
}

impl<'a> Step<'a> {
    fn len(&self) -> usize {
        match *self {
            Step::Read(ref data) => data.len(),
            Step::Write(ref data) => data.len()
        }
    }
}

struct Transaction<'a, 'b: 'a> {
    steps: &'a mut [Step<'b>],
    curr_step: usize,
    device_addr: u8
}

impl<'a, 'b> Transaction<'a, 'b> {
    fn on_last_step(&self) -> bool {
        self.curr_step >= self.steps.len()
    }
}

pub enum Peripheral {
    I2C1
}

impl Into<usize> for Peripheral {
    fn into(self) -> usize {
        match self {
            Peripheral::I2C1 => bsp::i2c::I2C1
        }
    }
}

pub fn run_transaction<'a>(device_addr: u8, steps: &mut [Step<'a>]) -> bool {
    unsafe {
        critical!({
            if IT_CONTEXT.current_transaction.is_some() || matches!(IT_CONTEXT.state, PeripheralState::Done(_)) {
                return false;
            }

            let periph = i2c_v1::I2C::get_periph(IT_CONTEXT.periph_addr);
            periph.reset();

            IT_CONTEXT.current_transaction = Some(Transaction {
                steps: mem::transmute::<&mut [Step], &mut [Step]>(steps),
                curr_step: 0,
                device_addr: device_addr
            });
        });

        loop {
            critical!({
                match IT_CONTEXT.state {
                    PeripheralState::Done(ret_val) => {
                        IT_CONTEXT.current_transaction = None;
                        return ret_val == 0;
                    },
                    _ => {}
                }
            });
        }
    }
}

pub struct InterruptContext<'a, 'b: 'a> {
    current_transaction: Option<Transaction<'a, 'b>>,
    periph_addr: usize,
    state: PeripheralState
}

static mut IT_CONTEXT: InterruptContext = InterruptContext {
    current_transaction: None,
    periph_addr: bsp::i2c::I2C1,
    state: PeripheralState::Done(0)
};
<commit_msg>More cleanup of I2C generic code<commit_after>
use core::mem;

pub mod i2c_v1;

use bsp;

#[derive(PartialEq)]
enum PeripheralState {
    StartBitSet,
    AddressSent,
    Transmitting(usize),
    Receiving(usize),
    Done(i32),
}

pub enum Step<'a> {
    Read(&'a mut [u8]),
    Write(&'a mut [u8]),
}

impl<'a> AsMut<[u8]> for Step<'a> {
    fn as_mut(&mut self) -> &mut [u8] {
        match *self {
            Step::Read(ref mut data) |
            Step::Write(ref mut data) => data,
        }
    }
}

impl<'a> AsRef<[u8]> for Step<'a> {
    fn as_ref(&self) -> &[u8] {
        match *self {
            Step::Read(ref data) |
            Step::Write(ref data) => data,
        }
    }
}

impl<'a> Step<'a> {
    fn len(&self) -> usize {
        match *self {
            Step::Read(ref data) => data.len(),
            Step::Write(ref data) => data.len(),
        }
    }
}

struct Transaction<'a, 'b: 'a> {
    steps: &'a mut [Step<'b>],
    curr_step: usize,
    device_addr: u8,
}

impl<'a, 'b> Transaction<'a, 'b> {
    fn on_last_step(&self) -> bool {
        self.curr_step >= self.steps.len()
    }
}

pub enum Peripherals {
    I2C1 = 0,
}

pub struct I2C<'a, 'b: 'a> {
    it_context: &'a mut InterruptContext<'a, 'b>,
}

impl<'a, 'b> I2C<'a, 'b> {
    pub fn new(periph: Peripherals) -> I2C<'a, 'b> {
        I2C {
            it_context: unsafe {
                mem::transmute::<&mut InterruptContext, &mut InterruptContext>(
                    &mut I2C_PERIPHS[periph as usize],
                )
            },
        }
    }

    pub fn run_transaction(&mut self, device_addr: u8, steps: &mut [Step]) -> Result<(), ()> {
        unsafe {
            critical!({
                if self.it_context.current_transaction.is_some() ||
                    matches!(self.it_context.state, PeripheralState::Done(_))
                {
                    return Err(());
                }

                let periph = i2c_v1::I2C::get_periph(self.it_context.periph_addr);
                periph.reset();

                self.it_context.current_transaction = Some(Transaction {
                    steps: mem::transmute::<&mut [Step], &mut [Step]>(steps),
                    curr_step: 0,
                    device_addr: device_addr,
                });
            });

            loop {
                critical!({
                    match self.it_context.state {
                        PeripheralState::Done(ret_val) => {
                            self.it_context.current_transaction = None;
                            if ret_val == 0 {
                                return Ok(());
                            } else {
                                return Err(());
                            }
                        },
                        _ => {}
                    }
                });
            }
        }
    }
}

pub struct InterruptContext<'a, 'b: 'a> {
    current_transaction: Option<Transaction<'a, 'b>>,
    periph_addr: usize,
    state: PeripheralState,
}

static mut I2C_PERIPHS: [InterruptContext; 1] = [
    InterruptContext {
        current_transaction: None,
        periph_addr: bsp::i2c::I2C1,
        state: PeripheralState::Done(0),
    },
];
<|endoftext|>


<commit_before>use anyhow::Result;
use defaults::Defaults;
use serde::{Deserialize, Serialize};
use std::path::Path;
use strum::ToString;
use validator::Validate;

#[derive(Debug, PartialEq, Clone, Copy, Deserialize, Serialize, ToString)]
#[serde(rename_all = "lowercase")]
pub enum Level {
    Debug,
    Info,
    Warn,
    Error,
    Never,
}

#[derive(Debug, PartialEq, Clone, Copy, Deserialize, Serialize)]
#[serde(rename_all = "lowercase")]
pub enum Format {
    Plain,
    Pretty,
    Json,
}

#[cfg(feature = "config")]
pub mod config {
    use super::*;
    use crate::util::dirs;

    #[derive(Debug, Defaults, PartialEq, Clone, Copy, Deserialize, Serialize, Validate)]
    pub struct StdErr {
        /// The maximum log level to emit
        #[def = "Level::Info"]
        pub level: Level,

        /// The format for the logs entries
        #[def = "Format::Pretty"]
        pub format: Format,
    }

    #[derive(Debug, Defaults, PartialEq, Clone, Deserialize, Serialize, Validate)]
    pub struct File {
        /// The path of the log file
        #[def = "default_file_path()"]
        pub path: String,

        /// The maximum log level to emit
        #[def = "Level::Debug"]
        pub level: Level,
    }

    /// Get the default value for `logging.file.path`
    pub fn default_file_path() -> String {
        dirs::logs(true)
            .expect("Unable to get logs directory")
            .join("log.json")
            .into_os_string()
            .into_string()
            .expect("Unable to convert path to string")
    }

    #[derive(Debug, Default, PartialEq, Clone, Deserialize, Serialize, Validate)]
    pub struct Config {
        pub stderr: StdErr,
        pub file: File,
    }
}

/// Create a preliminary logging subscriber.
///
/// This can be necessary to ensure that any log events that get emitted during
/// initialization are displayed to the user.
pub fn prelim() -> tracing::subscriber::DefaultGuard {
    let subscriber = tracing_subscriber::fmt()
        .pretty()
        .with_max_level(tracing::Level::INFO)
        .with_writer(std::io::stderr)
        .finish();
    tracing::subscriber::set_default(subscriber)
}

/// Initialize a logging subscriber based on passed args and read config.
pub fn init(
    level: Option<Level>,
    config: &config::Config,
) -> Result<[tracing_appender::non_blocking::WorkerGuard; 2]> {
    use tracing_subscriber::{fmt, layer::SubscriberExt, EnvFilter};

    let config::Config { stderr, file } = config;

    let level = level.unwrap_or(stderr.level);

    let (stderr_writer, stderr_guard) = if level != Level::Never {
        tracing_appender::non_blocking(std::io::stderr())
    } else {
        tracing_appender::non_blocking(std::io::sink())
    };
    let stderr_layer = fmt::Layer::new()
        .pretty()
        .without_time()
        .with_writer(stderr_writer);

    let (file_writer, file_guard) = if file.level != Level::Never {
        let path = Path::new(&file.path);
        let file_appender =
            tracing_appender::rolling::daily(&path.parent().unwrap(), &path.file_name().unwrap());
        tracing_appender::non_blocking(file_appender)
    } else {
        tracing_appender::non_blocking(std::io::sink())
    };
    let file_layer = fmt::Layer::new().json().with_writer(file_writer);

    let subscriber = tracing_subscriber::registry()
        .with(EnvFilter::new(level.to_string()))
        .with(stderr_layer)
        .with(file_layer);

    tracing::subscriber::set_global_default(subscriber)?;

    Ok([stderr_guard, file_guard])
}

/// A tracing subscriber which passes on events to a pubsub function
struct PublishSubscriber {
    publish: fn(topic: String, data: serde_json::Value) -> (),
}

use tracing::{
    span::{Attributes, Id, Record},
    Event, Metadata,
};
impl tracing::Subscriber for PublishSubscriber {
    /// Convert the even to a JSON object and send to
    /// the function
    fn event(&self, event: &Event) {
        use tracing_serde::AsSerde;
        let data = serde_json::json!(event.as_serde());
        (self.publish)("logging".to_string(), data);
    }

    // Methods that must be implemented fo a Subscriber
    fn enabled(&self, _: &Metadata) -> bool {
        true
    }
    fn new_span(&self, _: &Attributes) -> Id {
        Id::from_u64(1)
    }
    fn record(&self, _: &Id, _: &Record) {}
    fn record_follows_from(&self, _: &Id, _: &Id) {}
    fn enter(&self, _: &Id) {}
    fn exit(&self, _: &Id) {}
}

/// Initialize function to publish log events
pub fn init_publish(publish: fn(topic: String, data: serde_json::Value) -> ()) -> Result<()> {
    let subscriber = PublishSubscriber { publish };
    tracing::subscriber::set_global_default(subscriber)?;
    Ok(())
}

/// Generate some tracing events that can be used for testing
/// that they are propograted to subscribers
#[tracing::instrument]
pub fn test_events() {
    tracing::debug!("A debug event");
    tracing::info!("An info event");
    tracing::warn!("A warn event");
    tracing::error!("An error event");
}
<commit_msg>chore(Logging): Lint<commit_after>use anyhow::Result;
use defaults::Defaults;
use serde::{Deserialize, Serialize};
use std::path::Path;
use strum::ToString;
use validator::Validate;

#[derive(Debug, PartialEq, Clone, Copy, Deserialize, Serialize, ToString)]
#[serde(rename_all = "lowercase")]
pub enum Level {
    Debug,
    Info,
    Warn,
    Error,
    Never,
}

#[derive(Debug, PartialEq, Clone, Copy, Deserialize, Serialize)]
#[serde(rename_all = "lowercase")]
pub enum Format {
    Plain,
    Pretty,
    Json,
}

#[cfg(feature = "config")]
pub mod config {
    use super::*;
    use crate::util::dirs;

    #[derive(Debug, Defaults, PartialEq, Clone, Copy, Deserialize, Serialize, Validate)]
    pub struct StdErr {
        /// The maximum log level to emit
        #[def = "Level::Info"]
        pub level: Level,

        /// The format for the logs entries
        #[def = "Format::Pretty"]
        pub format: Format,
    }

    #[derive(Debug, Defaults, PartialEq, Clone, Deserialize, Serialize, Validate)]
    pub struct File {
        /// The path of the log file
        #[def = "default_file_path()"]
        pub path: String,

        /// The maximum log level to emit
        #[def = "Level::Debug"]
        pub level: Level,
    }

    /// Get the default value for `logging.file.path`
    pub fn default_file_path() -> String {
        dirs::logs(true)
            .expect("Unable to get logs directory")
            .join("log.json")
            .into_os_string()
            .into_string()
            .expect("Unable to convert path to string")
    }

    #[derive(Debug, Default, PartialEq, Clone, Deserialize, Serialize, Validate)]
    pub struct Config {
        pub stderr: StdErr,
        pub file: File,
    }
}

/// Create a preliminary logging subscriber.
///
/// This can be necessary to ensure that any log events that get emitted during
/// initialization are displayed to the user.
pub fn prelim() -> tracing::subscriber::DefaultGuard {
    let subscriber = tracing_subscriber::fmt()
        .pretty()
        .with_max_level(tracing::Level::INFO)
        .with_writer(std::io::stderr)
        .finish();
    tracing::subscriber::set_default(subscriber)
}

/// Initialize a logging subscriber based on passed args and read config.
pub fn init(
    level: Option<Level>,
    config: &config::Config,
) -> Result<[tracing_appender::non_blocking::WorkerGuard; 2]> {
    use tracing_subscriber::{fmt, layer::SubscriberExt, EnvFilter};

    let config::Config { stderr, file } = config;

    let level = level.unwrap_or(stderr.level);

    let (stderr_writer, stderr_guard) = if level != Level::Never {
        tracing_appender::non_blocking(std::io::stderr())
    } else {
        tracing_appender::non_blocking(std::io::sink())
    };
    let stderr_layer = fmt::Layer::new()
        .pretty()
        .without_time()
        .with_writer(stderr_writer);

    let (file_writer, file_guard) = if file.level != Level::Never {
        let path = Path::new(&file.path);
        let file_appender =
            tracing_appender::rolling::daily(&path.parent().unwrap(), &path.file_name().unwrap());
        tracing_appender::non_blocking(file_appender)
    } else {
        tracing_appender::non_blocking(std::io::sink())
    };
    let file_layer = fmt::Layer::new().json().with_writer(file_writer);

    let subscriber = tracing_subscriber::registry()
        .with(EnvFilter::new(level.to_string()))
        .with(stderr_layer)
        .with(file_layer);

    tracing::subscriber::set_global_default(subscriber)?;

    Ok([stderr_guard, file_guard])
}

/// A tracing subscriber which passes on events to a pubsub function
struct PublishSubscriber {
    publish: fn(topic: String, data: serde_json::Value) -> (),
}

use tracing::{
    span::{Attributes, Id, Record},
    Event, Metadata,
};
impl tracing::Subscriber for PublishSubscriber {
    /// Convert the even to a JSON object and send to
    /// the function
    fn event(&self, event: &Event) {
        use tracing_serde::AsSerde;
        let data = serde_json::json!(event.as_serde());
        (self.publish)("logging".to_string(), data);
    }

    // Methods that must be implemented fo a Subscriber
    fn enabled(&self, _: &Metadata) -> bool {
        true
    }
    fn new_span(&self, _: &Attributes) -> Id {
        Id::from_u64(1)
    }
    fn record(&self, _: &Id, _: &Record) {}
    fn record_follows_from(&self, _: &Id, _: &Id) {}
    fn enter(&self, _: &Id) {}
    fn exit(&self, _: &Id) {}
}

/// Initialize function to publish log events
pub fn init_publish(publish: fn(topic: String, data: serde_json::Value) -> ()) -> Result<()> {
    let subscriber = PublishSubscriber { publish };
    tracing::subscriber::set_global_default(subscriber)?;
    Ok(())
}

/// Generate some tracing events that can be used for testing
/// that they are propograted to subscribers
#[tracing::instrument]
pub fn test_events() {
    tracing::debug!("A debug event");
    tracing::info!("An info event");
    tracing::warn!("A warn event");
    tracing::error!("An error event");
}
<|endoftext|>


<commit_before>use crate::translation_utils::SignatureIndex;
use cranelift_entity::PrimaryMap;
use std::boxed::Box;

/// Contains information decoded from the Wasm module that must be referenced
/// during each Wasm function's translation.
///
/// This is only for data that is maintained by `cranelift-wasm` itself, as
/// opposed to being maintained by the embedder. Data that is maintained by the
/// embedder is represented with `ModuleEnvironment`.
#[derive(Debug)]
pub struct ModuleTranslationState {
    /// A map containing a Wasm module's original, raw signatures.
    ///
    /// This is used for translating multi-value Wasm blocks inside functions,
    /// which are encoded to refer to their type signature via index.
    pub(crate) wasm_types:
        PrimaryMap<SignatureIndex, (Box<[wasmparser::Type]>, Box<[wasmparser::Type]>)>,
}

impl ModuleTranslationState {
    pub(crate) fn new() -> Self {
        ModuleTranslationState {
            wasm_types: PrimaryMap::new(),
        }
    }
}
<commit_msg>[wasm] Make the ModuleTranslationState ctor public.<commit_after>use crate::translation_utils::SignatureIndex;
use cranelift_entity::PrimaryMap;
use std::boxed::Box;

/// Contains information decoded from the Wasm module that must be referenced
/// during each Wasm function's translation.
///
/// This is only for data that is maintained by `cranelift-wasm` itself, as
/// opposed to being maintained by the embedder. Data that is maintained by the
/// embedder is represented with `ModuleEnvironment`.
#[derive(Debug)]
pub struct ModuleTranslationState {
    /// A map containing a Wasm module's original, raw signatures.
    ///
    /// This is used for translating multi-value Wasm blocks inside functions,
    /// which are encoded to refer to their type signature via index.
    pub(crate) wasm_types:
        PrimaryMap<SignatureIndex, (Box<[wasmparser::Type]>, Box<[wasmparser::Type]>)>,
}

impl ModuleTranslationState {
    /// Creates a new empty ModuleTranslationState.
    pub fn new() -> Self {
        ModuleTranslationState {
            wasm_types: PrimaryMap::new(),
        }
    }
}
<|endoftext|>