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

use rustc_data_structures::fx::FxHashMap;

use crate::externalfiles::ExternalHtml;
use crate::html::escape::Escape;
use crate::html::format::{Buffer, Print};
use crate::html::render::{ensure_trailing_slash, StylePath};

#[derive(Clone)]
crate struct Layout {
    crate logo: String,
    crate favicon: String,
    crate external_html: ExternalHtml,
    crate default_settings: FxHashMap<String, String>,
    crate krate: String,
    /// The given user css file which allow to customize the generated
    /// documentation theme.
    crate css_file_extension: Option<PathBuf>,
    /// If false, the `select` element to have search filtering by crates on rendered docs
    /// won't be generated.
    crate generate_search_filter: bool,
}

crate struct Page<'a> {
    crate title: &'a str,
    crate css_class: &'a str,
    crate root_path: &'a str,
    crate static_root_path: Option<&'a str>,
    crate description: &'a str,
    crate keywords: &'a str,
    crate resource_suffix: &'a str,
    crate extra_scripts: &'a [&'a str],
    crate static_extra_scripts: &'a [&'a str],
}

crate fn render<T: Print, S: Print>(
    layout: &Layout,
    page: &Page<'_>,
    sidebar: S,
    t: T,
    style_files: &[StylePath],
) -> String {
    let static_root_path = page.static_root_path.unwrap_or(page.root_path);
    format!(
        "<!DOCTYPE html>\
\
\
    <meta charset=\"utf-8\">\
    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\
    <meta name=\"generator\" content=\"rustdoc\">\
    <meta name=\"description\" content=\"{description}\">\
    <meta name=\"keywords\" content=\"{keywords}\">\
    <title>{title}</title>\
    <link rel=\"stylesheet\" type=\"text/css\" href=\"{static_root_path}normalize{suffix}.css\">\
    <link rel=\"stylesheet\" type=\"text/css\" href=\"{static_root_path}rustdoc{suffix}.css\" \
          id=\"mainThemeStyle\">\
    {style_files}\
    \
    \
    \
    <link rel=\"stylesheet\" href=\"{static_root_path}noscript{suffix}.css\">\
    {css_extension}\
    {favicon}\
    {in_header}\
    \
\
\
    \
    {before_content}\
    \

☰
\
        {logo}\
        {sidebar}\
    \

\
        <button id=\"theme-picker\" aria-label=\"Pick another theme!\" aria-haspopup=\"menu\">\
            \
        </button>\

\

\
    \
        <form class=\"search-form\">\

\

{filter_crates}\
                    <input class=\"search-input\" name=\"search\" \
                           disabled \
                           autocomplete=\"off\" \
                           spellcheck=\"false\" \
                           placeholder=\"Click or press ‘S’ to search, ‘?’ for more options…\" \
                           type=\"search\">\

\
                <button type=\"button\" class=\"help-button\">?</button>
                \
                    \
                \

\
        </form>\
    \

{content}
\

\

\
    {after_content}\

    \
    {extra_scripts}\
\
",
        css_extension = if layout.css_file_extension.is_some() {
            format!(
                "<link rel=\"stylesheet\" \
                       type=\"text/css\" \
                       href=\"{static_root_path}theme{suffix}.css\">",
                static_root_path = static_root_path,
                suffix = page.resource_suffix
            )
        } else {
            String::new()
        },
        content = Buffer::html().to_display(t),
        static_root_path = static_root_path,
        root_path = page.root_path,
        css_class = page.css_class,
        logo = {
            if layout.logo.is_empty() {
                format!(
                    "\

\

",
                    root = page.root_path,
                    path = ensure_trailing_slash(&layout.krate),
                    static_root_path = static_root_path,
                    suffix = page.resource_suffix
                )
            } else {
                format!(
                    "\

",
                    root = page.root_path,
                    path = ensure_trailing_slash(&layout.krate),
                    logo = layout.logo
                )
            }
        },
        title = page.title,
        description = page.description,
        keywords = page.keywords,
        favicon = if layout.favicon.is_empty() {
            format!(
                r##"<link rel="icon" type="image/svg+xml" href="{static_root_path}favicon{suffix}.svg">
<link rel="alternate icon" type="image/png" href="{static_root_path}favicon-16x16{suffix}.png">
<link rel="alternate icon" type="image/png" href="{static_root_path}favicon-32x32{suffix}.png">"##,
                static_root_path = static_root_path,
                suffix = page.resource_suffix
            )
        } else {
            format!(r#"<link rel="shortcut icon" href="{}">"#, layout.favicon)
        },
        in_header = layout.external_html.in_header,
        before_content = layout.external_html.before_content,
        after_content = layout.external_html.after_content,
        sidebar = Buffer::html().to_display(sidebar),
        krate = layout.krate,
        default_settings = layout
            .default_settings
            .iter()
            .map(|(k, v)| format!(r#" data-{}="{}""#, k.replace('-', "_"), Escape(v)))
            .collect::<String>(),
        style_files = style_files
            .iter()
            .filter_map(|t| {
                if let Some(stem) = t.path.file_stem() { Some((stem, t.disabled)) } else { None }
            })
            .filter_map(|t| {
                if let Some(path) = t.0.to_str() { Some((path, t.1)) } else { None }
            })
            .map(|t| format!(
                r#"<link rel="stylesheet" type="text/css" href="{}.css" {} {}>"#,
                Escape(&format!("{}{}{}", static_root_path, t.0, page.resource_suffix)),
                if t.1 { "disabled" } else { "" },
                if t.0 == "light" { "id=\"themeStyle\"" } else { "" }
            ))
            .collect::<String>(),
        suffix = page.resource_suffix,
        extra_scripts = page
            .static_extra_scripts
            .iter()
            .map(|e| {
                format!(
                    "",
                    static_root_path = static_root_path,
                    extra_script = e
                )
            })
            .chain(page.extra_scripts.iter().map(|e| {
                format!(
                    "",
                    root_path = page.root_path,
                    extra_script = e
                )
            }))
            .collect::<String>(),
        filter_crates = if layout.generate_search_filter {
            "<select id=\"crate-search\">\
                 <option value=\"All crates\">All crates</option>\
             </select>"
        } else {
            ""
        },
    )
}

crate fn redirect(url: &str) -> String {
    //

"##,
        url = url,
    )
}
<commit_msg>Change root_path to static_root_path<commit_after>use std::path::PathBuf;

use rustc_data_structures::fx::FxHashMap;

use crate::externalfiles::ExternalHtml;
use crate::html::escape::Escape;
use crate::html::format::{Buffer, Print};
use crate::html::render::{ensure_trailing_slash, StylePath};

#[derive(Clone)]
crate struct Layout {
    crate logo: String,
    crate favicon: String,
    crate external_html: ExternalHtml,
    crate default_settings: FxHashMap<String, String>,
    crate krate: String,
    /// The given user css file which allow to customize the generated
    /// documentation theme.
    crate css_file_extension: Option<PathBuf>,
    /// If false, the `select` element to have search filtering by crates on rendered docs
    /// won't be generated.
    crate generate_search_filter: bool,
}

crate struct Page<'a> {
    crate title: &'a str,
    crate css_class: &'a str,
    crate root_path: &'a str,
    crate static_root_path: Option<&'a str>,
    crate description: &'a str,
    crate keywords: &'a str,
    crate resource_suffix: &'a str,
    crate extra_scripts: &'a [&'a str],
    crate static_extra_scripts: &'a [&'a str],
}

crate fn render<T: Print, S: Print>(
    layout: &Layout,
    page: &Page<'_>,
    sidebar: S,
    t: T,
    style_files: &[StylePath],
) -> String {
    let static_root_path = page.static_root_path.unwrap_or(page.root_path);
    format!(
        "<!DOCTYPE html>\
\
\
    <meta charset=\"utf-8\">\
    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\
    <meta name=\"generator\" content=\"rustdoc\">\
    <meta name=\"description\" content=\"{description}\">\
    <meta name=\"keywords\" content=\"{keywords}\">\
    <title>{title}</title>\
    <link rel=\"stylesheet\" type=\"text/css\" href=\"{static_root_path}normalize{suffix}.css\">\
    <link rel=\"stylesheet\" type=\"text/css\" href=\"{static_root_path}rustdoc{suffix}.css\" \
          id=\"mainThemeStyle\">\
    {style_files}\
    \
    \
    \
    <link rel=\"stylesheet\" href=\"{static_root_path}noscript{suffix}.css\">\
    {css_extension}\
    {favicon}\
    {in_header}\
    \
\
\
    \
    {before_content}\
    \

☰
\
        {logo}\
        {sidebar}\
    \

\
        <button id=\"theme-picker\" aria-label=\"Pick another theme!\" aria-haspopup=\"menu\">\
            \
        </button>\

\

\
    \
        <form class=\"search-form\">\

\

{filter_crates}\
                    <input class=\"search-input\" name=\"search\" \
                           disabled \
                           autocomplete=\"off\" \
                           spellcheck=\"false\" \
                           placeholder=\"Click or press ‘S’ to search, ‘?’ for more options…\" \
                           type=\"search\">\

\
                <button type=\"button\" class=\"help-button\">?</button>
                \
                    \
                \

\
        </form>\
    \

{content}
\

\

\
    {after_content}\

    \
    {extra_scripts}\
\
",
        css_extension = if layout.css_file_extension.is_some() {
            format!(
                "<link rel=\"stylesheet\" \
                       type=\"text/css\" \
                       href=\"{static_root_path}theme{suffix}.css\">",
                static_root_path = static_root_path,
                suffix = page.resource_suffix
            )
        } else {
            String::new()
        },
        content = Buffer::html().to_display(t),
        static_root_path = static_root_path,
        root_path = page.root_path,
        css_class = page.css_class,
        logo = {
            if layout.logo.is_empty() {
                format!(
                    "\

\

",
                    root = page.root_path,
                    path = ensure_trailing_slash(&layout.krate),
                    static_root_path = static_root_path,
                    suffix = page.resource_suffix
                )
            } else {
                format!(
                    "\

",
                    root = page.root_path,
                    path = ensure_trailing_slash(&layout.krate),
                    logo = layout.logo
                )
            }
        },
        title = page.title,
        description = page.description,
        keywords = page.keywords,
        favicon = if layout.favicon.is_empty() {
            format!(
                r##"<link rel="icon" type="image/svg+xml" href="{static_root_path}favicon{suffix}.svg">
<link rel="alternate icon" type="image/png" href="{static_root_path}favicon-16x16{suffix}.png">
<link rel="alternate icon" type="image/png" href="{static_root_path}favicon-32x32{suffix}.png">"##,
                static_root_path = static_root_path,
                suffix = page.resource_suffix
            )
        } else {
            format!(r#"<link rel="shortcut icon" href="{}">"#, layout.favicon)
        },
        in_header = layout.external_html.in_header,
        before_content = layout.external_html.before_content,
        after_content = layout.external_html.after_content,
        sidebar = Buffer::html().to_display(sidebar),
        krate = layout.krate,
        default_settings = layout
            .default_settings
            .iter()
            .map(|(k, v)| format!(r#" data-{}="{}""#, k.replace('-', "_"), Escape(v)))
            .collect::<String>(),
        style_files = style_files
            .iter()
            .filter_map(|t| {
                if let Some(stem) = t.path.file_stem() { Some((stem, t.disabled)) } else { None }
            })
            .filter_map(|t| {
                if let Some(path) = t.0.to_str() { Some((path, t.1)) } else { None }
            })
            .map(|t| format!(
                r#"<link rel="stylesheet" type="text/css" href="{}.css" {} {}>"#,
                Escape(&format!("{}{}{}", static_root_path, t.0, page.resource_suffix)),
                if t.1 { "disabled" } else { "" },
                if t.0 == "light" { "id=\"themeStyle\"" } else { "" }
            ))
            .collect::<String>(),
        suffix = page.resource_suffix,
        extra_scripts = page
            .static_extra_scripts
            .iter()
            .map(|e| {
                format!(
                    "",
                    static_root_path = static_root_path,
                    extra_script = e
                )
            })
            .chain(page.extra_scripts.iter().map(|e| {
                format!(
                    "",
                    root_path = page.root_path,
                    extra_script = e
                )
            }))
            .collect::<String>(),
        filter_crates = if layout.generate_search_filter {
            "<select id=\"crate-search\">\
                 <option value=\"All crates\">All crates</option>\
             </select>"
        } else {
            ""
        },
    )
}

crate fn redirect(url: &str) -> String {
    //

"##,
        url = url,
    )
}
<|endoftext|>


<commit_before>use std::thread;
use std::time::{Duration, Instant};

use sdl2;
use sdl2::event::Event;
use sdl2::keyboard::Keycode;

use sdl2::pixels::Color;
use sdl2::rect::Rect; // TODO: abstract my own drawtypes?

use graphics::Display;
use input::Input;

pub static COLOR_BG: Color  = Color::RGB(0,0,0);
pub static COLOR_FPS: Color = Color::RGB(255,255,0);
pub static COLOR_PEN: Color = Color::RGB(125, 0, 175);

#[derive(Debug)]
enum BrushMode {
    Squareish,
    WowSoEdgy,
}

pub struct Engine {
	context:     sdl2::Sdl,
	controller:  Input,
	display:     Display,

    brush:  BrushMode,
    cursor: (i32,i32),
}

impl Engine {
    pub fn new(context: sdl2::Sdl) -> Engine {
        let video_renderer = Display::new(&context);

        Engine {
            context:    context,
            controller: Input::new(),
            display:    video_renderer,

            brush:  BrushMode::Squareish,
            cursor: (0,0),
        }
    }

    pub fn run(&mut self) {
        let target_fps_ms  = Duration::from_millis(1000 / 120); // TODO: const fn?

		let mut event_pump = self.context.event_pump().unwrap();
        let mut is_running = true;

        let mut frame_start_at;
        let mut elapsed_time = Duration::from_millis(0);

        // drawing state
        let mut bitmap = Some(self.display.get_texture(1280,720));
        let mut mouse_clicked = false;
        let mut last_point = None;

        // init bitmap to good state
        let mut _last = self.display.retarget().set(bitmap.take().unwrap());
        self.display.clear_buffer();
        bitmap = self.display.retarget().reset()
            .ok().expect("did not get target back");

        while is_running {
            frame_start_at  = Instant::now();

			// drain input event queue once per frame
			self.controller.begin_new_frame();
			for event in event_pump.poll_iter() {
				match event {
					Event::KeyDown { keycode, .. } => {
						self.controller.key_down_event(keycode.unwrap());
					},

					Event::KeyUp { keycode, .. } => {
						self.controller.key_up_event(keycode.unwrap());
					},

                    Event::MouseMotion { x, y, .. } => self.cursor = (x,y),

                    Event::MouseButtonDown { .. } => mouse_clicked = true,
                    Event::MouseButtonUp   { .. } => mouse_clicked = false,

					_ => {},
				}
			}

            // handle exit game
			if self.controller.was_key_released(Keycode::Escape) { is_running = false; }

            // erase canvas
            if self.controller.was_key_released(Keycode::E) {
                let mut _last = self.display.retarget().set(bitmap.take().unwrap());
                self.display.clear_buffer();
                bitmap = self.display.retarget().reset()
                    .ok().expect("did not get target back");
            }

            // switch brush
            if self.controller.was_key_released(Keycode::B) {
                self.brush = match self.brush { // TODO: better cycle?
                    BrushMode::Squareish => BrushMode::WowSoEdgy,
                    BrushMode::WowSoEdgy => BrushMode::Squareish,
                }
            }

            if mouse_clicked {
                let (x2,y2) = self.cursor;

                if let Some((x1,y1)) = last_point {
                    let _last = self.display.retarget().set(bitmap.take().unwrap());

                    // let diffx = x2 - x1;
                    // let diffy = y2 - y1;
                    // println!("delta ({},{}), mag: {}", diffx, diffy, diffy-diffx);

                    match self.brush {
                        BrushMode::WowSoEdgy => for i in 0..10 {
                            self.display.draw_line(x1+i, y1, x2, y2+i, COLOR_PEN);
                        },

                        BrushMode::Squareish => for i in 0..5 {
                            self.display.draw_line(x1+i, y1, x2+i, y2, COLOR_PEN);
                        },
                    }

                    bitmap = self.display.retarget().reset()
                        .ok().expect("did not get target back");
                } // NOTE: doesn't draw point if mouse held for single frame

                last_point = Some((x2,y2));
           } else { last_point = None; }

            // handle draw calls
			self.display.clear_buffer(); // clear back-buffer
            self.display.copy(bitmap.as_ref().unwrap());
            self.draw_cursor();
            self.draw_debug(elapsed_time);
			self.display.switch_buffers();

            // sleep for <target> - <draw time> and floor to zero
            elapsed_time = frame_start_at.elapsed();
            let sleep_time = if elapsed_time > target_fps_ms {
                Duration::from_millis(0)
            } else { target_fps_ms - elapsed_time };

            thread::sleep(sleep_time);
        }
    }

    fn draw_cursor(&mut self) {
        self.display.fill_rect(Rect::new(self.cursor.0, self.cursor.1, 10, 10), COLOR_PEN);
    }

    fn draw_debug(&mut self, time: Duration) {
        let mut time_ms = time.as_secs() * 1000;        // -> millis
        time_ms += time.subsec_nanos() as u64 / (1000 * 1000); // /> micros /> millis

        let buf = format!("{}ms, e = erase all, b = brush ({:?})", time_ms, self.brush);
        self.display.blit_text(&buf[..], COLOR_FPS);
    }
}
<commit_msg>BASIC fricken color picker<commit_after>use std::thread;
use std::time::{Duration, Instant};

use sdl2;
use sdl2::event::Event;
use sdl2::keyboard::Keycode;

use sdl2::pixels::Color;
use sdl2::rect::Rect; // TODO: abstract my own drawtypes?

use graphics::Display;
use input::Input;

pub static COLOR_BG: Color  = Color::RGB(0,0,0);
pub static COLOR_FPS: Color = Color::RGB(255,255,0);
pub static COLOR_PEN: Color = Color::RGB(125, 0, 175);

#[derive(Debug)]
enum BrushMode {
    Normal,
    Squareish,
    WowSoEdgy,
}

pub struct Engine {
	context:     sdl2::Sdl,
	controller:  Input,
	display:     Display,

    brush:  BrushMode,
    color:  (u8,u8,u8),
    cursor: (i32,i32),
}

impl Engine {
    pub fn new(context: sdl2::Sdl) -> Engine {
        let video_renderer = Display::new(&context);

        Engine {
            context:    context,
            controller: Input::new(),
            display:    video_renderer,

            brush:  BrushMode::Normal,
            color:  (125,0,175),
            cursor: (0,0),
        }
    }

    pub fn run(&mut self) {
        let target_fps_ms  = Duration::from_millis(1000 / 120); // TODO: const fn?

		let mut event_pump = self.context.event_pump().unwrap();
        let mut is_running = true;

        let mut frame_start_at;
        let mut elapsed_time = Duration::from_millis(0);

        // drawing state
        let mut bitmap = Some(self.display.get_texture(1280,720));
        let mut mouse_clicked = false;
        let mut last_point = None;

        // init bitmap to good state
        let mut _last = self.display.retarget().set(bitmap.take().unwrap());
        self.display.clear_buffer();
        bitmap = self.display.retarget().reset()
            .ok().expect("did not get target back");

        while is_running {
            frame_start_at  = Instant::now();

			// drain input event queue once per frame
			self.controller.begin_new_frame();
			for event in event_pump.poll_iter() {
				match event {
					Event::KeyDown { keycode, .. } => {
						self.controller.key_down_event(keycode.unwrap());
					},

					Event::KeyUp { keycode, .. } => {
						self.controller.key_up_event(keycode.unwrap());
					},

                    Event::MouseMotion { x, y, .. } => self.cursor = (x,y),

                    Event::MouseButtonDown { .. } => mouse_clicked = true,
                    Event::MouseButtonUp   { .. } => mouse_clicked = false,

					_ => {},
				}
			}

            // handle exit game
			if self.controller.was_key_released(Keycode::Escape) { is_running = false; }

            // erase canvas
            if self.controller.was_key_released(Keycode::E) {
                let mut _last = self.display.retarget().set(bitmap.take().unwrap());
                self.display.clear_buffer();
                bitmap = self.display.retarget().reset()
                    .ok().expect("did not get target back");
            }

            // switch brush
            if self.controller.was_key_released(Keycode::B) {
                self.brush = match self.brush { // TODO: better cycle?
                    BrushMode::Normal    => BrushMode::Squareish,
                    BrushMode::Squareish => BrushMode::WowSoEdgy,
                    BrushMode::WowSoEdgy => BrushMode::Squareish,
                }
            }

            if self.controller.is_key_held(Keycode::I) {
                self.color.0 = self.color.0.wrapping_add(0x01);
            } else if self.controller.is_key_held(Keycode::O) {
                self.color.1 = self.color.1.wrapping_add(0x01);
            } else if self.controller.is_key_held(Keycode::P) {
                self.color.2 = self.color.2.wrapping_add(0x01);
            }

            let brush_color = Color::RGB(self.color.0, self.color.1, self.color.2);
            if mouse_clicked {
                let (x2,y2) = self.cursor;

                if let Some((x1,y1)) = last_point {
                    let _last = self.display.retarget().set(bitmap.take().unwrap());

                    // let diffx = x2 - x1;
                    // let diffy = y2 - y1;
                    // println!("delta ({},{}), mag: {}", diffx, diffy, diffy-diffx);

                    match self.brush {
                        BrushMode::WowSoEdgy => for i in 0..10 {
                            self.display.draw_line(x1+i, y1, x2, y2+i, brush_color);
                        },

                        BrushMode::Squareish => for i in 0..5 {
                            self.display.draw_line(x1+i, y1, x2+i, y2, brush_color);
                        },

                        BrushMode::Normal => {},
                    }

                    bitmap = self.display.retarget().reset()
                        .ok().expect("did not get target back");
                } // NOTE: doesn't draw point if mouse held for single frame

                last_point = Some((x2,y2));
           } else { last_point = None; }

            // handle draw calls
			self.display.clear_buffer(); // clear back-buffer
            self.display.copy(bitmap.as_ref().unwrap());
            self.draw_cursor(brush_color);
            self.draw_debug(elapsed_time);
			self.display.switch_buffers();

            // sleep for <target> - <draw time> and floor to zero
            elapsed_time = frame_start_at.elapsed();
            let sleep_time = if elapsed_time > target_fps_ms {
                Duration::from_millis(0)
            } else { target_fps_ms - elapsed_time };

            thread::sleep(sleep_time);
        }
    }

    fn draw_cursor(&mut self, brush_color: Color) {
        self.display.fill_rect(Rect::new(self.cursor.0, self.cursor.1, 10, 10), brush_color);
    }

    fn draw_debug(&mut self, time: Duration) {
        let mut time_ms = time.as_secs() * 1000;        // -> millis
        time_ms += time.subsec_nanos() as u64 / (1000 * 1000); // /> micros /> millis

        let (hue_r, hue_g, hue_b) = self.color;

        let buf = format!("{}ms, e = erase all, b = brush ({:?}), hue(i,o,p) => ({:x},{:x},{:x})",
                          time_ms,
                          self.brush,
                          hue_r, hue_g, hue_b);
        self.display.blit_text(&buf[..], COLOR_FPS);
    }
}
<|endoftext|>


<commit_before>// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// 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.

use core::prelude::*;

use boxed::Box;
use cmp;
use mem;
use ptr;
use libc::consts::os::posix01::{PTHREAD_CREATE_JOINABLE, PTHREAD_STACK_MIN};
use libc;
use thunk::Thunk;
use ffi::CString;

use sys_common::stack::RED_ZONE;
use sys_common::thread::*;

pub type rust_thread = libc::pthread_t;
pub type rust_thread_return = *mut u8;
pub type StartFn = extern "C" fn(*mut libc::c_void) -> rust_thread_return;

#[no_stack_check]
pub extern fn thread_start(main: *mut libc::c_void) -> rust_thread_return {
    return start_thread(main);
}

#[cfg(all(not(target_os = "linux"),
          not(target_os = "macos"),
          not(target_os = "openbsd")))]
pub mod guard {
    pub unsafe fn current() -> uint {
        0
    }

    pub unsafe fn main() -> uint {
        0
    }

    pub unsafe fn init() {
    }
}

#[cfg(any(target_os = "linux",
          target_os = "macos",
          target_os = "openbsd"))]
pub mod guard {
    use super::*;
    #[cfg(any(target_os = "linux",
              target_os = "android",
              target_os = "openbsd"))]
    use mem;
    #[cfg(any(target_os = "linux", target_os = "android"))]
    use ptr;
    use libc;
    use libc::funcs::posix88::mman::{mmap};
    use libc::consts::os::posix88::{PROT_NONE,
                                    MAP_PRIVATE,
                                    MAP_ANON,
                                    MAP_FAILED,
                                    MAP_FIXED};

    // These are initialized in init() and only read from after
    static mut PAGE_SIZE: uint = 0;
    static mut GUARD_PAGE: uint = 0;

    #[cfg(any(target_os = "macos", target_os = "openbsd"))]
    unsafe fn get_stack_start() -> *mut libc::c_void {
        current() as *mut libc::c_void
    }

    #[cfg(any(target_os = "linux", target_os = "android"))]
    unsafe fn get_stack_start() -> *mut libc::c_void {
        let mut attr: libc::pthread_attr_t = mem::zeroed();
        if pthread_getattr_np(pthread_self(), &mut attr) != 0 {
            panic!("failed to get thread attributes");
        }
        let mut stackaddr = ptr::null_mut();
        let mut stacksize = 0;
        if pthread_attr_getstack(&attr, &mut stackaddr, &mut stacksize) != 0 {
            panic!("failed to get stack information");
        }
        if pthread_attr_destroy(&mut attr) != 0 {
            panic!("failed to destroy thread attributes");
        }
        stackaddr
    }

    pub unsafe fn init() {
        let psize = libc::sysconf(libc::consts::os::sysconf::_SC_PAGESIZE);
        if psize == -1 {
            panic!("failed to get page size");
        }

        PAGE_SIZE = psize as uint;

        let mut stackaddr = get_stack_start();

        // Ensure stackaddr is page aligned! A parent process might
        // have reset RLIMIT_STACK to be non-page aligned. The
        // pthread_attr_getstack() reports the usable stack area
        // stackaddr < stackaddr + stacksize, so if stackaddr is not
        // page-aligned, calculate the fix such that stackaddr <
        // new_page_aligned_stackaddr < stackaddr + stacksize
        let remainder = (stackaddr as usize) % (PAGE_SIZE as usize);
        if remainder != 0 {
            stackaddr = ((stackaddr as usize) + (PAGE_SIZE as usize) - remainder)
                as *mut libc::c_void;
        }

        // Rellocate the last page of the stack.
        // This ensures SIGBUS will be raised on
        // stack overflow.
        let result = mmap(stackaddr,
                          PAGE_SIZE as libc::size_t,
                          PROT_NONE,
                          MAP_PRIVATE | MAP_ANON | MAP_FIXED,
                          -1,
                          0);

        if result != stackaddr || result == MAP_FAILED {
            panic!("failed to allocate a guard page");
        }

        let offset = if cfg!(target_os = "linux") {
            2
        } else {
            1
        };

        GUARD_PAGE = stackaddr as uint + offset * PAGE_SIZE;
    }

    pub unsafe fn main() -> uint {
        GUARD_PAGE
    }

    #[cfg(target_os = "macos")]
    pub unsafe fn current() -> uint {
        (pthread_get_stackaddr_np(pthread_self()) as libc::size_t -
         pthread_get_stacksize_np(pthread_self())) as uint
    }

    #[cfg(target_os = "openbsd")]
    pub unsafe fn current() -> uint {
        let mut current_stack: stack_t = mem::zeroed();
        if pthread_stackseg_np(pthread_self(), &mut current_stack) != 0 {
            panic!("failed to get current stack: pthread_stackseg_np")
        }

        if pthread_main_np() == 1 {
            // main thread
            current_stack.ss_sp as uint - current_stack.ss_size as uint + 3 * PAGE_SIZE as uint

        } else {
            // new thread
            current_stack.ss_sp as uint - current_stack.ss_size as uint
        }
    }

    #[cfg(any(target_os = "linux", target_os = "android"))]
    pub unsafe fn current() -> uint {
        let mut attr: libc::pthread_attr_t = mem::zeroed();
        if pthread_getattr_np(pthread_self(), &mut attr) != 0 {
            panic!("failed to get thread attributes");
        }
        let mut guardsize = 0;
        if pthread_attr_getguardsize(&attr, &mut guardsize) != 0 {
            panic!("failed to get stack guard page");
        }
        if guardsize == 0 {
            panic!("there is no guard page");
        }
        let mut stackaddr = ptr::null_mut();
        let mut stacksize = 0;
        if pthread_attr_getstack(&attr, &mut stackaddr, &mut stacksize) != 0 {
            panic!("failed to get stack information");
        }
        if pthread_attr_destroy(&mut attr) != 0 {
            panic!("failed to destroy thread attributes");
        }

        stackaddr as uint + guardsize as uint
    }
}

pub unsafe fn create(stack: uint, p: Thunk) -> rust_thread {
    let mut native: libc::pthread_t = mem::zeroed();
    let mut attr: libc::pthread_attr_t = mem::zeroed();
    assert_eq!(pthread_attr_init(&mut attr), 0);
    assert_eq!(pthread_attr_setdetachstate(&mut attr,
                                           PTHREAD_CREATE_JOINABLE), 0);

    // Reserve room for the red zone, the runtime's stack of last resort.
    let stack_size = cmp::max(stack, RED_ZONE + min_stack_size(&attr) as uint);
    match pthread_attr_setstacksize(&mut attr, stack_size as libc::size_t) {
        0 => {
        },
        libc::EINVAL => {
            // EINVAL means |stack_size| is either too small or not a
            // multiple of the system page size.  Because it's definitely
            // >= PTHREAD_STACK_MIN, it must be an alignment issue.
            // Round up to the nearest page and try again.
            let page_size = libc::sysconf(libc::_SC_PAGESIZE) as uint;
            let stack_size = (stack_size + page_size - 1) &
                             (-(page_size as int - 1) as uint - 1);
            assert_eq!(pthread_attr_setstacksize(&mut attr, stack_size as libc::size_t), 0);
        },
        errno => {
            // This cannot really happen.
            panic!("pthread_attr_setstacksize() error: {}", errno);
        },
    };

    let arg: *mut libc::c_void = mem::transmute(box p); // must box since sizeof(p)=2*uint
    let ret = pthread_create(&mut native, &attr, thread_start, arg);
    assert_eq!(pthread_attr_destroy(&mut attr), 0);

    if ret != 0 {
        // be sure to not leak the closure
        let _p: Box<Box<FnOnce()+Send>> = mem::transmute(arg);
        panic!("failed to spawn native thread: {}", ret);
    }
    native
}

#[cfg(any(target_os = "linux", target_os = "android"))]
pub unsafe fn set_name(name: &str) {
    // pthread_setname_np() since glibc 2.12
    // availability autodetected via weak linkage
    let cname = CString::from_slice(name.as_bytes());
    type F = unsafe extern "C" fn(libc::pthread_t, *const libc::c_char) -> libc::c_int;
    extern {
        #[linkage = "extern_weak"]
        static pthread_setname_np: *const ();
    }
    if !pthread_setname_np.is_null() {
        unsafe {
            mem::transmute::<*const (), F>(pthread_setname_np)(pthread_self(), cname.as_ptr());
        }
    }
}

#[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
pub unsafe fn set_name(name: &str) {
    // pthread_set_name_np() since almost forever on all BSDs
    let cname = CString::from_slice(name.as_bytes());
    pthread_set_name_np(pthread_self(), cname.as_ptr());
}

#[cfg(any(target_os = "macos", target_os = "ios"))]
pub unsafe fn set_name(name: &str) {
    // pthread_setname_np() since OS X 10.6 and iOS 3.2
    let cname = CString::from_slice(name.as_bytes());
    pthread_setname_np(cname.as_ptr());
}

pub unsafe fn join(native: rust_thread) {
    assert_eq!(pthread_join(native, ptr::null_mut()), 0);
}

pub unsafe fn detach(native: rust_thread) {
    assert_eq!(pthread_detach(native), 0);
}

pub unsafe fn yield_now() { assert_eq!(sched_yield(), 0); }
// glibc >= 2.15 has a __pthread_get_minstack() function that returns
// PTHREAD_STACK_MIN plus however many bytes are needed for thread-local
// storage.  We need that information to avoid blowing up when a small stack
// is created in an application with big thread-local storage requirements.
// See #6233 for rationale and details.
//
// Link weakly to the symbol for compatibility with older versions of glibc.
// Assumes that we've been dynamically linked to libpthread but that is
// currently always the case.  Note that you need to check that the symbol
// is non-null before calling it!
#[cfg(target_os = "linux")]
fn min_stack_size(attr: *const libc::pthread_attr_t) -> libc::size_t {
    type F = unsafe extern "C" fn(*const libc::pthread_attr_t) -> libc::size_t;
    extern {
        #[linkage = "extern_weak"]
        static __pthread_get_minstack: *const ();
    }
    if __pthread_get_minstack.is_null() {
        PTHREAD_STACK_MIN
    } else {
        unsafe { mem::transmute::<*const (), F>(__pthread_get_minstack)(attr) }
    }
}

// __pthread_get_minstack() is marked as weak but extern_weak linkage is
// not supported on OS X, hence this kludge...
#[cfg(not(target_os = "linux"))]
fn min_stack_size(_: *const libc::pthread_attr_t) -> libc::size_t {
    PTHREAD_STACK_MIN
}

#[cfg(any(target_os = "linux", target_os = "android"))]
extern {
    pub fn pthread_self() -> libc::pthread_t;
    pub fn pthread_getattr_np(native: libc::pthread_t,
                              attr: *mut libc::pthread_attr_t) -> libc::c_int;
    pub fn pthread_attr_getguardsize(attr: *const libc::pthread_attr_t,
                                     guardsize: *mut libc::size_t) -> libc::c_int;
    pub fn pthread_attr_getstack(attr: *const libc::pthread_attr_t,
                                 stackaddr: *mut *mut libc::c_void,
                                 stacksize: *mut libc::size_t) -> libc::c_int;
}

#[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
extern {
    pub fn pthread_self() -> libc::pthread_t;
    fn pthread_set_name_np(tid: libc::pthread_t, name: *const libc::c_char);
}

#[cfg(any(target_os = "macos", target_os = "ios"))]
extern {
    pub fn pthread_self() -> libc::pthread_t;
    pub fn pthread_get_stackaddr_np(thread: libc::pthread_t) -> *mut libc::c_void;
    pub fn pthread_get_stacksize_np(thread: libc::pthread_t) -> libc::size_t;
    fn pthread_setname_np(name: *const libc::c_char) -> libc::c_int;
}

#[cfg(target_os = "openbsd")]
extern {
        pub fn pthread_self() -> libc::pthread_t;
        pub fn pthread_stackseg_np(thread: libc::pthread_t,
                                   sinfo: *mut stack_t) -> libc::c_uint;
        pub fn pthread_main_np() -> libc::c_uint;
}

#[cfg(target_os = "openbsd")]
#[repr(C)]
pub struct stack_t {
    pub ss_sp: *mut libc::c_void,
    pub ss_size: libc::size_t,
    pub ss_flags: libc::c_int,
}

extern {
    fn pthread_create(native: *mut libc::pthread_t,
                      attr: *const libc::pthread_attr_t,
                      f: StartFn,
                      value: *mut libc::c_void) -> libc::c_int;
    fn pthread_join(native: libc::pthread_t,
                    value: *mut *mut libc::c_void) -> libc::c_int;
    fn pthread_attr_init(attr: *mut libc::pthread_attr_t) -> libc::c_int;
    pub fn pthread_attr_destroy(attr: *mut libc::pthread_attr_t) -> libc::c_int;
    fn pthread_attr_setstacksize(attr: *mut libc::pthread_attr_t,
                                 stack_size: libc::size_t) -> libc::c_int;
    fn pthread_attr_setdetachstate(attr: *mut libc::pthread_attr_t,
                                   state: libc::c_int) -> libc::c_int;
    fn pthread_detach(thread: libc::pthread_t) -> libc::c_int;
    fn sched_yield() -> libc::c_int;
}
<commit_msg>openbsd: rebase to master<commit_after>// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// 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.

use core::prelude::*;

use boxed::Box;
use cmp;
use mem;
use ptr;
use libc::consts::os::posix01::{PTHREAD_CREATE_JOINABLE, PTHREAD_STACK_MIN};
use libc;
use thunk::Thunk;
use ffi::CString;

use sys_common::stack::RED_ZONE;
use sys_common::thread::*;

pub type rust_thread = libc::pthread_t;
pub type rust_thread_return = *mut u8;
pub type StartFn = extern "C" fn(*mut libc::c_void) -> rust_thread_return;

#[no_stack_check]
pub extern fn thread_start(main: *mut libc::c_void) -> rust_thread_return {
    return start_thread(main);
}

#[cfg(all(not(target_os = "linux"),
          not(target_os = "macos"),
          not(target_os = "openbsd")))]
pub mod guard {
    pub unsafe fn current() -> uint {
        0
    }

    pub unsafe fn main() -> uint {
        0
    }

    pub unsafe fn init() {
    }
}

#[cfg(any(target_os = "linux",
          target_os = "macos",
          target_os = "openbsd"))]
pub mod guard {
    use super::*;
    #[cfg(any(target_os = "linux",
              target_os = "android",
              target_os = "openbsd"))]
    use mem;
    #[cfg(any(target_os = "linux", target_os = "android"))]
    use ptr;
    use libc;
    use libc::funcs::posix88::mman::{mmap};
    use libc::consts::os::posix88::{PROT_NONE,
                                    MAP_PRIVATE,
                                    MAP_ANON,
                                    MAP_FAILED,
                                    MAP_FIXED};

    // These are initialized in init() and only read from after
    static mut PAGE_SIZE: uint = 0;
    static mut GUARD_PAGE: uint = 0;

    #[cfg(any(target_os = "macos", target_os = "openbsd"))]
    unsafe fn get_stack_start() -> *mut libc::c_void {
        current() as *mut libc::c_void
    }

    #[cfg(any(target_os = "linux", target_os = "android"))]
    unsafe fn get_stack_start() -> *mut libc::c_void {
        let mut attr: libc::pthread_attr_t = mem::zeroed();
        if pthread_getattr_np(pthread_self(), &mut attr) != 0 {
            panic!("failed to get thread attributes");
        }
        let mut stackaddr = ptr::null_mut();
        let mut stacksize = 0;
        if pthread_attr_getstack(&attr, &mut stackaddr, &mut stacksize) != 0 {
            panic!("failed to get stack information");
        }
        if pthread_attr_destroy(&mut attr) != 0 {
            panic!("failed to destroy thread attributes");
        }
        stackaddr
    }

    pub unsafe fn init() {
        let psize = libc::sysconf(libc::consts::os::sysconf::_SC_PAGESIZE);
        if psize == -1 {
            panic!("failed to get page size");
        }

        PAGE_SIZE = psize as uint;

        let mut stackaddr = get_stack_start();

        // Ensure stackaddr is page aligned! A parent process might
        // have reset RLIMIT_STACK to be non-page aligned. The
        // pthread_attr_getstack() reports the usable stack area
        // stackaddr < stackaddr + stacksize, so if stackaddr is not
        // page-aligned, calculate the fix such that stackaddr <
        // new_page_aligned_stackaddr < stackaddr + stacksize
        let remainder = (stackaddr as usize) % (PAGE_SIZE as usize);
        if remainder != 0 {
            stackaddr = ((stackaddr as usize) + (PAGE_SIZE as usize) - remainder)
                as *mut libc::c_void;
        }

        // Rellocate the last page of the stack.
        // This ensures SIGBUS will be raised on
        // stack overflow.
        let result = mmap(stackaddr,
                          PAGE_SIZE as libc::size_t,
                          PROT_NONE,
                          MAP_PRIVATE | MAP_ANON | MAP_FIXED,
                          -1,
                          0);

        if result != stackaddr || result == MAP_FAILED {
            panic!("failed to allocate a guard page");
        }

        let offset = if cfg!(target_os = "linux") {
            2
        } else {
            1
        };

        GUARD_PAGE = stackaddr as uint + offset * PAGE_SIZE;
    }

    pub unsafe fn main() -> uint {
        GUARD_PAGE
    }

    #[cfg(target_os = "macos")]
    pub unsafe fn current() -> uint {
        (pthread_get_stackaddr_np(pthread_self()) as libc::size_t -
         pthread_get_stacksize_np(pthread_self())) as uint
    }

    #[cfg(target_os = "openbsd")]
    pub unsafe fn current() -> uint {
        let mut current_stack: stack_t = mem::zeroed();
        if pthread_stackseg_np(pthread_self(), &mut current_stack) != 0 {
            panic!("failed to get current stack: pthread_stackseg_np")
        }

        if pthread_main_np() == 1 {
            // main thread
            current_stack.ss_sp as uint - current_stack.ss_size as uint + 3 * PAGE_SIZE as uint

        } else {
            // new thread
            current_stack.ss_sp as uint - current_stack.ss_size as uint
        }
    }

    #[cfg(any(target_os = "linux", target_os = "android"))]
    pub unsafe fn current() -> uint {
        let mut attr: libc::pthread_attr_t = mem::zeroed();
        if pthread_getattr_np(pthread_self(), &mut attr) != 0 {
            panic!("failed to get thread attributes");
        }
        let mut guardsize = 0;
        if pthread_attr_getguardsize(&attr, &mut guardsize) != 0 {
            panic!("failed to get stack guard page");
        }
        if guardsize == 0 {
            panic!("there is no guard page");
        }
        let mut stackaddr = ptr::null_mut();
        let mut stacksize = 0;
        if pthread_attr_getstack(&attr, &mut stackaddr, &mut stacksize) != 0 {
            panic!("failed to get stack information");
        }
        if pthread_attr_destroy(&mut attr) != 0 {
            panic!("failed to destroy thread attributes");
        }

        stackaddr as uint + guardsize as uint
    }
}

pub unsafe fn create(stack: uint, p: Thunk) -> rust_thread {
    let mut native: libc::pthread_t = mem::zeroed();
    let mut attr: libc::pthread_attr_t = mem::zeroed();
    assert_eq!(pthread_attr_init(&mut attr), 0);
    assert_eq!(pthread_attr_setdetachstate(&mut attr,
                                           PTHREAD_CREATE_JOINABLE), 0);

    // Reserve room for the red zone, the runtime's stack of last resort.
    let stack_size = cmp::max(stack, RED_ZONE + min_stack_size(&attr) as uint);
    match pthread_attr_setstacksize(&mut attr, stack_size as libc::size_t) {
        0 => {
        },
        libc::EINVAL => {
            // EINVAL means |stack_size| is either too small or not a
            // multiple of the system page size.  Because it's definitely
            // >= PTHREAD_STACK_MIN, it must be an alignment issue.
            // Round up to the nearest page and try again.
            let page_size = libc::sysconf(libc::_SC_PAGESIZE) as uint;
            let stack_size = (stack_size + page_size - 1) &
                             (-(page_size as int - 1) as uint - 1);
            assert_eq!(pthread_attr_setstacksize(&mut attr, stack_size as libc::size_t), 0);
        },
        errno => {
            // This cannot really happen.
            panic!("pthread_attr_setstacksize() error: {}", errno);
        },
    };

    let arg: *mut libc::c_void = mem::transmute(box p); // must box since sizeof(p)=2*uint
    let ret = pthread_create(&mut native, &attr, thread_start, arg);
    assert_eq!(pthread_attr_destroy(&mut attr), 0);

    if ret != 0 {
        // be sure to not leak the closure
        let _p: Box<Box<FnOnce()+Send>> = mem::transmute(arg);
        panic!("failed to spawn native thread: {}", ret);
    }
    native
}

#[cfg(any(target_os = "linux", target_os = "android"))]
pub unsafe fn set_name(name: &str) {
    // pthread_setname_np() since glibc 2.12
    // availability autodetected via weak linkage
    let cname = CString::from_slice(name.as_bytes());
    type F = unsafe extern "C" fn(libc::pthread_t, *const libc::c_char) -> libc::c_int;
    extern {
        #[linkage = "extern_weak"]
        static pthread_setname_np: *const ();
    }
    if !pthread_setname_np.is_null() {
        unsafe {
            mem::transmute::<*const (), F>(pthread_setname_np)(pthread_self(), cname.as_ptr());
        }
    }
}

#[cfg(any(target_os = "freebsd",
          target_os = "dragonfly",
          target_os = "openbsd"))]
pub unsafe fn set_name(name: &str) {
    // pthread_set_name_np() since almost forever on all BSDs
    let cname = CString::from_slice(name.as_bytes());
    pthread_set_name_np(pthread_self(), cname.as_ptr());
}

#[cfg(any(target_os = "macos", target_os = "ios"))]
pub unsafe fn set_name(name: &str) {
    // pthread_setname_np() since OS X 10.6 and iOS 3.2
    let cname = CString::from_slice(name.as_bytes());
    pthread_setname_np(cname.as_ptr());
}

pub unsafe fn join(native: rust_thread) {
    assert_eq!(pthread_join(native, ptr::null_mut()), 0);
}

pub unsafe fn detach(native: rust_thread) {
    assert_eq!(pthread_detach(native), 0);
}

pub unsafe fn yield_now() { assert_eq!(sched_yield(), 0); }
// glibc >= 2.15 has a __pthread_get_minstack() function that returns
// PTHREAD_STACK_MIN plus however many bytes are needed for thread-local
// storage.  We need that information to avoid blowing up when a small stack
// is created in an application with big thread-local storage requirements.
// See #6233 for rationale and details.
//
// Link weakly to the symbol for compatibility with older versions of glibc.
// Assumes that we've been dynamically linked to libpthread but that is
// currently always the case.  Note that you need to check that the symbol
// is non-null before calling it!
#[cfg(target_os = "linux")]
fn min_stack_size(attr: *const libc::pthread_attr_t) -> libc::size_t {
    type F = unsafe extern "C" fn(*const libc::pthread_attr_t) -> libc::size_t;
    extern {
        #[linkage = "extern_weak"]
        static __pthread_get_minstack: *const ();
    }
    if __pthread_get_minstack.is_null() {
        PTHREAD_STACK_MIN
    } else {
        unsafe { mem::transmute::<*const (), F>(__pthread_get_minstack)(attr) }
    }
}

// __pthread_get_minstack() is marked as weak but extern_weak linkage is
// not supported on OS X, hence this kludge...
#[cfg(not(target_os = "linux"))]
fn min_stack_size(_: *const libc::pthread_attr_t) -> libc::size_t {
    PTHREAD_STACK_MIN
}

#[cfg(any(target_os = "linux", target_os = "android"))]
extern {
    pub fn pthread_self() -> libc::pthread_t;
    pub fn pthread_getattr_np(native: libc::pthread_t,
                              attr: *mut libc::pthread_attr_t) -> libc::c_int;
    pub fn pthread_attr_getguardsize(attr: *const libc::pthread_attr_t,
                                     guardsize: *mut libc::size_t) -> libc::c_int;
    pub fn pthread_attr_getstack(attr: *const libc::pthread_attr_t,
                                 stackaddr: *mut *mut libc::c_void,
                                 stacksize: *mut libc::size_t) -> libc::c_int;
}

#[cfg(any(target_os = "freebsd",
          target_os = "dragonfly",
          target_os = "openbsd"))]
extern {
    pub fn pthread_self() -> libc::pthread_t;
    fn pthread_set_name_np(tid: libc::pthread_t, name: *const libc::c_char);
}

#[cfg(any(target_os = "macos", target_os = "ios"))]
extern {
    pub fn pthread_self() -> libc::pthread_t;
    pub fn pthread_get_stackaddr_np(thread: libc::pthread_t) -> *mut libc::c_void;
    pub fn pthread_get_stacksize_np(thread: libc::pthread_t) -> libc::size_t;
    fn pthread_setname_np(name: *const libc::c_char) -> libc::c_int;
}

#[cfg(target_os = "openbsd")]
extern {
        pub fn pthread_stackseg_np(thread: libc::pthread_t,
                                   sinfo: *mut stack_t) -> libc::c_uint;
        pub fn pthread_main_np() -> libc::c_uint;
}

#[cfg(target_os = "openbsd")]
#[repr(C)]
pub struct stack_t {
    pub ss_sp: *mut libc::c_void,
    pub ss_size: libc::size_t,
    pub ss_flags: libc::c_int,
}

extern {
    fn pthread_create(native: *mut libc::pthread_t,
                      attr: *const libc::pthread_attr_t,
                      f: StartFn,
                      value: *mut libc::c_void) -> libc::c_int;
    fn pthread_join(native: libc::pthread_t,
                    value: *mut *mut libc::c_void) -> libc::c_int;
    fn pthread_attr_init(attr: *mut libc::pthread_attr_t) -> libc::c_int;
    pub fn pthread_attr_destroy(attr: *mut libc::pthread_attr_t) -> libc::c_int;
    fn pthread_attr_setstacksize(attr: *mut libc::pthread_attr_t,
                                 stack_size: libc::size_t) -> libc::c_int;
    fn pthread_attr_setdetachstate(attr: *mut libc::pthread_attr_t,
                                   state: libc::c_int) -> libc::c_int;
    fn pthread_detach(thread: libc::pthread_t) -> libc::c_int;
    fn sched_yield() -> libc::c_int;
}
<|endoftext|>


<commit_before>#[derive(Clone, Serialize, Deserialize, Debug)]
pub struct Contact {
    pub phone_number: String,
    pub first_name: String,
    pub last_name: Option<String>,
    pub user_id: Option<i64>,
}

impl Contact {
	pub fn new(phone_number: String,
				first_name: String,
				last_name: Option<String>,
				user_id: Option<i64>) -> Contact {
		Contact {
			phone_number: phone_number.to_string(),
			first_name: first_name.to_string(),
			last_name: last_name,
			user_id: user_id,
		}
	}
}<commit_msg>removed empty char at end of variables<commit_after>#[derive(Clone, Serialize, Deserialize, Debug)]
pub struct Contact {
    pub phone_number: String,
    pub first_name: String,
    pub last_name: Option<String>,
    pub user_id: Option<i64>,
}

impl Contact {
	pub fn new(phone_number: String,
				first_name: String,
				last_name: Option<String>,
				user_id: Option<i64>) -> Contact {
		Contact {
			phone_number: phone_number.to_string(),
			first_name: first_name.to_string(),
			last_name: last_name,
			user_id: user_id,
		}
	}
}<|endoftext|>


<commit_before>//! Client errors

use std::error::Error as StdError;
use std::io::Error as IoError;
use hyper::Error as HttpError;
use hyper::status::StatusCode;
use serde_json::error::Error as SerdeError;

/// enumerated types of client errors
error_chain! {
    errors {
        Fault {
            code: StatusCode,
            error: ClientError,
        }
    }
    foreign_links {
        Codec(SerdeError);
        Http(HttpError);
        IO(IoError);
    }
}

// preresentations

#[derive(Debug, Deserialize, PartialEq)]
pub struct FieldErr {
    pub resource: String,
    pub field: Option<String>,
    pub code: String,
    pub message: Option<String>,
    pub documentation_url: Option<String>,
}

#[derive(Debug, Deserialize, PartialEq)]
pub struct ClientError {
    pub message: String,
    pub errors: Option<Vec<FieldErr>>,
}

#[cfg(test)]
mod tests {
    use serde_json;
    use super::{ClientError, FieldErr};
    #[test]
    fn deserialize_client_field_errors() {
        for (json, expect) in vec![
            // see https://github.com/softprops/hubcaps/issues/31
            (
                r#"{"message": "Validation Failed","errors":
                [{
                    "resource": "Release",
                    "code": "custom",
                    "message": "Published releases must have a valid tag"
                }]}"#,
                ClientError {
                    message: "Validation Failed".to_owned(),
                    errors: Some(vec![
                        FieldErr {
                            resource: "Release".to_owned(),
                            code: "custom".to_owned(),
                            field: None,
                            message: Some(
                                "Published releases \
                                                                            must have a valid tag"
                                    .to_owned()
                            ),
                            documentation_url: None,
                        },
                    ]),
                }
            ),
        ]
        {
            assert_eq!(serde_json::from_str::<ClientError>(json).unwrap(), expect);
        }
    }
}
<commit_msg>Remove unused import<commit_after>//! Client errors

use std::io::Error as IoError;
use hyper::Error as HttpError;
use hyper::status::StatusCode;
use serde_json::error::Error as SerdeError;

/// enumerated types of client errors
error_chain! {
    errors {
        Fault {
            code: StatusCode,
            error: ClientError,
        }
    }
    foreign_links {
        Codec(SerdeError);
        Http(HttpError);
        IO(IoError);
    }
}

// preresentations

#[derive(Debug, Deserialize, PartialEq)]
pub struct FieldErr {
    pub resource: String,
    pub field: Option<String>,
    pub code: String,
    pub message: Option<String>,
    pub documentation_url: Option<String>,
}

#[derive(Debug, Deserialize, PartialEq)]
pub struct ClientError {
    pub message: String,
    pub errors: Option<Vec<FieldErr>>,
}

#[cfg(test)]
mod tests {
    use serde_json;
    use super::{ClientError, FieldErr};
    #[test]
    fn deserialize_client_field_errors() {
        for (json, expect) in vec![
            // see https://github.com/softprops/hubcaps/issues/31
            (
                r#"{"message": "Validation Failed","errors":
                [{
                    "resource": "Release",
                    "code": "custom",
                    "message": "Published releases must have a valid tag"
                }]}"#,
                ClientError {
                    message: "Validation Failed".to_owned(),
                    errors: Some(vec![
                        FieldErr {
                            resource: "Release".to_owned(),
                            code: "custom".to_owned(),
                            field: None,
                            message: Some(
                                "Published releases \
                                                                            must have a valid tag"
                                    .to_owned()
                            ),
                            documentation_url: None,
                        },
                    ]),
                }
            ),
        ]
        {
            assert_eq!(serde_json::from_str::<ClientError>(json).unwrap(), expect);
        }
    }
}
<|endoftext|>


<commit_before>use std::io;
use std::cmp;

use winapi::shared::minwindef::*;
use winapi::shared::ntdef::HANDLE;
use winapi::shared::winerror::*;
use winapi::um::fileapi::*;
use winapi::um::handleapi::*;
use winapi::um::minwinbase::*;

#[derive(Debug)]
pub struct Handle(HANDLE);

unsafe impl Send for Handle {}
unsafe impl Sync for Handle {}

impl Handle {
    pub fn new(handle: HANDLE) -> Handle {
        Handle(handle)
    }

    pub fn raw(&self) -> HANDLE { self.0 }

    pub fn into_raw(self) -> HANDLE {
        use std::mem;

        let ret = self.0;
        mem::forget(self);
        ret
    }

    pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
        let mut bytes = 0;
        let len = cmp::min(buf.len(), <DWORD>::max_value() as usize) as DWORD;
        try!(::cvt(unsafe {
            WriteFile(self.0, buf.as_ptr() as *const _, len, &mut bytes,
                      0 as *mut _)
        }));
        Ok(bytes as usize)
    }

    pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
        let mut bytes = 0;
        let len = cmp::min(buf.len(), <DWORD>::max_value() as usize) as DWORD;
        try!(::cvt(unsafe {
            ReadFile(self.0, buf.as_mut_ptr() as *mut _, len, &mut bytes,
                     0 as *mut _)
        }));
        Ok(bytes as usize)
    }

    pub unsafe fn read_overlapped(&self, buf: &mut [u8],
                                  overlapped: *mut OVERLAPPED)
                                  -> io::Result<Option<usize>> {
        let len = cmp::min(buf.len(), <DWORD>::max_value() as usize) as DWORD;
        let mut bytes = 0;
        let res = ::cvt({
            ReadFile(self.0,
                     buf.as_mut_ptr() as *mut _,
                     len,
                     &mut bytes,
                     overlapped)
        });
        match res {
            Ok(_) => Ok(Some(bytes as usize)),
            Err(ref e) if e.raw_os_error() == Some(ERROR_IO_PENDING as i32)
                => Ok(None),
            Err(e) => Err(e),
        }
    }

    pub unsafe fn write_overlapped(&self, buf: &[u8],
                                   overlapped: *mut OVERLAPPED)
                                   -> io::Result<Option<usize>> {
        let len = cmp::min(buf.len(), <DWORD>::max_value() as usize) as DWORD;
        let mut bytes = 0;
        let res = ::cvt({
            WriteFile(self.0,
                      buf.as_ptr() as *const _,
                      len,
                      &mut bytes,
                      overlapped)
        });
        match res {
            Ok(_) => Ok(Some(bytes as usize)),
            Err(ref e) if e.raw_os_error() == Some(ERROR_IO_PENDING as i32)
                => Ok(None),
            Err(e) => Err(e),
        }
    }
}

impl Drop for Handle {
    fn drop(&mut self) {
        unsafe { CloseHandle(self.0) };
    }
}
<commit_msg>GetOverlappedResult<commit_after>use std::io;
use std::cmp;
use std::ptr;

use winapi::shared::minwindef::*;
use winapi::shared::ntdef::HANDLE;
use winapi::shared::winerror::*;
use winapi::um::fileapi::*;
use winapi::um::handleapi::*;
use winapi::um::minwinbase::*;

#[derive(Debug)]
pub struct Handle(HANDLE);

unsafe impl Send for Handle {}
unsafe impl Sync for Handle {}

impl Handle {
    pub fn new(handle: HANDLE) -> Handle {
        Handle(handle)
    }

    pub fn raw(&self) -> HANDLE { self.0 }

    pub fn into_raw(self) -> HANDLE {
        use std::mem;

        let ret = self.0;
        mem::forget(self);
        ret
    }

    pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
        let mut bytes = 0;
        let len = cmp::min(buf.len(), <DWORD>::max_value() as usize) as DWORD;
        try!(::cvt(unsafe {
            WriteFile(self.0, buf.as_ptr() as *const _, len, &mut bytes,
                      0 as *mut _)
        }));
        Ok(bytes as usize)
    }

    pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
        let mut bytes = 0;
        let len = cmp::min(buf.len(), <DWORD>::max_value() as usize) as DWORD;
        try!(::cvt(unsafe {
            ReadFile(self.0, buf.as_mut_ptr() as *mut _, len, &mut bytes,
                     0 as *mut _)
        }));
        Ok(bytes as usize)
    }

    pub unsafe fn read_overlapped(&self, buf: &mut [u8],
                                  overlapped: *mut OVERLAPPED)
                                  -> io::Result<Option<usize>> {
        let len = cmp::min(buf.len(), <DWORD>::max_value() as usize) as DWORD;
        let res = ::cvt({
            ReadFile(self.0,
                     buf.as_mut_ptr() as *mut _,
                     len,
                     ptr::null_mut(),
                     overlapped)
        });
        match res {
            Ok(_) => (),
            Err(ref e) if e.raw_os_error() == Some(ERROR_IO_PENDING as i32)
                => (),
            Err(e) => return Err(e),
        }

        let mut bytes = 0;
        let res = ::cvt({
            GetOverlappedResult(self.0,
                                overlapped,
                                &mut bytes,
                                false)
        });
        match res {
            Ok(_) => Ok(Some(bytes as usize)),
            Err(ref e) if e.raw_os_error() == Some(ERROR_IO_INCOMPLETE as i32)
                => Ok(None),
            Err(e) => Err(e),
        }
    }

    pub unsafe fn write_overlapped(&self, buf: &[u8],
                                   overlapped: *mut OVERLAPPED)
                                   -> io::Result<Option<usize>> {
        let len = cmp::min(buf.len(), <DWORD>::max_value() as usize) as DWORD;
        let res = ::cvt({
            WriteFile(self.0,
                      buf.as_ptr() as *const _,
                      len,
                      ptr::null_mut(),
                      overlapped)
        });
        match res {
            Ok(_) => Ok(Some(bytes as usize)),
            Err(ref e) if e.raw_os_error() == Some(ERROR_IO_PENDING as i32)
                => Ok(None),
            Err(e) => Err(e),
        }

        let mut bytes = 0;
        let res = ::cvt({
            GetOverlappedResult(self.0,
                                overlapped,
                                &mut bytes,
                                false)
        });
        match res {
            Ok(_) => Ok(Some(bytes as usize)),
            Err(ref e) if e.raw_os_error() == Some(ERROR_IO_INCOMPLETE as i32)
                => Ok(None),
            Err(e) => Err(e),
        }
    }
}

impl Drop for Handle {
    fn drop(&mut self) {
        unsafe { CloseHandle(self.0) };
    }
}
<|endoftext|>


<commit_before>use super::{XWaylandManager, XWaylandManagerHandler};
use wayland_sys::server::signal::wl_signal_add;
use wlroots_sys::{wl_display, wlr_compositor, wlr_xwayland, wlr_xwayland_create,
                  wlr_xwayland_destroy};

pub struct XWaylandServer {
    manager: Box<XWaylandManager>,
    xwayland: *mut wlr_xwayland
}

impl XWaylandServer {
    pub(crate) unsafe fn new(display: *mut wl_display,
                             compositor: *mut wlr_compositor,
                             manager: Box<XWaylandManagerHandler>)
                             -> Self {
        let xwayland = wlr_xwayland_create(display, compositor);
        let mut manager = XWaylandManager::new(manager);
        wl_signal_add(&mut (*xwayland).events.ready as *mut _ as _,
                      manager.on_ready_listener() as *mut _ as _);
        wl_signal_add(&mut (*xwayland).events.new_surface as *mut _ as _,
                      manager.new_surface_listener() as *mut _ as _);
        if xwayland.is_null() {
            panic!("Could not start XWayland server")
        }
        XWaylandServer { xwayland, manager }
    }
}

impl Drop for XWaylandServer {
    fn drop(&mut self) {
        unsafe { wlr_xwayland_destroy(self.xwayland) }
    }
}
<commit_msg>Added field accessors for XwaylandServer<commit_after>use libc::c_int;
use wayland_sys::server::signal::wl_signal_add;
use wlroots_sys::{wl_display, wlr_compositor, wlr_xwayland, wlr_xwayland_create,
                  wlr_xwayland_destroy, pid_t, wl_client};

use super::{XWaylandManager, XWaylandManagerHandler};

pub struct XWaylandServer {
    xwayland: *mut wlr_xwayland,
    manager: Box<XWaylandManager>
}

impl XWaylandServer {
    pub(crate) unsafe fn new(display: *mut wl_display,
                             compositor: *mut wlr_compositor,
                             manager: Box<XWaylandManagerHandler>)
                             -> Self {
        let xwayland = wlr_xwayland_create(display, compositor);
        let mut manager = XWaylandManager::new(manager);
        wl_signal_add(&mut (*xwayland).events.ready as *mut _ as _,
                      manager.on_ready_listener() as *mut _ as _);
        wl_signal_add(&mut (*xwayland).events.new_surface as *mut _ as _,
                      manager.new_surface_listener() as *mut _ as _);
        if xwayland.is_null() {
            panic!("Could not start XWayland server")
        }
        XWaylandServer { xwayland, manager }
    }

    /// Get the PID of the XWayland server.
    pub fn pid(&self) -> pid_t {
        unsafe { (*self.xwayland).pid }
    }

    pub fn display(&self) -> c_int {
        unsafe { (*self.xwayland).display }
    }

    pub fn x_fd(&self) -> [c_int; 2] {
        unsafe { (*self.xwayland).x_fd }
    }

    pub fn wl_fd(&self) -> [c_int; 2] {
        unsafe { (*self.xwayland).wl_fd }
    }

    pub fn wm_fd(&self) -> [c_int; 2] {
        unsafe {(*self.xwayland).wm_fd }
    }

    pub fn wl_client(&self) -> *mut wl_client {
        unsafe { (*self.xwayland).client }
    }
}

impl Drop for XWaylandServer {
    fn drop(&mut self) {
        unsafe { wlr_xwayland_destroy(self.xwayland) }
    }
}
<|endoftext|>


<commit_before>//! TODO Documentation

use std::time::Duration;

use libc::{c_float, c_int, c_void};

use {Area, Output, PixmanRegion};
use render::Texture;
use wlroots_sys::{wl_shm_format, wlr_backend, wlr_backend_get_renderer,
                  wlr_render_ellipse_with_matrix, wlr_render_quad_with_matrix, wlr_render_rect,
                  wlr_render_texture, wlr_render_texture_with_matrix, wlr_renderer,
                  wlr_renderer_begin, wlr_renderer_clear, wlr_renderer_destroy, wlr_renderer_end,
                  wlr_texture_from_pixels};

/// A generic interface for rendering to the screen.
///
/// Note that it will technically be possible to have multiple renderers
/// at the same time.
#[derive(Debug)]
pub struct GenericRenderer {
    renderer: *mut wlr_renderer
}

/// The state machine type that allows you to manipulate a screen and
/// its buffer.
///
/// When this structure is dropped it automatically calls wlr_renderer_end
/// and swaps the buffers.
#[derive(Debug)]
pub struct Renderer<'output> {
    renderer: *mut wlr_renderer,
    pub damage: Option<(PixmanRegion, Duration)>,
    pub output: &'output mut Output
}

impl GenericRenderer {
    /// Make a gles2 renderer.
    pub(crate) unsafe fn gles2_renderer(backend: *mut wlr_backend) -> Self {
        let renderer = wlr_backend_get_renderer(backend);
        if renderer.is_null() {
            panic!("Could not construct GLES2 renderer");
        }
        GenericRenderer { renderer }
    }

    /// Make the `Renderer` state machine type.
    ///
    /// This automatically makes the given output the current output.
    pub fn render<'output, T>(&mut self,
                              output: &'output mut Output,
                              damage: T)
                              -> Renderer<'output>
        where T: Into<Option<(PixmanRegion, Duration)>>
    {
        unsafe {
            output.make_current();
            let (width, height) = output.size();
            wlr_renderer_begin(self.renderer, width, height);
            Renderer { renderer: self.renderer,
                       damage: damage.into(),
                       output }
        }
    }

    /// Create a texture using this renderer.
    pub fn create_texture_from_pixels(&mut self,
                                      format: wl_shm_format,
                                      stride: u32,
                                      width: u32,
                                      height: u32,
                                      data: &[u8])
                                      -> Option<Texture> {
        unsafe {
            create_texture_from_pixels(self.renderer,
                                       format,
                                       stride,
                                       width,
                                       height,
                                       data.as_ptr() as _)
        }
    }

    pub(crate) unsafe fn as_ptr(&self) -> *mut wlr_renderer {
        self.renderer
    }
}

impl Drop for GenericRenderer {
    fn drop(&mut self) {
        unsafe { wlr_renderer_destroy(self.renderer) }
    }
}

impl<'output> Renderer<'output> {
    pub fn clear(&mut self, float: [f32; 4]) {
        unsafe { wlr_renderer_clear(self.renderer, float.as_ptr()) }
    }

    /// Renders the requseted texture.
    pub fn render_texture(&mut self,
                          texture: &Texture,
                          projection: [f32; 9],
                          x: c_int,
                          y: c_int,
                          alpha: c_float)
                          -> bool {
        unsafe {
            wlr_render_texture(self.renderer,
                               texture.as_ptr(),
                               projection.as_ptr(),
                               x,
                               y,
                               alpha)
        }
    }

    /// Renders the requested texture using the provided matrix. A typical texture
    /// rendering goes like so:
    ///
    /// TODO FIXME Show how the typical rendering goes in Rust.
    ///
    /// ```c
    /// struct wlr_renderer *renderer;
    /// struct wlr_texture *texture;
    /// float projection[16];
    /// float matrix[16];
    /// wlr_texture_get_matrix(texture, &matrix, &projection, 123, 321);
    /// wlr_render_texture_with_matrix(renderer, texture, &matrix);
    /// ```
    ///
    /// This will render the texture at <123, 321>.
    pub fn render_texture_with_matrix(&mut self, texture: &Texture, matrix: [f32; 9]) -> bool {
        // TODO FIXME Add alpha as param
        unsafe {
            wlr_render_texture_with_matrix(self.renderer, texture.as_ptr(), matrix.as_ptr(), 1.0)
        }
    }

    /// Renders a solid quad in the specified color.
    pub fn render_colored_quad(&mut self, color: [f32; 4], matrix: [f32; 9]) {
        unsafe { wlr_render_quad_with_matrix(self.renderer, color.as_ptr(), matrix.as_ptr()) }
    }

    /// Renders a solid ellipse in the specified color.
    pub fn render_colored_ellipse(&mut self, color: [f32; 4], matrix: [f32; 9]) {
        unsafe { wlr_render_ellipse_with_matrix(self.renderer, color.as_ptr(), matrix.as_ptr()) }
    }

    /// Renders a solid rectangle in the specified color.
    pub fn render_colored_rect(&mut self, area: Area, color: [f32; 4], matrix: [f32; 9]) {
        unsafe { wlr_render_rect(self.renderer, &area.into(), color.as_ptr(), matrix.as_ptr()) }
    }
}

impl<'output> Drop for Renderer<'output> {
    fn drop(&mut self) {
        unsafe {
            wlr_renderer_end(self.renderer);
            if let Some((mut damage, when)) = self.damage.take() {
                self.output.swap_buffers(Some(when), Some(&mut damage));
            } else {
                self.output.swap_buffers(None, None);
            }
        }
    }
}

unsafe fn create_texture_from_pixels(renderer: *mut wlr_renderer,
                                     format: wl_shm_format,
                                     stride: u32,
                                     width: u32,
                                     height: u32,
                                     // TODO Slice of u8? It's a void*, hmm
                                     data: *const c_void)
                                     -> Option<Texture> {
    let texture = wlr_texture_from_pixels(renderer, format, stride, width, height, data);
    if texture.is_null() {
        None
    } else {
        Some(Texture::from_ptr(texture))
    }
}
<commit_msg>Added create_texture_from_pixels<commit_after>//! TODO Documentation

use std::time::Duration;

use libc::{c_float, c_int, c_void};

use {Area, Output, PixmanRegion};
use render::Texture;
use wlroots_sys::{wl_shm_format, wlr_backend, wlr_backend_get_renderer,
                  wlr_render_ellipse_with_matrix, wlr_render_quad_with_matrix, wlr_render_rect,
                  wlr_render_texture, wlr_render_texture_with_matrix, wlr_renderer,
                  wlr_renderer_begin, wlr_renderer_clear, wlr_renderer_destroy, wlr_renderer_end,
                  wlr_texture_from_pixels};

/// A generic interface for rendering to the screen.
///
/// Note that it will technically be possible to have multiple renderers
/// at the same time.
#[derive(Debug)]
pub struct GenericRenderer {
    renderer: *mut wlr_renderer
}

/// The state machine type that allows you to manipulate a screen and
/// its buffer.
///
/// When this structure is dropped it automatically calls wlr_renderer_end
/// and swaps the buffers.
#[derive(Debug)]
pub struct Renderer<'output> {
    renderer: *mut wlr_renderer,
    pub damage: Option<(PixmanRegion, Duration)>,
    pub output: &'output mut Output
}

impl GenericRenderer {
    /// Make a gles2 renderer.
    pub(crate) unsafe fn gles2_renderer(backend: *mut wlr_backend) -> Self {
        let renderer = wlr_backend_get_renderer(backend);
        if renderer.is_null() {
            panic!("Could not construct GLES2 renderer");
        }
        GenericRenderer { renderer }
    }

    /// Make the `Renderer` state machine type.
    ///
    /// This automatically makes the given output the current output.
    pub fn render<'output, T>(&mut self,
                              output: &'output mut Output,
                              damage: T)
                              -> Renderer<'output>
        where T: Into<Option<(PixmanRegion, Duration)>>
    {
        unsafe {
            output.make_current();
            let (width, height) = output.size();
            wlr_renderer_begin(self.renderer, width, height);
            Renderer { renderer: self.renderer,
                       damage: damage.into(),
                       output }
        }
    }

    /// Create a texture using this renderer.
    pub fn create_texture_from_pixels(&mut self,
                                      format: wl_shm_format,
                                      stride: u32,
                                      width: u32,
                                      height: u32,
                                      data: &[u8])
                                      -> Option<Texture> {
        unsafe {
            create_texture_from_pixels(self.renderer,
                                       format,
                                       stride,
                                       width,
                                       height,
                                       data.as_ptr() as _)
        }
    }

    pub(crate) unsafe fn as_ptr(&self) -> *mut wlr_renderer {
        self.renderer
    }
}

impl Drop for GenericRenderer {
    fn drop(&mut self) {
        unsafe { wlr_renderer_destroy(self.renderer) }
    }
}

impl<'output> Renderer<'output> {
    /// Create a texture using this renderer.
    pub fn create_texture_from_pixels(&mut self,
                                      format: wl_shm_format,
                                      stride: u32,
                                      width: u32,
                                      height: u32,
                                      data: &[u8])
                                      -> Option<Texture> {
        unsafe {
            create_texture_from_pixels(self.renderer,
                                       format,
                                       stride,
                                       width,
                                       height,
                                       data.as_ptr() as _)
        }
    }

    pub fn clear(&mut self, float: [f32; 4]) {
        unsafe { wlr_renderer_clear(self.renderer, float.as_ptr()) }
    }

    /// Renders the requseted texture.
    pub fn render_texture(&mut self,
                          texture: &Texture,
                          projection: [f32; 9],
                          x: c_int,
                          y: c_int,
                          alpha: c_float)
                          -> bool {
        unsafe {
            wlr_render_texture(self.renderer,
                               texture.as_ptr(),
                               projection.as_ptr(),
                               x,
                               y,
                               alpha)
        }
    }

    /// Renders the requested texture using the provided matrix. A typical texture
    /// rendering goes like so:
    ///
    /// TODO FIXME Show how the typical rendering goes in Rust.
    ///
    /// ```c
    /// struct wlr_renderer *renderer;
    /// struct wlr_texture *texture;
    /// float projection[16];
    /// float matrix[16];
    /// wlr_texture_get_matrix(texture, &matrix, &projection, 123, 321);
    /// wlr_render_texture_with_matrix(renderer, texture, &matrix);
    /// ```
    ///
    /// This will render the texture at <123, 321>.
    pub fn render_texture_with_matrix(&mut self, texture: &Texture, matrix: [f32; 9]) -> bool {
        // TODO FIXME Add alpha as param
        unsafe {
            wlr_render_texture_with_matrix(self.renderer, texture.as_ptr(), matrix.as_ptr(), 1.0)
        }
    }

    /// Renders a solid quad in the specified color.
    pub fn render_colored_quad(&mut self, color: [f32; 4], matrix: [f32; 9]) {
        unsafe { wlr_render_quad_with_matrix(self.renderer, color.as_ptr(), matrix.as_ptr()) }
    }

    /// Renders a solid ellipse in the specified color.
    pub fn render_colored_ellipse(&mut self, color: [f32; 4], matrix: [f32; 9]) {
        unsafe { wlr_render_ellipse_with_matrix(self.renderer, color.as_ptr(), matrix.as_ptr()) }
    }

    /// Renders a solid rectangle in the specified color.
    pub fn render_colored_rect(&mut self, area: Area, color: [f32; 4], matrix: [f32; 9]) {
        unsafe { wlr_render_rect(self.renderer, &area.into(), color.as_ptr(), matrix.as_ptr()) }
    }
}

impl<'output> Drop for Renderer<'output> {
    fn drop(&mut self) {
        unsafe {
            wlr_renderer_end(self.renderer);
            if let Some((mut damage, when)) = self.damage.take() {
                self.output.swap_buffers(Some(when), Some(&mut damage));
            } else {
                self.output.swap_buffers(None, None);
            }
        }
    }
}

unsafe fn create_texture_from_pixels(renderer: *mut wlr_renderer,
                                     format: wl_shm_format,
                                     stride: u32,
                                     width: u32,
                                     height: u32,
                                     // TODO Slice of u8? It's a void*, hmm
                                     data: *const c_void)
                                     -> Option<Texture> {
    let texture = wlr_texture_from_pixels(renderer, format, stride, width, height, data);
    if texture.is_null() {
        None
    } else {
        Some(Texture::from_ptr(texture))
    }
}
<|endoftext|>