<commit_before>//! The CXX code generator for constructing and compiling C++ code.
//!
//! This is intended to be used from Cargo build scripts to execute CXX's
//! C++ code generator, set up any additional compiler flags depending on
//! the use case, and make the C++ compiler invocation.
//!
//!

//!
//! # Example
//!
//! Example of a canonical Cargo build script that builds a CXX bridge:
//!
//! ```no_run
//! // build.rs
//!
//! fn main() {
//!     cxx_build::bridge("src/main.rs")
//!         .file("src/demo.cc")
//!         .flag_if_supported("-std=c++11")
//!         .compile("cxxbridge-demo");
//!
//!     println!("cargo:rerun-if-changed=src/main.rs");
//!     println!("cargo:rerun-if-changed=src/demo.cc");
//!     println!("cargo:rerun-if-changed=include/demo.h");
//! }
//! ```
//!
//! A runnable working setup with this build script is shown in the *demo*
//! directory of [https://github.com/dtolnay/cxx].
//!
//! [https://github.com/dtolnay/cxx]: https://github.com/dtolnay/cxx
//!
//!

//!
//! # Alternatives
//!
//! For use in non-Cargo builds like Bazel or Buck, CXX provides an
//! alternate way of invoking the C++ code generator as a standalone command
//! line tool. The tool is packaged as the `cxxbridge-cmd` crate.
//!
//! ```bash
//! $ cargo install cxxbridge-cmd  # or build it from the repo
//!
//! $ cxxbridge src/main.rs --header > path/to/mybridge.h
//! $ cxxbridge src/main.rs > path/to/mybridge.cc
//! ```

#![allow(
    clippy::inherent_to_string,
    clippy::needless_doctest_main,
    clippy::new_without_default,
    clippy::or_fun_call,
    clippy::toplevel_ref_arg
)]

mod cargo;
mod error;
mod gen;
mod out;
mod paths;
mod syntax;

use crate::error::{Error, Result};
use crate::gen::error::report;
use crate::gen::Opt;
use crate::paths::{PathExt, TargetDir};
use cc::Build;
use std::env;
use std::ffi::{OsStr, OsString};
use std::io::{self, Write};
use std::iter;
use std::path::{Path, PathBuf};
use std::process;

/// This returns a [`cc::Build`] on which you should continue to set up any
/// additional source files or compiler flags, and lastly call its [`compile`]
/// method to execute the C++ build.
///
/// [`compile`]: https://docs.rs/cc/1.0.49/cc/struct.Build.html#method.compile
#[must_use]
pub fn bridge(rust_source_file: impl AsRef<Path>) -> Build {
    bridges(iter::once(rust_source_file))
}

/// `cxx_build::bridge` but for when more than one file contains a
/// #\[cxx::bridge\] module.
///
/// ```no_run
/// let source_files = vec!["src/main.rs", "src/path/to/other.rs"];
/// cxx_build::bridges(source_files)
///     .file("src/demo.cc")
///     .flag_if_supported("-std=c++11")
///     .compile("cxxbridge-demo");
/// ```
#[must_use]
pub fn bridges(rust_source_files: impl IntoIterator<Item = impl AsRef<Path>>) -> Build {
    let ref mut rust_source_files = rust_source_files.into_iter();
    build(rust_source_files).unwrap_or_else(|err| {
        let _ = writeln!(io::stderr(), "\n\ncxxbridge error: {}\n\n", report(err));
        process::exit(1);
    })
}

struct Project {
    package_name: OsString,
    manifest_dir: PathBuf,
    // Output directory as received from Cargo.
    out_dir: PathBuf,
    // Directory into which to symlink all generated code.
    //
    // This is *not* used for an #include path, only as a debugging convenience.
    // Normally available at target/cxxbridge/ if we are able to know where the
    // target dir is, otherwise under a common scratch dir.
    //
    // The reason this isn't the #include dir is that we do not want builds to
    // have access to headers from arbitrary other parts of the dependency
    // graph. Using a global directory for all builds would be both a race
    // condition depending on what order Cargo randomly executes the build
    // scripts, as well as semantically undesirable for builds not to have to
    // declare their real dependencies.
    shared_dir: PathBuf,
}

impl Project {
    fn init() -> Result<Self> {
        let package_name = env_os("CARGO_PKG_NAME")?;
        let manifest_dir = paths::manifest_dir()?;
        let out_dir = paths::out_dir()?;

        let target_dir = match cargo::target_dir(&out_dir) {
            target_dir @ TargetDir::Path(_) => target_dir,
            // Fallback if Cargo did not work.
            TargetDir::Unknown => paths::search_parents_for_target_dir(&out_dir),
        };

        let shared_dir = match target_dir {
            TargetDir::Path(target_dir) => target_dir.join("cxxbridge"),
            // Use cxx-build's OUT_DIR.
            TargetDir::Unknown => PathBuf::from(env!("OUT_DIR")),
        };

        Ok(Project {
            package_name,
            manifest_dir,
            out_dir,
            shared_dir,
        })
    }
}

// We lay out the OUT_DIR as follows. Everything is namespaced under a cxxbridge
// subdirectory to avoid stomping on other things that the caller's build script
// might be doing inside OUT_DIR.
//
//     $OUT_DIR/
//        cxxbridge/
//           crate/
//              $CARGO_PKG_NAME -> $CARGO_MANIFEST_DIR
//           include/
//              rust/
//                 cxx.h
//              $CARGO_PKG_NAME/
//                 .../
//                    lib.rs.h
//           sources/
//              $CARGO_PKG_NAME/
//                 .../
//                    lib.rs.cc
//
// The crate/ and include/ directories are placed on the #include path.
fn build(rust_source_files: &mut dyn Iterator<Item = impl AsRef<Path>>) -> Result<Build> {
    let ref prj = Project::init()?;

    let ref crate_dir = make_crate_dir(prj);
    let ref include_dir = make_include_dir(prj)?;

    let mut build = Build::new();
    build.cpp(true);
    build.cpp_link_stdlib(None); // linked via link-cplusplus crate
    if let Some(crate_dir) = crate_dir {
        build.include(crate_dir);
    }
    build.include(include_dir);

    for path in rust_source_files {
        generate_bridge(prj, &mut build, path.as_ref())?;
    }

    eprintln!("\nCXX include path:");
    if let Some(crate_dir) = crate_dir {
        eprintln!("  {}", crate_dir.display());
    }
    eprintln!("  {}", include_dir.display());
    Ok(build)
}

fn make_crate_dir(prj: &Project) -> Option<PathBuf> {
    let crate_dir = prj.out_dir.join("cxxbridge").join("crate");
    let link = crate_dir.join(&prj.package_name);
    if out::symlink_dir(&prj.manifest_dir, link).is_ok() {
        Some(crate_dir)
    } else {
        None
    }
}

fn make_include_dir(prj: &Project) -> Result<PathBuf> {
    let include_dir = prj.out_dir.join("cxxbridge").join("include");
    let cxx_h = include_dir.join("rust").join("cxx.h");
    let ref shared_cxx_h = prj.shared_dir.join("rust").join("cxx.h");
    if let Some(ref original) = env::var_os("DEP_CXXBRIDGE04_HEADER") {
        out::symlink_file(original, cxx_h)?;
        out::symlink_file(original, shared_cxx_h)?;
    } else {
        out::write(shared_cxx_h, gen::include::HEADER.as_bytes())?;
        out::symlink_file(shared_cxx_h, cxx_h)?;
    }
    Ok(include_dir)
}

fn generate_bridge(prj: &Project, build: &mut Build, rust_source_file: &Path) -> Result<()> {
    let opt = Opt::default();
    let generated = gen::generate_from_path(rust_source_file, &opt);
    let ref rel_path = paths::local_relative_path(rust_source_file);

    let cxxbridge = prj.out_dir.join("cxxbridge");
    let include_dir = cxxbridge.join("include").join(&prj.package_name);
    let sources_dir = cxxbridge.join("sources").join(&prj.package_name);

    let ref rel_path_h = rel_path.with_appended_extension(".h");
    let ref header_path = include_dir.join(rel_path_h);
    out::write(header_path, &generated.header)?;

    let ref link_path = include_dir.join(rel_path);
    let _ = out::symlink_file(header_path, link_path);

    let ref rel_path_cc = rel_path.with_appended_extension(".cc");
    let ref implementation_path = sources_dir.join(rel_path_cc);
    out::write(implementation_path, &generated.implementation)?;
    build.file(implementation_path);

    let shared_h = prj.shared_dir.join(&prj.package_name).join(rel_path_h);
    let shared_cc = prj.shared_dir.join(&prj.package_name).join(rel_path_cc);
    let _ = out::symlink_file(header_path, shared_h);
    let _ = out::symlink_file(implementation_path, shared_cc);
    Ok(())
}

fn env_os(key: impl AsRef<OsStr>) -> Result<OsString> {
    let key = key.as_ref();
    env::var_os(key).ok_or_else(|| Error::NoEnv(key.to_owned()))
}
<commit_msg>Swap include line order to support #include of a .rs file<commit_after>//! The CXX code generator for constructing and compiling C++ code.
//!
//! This is intended to be used from Cargo build scripts to execute CXX's
//! C++ code generator, set up any additional compiler flags depending on
//! the use case, and make the C++ compiler invocation.
//!
//!

//!
//! # Example
//!
//! Example of a canonical Cargo build script that builds a CXX bridge:
//!
//! ```no_run
//! // build.rs
//!
//! fn main() {
//!     cxx_build::bridge("src/main.rs")
//!         .file("src/demo.cc")
//!         .flag_if_supported("-std=c++11")
//!         .compile("cxxbridge-demo");
//!
//!     println!("cargo:rerun-if-changed=src/main.rs");
//!     println!("cargo:rerun-if-changed=src/demo.cc");
//!     println!("cargo:rerun-if-changed=include/demo.h");
//! }
//! ```
//!
//! A runnable working setup with this build script is shown in the *demo*
//! directory of [https://github.com/dtolnay/cxx].
//!
//! [https://github.com/dtolnay/cxx]: https://github.com/dtolnay/cxx
//!
//!

//!
//! # Alternatives
//!
//! For use in non-Cargo builds like Bazel or Buck, CXX provides an
//! alternate way of invoking the C++ code generator as a standalone command
//! line tool. The tool is packaged as the `cxxbridge-cmd` crate.
//!
//! ```bash
//! $ cargo install cxxbridge-cmd  # or build it from the repo
//!
//! $ cxxbridge src/main.rs --header > path/to/mybridge.h
//! $ cxxbridge src/main.rs > path/to/mybridge.cc
//! ```

#![allow(
    clippy::inherent_to_string,
    clippy::needless_doctest_main,
    clippy::new_without_default,
    clippy::or_fun_call,
    clippy::toplevel_ref_arg
)]

mod cargo;
mod error;
mod gen;
mod out;
mod paths;
mod syntax;

use crate::error::{Error, Result};
use crate::gen::error::report;
use crate::gen::Opt;
use crate::paths::{PathExt, TargetDir};
use cc::Build;
use std::env;
use std::ffi::{OsStr, OsString};
use std::io::{self, Write};
use std::iter;
use std::path::{Path, PathBuf};
use std::process;

/// This returns a [`cc::Build`] on which you should continue to set up any
/// additional source files or compiler flags, and lastly call its [`compile`]
/// method to execute the C++ build.
///
/// [`compile`]: https://docs.rs/cc/1.0.49/cc/struct.Build.html#method.compile
#[must_use]
pub fn bridge(rust_source_file: impl AsRef<Path>) -> Build {
    bridges(iter::once(rust_source_file))
}

/// `cxx_build::bridge` but for when more than one file contains a
/// #\[cxx::bridge\] module.
///
/// ```no_run
/// let source_files = vec!["src/main.rs", "src/path/to/other.rs"];
/// cxx_build::bridges(source_files)
///     .file("src/demo.cc")
///     .flag_if_supported("-std=c++11")
///     .compile("cxxbridge-demo");
/// ```
#[must_use]
pub fn bridges(rust_source_files: impl IntoIterator<Item = impl AsRef<Path>>) -> Build {
    let ref mut rust_source_files = rust_source_files.into_iter();
    build(rust_source_files).unwrap_or_else(|err| {
        let _ = writeln!(io::stderr(), "\n\ncxxbridge error: {}\n\n", report(err));
        process::exit(1);
    })
}

struct Project {
    package_name: OsString,
    manifest_dir: PathBuf,
    // Output directory as received from Cargo.
    out_dir: PathBuf,
    // Directory into which to symlink all generated code.
    //
    // This is *not* used for an #include path, only as a debugging convenience.
    // Normally available at target/cxxbridge/ if we are able to know where the
    // target dir is, otherwise under a common scratch dir.
    //
    // The reason this isn't the #include dir is that we do not want builds to
    // have access to headers from arbitrary other parts of the dependency
    // graph. Using a global directory for all builds would be both a race
    // condition depending on what order Cargo randomly executes the build
    // scripts, as well as semantically undesirable for builds not to have to
    // declare their real dependencies.
    shared_dir: PathBuf,
}

impl Project {
    fn init() -> Result<Self> {
        let package_name = env_os("CARGO_PKG_NAME")?;
        let manifest_dir = paths::manifest_dir()?;
        let out_dir = paths::out_dir()?;

        let target_dir = match cargo::target_dir(&out_dir) {
            target_dir @ TargetDir::Path(_) => target_dir,
            // Fallback if Cargo did not work.
            TargetDir::Unknown => paths::search_parents_for_target_dir(&out_dir),
        };

        let shared_dir = match target_dir {
            TargetDir::Path(target_dir) => target_dir.join("cxxbridge"),
            // Use cxx-build's OUT_DIR.
            TargetDir::Unknown => PathBuf::from(env!("OUT_DIR")),
        };

        Ok(Project {
            package_name,
            manifest_dir,
            out_dir,
            shared_dir,
        })
    }
}

// We lay out the OUT_DIR as follows. Everything is namespaced under a cxxbridge
// subdirectory to avoid stomping on other things that the caller's build script
// might be doing inside OUT_DIR.
//
//     $OUT_DIR/
//        cxxbridge/
//           crate/
//              $CARGO_PKG_NAME -> $CARGO_MANIFEST_DIR
//           include/
//              rust/
//                 cxx.h
//              $CARGO_PKG_NAME/
//                 .../
//                    lib.rs.h
//           sources/
//              $CARGO_PKG_NAME/
//                 .../
//                    lib.rs.cc
//
// The crate/ and include/ directories are placed on the #include path.
fn build(rust_source_files: &mut dyn Iterator<Item = impl AsRef<Path>>) -> Result<Build> {
    let ref prj = Project::init()?;

    let ref crate_dir = make_crate_dir(prj);
    let ref include_dir = make_include_dir(prj)?;

    let mut build = Build::new();
    build.cpp(true);
    build.cpp_link_stdlib(None); // linked via link-cplusplus crate
    build.include(include_dir);
    if let Some(crate_dir) = crate_dir {
        // Placed after the generated code directory (include_dir) on the
        // include line so that `#include "path/to/file.rs"` from C++
        // "magically" works and refers to the API generated from that Rust
        // source file.
        build.include(crate_dir);
    }

    for path in rust_source_files {
        generate_bridge(prj, &mut build, path.as_ref())?;
    }

    eprintln!("\nCXX include path:");
    if let Some(crate_dir) = crate_dir {
        eprintln!("  {}", crate_dir.display());
    }
    eprintln!("  {}", include_dir.display());
    Ok(build)
}

fn make_crate_dir(prj: &Project) -> Option<PathBuf> {
    let crate_dir = prj.out_dir.join("cxxbridge").join("crate");
    let link = crate_dir.join(&prj.package_name);
    if out::symlink_dir(&prj.manifest_dir, link).is_ok() {
        Some(crate_dir)
    } else {
        None
    }
}

fn make_include_dir(prj: &Project) -> Result<PathBuf> {
    let include_dir = prj.out_dir.join("cxxbridge").join("include");
    let cxx_h = include_dir.join("rust").join("cxx.h");
    let ref shared_cxx_h = prj.shared_dir.join("rust").join("cxx.h");
    if let Some(ref original) = env::var_os("DEP_CXXBRIDGE04_HEADER") {
        out::symlink_file(original, cxx_h)?;
        out::symlink_file(original, shared_cxx_h)?;
    } else {
        out::write(shared_cxx_h, gen::include::HEADER.as_bytes())?;
        out::symlink_file(shared_cxx_h, cxx_h)?;
    }
    Ok(include_dir)
}

fn generate_bridge(prj: &Project, build: &mut Build, rust_source_file: &Path) -> Result<()> {
    let opt = Opt::default();
    let generated = gen::generate_from_path(rust_source_file, &opt);
    let ref rel_path = paths::local_relative_path(rust_source_file);

    let cxxbridge = prj.out_dir.join("cxxbridge");
    let include_dir = cxxbridge.join("include").join(&prj.package_name);
    let sources_dir = cxxbridge.join("sources").join(&prj.package_name);

    let ref rel_path_h = rel_path.with_appended_extension(".h");
    let ref header_path = include_dir.join(rel_path_h);
    out::write(header_path, &generated.header)?;

    let ref link_path = include_dir.join(rel_path);
    let _ = out::symlink_file(header_path, link_path);

    let ref rel_path_cc = rel_path.with_appended_extension(".cc");
    let ref implementation_path = sources_dir.join(rel_path_cc);
    out::write(implementation_path, &generated.implementation)?;
    build.file(implementation_path);

    let shared_h = prj.shared_dir.join(&prj.package_name).join(rel_path_h);
    let shared_cc = prj.shared_dir.join(&prj.package_name).join(rel_path_cc);
    let _ = out::symlink_file(header_path, shared_h);
    let _ = out::symlink_file(implementation_path, shared_cc);
    Ok(())
}

fn env_os(key: impl AsRef<OsStr>) -> Result<OsString> {
    let key = key.as_ref();
    env::var_os(key).ok_or_else(|| Error::NoEnv(key.to_owned()))
}
<|endoftext|>


<commit_before>use layout::{AnonymousBlock, BlockNode, InlineNode, LayoutBox, Rect};
use css::{ColorValue, Color};
use std::iter::range;

/// Paint a tree of LayoutBoxes to an array of pixels.
pub fn paint(layout_root: &LayoutBox, bounds: Rect) -> Canvas {
    let display_list = build_display_list(layout_root);
    let mut canvas = Canvas::new(bounds.width as uint, bounds.height as uint);
    for item in display_list.iter() {
        canvas.paint_item(item);
    }
    return canvas;
}

#[deriving(Show)]
enum DisplayItem {
    SolidColor(Color, Rect),
}

type DisplayList = Vec<DisplayItem>;

fn build_display_list(layout_root: &LayoutBox) -> DisplayList {
    let mut list = Vec::new();
    render_layout_box(&mut list, layout_root);
    return list;
}

fn render_layout_box(list: &mut DisplayList, layout_box: &LayoutBox) {
    render_background(list, layout_box);
    render_borders(list, layout_box);
    for child in layout_box.children.iter() {
        render_layout_box(list, child);
    }
}

fn render_background(list: &mut DisplayList, layout_box: &LayoutBox) {
    get_color(layout_box, "background").map(|color|
        list.push(SolidColor(color, layout_box.dimensions.border_box())));
}

fn render_borders(list: &mut DisplayList, layout_box: &LayoutBox) {
    let color = match get_color(layout_box, "border-color") {
        Some(color) => color,
        _ => return
    };

    let d = &layout_box.dimensions;
    let border_box = d.border_box();

    // Left border
    list.push(SolidColor(color, Rect {
        x: border_box.x,
        y: border_box.y,
        width: d.border.left,
        height: border_box.height,
    }));

    // Right border
    list.push(SolidColor(color, Rect {
        x: border_box.x + border_box.width - d.border.right,
        y: border_box.y,
        width: d.border.right,
        height: border_box.height,
    }));

    // Top border
    list.push(SolidColor(color, Rect {
        x: border_box.x,
        y: border_box.y,
        width: border_box.width,
        height: d.border.top,
    }));

    // Bottom border
    list.push(SolidColor(color, Rect {
        x: border_box.x,
        y: border_box.y + border_box.height - d.border.bottom,
        width: border_box.width,
        height: d.border.bottom,
    }));
}

fn get_color(layout_box: &LayoutBox, name: &str) -> Option<Color> {
    match layout_box.box_type {
        BlockNode(style) | InlineNode(style) => match style.value(name) {
            Some(ColorValue(color)) => Some(color),
            _ => None
        },
        AnonymousBlock => None
    }
}

pub struct Canvas {
    pub pixels: Vec<Color>,
    pub width: uint,
    pub height: uint,
}

impl Canvas {
    fn new(width: uint, height: uint) -> Canvas {
        let white = Color { r: 255, g: 255, b: 255, a: 255 };
        return Canvas {
            pixels: Vec::from_elem(width * height, white),
            width: width,
            height: height,
        }
    }

    fn paint_item(&mut self, item: &DisplayItem) {
        match item {
            &SolidColor(color, rect) => {
                // Clip the rectangle to the canvas boundaries.
                let x0 = rect.x.clamp(0.0, self.width as f32) as uint;
                let y0 = rect.y.clamp(0.0, self.height as f32) as uint;
                let x1 = (rect.x + rect.width).clamp(0.0, self.width as f32) as uint;
                let y1 = (rect.y + rect.height).clamp(0.0, self.height as f32) as uint;

                for x in range(x0, x1) {
                    for y in range(y0, y1) {
                        // TODO: alpha compositing with existing pixel
                        self.pixels[x + y * self.width] = color;
                    }
                }
            }
        }
    }
}

trait FloatClamp : FloatMath {
    fn clamp(self, lower: Self, upper: Self) -> Self {
        self.max(lower).min(upper)
    }
}
impl<T: FloatMath> FloatClamp for T {}
<commit_msg>Paint by row, not by column<commit_after>use layout::{AnonymousBlock, BlockNode, InlineNode, LayoutBox, Rect};
use css::{ColorValue, Color};
use std::iter::range;

/// Paint a tree of LayoutBoxes to an array of pixels.
pub fn paint(layout_root: &LayoutBox, bounds: Rect) -> Canvas {
    let display_list = build_display_list(layout_root);
    let mut canvas = Canvas::new(bounds.width as uint, bounds.height as uint);
    for item in display_list.iter() {
        canvas.paint_item(item);
    }
    return canvas;
}

#[deriving(Show)]
enum DisplayItem {
    SolidColor(Color, Rect),
}

type DisplayList = Vec<DisplayItem>;

fn build_display_list(layout_root: &LayoutBox) -> DisplayList {
    let mut list = Vec::new();
    render_layout_box(&mut list, layout_root);
    return list;
}

fn render_layout_box(list: &mut DisplayList, layout_box: &LayoutBox) {
    render_background(list, layout_box);
    render_borders(list, layout_box);
    for child in layout_box.children.iter() {
        render_layout_box(list, child);
    }
}

fn render_background(list: &mut DisplayList, layout_box: &LayoutBox) {
    get_color(layout_box, "background").map(|color|
        list.push(SolidColor(color, layout_box.dimensions.border_box())));
}

fn render_borders(list: &mut DisplayList, layout_box: &LayoutBox) {
    let color = match get_color(layout_box, "border-color") {
        Some(color) => color,
        _ => return
    };

    let d = &layout_box.dimensions;
    let border_box = d.border_box();

    // Left border
    list.push(SolidColor(color, Rect {
        x: border_box.x,
        y: border_box.y,
        width: d.border.left,
        height: border_box.height,
    }));

    // Right border
    list.push(SolidColor(color, Rect {
        x: border_box.x + border_box.width - d.border.right,
        y: border_box.y,
        width: d.border.right,
        height: border_box.height,
    }));

    // Top border
    list.push(SolidColor(color, Rect {
        x: border_box.x,
        y: border_box.y,
        width: border_box.width,
        height: d.border.top,
    }));

    // Bottom border
    list.push(SolidColor(color, Rect {
        x: border_box.x,
        y: border_box.y + border_box.height - d.border.bottom,
        width: border_box.width,
        height: d.border.bottom,
    }));
}

fn get_color(layout_box: &LayoutBox, name: &str) -> Option<Color> {
    match layout_box.box_type {
        BlockNode(style) | InlineNode(style) => match style.value(name) {
            Some(ColorValue(color)) => Some(color),
            _ => None
        },
        AnonymousBlock => None
    }
}

pub struct Canvas {
    pub pixels: Vec<Color>,
    pub width: uint,
    pub height: uint,
}

impl Canvas {
    /// Create a blank canvas
    fn new(width: uint, height: uint) -> Canvas {
        let white = Color { r: 255, g: 255, b: 255, a: 255 };
        return Canvas {
            pixels: Vec::from_elem(width * height, white),
            width: width,
            height: height,
        }
    }

    fn paint_item(&mut self, item: &DisplayItem) {
        match item {
            &SolidColor(color, rect) => {
                // Clip the rectangle to the canvas boundaries.
                let x0 = rect.x.clamp(0.0, self.width as f32) as uint;
                let y0 = rect.y.clamp(0.0, self.height as f32) as uint;
                let x1 = (rect.x + rect.width).clamp(0.0, self.width as f32) as uint;
                let y1 = (rect.y + rect.height).clamp(0.0, self.height as f32) as uint;

                for y in range(y0, y1) {
                    for x in range(x0, x1) {
                        // TODO: alpha compositing with existing pixel
                        self.pixels[y * self.width + x] = color;
                    }
                }
            }
        }
    }
}

trait FloatClamp : FloatMath {
    fn clamp(self, lower: Self, upper: Self) -> Self {
        self.max(lower).min(upper)
    }
}
impl<T: FloatMath> FloatClamp for T {}
<|endoftext|>


<commit_before>#[feature(globs)];
#[feature(managed_boxes)];

use std::str;
use std::io::stdout;
use std::io::fs::File;
use std::os;
use peg::{compile_grammar};
use codegen::RustWriter;

mod peg;
mod codegen;
mod grammar;

fn main() {
	let args = os::args();
	let source = str::from_utf8(File::open(&Path::new(args[1])).read_to_end());
	let grammar_def = grammar::grammar(source).unwrap();
	let w = RustWriter::new(stdout());
	compile_grammar(&w, grammar_def);
}
<commit_msg>Fix for from_utf8 change<commit_after>#[feature(globs)];
#[feature(managed_boxes)];

use std::str;
use std::io::stdout;
use std::io::fs::File;
use std::os;
use peg::{compile_grammar};
use codegen::RustWriter;

mod peg;
mod codegen;
mod grammar;

fn main() {
	let args = os::args();
	let source_utf8 = File::open(&Path::new(args[1])).read_to_end();
	let source = str::from_utf8(source_utf8);
	let grammar_def = grammar::grammar(source).unwrap();
	let w = RustWriter::new(stdout());
	compile_grammar(&w, grammar_def);
}
<|endoftext|>


<commit_before>// 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 std::ffi::CStr;
use sys;

/// A platform that can represent the current host or a
/// remote host debug platform.
///
/// The `SBPlatform` class represents the current host, or a remote host.
/// It can be connected to a remote platform in order to provide ways
/// to remotely launch and attach to processes, upload/download files,
/// create directories, run remote shell commands, find locally cached
/// versions of files from the remote system, and much more.
///
/// `SBPlatform` objects can be created and then used to connect to a remote
/// platform which allows the `SBPlatform` to be used to get a list of the
/// current processes on the remote host, attach to one of those processes,
/// install programs on the remote system, attach and launch processes,
/// and much more.
///
/// Every [`SBTarget`] has a corresponding `SBPlatform`. The platform can be
/// specified upon target creation, or the currently selected platform
/// will attempt to be used when creating the target automatically as long
/// as the currently selected platform matches the target architecture
/// and executable type. If the architecture or executable type do not match,
/// a suitable platform will be found automatically.
///
/// [`SBTarget`]: struct.SBTarget.html
#[derive(Debug)]
pub struct SBPlatform {
    /// The underlying raw `SBPlatformRef`.
    pub raw: sys::SBPlatformRef,
}

impl SBPlatform {
    /// Construct a new `SBPlatform`.
    pub fn wrap(raw: sys::SBPlatformRef) -> SBPlatform {
        SBPlatform { raw: raw }
    }

    /// Construct a new `Some(SBPlatform)` or `None`.
    pub fn maybe_wrap(raw: sys::SBPlatformRef) -> Option<SBPlatform> {
        if unsafe { sys::SBPlatformIsValid(raw) != 0 } {
            Some(SBPlatform { raw: raw })
        } else {
            None
        }
    }

    /// Check whether or not this is a valid `SBPlatform` value.
    pub fn is_valid(&self) -> bool {
        unsafe { sys::SBPlatformIsValid(self.raw) != 0 }
    }

    /// The working directory for this platform.
    pub fn working_directory(&self) -> &str {
        unsafe {
            match CStr::from_ptr(sys::SBPlatformGetWorkingDirectory(self.raw)).to_str() {
                Ok(s) => s,
                _ => panic!("Invalid string?"),
            }
        }
    }

    /// The name of the platform.
    ///
    /// When debugging on the host platform, this would be `"host"`.
    pub fn name(&self) -> &str {
        unsafe {
            match CStr::from_ptr(sys::SBPlatformGetName(self.raw)).to_str() {
                Ok(s) => s,
                _ => panic!("Invalid string?"),
            }
        }
    }

    /// The triple used to describe this platform.
    ///
    /// An example value might be `"x86_64-apple-macosx"`.
    pub fn triple(&self) -> &str {
        unsafe {
            match CStr::from_ptr(sys::SBPlatformGetTriple(self.raw)).to_str() {
                Ok(s) => s,
                _ => panic!("Invalid string?"),
            }
        }
    }

    /// The hostname for this platform.
    pub fn hostname(&self) -> &str {
        unsafe {
            match CStr::from_ptr(sys::SBPlatformGetHostname(self.raw)).to_str() {
                Ok(s) => s,
                _ => panic!("Invalid string?"),
            }
        }
    }

    /// The build ID for the platforms' OS version.
    pub fn os_build(&self) -> &str {
        unsafe {
            match CStr::from_ptr(sys::SBPlatformGetOSBuild(self.raw)).to_str() {
                Ok(s) => s,
                _ => panic!("Invalid string?"),
            }
        }
    }

    /// The long form description of the platform's OS version.
    ///
    /// On Mac OS X, this might look like `"Darwin Kernel Version 15.5.0:
    /// Tue Apr 19 18:36:36 PDT 2016; root:xnu-3248.50.21~8/RELEASE_X86_64"`.
    pub fn os_description(&self) -> &str {
        unsafe {
            match CStr::from_ptr(sys::SBPlatformGetOSDescription(self.raw)).to_str() {
                Ok(s) => s,
                _ => panic!("Invalid string?"),
            }
        }
    }

    /// The major component of the platform's OS version.
    ///
    /// On Mac OS X 10.11.4, this would have the value `10`.
    pub fn os_major_version(&self) -> u32 {
        unsafe { sys::SBPlatformGetOSMajorVersion(self.raw) }
    }

    /// The minor component of the platform's OS version.
    ///
    /// On Mac OS X 10.11.4, this would have the value `11`.
    pub fn os_minor_version(&self) -> u32 {
        unsafe { sys::SBPlatformGetOSMinorVersion(self.raw) }
    }

    /// The patch or update component of the platform's OS version.
    ///
    /// On Mac OS X 10.11.4, this would have the value `4`.
    pub fn os_update_version(&self) -> u32 {
        unsafe { sys::SBPlatformGetOSUpdateVersion(self.raw) }
    }
}

impl Drop for SBPlatform {
    fn drop(&mut self) {
        unsafe { sys::DisposeSBPlatform(self.raw) };
    }
}
<commit_msg>Wrapper for SBPlatform::launch and ::kill.<commit_after>// 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 std::ffi::CStr;
use super::error::SBError;
use super::launchinfo::SBLaunchInfo;
use super::lldb_pid_t;
use sys;

/// A platform that can represent the current host or a
/// remote host debug platform.
///
/// The `SBPlatform` class represents the current host, or a remote host.
/// It can be connected to a remote platform in order to provide ways
/// to remotely launch and attach to processes, upload/download files,
/// create directories, run remote shell commands, find locally cached
/// versions of files from the remote system, and much more.
///
/// `SBPlatform` objects can be created and then used to connect to a remote
/// platform which allows the `SBPlatform` to be used to get a list of the
/// current processes on the remote host, attach to one of those processes,
/// install programs on the remote system, attach and launch processes,
/// and much more.
///
/// Every [`SBTarget`] has a corresponding `SBPlatform`. The platform can be
/// specified upon target creation, or the currently selected platform
/// will attempt to be used when creating the target automatically as long
/// as the currently selected platform matches the target architecture
/// and executable type. If the architecture or executable type do not match,
/// a suitable platform will be found automatically.
///
/// [`SBTarget`]: struct.SBTarget.html
#[derive(Debug)]
pub struct SBPlatform {
    /// The underlying raw `SBPlatformRef`.
    pub raw: sys::SBPlatformRef,
}

impl SBPlatform {
    /// Construct a new `SBPlatform`.
    pub fn wrap(raw: sys::SBPlatformRef) -> SBPlatform {
        SBPlatform { raw: raw }
    }

    /// Construct a new `Some(SBPlatform)` or `None`.
    pub fn maybe_wrap(raw: sys::SBPlatformRef) -> Option<SBPlatform> {
        if unsafe { sys::SBPlatformIsValid(raw) != 0 } {
            Some(SBPlatform { raw: raw })
        } else {
            None
        }
    }

    /// Check whether or not this is a valid `SBPlatform` value.
    pub fn is_valid(&self) -> bool {
        unsafe { sys::SBPlatformIsValid(self.raw) != 0 }
    }

    /// The working directory for this platform.
    pub fn working_directory(&self) -> &str {
        unsafe {
            match CStr::from_ptr(sys::SBPlatformGetWorkingDirectory(self.raw)).to_str() {
                Ok(s) => s,
                _ => panic!("Invalid string?"),
            }
        }
    }

    /// The name of the platform.
    ///
    /// When debugging on the host platform, this would be `"host"`.
    pub fn name(&self) -> &str {
        unsafe {
            match CStr::from_ptr(sys::SBPlatformGetName(self.raw)).to_str() {
                Ok(s) => s,
                _ => panic!("Invalid string?"),
            }
        }
    }

    /// The triple used to describe this platform.
    ///
    /// An example value might be `"x86_64-apple-macosx"`.
    pub fn triple(&self) -> &str {
        unsafe {
            match CStr::from_ptr(sys::SBPlatformGetTriple(self.raw)).to_str() {
                Ok(s) => s,
                _ => panic!("Invalid string?"),
            }
        }
    }

    /// The hostname for this platform.
    pub fn hostname(&self) -> &str {
        unsafe {
            match CStr::from_ptr(sys::SBPlatformGetHostname(self.raw)).to_str() {
                Ok(s) => s,
                _ => panic!("Invalid string?"),
            }
        }
    }

    /// The build ID for the platforms' OS version.
    pub fn os_build(&self) -> &str {
        unsafe {
            match CStr::from_ptr(sys::SBPlatformGetOSBuild(self.raw)).to_str() {
                Ok(s) => s,
                _ => panic!("Invalid string?"),
            }
        }
    }

    /// The long form description of the platform's OS version.
    ///
    /// On Mac OS X, this might look like `"Darwin Kernel Version 15.5.0:
    /// Tue Apr 19 18:36:36 PDT 2016; root:xnu-3248.50.21~8/RELEASE_X86_64"`.
    pub fn os_description(&self) -> &str {
        unsafe {
            match CStr::from_ptr(sys::SBPlatformGetOSDescription(self.raw)).to_str() {
                Ok(s) => s,
                _ => panic!("Invalid string?"),
            }
        }
    }

    /// The major component of the platform's OS version.
    ///
    /// On Mac OS X 10.11.4, this would have the value `10`.
    pub fn os_major_version(&self) -> u32 {
        unsafe { sys::SBPlatformGetOSMajorVersion(self.raw) }
    }

    /// The minor component of the platform's OS version.
    ///
    /// On Mac OS X 10.11.4, this would have the value `11`.
    pub fn os_minor_version(&self) -> u32 {
        unsafe { sys::SBPlatformGetOSMinorVersion(self.raw) }
    }

    /// The patch or update component of the platform's OS version.
    ///
    /// On Mac OS X 10.11.4, this would have the value `4`.
    pub fn os_update_version(&self) -> u32 {
        unsafe { sys::SBPlatformGetOSUpdateVersion(self.raw) }
    }

    /// Launch a process. This is not for debugging that process.
    pub fn launch(&self, launch_info: &SBLaunchInfo) -> Result<(), SBError> {
        let error = SBError::wrap(unsafe { sys::SBPlatformLaunch(self.raw, launch_info.raw) });
        if error.is_success() {
            Ok(())
        } else {
            Err(error)
        }
    }

    /// Kill a process.
    pub fn kill(&self, pid: lldb_pid_t) -> Result<(), SBError> {
        let error = SBError::wrap(unsafe { sys::SBPlatformKill(self.raw, pid) });
        if error.is_success() {
            Ok(())
        } else {
            Err(error)
        }
    }
}

impl Drop for SBPlatform {
    fn drop(&mut self) {
        unsafe { sys::DisposeSBPlatform(self.raw) };
    }
}
<|endoftext|>


<commit_before>use num::{FromPrimitive};
use std::marker::PhantomData;

use log::{debug};
use goblin::{Object};
use failure::{Error};

use super::super::super::arch::Arch;
use super::super::super::workspace::Workspace;
use super::super::{Analyzer, AnalysisError};

pub struct ExportsAnalyzer<A: Arch> {
    // This Analyzer must have a type parameter for it
    //  to implement Analyzer<A>.
    // however, it doesn't actually use this type itself.
    // so, we use a phantom data marker which has zero type,
    //  to ensure there is not an unused type parameter,
    //  which is a compile error.
    _phantom: PhantomData<A>,
}

impl<A: Arch> ExportsAnalyzer<A> {
    pub fn new() -> ExportsAnalyzer<A> {
        ExportsAnalyzer {
            _phantom: PhantomData {},
        }
    }
}

impl<A: Arch + 'static> Analyzer<A> for ExportsAnalyzer<A> {
    fn get_name(&self) -> String {
        "PE exports analyzer".to_string()
    }

    fn analyze(&self, ws: &mut Workspace<A>) -> Result<(), Error> {
        let pe = match Object::parse(&ws.buf) {
            Ok(Object::PE(pe)) => pe,
            _ => panic!("can't analyze unexpected format"),
        };

        // TODO include this one
        let entry = match A::RVA::from_usize(pe.entry) {
            Some(entry) => entry,
            None => return Err(AnalysisError::NotSupported.into()),
        };

        let exports: Vec<usize> = pe.exports.iter()
            // re-exports are simply strings that point to a `DLL.export_name` ASCII string.
            // therefore, they're not functions/code.
            .filter(|exp| exp.reexport.is_none())
            .map(|exp| exp.rva).collect();

        let symbols: Vec<(usize, String)> = pe.exports.iter()
            .filter(|exp| exp.name.is_some())
            .map(|exp| (exp.rva, exp.name.unwrap().to_string()))
            .collect();

        for (rva, name) in symbols.iter() {
            let rva = match A::RVA::from_usize(*rva) {
                Some(rva) => rva,
                // we panic here because some work is done, but not all.
                // alternatively, we could warn.
                // but i'd like to bail early and figure out why this can happen.
                None => panic!("failed to convert RVA")
            };

            debug!("export: {:#x}: {}", rva, name);

            ws.make_symbol(rva, name)?;
            ws.analyze()?;
        }

        for rva in exports.iter() {
            let rva = match A::RVA::from_usize(*rva) {
                Some(rva) => rva,
                None => panic!("failed to convert RVA")
            };

            ws.make_function(rva)?;
            ws.analyze()?;
        }

        Ok(())
    }
}
<commit_msg>analysis/pe/exports: include entrypoint<commit_after>use num::{FromPrimitive};
use std::marker::PhantomData;

use log::{debug};
use goblin::{Object};
use failure::{Error};

use super::super::super::arch::Arch;
use super::super::super::workspace::Workspace;
use super::super::{Analyzer, AnalysisError};

pub struct ExportsAnalyzer<A: Arch> {
    // This Analyzer must have a type parameter for it
    //  to implement Analyzer<A>.
    // however, it doesn't actually use this type itself.
    // so, we use a phantom data marker which has zero type,
    //  to ensure there is not an unused type parameter,
    //  which is a compile error.
    _phantom: PhantomData<A>,
}

impl<A: Arch> ExportsAnalyzer<A> {
    pub fn new() -> ExportsAnalyzer<A> {
        ExportsAnalyzer {
            _phantom: PhantomData {},
        }
    }
}

impl<A: Arch + 'static> Analyzer<A> for ExportsAnalyzer<A> {
    fn get_name(&self) -> String {
        "PE exports analyzer".to_string()
    }

    fn analyze(&self, ws: &mut Workspace<A>) -> Result<(), Error> {
        let pe = match Object::parse(&ws.buf) {
            Ok(Object::PE(pe)) => pe,
            _ => panic!("can't analyze unexpected format"),
        };

        let entry = match A::RVA::from_usize(pe.entry) {
            Some(entry) => entry,
            None => return Err(AnalysisError::NotSupported.into()),
        };

        let exports: Vec<usize> = pe.exports.iter()
            // re-exports are simply strings that point to a `DLL.export_name` ASCII string.
            // therefore, they're not functions/code.
            .filter(|exp| exp.reexport.is_none())
            .map(|exp| exp.rva).collect();

        let symbols: Vec<(usize, String)> = pe.exports.iter()
            .filter(|exp| exp.name.is_some())
            .map(|exp| (exp.rva, exp.name.unwrap().to_string()))
            .collect();

        for (rva, name) in symbols.iter() {
            let rva = match A::RVA::from_usize(*rva) {
                Some(rva) => rva,
                // we panic here because some work is done, but not all.
                // alternatively, we could warn.
                // but i'd like to bail early and figure out why this can happen.
                None => panic!("failed to convert RVA")
            };

            debug!("export: {:#x}: {}", rva, name);

            ws.make_symbol(rva, name)?;
            ws.analyze()?;
        }

        for rva in exports.iter() {
            let rva = match A::RVA::from_usize(*rva) {
                Some(rva) => rva,
                None => panic!("failed to convert RVA")
            };

            ws.make_function(rva)?;
            ws.analyze()?;
        }

        ws.make_function(entry)?;
        ws.make_symbol(entry, "entry")?;
        ws.analyze()?;

        Ok(())
    }
}
<|endoftext|>


<commit_before>extern crate thoughtfuck;

mod common;

use std::fs::File;
use std::io::Read;

use common::FauxStdout;
use thoughtfuck::vm::*;
use thoughtfuck::program::*;
use thoughtfuck::parse::parse;

fn read_file(filename: &str) -> String {
    let mut file = File::open(filename).unwrap();
    let mut source = String::new();
    file.read_to_string(&mut source).unwrap();
    source
}

#[test]
fn hello_world () {
    const SOURCE: &str = "++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.";
    let commands = parse(SOURCE);

    let mut program = Program::new();
    program.append(&commands);

    let mut stdout = FauxStdout::new();
    {
        let mut vm = VM::new(&mut stdout);
        program.execute(&mut vm);
    }
    assert_eq!(stdout.buffer, "Hello World!\n");
}
<commit_msg>Add test_ouput testing helper function<commit_after>extern crate thoughtfuck;

mod common;

use std::fs::File;
use std::io::Read;

use common::FauxStdout;
use thoughtfuck::vm::*;
use thoughtfuck::program::*;
use thoughtfuck::parse::parse;

fn read_file(filename: &str) -> String {
    let mut file = File::open(filename).unwrap();
    let mut source = String::new();
    file.read_to_string(&mut source).unwrap();
    source
}

fn test_output(input_filename: &str, expected_answer_filename: &str) {
    let source = read_file(input_filename);

    let commands = parse(&source);

    let mut program = Program::new();
    program.append(&commands);

    let mut stdout = FauxStdout::new();
    {
        let mut vm = VM::new(&mut stdout);
        program.execute(&mut vm);
    }
    assert_eq!(stdout.buffer, read_file(expected_answer_filename));
}

#[test]
fn hello_world () {
    const SOURCE: &str = "++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.";
    let commands = parse(SOURCE);

    let mut program = Program::new();
    program.append(&commands);

    let mut stdout = FauxStdout::new();
    {
        let mut vm = VM::new(&mut stdout);
        program.execute(&mut vm);
    }
    assert_eq!(stdout.buffer, "Hello World!\n");
}
<|endoftext|>


<commit_before>extern crate o2lsh;

#[test]
fn build_table_from_mnist() {
    let mnist_data = match o2lsh::util::get_mnist_vector("mnist1k.dts") {
        Ok(v) => v,
        Err(reason) => panic!("couldnt open because {}", reason)
    };

    let vec_length = mnist_data[0].len();

    let num_hashes = 10;
    let hash_boxes: Vec<_> = (1..num_hashes).map(|_| o2lsh::hashes::get_hash_closure(vec_length, 1.0)).collect();

    let hash_table: o2lsh::table::LSHTable<Vec<f64>, Fn(&Vec<f64>) -> f64> = o2lsh::table::LSHTable::new_build(&mnist_data, &hash_boxes);
}
<commit_msg>added another integration test<commit_after>extern crate o2lsh;

#[test]
fn build_table_from_mnist() {
    let mnist_data = match o2lsh::util::get_mnist_vector("mnist1k.dts") {
        Ok(v) => v,
        Err(reason) => panic!("couldnt open because {}", reason)
    };

    let vec_length = mnist_data[0].len();

    let num_hashes = 10;
    let hash_boxes: Vec<_> = (1..num_hashes).map(|| o2lsh::hashes::get_hash_closure(vec_length, 1.0)).collect();

    let hash_table: o2lsh::table::LSHTable<Vec<f64>, Fn(&Vec<f64>) -> f64> = o2lsh::table::LSHTable::new_build(&mnist_data, &hash_boxes);
}

#[test]
fn build_table_from_mnist_and_query() {
    let mnist_data = match o2lsh::util::get_mnist_vector("mnist1k.dts") {
        Ok(v) => v,
        Err(reason) => panic!("couldnt open because {}", reason)
    };

    let vec_length = mnist_data[0].len();

    let num_hashes = 10;
    let hash_boxes: Vec<_> = (1..num_hashes).map(|| o2lsh::hashes::get_hash_closure(vec_length, 1.0)).collect();

    let hash_table: o2lsh::table::LSHTable<Vec<f64>, Fn(&Vec<f64>) -> f64> = o2lsh::table::LSHTable::new_build(&mnist_data, &hash_boxes);
    let mnist_q = match o2lsh::util::get_mnist_vector("mnist1k.q") {
        Ok(v) => v,
        Err(reason) => panic!("couldnt open because {}", reason)
    };

    for vec in mnist_q.iter() {
        hash_table.query_vec(&vec);
    }
}
<|endoftext|>


<commit_before>//!
//! Egl [`NativeDisplay`](::backend::egl::native::NativeDisplay) and
//! [`NativeSurface`](::backend::egl::native::NativeSurface) support for
//! [`GbmDevice`](GbmDevice) and [`GbmSurface`](GbmSurface).
//!

use crate::backend::drm::{Device, RawDevice, Surface};
use crate::backend::egl::native::{Backend, NativeDisplay, NativeSurface};
use crate::backend::egl::{display::EGLDisplayHandle, ffi};
use crate::backend::egl::{
    wrap_egl_call, EGLError, Error as EglBackendError, SurfaceCreationError, SwapBuffersError,
};

use super::{Error, GbmDevice, GbmSurface};

use drm::control::{connector, crtc, Device as ControlDevice, Mode};
use gbm::AsRaw;
use nix::libc::{c_int, c_void};
use std::marker::PhantomData;

/// Egl Gbm backend type
///
/// See [`Backend`](::backend::egl::native::Backend).
pub struct Gbm<D: RawDevice + 'static> {
    _userdata: PhantomData<D>,
}

impl<D: RawDevice + 'static> Backend for Gbm<D> {
    type Surface = GbmSurface<D>;
    type Error = Error<<<D as Device>::Surface as Surface>::Error>;

    unsafe fn get_display<F>(
        display: ffi::NativeDisplayType,
        attribs: &[ffi::EGLint],
        has_dp_extension: F,
        log: ::slog::Logger,
    ) -> Result<ffi::egl::types::EGLDisplay, EGLError>
    where
        F: Fn(&str) -> bool,
    {
        if has_dp_extension("EGL_KHR_platform_gbm") && ffi::egl::GetPlatformDisplay::is_loaded() {
            trace!(log, "EGL Display Initialization via EGL_KHR_platform_gbm");
            let attribs = attribs.iter().map(|x| *x as isize).collect::<Vec<_>>();
            wrap_egl_call(|| {
                ffi::egl::GetPlatformDisplay(ffi::egl::PLATFORM_GBM_KHR, display as *mut _, attribs.as_ptr())
            })
        } else if has_dp_extension("EGL_MESA_platform_gbm") && ffi::egl::GetPlatformDisplayEXT::is_loaded() {
            trace!(log, "EGL Display Initialization via EGL_MESA_platform_gbm");
            wrap_egl_call(|| {
                ffi::egl::GetPlatformDisplayEXT(
                    ffi::egl::PLATFORM_GBM_MESA,
                    display as *mut _,
                    attribs.as_ptr(),
                )
            })
        } else if has_dp_extension("EGL_MESA_platform_gbm") && ffi::egl::GetPlatformDisplay::is_loaded() {
            trace!(log, "EGL Display Initialization via EGL_MESA_platform_gbm");
            let attribs = attribs.iter().map(|x| *x as isize).collect::<Vec<_>>();
            wrap_egl_call(|| {
                ffi::egl::GetPlatformDisplay(ffi::egl::PLATFORM_GBM_MESA, display as *mut _, attribs.as_ptr())
            })
        } else {
            trace!(log, "Default EGL Display Initialization via GetDisplay");
            wrap_egl_call(|| ffi::egl::GetDisplay(display as *mut _))
        }
    }
}

unsafe impl<D: RawDevice + ControlDevice + 'static> NativeDisplay<Gbm<D>> for GbmDevice<D> {
    type Arguments = (crtc::Handle, Mode, Vec<connector::Handle>);

    fn is_backend(&self) -> bool {
        true
    }

    fn ptr(&self) -> Result<ffi::NativeDisplayType, EglBackendError> {
        Ok(self.dev.borrow().as_raw() as *const _)
    }

    fn create_surface(
        &mut self,
        args: Self::Arguments,
    ) -> Result<GbmSurface<D>, Error<<<D as Device>::Surface as Surface>::Error>> {
        Device::create_surface(self, args.0, args.1, &args.2)
    }
}

unsafe impl<D: RawDevice + 'static> NativeSurface for GbmSurface<D> {
    type Error = Error<<<D as Device>::Surface as Surface>::Error>;

    unsafe fn create(
        &self,
        display: &EGLDisplayHandle,
        config_id: ffi::egl::types::EGLConfig,
        surface_attributes: &[c_int],
    ) -> Result<*const c_void, SurfaceCreationError<Self::Error>> {
        GbmSurface::recreate(self).map_err(SurfaceCreationError::NativeSurfaceCreationFailed)?;

        wrap_egl_call(|| {
            ffi::egl::CreateWindowSurface(
                display.handle,
                config_id,
                self.0.surface.borrow().as_raw() as *const _,
                surface_attributes.as_ptr(),
            )
        })
        .map_err(SurfaceCreationError::EGLSurfaceCreationFailed)
    }

    fn needs_recreation(&self) -> bool {
        self.needs_recreation()
    }

    fn swap_buffers(
        &self,
        display: &Arc<EGLDisplayHandle>,
        surface: ffi::egl::types::EGLSurface,
    ) -> Result<(), SwapBuffersError<Self::Error>> {
        wrap_egl_call(|| unsafe { ffi::egl::SwapBuffers(***display, surface as *const _) })
            .map_err(SwapBuffersError::EGLSwapBuffers)?;
        // this is safe since `eglSwapBuffers` will have been called exactly once
        // if this is used by our egl module, which is why this trait is unsafe.
        unsafe { self.page_flip() }.map_err(SwapBuffersError::Underlying)
    }
}
<commit_msg>gbm: Do not try to use eglGetDisplay<commit_after>//!
//! Egl [`NativeDisplay`](::backend::egl::native::NativeDisplay) and
//! [`NativeSurface`](::backend::egl::native::NativeSurface) support for
//! [`GbmDevice`](GbmDevice) and [`GbmSurface`](GbmSurface).
//!

use crate::backend::drm::{Device, RawDevice, Surface};
use crate::backend::egl::native::{Backend, NativeDisplay, NativeSurface};
use crate::backend::egl::{display::EGLDisplayHandle, ffi};
use crate::backend::egl::{
    wrap_egl_call, EGLError, Error as EglBackendError, SurfaceCreationError, SwapBuffersError,
};

use super::{Error, GbmDevice, GbmSurface};

use drm::control::{connector, crtc, Device as ControlDevice, Mode};
use gbm::AsRaw;
use nix::libc::{c_int, c_void};
use std::marker::PhantomData;

/// Egl Gbm backend type
///
/// See [`Backend`](::backend::egl::native::Backend).
pub struct Gbm<D: RawDevice + 'static> {
    _userdata: PhantomData<D>,
}

impl<D: RawDevice + 'static> Backend for Gbm<D> {
    type Surface = GbmSurface<D>;
    type Error = Error<<<D as Device>::Surface as Surface>::Error>;

    unsafe fn get_display<F>(
        display: ffi::NativeDisplayType,
        attribs: &[ffi::EGLint],
        has_dp_extension: F,
        log: ::slog::Logger,
    ) -> Result<ffi::egl::types::EGLDisplay, EGLError>
    where
        F: Fn(&str) -> bool,
    {
        if has_dp_extension("EGL_KHR_platform_gbm") && ffi::egl::GetPlatformDisplay::is_loaded() {
            trace!(log, "EGL Display Initialization via EGL_KHR_platform_gbm");
            let attribs = attribs.iter().map(|x| *x as isize).collect::<Vec<_>>();
            wrap_egl_call(|| {
                ffi::egl::GetPlatformDisplay(ffi::egl::PLATFORM_GBM_KHR, display as *mut _, attribs.as_ptr())
            })
        } else if has_dp_extension("EGL_MESA_platform_gbm") && ffi::egl::GetPlatformDisplayEXT::is_loaded() {
            trace!(log, "EGL Display Initialization via EGL_MESA_platform_gbm");
            wrap_egl_call(|| {
                ffi::egl::GetPlatformDisplayEXT(
                    ffi::egl::PLATFORM_GBM_MESA,
                    display as *mut _,
                    attribs.as_ptr(),
                )
            })
        } else if has_dp_extension("EGL_MESA_platform_gbm") && ffi::egl::GetPlatformDisplay::is_loaded() {
            trace!(log, "EGL Display Initialization via EGL_MESA_platform_gbm");
            let attribs = attribs.iter().map(|x| *x as isize).collect::<Vec<_>>();
            wrap_egl_call(|| {
                ffi::egl::GetPlatformDisplay(ffi::egl::PLATFORM_GBM_MESA, display as *mut _, attribs.as_ptr())
            })
        } else {
            Ok(ffi::egl::NO_DISPLAY)
        }
    }
}

unsafe impl<D: RawDevice + ControlDevice + 'static> NativeDisplay<Gbm<D>> for GbmDevice<D> {
    type Arguments = (crtc::Handle, Mode, Vec<connector::Handle>);

    fn is_backend(&self) -> bool {
        true
    }

    fn ptr(&self) -> Result<ffi::NativeDisplayType, EglBackendError> {
        Ok(self.dev.borrow().as_raw() as *const _)
    }

    fn create_surface(
        &mut self,
        args: Self::Arguments,
    ) -> Result<GbmSurface<D>, Error<<<D as Device>::Surface as Surface>::Error>> {
        Device::create_surface(self, args.0, args.1, &args.2)
    }
}

unsafe impl<D: RawDevice + 'static> NativeSurface for GbmSurface<D> {
    type Error = Error<<<D as Device>::Surface as Surface>::Error>;

    unsafe fn create(
        &self,
        display: &EGLDisplayHandle,
        config_id: ffi::egl::types::EGLConfig,
        surface_attributes: &[c_int],
    ) -> Result<*const c_void, SurfaceCreationError<Self::Error>> {
        GbmSurface::recreate(self).map_err(SurfaceCreationError::NativeSurfaceCreationFailed)?;

        wrap_egl_call(|| {
            ffi::egl::CreateWindowSurface(
                display.handle,
                config_id,
                self.0.surface.borrow().as_raw() as *const _,
                surface_attributes.as_ptr(),
            )
        })
        .map_err(SurfaceCreationError::EGLSurfaceCreationFailed)
    }

    fn needs_recreation(&self) -> bool {
        self.needs_recreation()
    }

    fn swap_buffers(
        &self,
        display: &Arc<EGLDisplayHandle>,
        surface: ffi::egl::types::EGLSurface,
    ) -> Result<(), SwapBuffersError<Self::Error>> {
        wrap_egl_call(|| unsafe { ffi::egl::SwapBuffers(***display, surface as *const _) })
            .map_err(SwapBuffersError::EGLSwapBuffers)?;
        // this is safe since `eglSwapBuffers` will have been called exactly once
        // if this is used by our egl module, which is why this trait is unsafe.
        unsafe { self.page_flip() }.map_err(SwapBuffersError::Underlying)
    }
}
<|endoftext|>


<commit_before>use serde_json;
use sputnikvm;

use sputnikvm::{read_hex, Gas, M256, Address};
use sputnikvm::vm::{Machine, VectorMachine, Stack, PC};
use sputnikvm::blockchain::Block;
use sputnikvm::transaction::{Transaction, VectorTransaction};

use super::json_schema::{create_machine, test_machine};

use serde_json::{Value, Error};
use std::fs::File;
use std::path::Path;
use std::io::{BufReader, Write, stdout};
use std::str::FromStr;

use rustyline::error::ReadlineError;
use rustyline::Editor;

pub fn test_transaction(name: &str, v: &Value, debug: bool) {
    print!("Testing {} ... ", name);
    if debug {
        print!("\n");
    }
    stdout().flush();

    let mut machine = create_machine(v);
    let result = machine.fire();

    let out = v["out"].as_str();

    if out.is_some() {
        if result.is_ok() && test_machine(v, &machine, debug) {
            println!("OK");
        } else {
            println!("Failed");
        }
    } else {
        if result.is_err() {
            println!("OK");
        } else {
            println!("Failed");
        }
    }
}

pub fn debug_transaction(v: &Value) {
    let mut machine = create_machine(v);
    let mut rl = Editor::<()>::new();

    loop {
        let readline = rl.readline(">> ");
        match readline {
            Ok(line) => {
                rl.add_history_entry(&line);
                match line.as_ref() {
                    "step" => {
                        println!("{:?}", machine.pc().peek_opcode());
                        machine.step();
                    },
                    "fire" => {
                        machine.fire();
                    },
                    "print stack" => {
                        for i in 0..machine.stack().size() {
                            println!("{}: {:x}", i, machine.stack().peek(i).unwrap());
                        }
                    },
                    _ => {
                        println!("Unknown command.");
                    }
                }
            },
            Err(ReadlineError::Interrupted) => {
                println!("CTRL-C");
                break
            },
            Err(ReadlineError::Eof) => {
                println!("CTRL-D");
                break
            },
            Err(err) => {
                println!("Error: {:?}", err);
                break
            }
        }
    }
}
<commit_msg>Problem: EDB would continue to try to step when machine's stopped Solution: check whether the machine has stopped<commit_after>use serde_json;
use sputnikvm;

use sputnikvm::{read_hex, Gas, M256, Address};
use sputnikvm::vm::{Machine, VectorMachine, Stack, PC};
use sputnikvm::blockchain::Block;
use sputnikvm::transaction::{Transaction, VectorTransaction};

use super::json_schema::{create_machine, test_machine};

use serde_json::{Value, Error};
use std::fs::File;
use std::path::Path;
use std::io::{BufReader, Write, stdout};
use std::str::FromStr;

use rustyline::error::ReadlineError;
use rustyline::Editor;

pub fn test_transaction(name: &str, v: &Value, debug: bool) {
    print!("Testing {} ... ", name);
    if debug {
        print!("\n");
    }
    stdout().flush();

    let mut machine = create_machine(v);
    let result = machine.fire();

    let out = v["out"].as_str();

    if out.is_some() {
        if result.is_ok() && test_machine(v, &machine, debug) {
            println!("OK");
        } else {
            println!("Failed");
        }
    } else {
        if result.is_err() {
            println!("OK");
        } else {
            println!("Failed");
        }
    }
}

pub fn debug_transaction(v: &Value) {
    let mut machine = create_machine(v);
    let mut rl = Editor::<()>::new();

    loop {
        let readline = rl.readline(">> ");
        match readline {
            Ok(line) => {
                rl.add_history_entry(&line);
                match line.as_ref() {
                    "step" => {
                        if machine.pc().stopped() {
                            println!("Stopped");
                        } else {
                            println!("{:?}", machine.pc().peek_opcode());
                            machine.step();
                        }
                    },
                    "fire" => {
                        machine.fire();
                    },
                    "print stack" => {
                        for i in 0..machine.stack().size() {
                            println!("{}: {:x}", i, machine.stack().peek(i).unwrap());
                        }
                    },
                    _ => {
                        println!("Unknown command.");
                    }
                }
            },
            Err(ReadlineError::Interrupted) => {
                println!("CTRL-C");
                break
            },
            Err(ReadlineError::Eof) => {
                println!("CTRL-D");
                break
            },
            Err(err) => {
                println!("Error: {:?}", err);
                break
            }
        }
    }
}
<|endoftext|>


<commit_before>// Transfer all crates from one user to another.
//
// Usage:
//      cargo run --bin transfer-crates from-user to-user

#![deny(warnings)]

extern crate cargo_registry;
extern crate postgres;
extern crate time;
extern crate semver;

use std::env;
use std::io;
use std::io::prelude::*;

use cargo_registry::{Crate, User};
use cargo_registry::owner::OwnerKind;
use cargo_registry::Model;

#[allow(dead_code)]
fn main() {
    let conn = cargo_registry::db::connect_now();
    {
        let tx = conn.transaction().unwrap();
        transfer(&tx);
        tx.set_commit();
        tx.finish().unwrap();
    }
}

fn transfer(tx: &postgres::transaction::Transaction) {
    let from = match env::args().nth(1) {
        None => {
            println!("needs a from-user argument");
            return;
        }
        Some(s) => s,
    };
    let to = match env::args().nth(2) {
        None => {
            println!("needs a to-user argument");
            return;
        }
        Some(s) => s,
    };

    let from = User::find_by_login(tx, &from).unwrap();
    let to = User::find_by_login(tx, &to).unwrap();

    if from.gh_id != to.gh_id {
        println!("====================================================");
        println!("WARNING");
        println!("");
        println!("this may not be the same github user, different github IDs");
        println!("");
        println!("from: {:?}", from.gh_id);
        println!("to:   {:?}", to.gh_id);

        get_confirm("continue?");
    }

    println!(
        "Are you sure you want to transfer crates from {} to {}",
        from.gh_login,
        to.gh_login
    );
    get_confirm("continue");

    let stmt = tx.prepare(
        "SELECT * FROM crate_owners
                                   WHERE owner_id = $1
                                     AND owner_kind = $2",
    ).unwrap();
    let rows = stmt.query(&[&from.id, &(OwnerKind::User as i32)]).unwrap();

    for row in rows.iter() {
        let krate = Crate::find(tx, row.get("crate_id")).unwrap();
        println!("transferring {}", krate.name);
        let owners = krate.owners_old(tx).unwrap();
        if owners.len() != 1 {
            println!("warning: not exactly one owner for {}", krate.name);
        }
    }

    let _ = tx.execute(
        "UPDATE crate_owners SET owner_id = $1
                             WHERE owner_id = $2",
        &[&to.id, &from.id],
    ).unwrap();

    get_confirm("commit?");
}

fn get_confirm(msg: &str) {
    print!("{} [y/N]: ", msg);
    io::stdout().flush().unwrap();
    let mut line = String::new();
    io::stdin().read_line(&mut line).unwrap();
    if !line.starts_with("y") {
        std::process::exit(0);
    }
}
<commit_msg>Code improvments<commit_after>// Transfer all crates from one user to another.
//
// Usage:
//      cargo run --bin transfer-crates from-user to-user

#![deny(warnings)]

extern crate cargo_registry;
extern crate postgres;
extern crate time;
extern crate semver;

use std::env;
use std::io;
use std::io::prelude::*;

use cargo_registry::{Crate, User};
use cargo_registry::owner::OwnerKind;
use cargo_registry::Model;

#[allow(dead_code)]
fn main() {
    let conn = cargo_registry::db::connect_now();
    {
        let tx = conn.transaction().unwrap();
        transfer(&tx);
        tx.set_commit();
        tx.finish().unwrap();
    }
}

fn transfer(tx: &postgres::transaction::Transaction) {
    let from = match env::args().nth(1) {
        None => {
            println!("needs a from-user argument");
            return;
        }
        Some(s) => s,
    };
    let to = match env::args().nth(2) {
        None => {
            println!("needs a to-user argument");
            return;
        }
        Some(s) => s,
    };

    let from = User::find_by_login(tx, &from).unwrap();
    let to = User::find_by_login(tx, &to).unwrap();

    if from.gh_id != to.gh_id {
        println!("====================================================");
        println!("WARNING");
        println!("");
        println!("this may not be the same github user, different github IDs");
        println!("");
        println!("from: {:?}", from.gh_id);
        println!("to:   {:?}", to.gh_id);

        get_confirm("continue?");
    }

    println!(
        "Are you sure you want to transfer crates from {} to {}",
        from.gh_login,
        to.gh_login
    );
    get_confirm("continue");

    let stmt = tx.prepare(
        "SELECT * FROM crate_owners
                                   WHERE owner_id = $1
                                     AND owner_kind = $2",
    ).unwrap();
    let rows = stmt.query(&[&from.id, &(OwnerKind::User as i32)]).unwrap();

    for row in rows.iter() {
        let krate = Crate::find(tx, row.get("crate_id")).unwrap();
        println!("transferring {}", krate.name);
        let owners = krate.owners_old(tx).unwrap();
        if owners.len() != 1 {
            println!("warning: not exactly one owner for {}", krate.name);
        }
    }

    tx.execute(
        "UPDATE crate_owners SET owner_id = $1
                             WHERE owner_id = $2",
        &[&to.id, &from.id],
    ).unwrap();

    get_confirm("commit?");
}

fn get_confirm(msg: &str) {
    print!("{} [y/N]: ", msg);
    io::stdout().flush().unwrap();
    let mut line = String::new();
    io::stdin().read_line(&mut line).unwrap();
    if !line.starts_with("y") {
        std::process::exit(0);
    }
}
<|endoftext|>


<commit_before>import core::{vec, uint, str, option, result};
import std::{term, io};
import io::writer_util;
import option::{some, none};

type filename = str;

type file_pos = {ch: uint, byte: uint};

/* A codemap is a thing that maps uints to file/line/column positions
 * in a crate. This to make it possible to represent the positions
 * with single-word things, rather than passing records all over the
 * compiler.
 */
type filemap =
    @{name: filename, start_pos: file_pos, mutable lines: [file_pos]};

type codemap = @{mutable files: [filemap]};

type loc = {filename: filename, line: uint, col: uint};

fn new_codemap() -> codemap { ret @{mutable files: []}; }

fn new_filemap(filename: filename, start_pos_ch: uint, start_pos_byte: uint)
   -> filemap {
    ret @{name: filename,
          start_pos: {ch: start_pos_ch, byte: start_pos_byte},
          mutable lines: [{ch: start_pos_ch, byte: start_pos_byte}]};
}

fn next_line(file: filemap, chpos: uint, byte_pos: uint) {
    file.lines += [{ch: chpos, byte: byte_pos}];
}

type lookup_fn = fn@(file_pos) -> uint;

fn lookup_pos(map: codemap, pos: uint, lookup: lookup_fn) -> loc {
    let len = vec::len(map.files);
    if len > 1u && map.files[len - 1u].name == "-" {
        // the trailing "-" must be the core_macros inserted by expand_crate,
        // exclude it from the targets to lookup
        len = len - 1u;
    }
    let a = 0u;
    let b = len;
    while b - a > 1u {
        let m = (a + b) / 2u;
        if lookup(map.files[m].start_pos) > pos { b = m; } else { a = m; }
    }
    let f = map.files[a];
    a = 0u;
    b = vec::len(f.lines);
    while b - a > 1u {
        let m = (a + b) / 2u;
        if lookup(f.lines[m]) > pos { b = m; } else { a = m; }
    }
    ret {filename: f.name, line: a + 1u, col: pos - lookup(f.lines[a])};
}

fn lookup_char_pos(map: codemap, pos: uint) -> loc {
    fn lookup(pos: file_pos) -> uint { ret pos.ch; }
    ret lookup_pos(map, pos, lookup);
}

fn lookup_byte_pos(map: codemap, pos: uint) -> loc {
    fn lookup(pos: file_pos) -> uint { ret pos.byte; }
    ret lookup_pos(map, pos, lookup);
}

tag opt_span {

    //hack (as opposed to option::t), to make `span` compile
    os_none;
    os_some(@span);
}
type span = {lo: uint, hi: uint, expanded_from: opt_span};

fn span_to_str(sp: span, cm: codemap) -> str {
    let cur = sp;
    let res = "";
    let prev_file = none;
    while true {
        let lo = lookup_char_pos(cm, cur.lo);
        let hi = lookup_char_pos(cm, cur.hi);
        res +=
            #fmt["%s:%u:%u: %u:%u",
                 if some(lo.filename) == prev_file {
                     "-"
                 } else { lo.filename }, lo.line, lo.col, hi.line, hi.col];
        alt cur.expanded_from {
          os_none. { break; }
          os_some(new_sp) {
            cur = *new_sp;
            prev_file = some(lo.filename);
            res += "<<";
          }
        }
    }

    ret res;
}

tag diagnostictype {
    warning;
    error;
    note;
}

fn diagnosticstr(t: diagnostictype) -> str {
    alt t {
      warning. { "warning" }
      error. { "error" }
      note. { "note" }
    }
}

fn diagnosticcolor(t: diagnostictype) -> u8 {
    alt t {
      warning. { term::color_bright_yellow }
      error. { term::color_bright_red }
      note. { term::color_bright_green }
    }
}

fn print_diagnostic(topic: str, t: diagnostictype, msg: str) {
    if str::is_not_empty(topic) {
        io::stdout().write_str(#fmt["%s ", topic]);
    }
    if term::color_supported() {
        term::fg(io::stdout(), diagnosticcolor(t));
    }
    io::stdout().write_str(#fmt["%s:", diagnosticstr(t)]);
    if term::color_supported() {
        term::reset(io::stdout());
    }
    io::stdout().write_str(#fmt[" %s\n", msg]);
}

fn emit_diagnostic(cmsp: option<(codemap, span)>, msg: str,
                   t: diagnostictype) {
    let ss = "";
    let maybe_lines: option::t<@file_lines> = none;
    alt cmsp {
      some((cm, sp)) {
        ss = span_to_str(sp, cm);
        maybe_lines = some(span_to_lines(sp, cm));
      }
      none. { }
    }
    print_diagnostic(ss, t, msg);
    maybe_highlight_lines(cmsp, maybe_lines);
}

fn maybe_highlight_lines(cmsp: option<(codemap, span)>,
                         maybe_lines: option::t<@file_lines>) {

    alt maybe_lines {
      some(lines) {
        let (cm, sp) = option::get(cmsp);

        // If we're not looking at a real file then we can't re-open it to
        // pull out the lines
        if lines.name == "-" { ret; }

        // FIXME: reading in the entire file is the worst possible way to
        //        get access to the necessary lines.
        let file = alt io::read_whole_file_str(lines.name) {
          result::ok(file) { file }
          result::err(e) {
            emit_error(none, e);
            fail;
          }
        };
        let fm = get_filemap(cm, lines.name);

        // arbitrarily only print up to six lines of the error
        let max_lines = 6u;
        let elided = false;
        let display_lines = lines.lines;
        if vec::len(display_lines) > max_lines {
            display_lines = vec::slice(display_lines, 0u, max_lines);
            elided = true;
        }
        // Print the offending lines
        for line: uint in display_lines {
            io::stdout().write_str(#fmt["%s:%u ", fm.name, line + 1u]);
            let s = get_line(fm, line as int, file);
            if !str::ends_with(s, "\n") { s += "\n"; }
            io::stdout().write_str(s);
        }
        if elided {
            let last_line = display_lines[vec::len(display_lines) - 1u];
            let s = #fmt["%s:%u ", fm.name, last_line + 1u];
            let indent = str::char_len(s);
            let out = "";
            while indent > 0u { out += " "; indent -= 1u; }
            out += "...\n";
            io::stdout().write_str(out);
        }

        // If there's one line at fault we can easily point to the problem
        if vec::len(lines.lines) == 1u {
            let lo = lookup_char_pos(cm, sp.lo);
            let digits = 0u;
            let num = (lines.lines[0] + 1u) / 10u;

            // how many digits must be indent past?
            while num > 0u { num /= 10u; digits += 1u; }

            // indent past |name:## | and the 0-offset column location
            let left = str::char_len(fm.name) + digits + lo.col + 3u;
            let s = "";
            while left > 0u { str::push_char(s, ' '); left -= 1u; }

            s += "^";
            let hi = lookup_char_pos(cm, sp.hi);
            if hi.col != lo.col {
                // the ^ already takes up one space
                let width = hi.col - lo.col - 1u;
                while width > 0u { str::push_char(s, '~'); width -= 1u; }
            }
            io::stdout().write_str(s + "\n");
        }
      }
      _ { }
    }
}

fn emit_warning(cmsp: option<(codemap, span)>, msg: str) {
    emit_diagnostic(cmsp, msg, warning);
}
fn emit_error(cmsp: option<(codemap, span)>, msg: str) {
    emit_diagnostic(cmsp, msg, error);
}
fn emit_note(cmsp: option<(codemap, span)>, msg: str) {
    emit_diagnostic(cmsp, msg, note);
}

type file_lines = {name: str, lines: [uint]};

fn span_to_lines(sp: span, cm: codemap::codemap) -> @file_lines {
    let lo = lookup_char_pos(cm, sp.lo);
    let hi = lookup_char_pos(cm, sp.hi);
    let lines = [];
    uint::range(lo.line - 1u, hi.line as uint) {|i| lines += [i]; };
    ret @{name: lo.filename, lines: lines};
}

fn get_line(fm: filemap, line: int, file: str) -> str {
    let begin: uint = fm.lines[line].byte - fm.start_pos.byte;
    let end: uint;
    if line as uint < vec::len(fm.lines) - 1u {
        end = fm.lines[line + 1].byte - fm.start_pos.byte;
    } else {
        // If we're not done parsing the file, we're at the limit of what's
        // parsed. If we just slice the rest of the string, we'll print out
        // the remainder of the file, which is undesirable.
        end = str::byte_len(file);
        let rest = str::slice(file, begin, end);
        let newline = str::index(rest, '\n' as u8);
        if newline != -1 { end = begin + (newline as uint); }
    }
    ret str::slice(file, begin, end);
}

fn get_filemap(cm: codemap, filename: str) -> filemap {
    for fm: filemap in cm.files { if fm.name == filename { ret fm; } }
    //XXjdm the following triggers a mismatched type bug
    //      (or expected function, found _|_)
    fail; // ("asking for " + filename + " which we don't know about");
}
//
// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
//
<commit_msg>rustc: Some more codemap refactoring<commit_after>import core::{vec, uint, str, option, result};
import std::{term, io};
import io::writer_util;
import option::{some, none};

type filename = str;

type file_pos = {ch: uint, byte: uint};

/* A codemap is a thing that maps uints to file/line/column positions
 * in a crate. This to make it possible to represent the positions
 * with single-word things, rather than passing records all over the
 * compiler.
 */
type filemap =
    @{name: filename, start_pos: file_pos, mutable lines: [file_pos]};

type codemap = @{mutable files: [filemap]};

type loc = {filename: filename, line: uint, col: uint};

fn new_codemap() -> codemap { ret @{mutable files: []}; }

fn new_filemap(filename: filename, start_pos_ch: uint, start_pos_byte: uint)
   -> filemap {
    ret @{name: filename,
          start_pos: {ch: start_pos_ch, byte: start_pos_byte},
          mutable lines: [{ch: start_pos_ch, byte: start_pos_byte}]};
}

fn next_line(file: filemap, chpos: uint, byte_pos: uint) {
    file.lines += [{ch: chpos, byte: byte_pos}];
}

type lookup_fn = fn@(file_pos) -> uint;

fn lookup_pos(map: codemap, pos: uint, lookup: lookup_fn) -> loc {
    let len = vec::len(map.files);
    if len > 1u && map.files[len - 1u].name == "-" {
        // the trailing "-" must be the core_macros inserted by expand_crate,
        // exclude it from the targets to lookup
        len = len - 1u;
    }
    let a = 0u;
    let b = len;
    while b - a > 1u {
        let m = (a + b) / 2u;
        if lookup(map.files[m].start_pos) > pos { b = m; } else { a = m; }
    }
    let f = map.files[a];
    a = 0u;
    b = vec::len(f.lines);
    while b - a > 1u {
        let m = (a + b) / 2u;
        if lookup(f.lines[m]) > pos { b = m; } else { a = m; }
    }
    ret {filename: f.name, line: a + 1u, col: pos - lookup(f.lines[a])};
}

fn lookup_char_pos(map: codemap, pos: uint) -> loc {
    fn lookup(pos: file_pos) -> uint { ret pos.ch; }
    ret lookup_pos(map, pos, lookup);
}

fn lookup_byte_pos(map: codemap, pos: uint) -> loc {
    fn lookup(pos: file_pos) -> uint { ret pos.byte; }
    ret lookup_pos(map, pos, lookup);
}

tag opt_span {

    //hack (as opposed to option::t), to make `span` compile
    os_none;
    os_some(@span);
}
type span = {lo: uint, hi: uint, expanded_from: opt_span};

fn span_to_str(sp: span, cm: codemap) -> str {
    let cur = sp;
    let res = "";
    let prev_file = none;
    while true {
        let lo = lookup_char_pos(cm, cur.lo);
        let hi = lookup_char_pos(cm, cur.hi);
        res +=
            #fmt["%s:%u:%u: %u:%u",
                 if some(lo.filename) == prev_file {
                     "-"
                 } else { lo.filename }, lo.line, lo.col, hi.line, hi.col];
        alt cur.expanded_from {
          os_none. { break; }
          os_some(new_sp) {
            cur = *new_sp;
            prev_file = some(lo.filename);
            res += "<<";
          }
        }
    }

    ret res;
}

tag diagnostictype {
    warning;
    error;
    note;
}

fn diagnosticstr(t: diagnostictype) -> str {
    alt t {
      warning. { "warning" }
      error. { "error" }
      note. { "note" }
    }
}

fn diagnosticcolor(t: diagnostictype) -> u8 {
    alt t {
      warning. { term::color_bright_yellow }
      error. { term::color_bright_red }
      note. { term::color_bright_green }
    }
}

fn print_diagnostic(topic: str, t: diagnostictype, msg: str) {
    if str::is_not_empty(topic) {
        io::stdout().write_str(#fmt["%s ", topic]);
    }
    if term::color_supported() {
        term::fg(io::stdout(), diagnosticcolor(t));
    }
    io::stdout().write_str(#fmt["%s:", diagnosticstr(t)]);
    if term::color_supported() {
        term::reset(io::stdout());
    }
    io::stdout().write_str(#fmt[" %s\n", msg]);
}

fn emit_diagnostic(cmsp: option<(codemap, span)>, msg: str,
                   t: diagnostictype) {
    alt cmsp {
      some((cm, sp)) {
        let ss = span_to_str(sp, cm);
        let lines = span_to_lines(sp, cm);
        print_diagnostic(ss, t, msg);
        highlight_lines(cm, sp, lines);
      }
      none. {
        print_diagnostic("", t, msg);
      }
    }
}

fn highlight_lines(cm: codemap, sp: span,
                   lines: @file_lines) {

    // If we're not looking at a real file then we can't re-open it to
    // pull out the lines
    if lines.name == "-" { ret; }

    // FIXME: reading in the entire file is the worst possible way to
    //        get access to the necessary lines.
    let file = alt io::read_whole_file_str(lines.name) {
      result::ok(file) { file }
      result::err(e) {
        emit_error(none, e);
        fail;
      }
    };
    let fm = get_filemap(cm, lines.name);

    // arbitrarily only print up to six lines of the error
    let max_lines = 6u;
    let elided = false;
    let display_lines = lines.lines;
    if vec::len(display_lines) > max_lines {
        display_lines = vec::slice(display_lines, 0u, max_lines);
        elided = true;
    }
    // Print the offending lines
    for line: uint in display_lines {
        io::stdout().write_str(#fmt["%s:%u ", fm.name, line + 1u]);
        let s = get_line(fm, line as int, file);
        if !str::ends_with(s, "\n") { s += "\n"; }
        io::stdout().write_str(s);
    }
    if elided {
        let last_line = display_lines[vec::len(display_lines) - 1u];
        let s = #fmt["%s:%u ", fm.name, last_line + 1u];
        let indent = str::char_len(s);
        let out = "";
        while indent > 0u { out += " "; indent -= 1u; }
        out += "...\n";
        io::stdout().write_str(out);
    }

    // If there's one line at fault we can easily point to the problem
    if vec::len(lines.lines) == 1u {
        let lo = lookup_char_pos(cm, sp.lo);
        let digits = 0u;
        let num = (lines.lines[0] + 1u) / 10u;

        // how many digits must be indent past?
        while num > 0u { num /= 10u; digits += 1u; }

        // indent past |name:## | and the 0-offset column location
        let left = str::char_len(fm.name) + digits + lo.col + 3u;
        let s = "";
        while left > 0u { str::push_char(s, ' '); left -= 1u; }

        s += "^";
        let hi = lookup_char_pos(cm, sp.hi);
        if hi.col != lo.col {
            // the ^ already takes up one space
            let width = hi.col - lo.col - 1u;
            while width > 0u { str::push_char(s, '~'); width -= 1u; }
        }
        io::stdout().write_str(s + "\n");
    }
}

fn emit_warning(cmsp: option<(codemap, span)>, msg: str) {
    emit_diagnostic(cmsp, msg, warning);
}
fn emit_error(cmsp: option<(codemap, span)>, msg: str) {
    emit_diagnostic(cmsp, msg, error);
}
fn emit_note(cmsp: option<(codemap, span)>, msg: str) {
    emit_diagnostic(cmsp, msg, note);
}

type file_lines = {name: str, lines: [uint]};

fn span_to_lines(sp: span, cm: codemap::codemap) -> @file_lines {
    let lo = lookup_char_pos(cm, sp.lo);
    let hi = lookup_char_pos(cm, sp.hi);
    let lines = [];
    uint::range(lo.line - 1u, hi.line as uint) {|i| lines += [i]; };
    ret @{name: lo.filename, lines: lines};
}

fn get_line(fm: filemap, line: int, file: str) -> str {
    let begin: uint = fm.lines[line].byte - fm.start_pos.byte;
    let end: uint;
    if line as uint < vec::len(fm.lines) - 1u {
        end = fm.lines[line + 1].byte - fm.start_pos.byte;
    } else {
        // If we're not done parsing the file, we're at the limit of what's
        // parsed. If we just slice the rest of the string, we'll print out
        // the remainder of the file, which is undesirable.
        end = str::byte_len(file);
        let rest = str::slice(file, begin, end);
        let newline = str::index(rest, '\n' as u8);
        if newline != -1 { end = begin + (newline as uint); }
    }
    ret str::slice(file, begin, end);
}

fn get_filemap(cm: codemap, filename: str) -> filemap {
    for fm: filemap in cm.files { if fm.name == filename { ret fm; } }
    //XXjdm the following triggers a mismatched type bug
    //      (or expected function, found _|_)
    fail; // ("asking for " + filename + " which we don't know about");
}
//
// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
//
<|endoftext|>


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

//! Configuration options for a single run of the servo application. Created
//! from command line arguments.

use azure::azure_hl::{BackendType, CairoBackend, CoreGraphicsBackend};
use azure::azure_hl::{CoreGraphicsAcceleratedBackend, Direct2DBackend, SkiaBackend};

use std::float;
use std::result;
use std::uint;

pub struct Opts {
    urls: ~[~str],
    render_backend: BackendType,
    n_render_threads: uint,
    tile_size: uint,
    profiler_period: Option<float>,

    /// A scale factor to apply to tiles, to allow rendering tiles at higher resolutions for
    /// testing pan and zoom code.
    zoom: uint,
}

#[allow(non_implicitly_copyable_typarams)]
pub fn from_cmdline_args(args: &[~str]) -> Opts {
    use extra::getopts;

    let args = args.tail();

    let opts = ~[
        getopts::optopt("o"),  // output file
        getopts::optopt("r"),  // rendering backend
        getopts::optopt("s"),  // size of tiles
        getopts::optopt("t"),  // threads to render with
        getopts::optflagopt("p"),  // profiler flag and output interval
        getopts::optopt("z"),  // zoom level
    ];

    let opt_match = match getopts::getopts(args, opts) {
      result::Ok(m) => m,
      result::Err(f) => fail!(getopts::fail_str(copy f)),
    };

    let urls = if opt_match.free.is_empty() {
        fail!(~"servo asks that you provide 1 or more URLs")
    } else {
        copy opt_match.free
    };

    if getopts::opt_present(&opt_match, "o") {
        fail!(~"servo cannot treat 'o' option now.")
    }

    let render_backend = match getopts::opt_maybe_str(&opt_match, "r") {
        Some(backend_str) => {
            if backend_str == ~"direct2d" {
                Direct2DBackend
            } else if backend_str == ~"core-graphics" {
                CoreGraphicsBackend
            } else if backend_str == ~"core-graphics-accelerated" {
                CoreGraphicsAcceleratedBackend
            } else if backend_str == ~"cairo" {
                CairoBackend
            } else if backend_str == ~"skia" {
                SkiaBackend
            } else {
                fail!(~"unknown backend type")
            }
        }
        None => SkiaBackend
    };

    let tile_size: uint = match getopts::opt_maybe_str(&opt_match, "s") {
        Some(tile_size_str) => uint::from_str(tile_size_str).get(),
        None => 512,
    };

    let n_render_threads: uint = match getopts::opt_maybe_str(&opt_match, "t") {
        Some(n_render_threads_str) => uint::from_str(n_render_threads_str).get(),
        None => 1,      // FIXME: Number of cores.
    };

    let profiler_period: Option<float> =
        // if only flag is present, default to 5 second period
        match getopts::opt_default(&opt_match, "p", "5") {
        Some(period) => Some(float::from_str(period).get()),
        None => None,
    };

    let zoom: uint = match getopts::opt_maybe_str(&opt_match, "z") {
        Some(zoom_str) => uint::from_str(zoom_str).get(),
        None => 1,
    };

    Opts {
        urls: urls,
        render_backend: render_backend,
        n_render_threads: n_render_threads,
        tile_size: tile_size,
        profiler_period: profiler_period,
        zoom: zoom,
    }
}
<commit_msg>auto merge of #576 : eschweic/servo/master, r=pcwalton<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! Configuration options for a single run of the servo application. Created
//! from command line arguments.

use azure::azure_hl::{BackendType, CairoBackend, CoreGraphicsBackend};
use azure::azure_hl::{CoreGraphicsAcceleratedBackend, Direct2DBackend, SkiaBackend};

use std::float;
use std::result;
use std::uint;

pub struct Opts {
    urls: ~[~str],
    render_backend: BackendType,
    n_render_threads: uint,
    tile_size: uint,
    profiler_period: Option<float>,
}

#[allow(non_implicitly_copyable_typarams)]
pub fn from_cmdline_args(args: &[~str]) -> Opts {
    use extra::getopts;

    let args = args.tail();

    let opts = ~[
        getopts::optopt("o"),  // output file
        getopts::optopt("r"),  // rendering backend
        getopts::optopt("s"),  // size of tiles
        getopts::optopt("t"),  // threads to render with
        getopts::optflagopt("p"),  // profiler flag and output interval
    ];

    let opt_match = match getopts::getopts(args, opts) {
      result::Ok(m) => m,
      result::Err(f) => fail!(getopts::fail_str(copy f)),
    };

    let urls = if opt_match.free.is_empty() {
        fail!(~"servo asks that you provide 1 or more URLs")
    } else {
        copy opt_match.free
    };

    if getopts::opt_present(&opt_match, "o") {
        fail!(~"servo cannot treat 'o' option now.")
    }

    let render_backend = match getopts::opt_maybe_str(&opt_match, "r") {
        Some(backend_str) => {
            if backend_str == ~"direct2d" {
                Direct2DBackend
            } else if backend_str == ~"core-graphics" {
                CoreGraphicsBackend
            } else if backend_str == ~"core-graphics-accelerated" {
                CoreGraphicsAcceleratedBackend
            } else if backend_str == ~"cairo" {
                CairoBackend
            } else if backend_str == ~"skia" {
                SkiaBackend
            } else {
                fail!(~"unknown backend type")
            }
        }
        None => SkiaBackend
    };

    let tile_size: uint = match getopts::opt_maybe_str(&opt_match, "s") {
        Some(tile_size_str) => uint::from_str(tile_size_str).get(),
        None => 512,
    };

    let n_render_threads: uint = match getopts::opt_maybe_str(&opt_match, "t") {
        Some(n_render_threads_str) => uint::from_str(n_render_threads_str).get(),
        None => 1,      // FIXME: Number of cores.
    };

    let profiler_period: Option<float> =
        // if only flag is present, default to 5 second period
        match getopts::opt_default(&opt_match, "p", "5") {
        Some(period) => Some(float::from_str(period).get()),
        None => None,
    };

    Opts {
        urls: urls,
        render_backend: render_backend,
        n_render_threads: n_render_threads,
        tile_size: tile_size,
        profiler_period: profiler_period,
    }
}
<|endoftext|>


<commit_before>
#[doc(hidden)]
#[macro_export]
macro_rules! log{ ($lvl:expr, $modname:expr, $($arg:tt)*) => (
	if $crate::logging::enabled($lvl, $modname)
	{
		use core::fmt::Write;

		let _ = write!(&mut $crate::logging::getstream($lvl, $modname), $($arg)*);
	}
	)}
/// Log a panic-level message (kernel intents to halt immediately after printing)
#[macro_export]
macro_rules! log_panic{   ($($arg:tt)*) => (log!($crate::logging::Level::LevelPanic,   module_path!(), $($arg)*))}
/// "Error" - The current subsystem errored, and most likely will no longer function
#[macro_export]
macro_rules! log_error{   ($($arg:tt)*) => (log!($crate::logging::Level::LevelError,   module_path!(), $($arg)*))}
/// Warning - Something unexpected happened, but it was recovered
#[macro_export]
macro_rules! log_warning{ ($($arg:tt)*) => (log!($crate::logging::Level::LevelWarning, module_path!(), $($arg)*))}
/// Notice - Out of the ordinary, but not unexpected
#[macro_export]
macro_rules! log_notice{  ($($arg:tt)*) => (log!($crate::logging::Level::LevelNotice,  module_path!(), $($arg)*))}
/// Information - Needs to be logged, but nothing to worry about
#[macro_export]
macro_rules! log_info{    ($($arg:tt)*) => (log!($crate::logging::Level::LevelInfo,    module_path!(), $($arg)*))}
/// Log - High-level debugging information
#[macro_export]
macro_rules! log_log{     ($($arg:tt)*) => (log!($crate::logging::Level::LevelLog,     module_path!(), $($arg)*))}
/// Debug - Low level debugging information (values mostly)
#[macro_export]
macro_rules! log_debug{   ($($arg:tt)*) => (log!($crate::logging::Level::LevelDebug,   module_path!(), $($arg)*))}
/// Trace - Very low level debugging information (action-by-action updates)
#[macro_export]
macro_rules! log_trace{
	($fmt:expr, $($arg:expr),*) => (log!($crate::logging::Level::LevelTrace, module_path!(), concat!("L{}: ",$fmt), line!() $(, $arg)*) );
	($str:expr) => (log_trace!($str, ));
	}

// vim: ft=rust

<commit_msg>Kernel/Logging - Evaluate log arguments before opening channel<commit_after>
#[doc(hidden)]
#[macro_export]
macro_rules! log{ ($lvl:expr, $modname:expr, $($arg:tt)*) => (
	if $crate::logging::enabled($lvl, $modname)
	{
		use core::fmt::Write;

		let _ = match format_args!( $($arg)* )
		{
		a => write!(&mut $crate::logging::getstream($lvl, $modname), "{}", a),
		};
	}
	)}
/// Log a panic-level message (kernel intents to halt immediately after printing)
#[macro_export]
macro_rules! log_panic{   ($($arg:tt)*) => (log!($crate::logging::Level::LevelPanic,   module_path!(), $($arg)*))}
/// "Error" - The current subsystem errored, and most likely will no longer function
#[macro_export]
macro_rules! log_error{   ($($arg:tt)*) => (log!($crate::logging::Level::LevelError,   module_path!(), $($arg)*))}
/// Warning - Something unexpected happened, but it was recovered
#[macro_export]
macro_rules! log_warning{ ($($arg:tt)*) => (log!($crate::logging::Level::LevelWarning, module_path!(), $($arg)*))}
/// Notice - Out of the ordinary, but not unexpected
#[macro_export]
macro_rules! log_notice{  ($($arg:tt)*) => (log!($crate::logging::Level::LevelNotice,  module_path!(), $($arg)*))}
/// Information - Needs to be logged, but nothing to worry about
#[macro_export]
macro_rules! log_info{    ($($arg:tt)*) => (log!($crate::logging::Level::LevelInfo,    module_path!(), $($arg)*))}
/// Log - High-level debugging information
#[macro_export]
macro_rules! log_log{     ($($arg:tt)*) => (log!($crate::logging::Level::LevelLog,     module_path!(), $($arg)*))}
/// Debug - Low level debugging information (values mostly)
#[macro_export]
macro_rules! log_debug{   ($($arg:tt)*) => (log!($crate::logging::Level::LevelDebug,   module_path!(), $($arg)*))}
/// Trace - Very low level debugging information (action-by-action updates)
#[macro_export]
macro_rules! log_trace{
	($fmt:expr, $($arg:expr),*) => (log!($crate::logging::Level::LevelTrace, module_path!(), concat!("L{}: ",$fmt), line!() $(, $arg)*) );
	($str:expr) => (log_trace!($str, ));
	}

// vim: ft=rust

<|endoftext|>


<commit_before>use std::io::{IoResult, File};
use std::io::util::copy;
use http;
use time;
use mimes::get_media_type;

///A container for the response
pub struct Response<'a, 'b> {
    ///the original `http::server::ResponseWriter`
    pub origin: &'a mut http::server::ResponseWriter<'b>,
}

impl<'a, 'b> Response<'a, 'b> {

    pub fn from_internal<'c, 'd>(response: &'c mut http::server::ResponseWriter<'d>) -> Response<'c, 'd> {
        Response {
            origin: response
        }
    }

    /// Writes a response
    ///
    /// # Example
    /// ```{rust,ignore}
    /// response.send("hello world");
    /// ```
    pub fn send (&mut self, text: &str) {
        // TODO: This needs to be more sophisticated to return the correct headers
        // not just "some headers" :)
        Response::set_headers(self.origin);
        let _ = self.origin.write(text.as_bytes());
    }

    /// sets the content type by it's short form.
    ///
    /// # Example
    /// ```{rust,ignore}
    /// response.set_content_type("html");
    /// ```
    pub fn set_content_type(&mut self, text: &str) {
        // TODO: make this a chaining API. (Fight the lifetime hell!)
        self.origin.headers.content_type = get_media_type(text);
    }

    fn set_headers(response_writer: &mut http::server::ResponseWriter) {
        response_writer.headers.date = Some(time::now_utc());

        // we don't need to set this https://github.com/Ogeon/rustful/issues/3#issuecomment-44787613
        response_writer.headers.content_length = None;
        response_writer.headers.content_type = response_writer.headers.content_type
                                                                      .clone()
                                                                      .or(get_media_type("txt"));

        response_writer.headers.server = Some(String::from_str("Nickel"));
    }

    pub fn send_file(&mut self, path: &Path) -> IoResult<()> {
        let mut file = try!(File::open(path));
        self.origin.headers.content_length = None;

        self.origin.headers.content_type = path.extension_str().and_then(get_media_type);
        self.origin.headers.server = Some(String::from_str("Nickel"));
        copy(&mut file, self.origin)
    }
}

#[test]
fn matches_content_type () {
    let path = &Path::new("test.txt");
    let content_type = path.extension_str().and_then(get_media_type).unwrap();

    assert_eq!(content_type.type_.as_slice(), "text");
    assert_eq!(content_type.subtype.as_slice(), "plain");
}
<commit_msg>feat(response): use BytesContainer for send<commit_after>use std::io::{IoResult, File};
use std::io::util::copy;
use std::path::BytesContainer;
use http;
use time;
use mimes::get_media_type;

///A container for the response
pub struct Response<'a, 'b> {
    ///the original `http::server::ResponseWriter`
    pub origin: &'a mut http::server::ResponseWriter<'b>,
}

impl<'a, 'b> Response<'a, 'b> {

    pub fn from_internal<'c, 'd>(response: &'c mut http::server::ResponseWriter<'d>) -> Response<'c, 'd> {
        Response {
            origin: response
        }
    }

    /// Writes a response
    ///
    /// # Example
    /// ```{rust,ignore}
    /// response.send("hello world");
    /// ```
    pub fn send<T: BytesContainer> (&mut self, text: T) {
        // TODO: This needs to be more sophisticated to return the correct headers
        // not just "some headers" :)
        Response::set_headers(self.origin);
        let _ = self.origin.write(text.container_as_bytes());
    }

    /// sets the content type by it's short form.
    ///
    /// # Example
    /// ```{rust,ignore}
    /// response.set_content_type("html");
    /// ```
    pub fn set_content_type(&mut self, text: &str) {
        // TODO: make this a chaining API. (Fight the lifetime hell!)
        self.origin.headers.content_type = get_media_type(text);
    }

    fn set_headers(response_writer: &mut http::server::ResponseWriter) {
        response_writer.headers.date = Some(time::now_utc());

        // we don't need to set this https://github.com/Ogeon/rustful/issues/3#issuecomment-44787613
        response_writer.headers.content_length = None;
        response_writer.headers.content_type = response_writer.headers.content_type
                                                                      .clone()
                                                                      .or(get_media_type("txt"));

        response_writer.headers.server = Some(String::from_str("Nickel"));
    }

    pub fn send_file(&mut self, path: &Path) -> IoResult<()> {
        let mut file = try!(File::open(path));
        self.origin.headers.content_length = None;

        self.origin.headers.content_type = path.extension_str().and_then(get_media_type);
        self.origin.headers.server = Some(String::from_str("Nickel"));
        copy(&mut file, self.origin)
    }
}

#[test]
fn matches_content_type () {
    let path = &Path::new("test.txt");
    let content_type = path.extension_str().and_then(get_media_type).unwrap();

    assert_eq!(content_type.type_.as_slice(), "text");
    assert_eq!(content_type.subtype.as_slice(), "plain");
}
<|endoftext|>