<commit_before>//! `cargo add`

#![deny(missing_docs, missing_debug_implementations, missing_copy_implementations, trivial_casts, trivial_numeric_casts, unsafe_code, unstable_features, unused_import_braces, unused_qualifications)]
#![cfg_attr(feature = "dev", allow(unstable_features))]
#![cfg_attr(feature = "dev", feature(plugin))]
#![cfg_attr(feature = "dev", plugin(clippy))]

extern crate docopt;
extern crate toml;
extern crate semver;
extern crate rustc_serialize;
extern crate curl;
#[macro_use]
extern crate quick_error;

use std::error::Error;
use std::process;
use std::io::{self, Write};

extern crate cargo_edit;
use cargo_edit::Manifest;

mod fetch_version;
mod args;
use args::Args;

static USAGE: &'static str = r"
Usage:
    cargo add <crate> [--dev|--build|--optional] [--vers=<ver>|--git=<uri>|--path=<uri>] [options]
    cargo add (-h|--help)
    cargo add --version

Specify what crate to add:
    --vers <ver>            Specify the version to grab from the registry (crates.io).
                            You can also specify versions as part of the name, e.g
                            `cargo add bitflags@0.3.2`.
    --git <uri>             Specify a git repository to download the crate from.
    --path <uri>            Specify the path the crate should be loaded from.

Specify where to add the crate:
    -D --dev                Add crate as development dependency.
    -B --build              Add crate as build dependency.
    --optional              Add as an optional dependency (for use in features). This does not work
                            for `dev-dependencies` or `build-dependencies`.

Options:
    --manifest-path=<path>  Path to the manifest to add a dependency to.
    -h --help               Show this help page.
    --version               Show version.

This command allows you to add a dependency to a Cargo.toml manifest file.
";

fn handle_add(args: &Args) -> Result<(), Box<Error>> {
    let mut manifest = try!(Manifest::open(&args.flag_manifest_path.as_ref().map(|s| &s[..])));
    let dep = try!(args.parse_dependency());

    manifest.insert_into_table(&args.get_section(), &dep)
            .map_err(From::from)
            .and_then(|_| {
                let mut file = try!(Manifest::find_file(&args.flag_manifest_path
                                                             .as_ref()
                                                             .map(|s| &s[..])));
                manifest.write_to_file(&mut file)
            })
            .or_else(|err| {
                println!("Could not edit `Cargo.toml`.\n\nERROR: {}", err);
                Err(err)
            })
}

fn main() {
    let args = docopt::Docopt::new(USAGE)
                   .and_then(|d| d.decode::<Args>())
                   .unwrap_or_else(|err| err.exit());

    if args.flag_version {
        println!("cargo-add version {}", env!("CARGO_PKG_VERSION"));
        process::exit(0);
    }

    if let Err(err) = handle_add(&args) {
        write!(io::stderr(),
               "Command failed due to unhandled error: {}",
               err)
            .unwrap();
        process::exit(1);
    }
}
<commit_msg>Mention Cargo's Caret-As-Default Behavior<commit_after>//! `cargo add`

#![deny(missing_docs, missing_debug_implementations, missing_copy_implementations, trivial_casts, trivial_numeric_casts, unsafe_code, unstable_features, unused_import_braces, unused_qualifications)]
#![cfg_attr(feature = "dev", allow(unstable_features))]
#![cfg_attr(feature = "dev", feature(plugin))]
#![cfg_attr(feature = "dev", plugin(clippy))]

extern crate docopt;
extern crate toml;
extern crate semver;
extern crate rustc_serialize;
extern crate curl;
#[macro_use]
extern crate quick_error;

use std::error::Error;
use std::process;
use std::io::{self, Write};

extern crate cargo_edit;
use cargo_edit::Manifest;

mod fetch_version;
mod args;
use args::Args;

static USAGE: &'static str = r#"
Usage:
    cargo add <crate> [--dev|--build|--optional] [--vers=<ver>|--git=<uri>|--path=<uri>] [options]
    cargo add (-h|--help)
    cargo add --version

Specify what crate to add:
    --vers <ver>            Specify the version to grab from the registry (crates.io).
                            You can also specify versions as part of the name, e.g
                            `cargo add bitflags@0.3.2`.
    --git <uri>             Specify a git repository to download the crate from.
    --path <uri>            Specify the path the crate should be loaded from.

Specify where to add the crate:
    -D --dev                Add crate as development dependency.
    -B --build              Add crate as build dependency.
    --optional              Add as an optional dependency (for use in features). This does not work
                            for `dev-dependencies` or `build-dependencies`.

Options:
    --manifest-path=<path>  Path to the manifest to add a dependency to.
    -h --help               Show this help page.
    --version               Show version.

This command allows you to add a dependency to a Cargo.toml manifest file.

Please note that Cargo treats versions like "1.2.3" as "^1.2.3" (and that "^1.2.3" is specified
as ">=1.2.3 and <2.0.0"). By default, `cargo add` will use this format, as it is the one that the
crates.io registry suggests. One goal of `cargo add` is to prevent you from using wildcard
dependencies (version set to "*").
"#;

fn handle_add(args: &Args) -> Result<(), Box<Error>> {
    let mut manifest = try!(Manifest::open(&args.flag_manifest_path.as_ref().map(|s| &s[..])));
    let dep = try!(args.parse_dependency());

    manifest.insert_into_table(&args.get_section(), &dep)
            .map_err(From::from)
            .and_then(|_| {
                let mut file = try!(Manifest::find_file(&args.flag_manifest_path
                                                             .as_ref()
                                                             .map(|s| &s[..])));
                manifest.write_to_file(&mut file)
            })
            .or_else(|err| {
                println!("Could not edit `Cargo.toml`.\n\nERROR: {}", err);
                Err(err)
            })
}

fn main() {
    let args = docopt::Docopt::new(USAGE)
                   .and_then(|d| d.decode::<Args>())
                   .unwrap_or_else(|err| err.exit());

    if args.flag_version {
        println!("cargo-add version {}", env!("CARGO_PKG_VERSION"));
        process::exit(0);
    }

    if let Err(err) = handle_add(&args) {
        write!(io::stderr(),
               "Command failed due to unhandled error: {}",
               err)
            .unwrap();
        process::exit(1);
    }
}
<|endoftext|>


<commit_before>use cairo;

use librsvg::{
    CairoRenderer, DefsLookupErrorKind, HrefError, IntrinsicDimensions, Length, LengthUnit,
    RenderingError,
};

mod utils;

use self::utils::load_svg;

#[test]
fn no_intrinsic_dimensions() {
    let svg = load_svg(
        br#"<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg"/>
"#,
    );

    assert_eq!(
        CairoRenderer::new(&svg).intrinsic_dimensions(),
        IntrinsicDimensions {
            width: None,
            height: None,
            vbox: None,
        }
    );
}

#[test]
fn has_intrinsic_dimensions() {
    let svg = load_svg(
        br#"<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="10cm" height="20" viewBox="0 0 100 200"/>
"#,
    );

    assert_eq!(
        CairoRenderer::new(&svg).intrinsic_dimensions(),
        IntrinsicDimensions {
            width: Some(Length::new(10.0, LengthUnit::Cm)),
            height: Some(Length::new(20.0, LengthUnit::Px)),
            vbox: Some(cairo::Rectangle {
                x: 0.0,
                y: 0.0,
                width: 100.0,
                height: 200.0,
            }),
        }
    );
}

#[test]
fn root_geometry_with_percent_viewport() {
    let svg = load_svg(
        br#"<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%">
  <rect x="10" y="20" width="30" height="40"/>
</svg>
"#,
    );

    let renderer = CairoRenderer::new(&svg);

    let viewport = cairo::Rectangle {
        x: 0.0,
        y: 0.0,
        width: 100.0,
        height: 100.0,
    };

    let (ink_r, logical_r) = renderer.geometry_for_layer(None, &viewport).unwrap();

    let rect = cairo::Rectangle {
        x: 10.0,
        y: 20.0,
        width: 30.0,
        height: 40.0,
    };

    assert_eq!((ink_r, logical_r), (rect, rect));
}

#[cfg(ignore)]
#[test]
fn root_geometry_with_percent_viewport_with_offset() {
    let svg = load_svg(
        br#"<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%">
  <rect x="10" y="20" width="30" height="40"/>
</svg>
"#,
    );

    let renderer = CairoRenderer::new(&svg);

    let viewport = cairo::Rectangle {
        x: 100.0,
        y: 100.0,
        width: 100.0,
        height: 100.0,
    };

    let (ink_r, logical_r) = renderer.geometry_for_layer(None, &viewport).unwrap();

    let rect = cairo::Rectangle {
        x: 110.0,
        y: 120.0,
        width: 30.0,
        height: 40.0,
    };

    assert_eq!((ink_r, logical_r), (rect, rect));
}

#[test]
fn layer_geometry_with_percent_viewport() {
    let svg = load_svg(
        br#"<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%">
  <rect id="foo" x="10" y="20" width="30" height="40"/>
</svg>
"#,
    );

    let renderer = CairoRenderer::new(&svg);

    let viewport = cairo::Rectangle {
        x: 0.0,
        y: 0.0,
        width: 100.0,
        height: 100.0,
    };

    let (ink_r, logical_r) = renderer
        .geometry_for_layer(Some("#foo"), &viewport)
        .unwrap();

    let rect = cairo::Rectangle {
        x: 10.0,
        y: 20.0,
        width: 30.0,
        height: 40.0,
    };

    assert_eq!((ink_r, logical_r), (rect, rect));
}

#[test]
fn layer_geometry_viewport_viewbox() {
    let svg = load_svg(
        br#"<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="400" viewBox="0 0 100 400">
  <rect id="one" x="0" y="0" width="100" height="200" fill="rgb(0,255,0)"/>
  <rect id="two" x="0" y="200" width="100" height="200" fill="rgb(0,0,255)"/>
</svg>
"#,
    );

    let renderer = CairoRenderer::new(&svg);

    let viewport = cairo::Rectangle {
        x: 0.0,
        y: 0.0,
        width: 100.0,
        height: 400.0,
    };

    let (ink_r, logical_r) = renderer
        .geometry_for_layer(Some("#two"), &viewport)
        .unwrap();

    let rect = cairo::Rectangle {
        x: 0.0,
        y: 200.0,
        width: 100.0,
        height: 200.0,
    };

    assert_eq!((ink_r, logical_r), (rect, rect));
}

#[test]
fn layer_geometry_for_nonexistent_element() {
    let svg = load_svg(
        br#"<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%"/>
"#,
    );

    let viewport = cairo::Rectangle {
        x: 0.0,
        y: 0.0,
        width: 100.0,
        height: 100.0,
    };

    let renderer = CairoRenderer::new(&svg);

    match renderer.geometry_for_layer(Some("#foo"), &viewport) {
        Err(RenderingError::InvalidId(DefsLookupErrorKind::NotFound)) => (),
        _ => panic!(),
    }
}

#[test]
fn layer_geometry_for_invalid_id() {
    let svg = load_svg(
        br#"<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%"/>
"#,
    );

    let viewport = cairo::Rectangle {
        x: 0.0,
        y: 0.0,
        width: 100.0,
        height: 100.0,
    };

    let renderer = CairoRenderer::new(&svg);
    match renderer.geometry_for_layer(Some("foo"), &viewport) {
        Err(RenderingError::InvalidId(DefsLookupErrorKind::CannotLookupExternalReferences)) => (),
        _ => panic!(),
    }

    match renderer.geometry_for_layer(Some("foo.svg#foo"), &viewport) {
        Err(RenderingError::InvalidId(DefsLookupErrorKind::CannotLookupExternalReferences)) => (),
        _ => panic!(),
    }

    match renderer.geometry_for_layer(Some(""), &viewport) {
        Err(RenderingError::InvalidId(DefsLookupErrorKind::HrefError(HrefError::ParseError))) => (),
        _ => panic!(),
    }
}
<commit_msg>Give a better name to the failing test and adjust it<commit_after>use cairo;

use librsvg::{
    CairoRenderer, DefsLookupErrorKind, HrefError, IntrinsicDimensions, Length, LengthUnit,
    RenderingError,
};

mod utils;

use self::utils::load_svg;

#[test]
fn no_intrinsic_dimensions() {
    let svg = load_svg(
        br#"<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg"/>
"#,
    );

    assert_eq!(
        CairoRenderer::new(&svg).intrinsic_dimensions(),
        IntrinsicDimensions {
            width: None,
            height: None,
            vbox: None,
        }
    );
}

#[test]
fn has_intrinsic_dimensions() {
    let svg = load_svg(
        br#"<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="10cm" height="20" viewBox="0 0 100 200"/>
"#,
    );

    assert_eq!(
        CairoRenderer::new(&svg).intrinsic_dimensions(),
        IntrinsicDimensions {
            width: Some(Length::new(10.0, LengthUnit::Cm)),
            height: Some(Length::new(20.0, LengthUnit::Px)),
            vbox: Some(cairo::Rectangle {
                x: 0.0,
                y: 0.0,
                width: 100.0,
                height: 200.0,
            }),
        }
    );
}

#[test]
fn root_geometry_with_percent_viewport() {
    let svg = load_svg(
        br#"<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%">
  <rect x="10" y="20" width="30" height="40"/>
</svg>
"#,
    );

    let renderer = CairoRenderer::new(&svg);

    let viewport = cairo::Rectangle {
        x: 0.0,
        y: 0.0,
        width: 100.0,
        height: 100.0,
    };

    let (ink_r, logical_r) = renderer.geometry_for_layer(None, &viewport).unwrap();

    let rect = cairo::Rectangle {
        x: 10.0,
        y: 20.0,
        width: 30.0,
        height: 40.0,
    };

    assert_eq!((ink_r, logical_r), (rect, rect));
}

#[cfg(ignore)]
#[test]
fn layer_geometry_with_offset_viewport() {
    let svg = load_svg(
        br#"<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100">
  <rect x="10" y="20" width="30" height="40"/>
</svg>
"#,
    );

    let renderer = CairoRenderer::new(&svg);

    let viewport = cairo::Rectangle {
        x: 100.0,
        y: 100.0,
        width: 100.0,
        height: 100.0,
    };

    let (ink_r, logical_r) = renderer.geometry_for_layer(None, &viewport).unwrap();

    let rect = cairo::Rectangle {
        x: 110.0,
        y: 120.0,
        width: 30.0,
        height: 40.0,
    };

    assert_eq!((ink_r, logical_r), (rect, rect));
}

#[test]
fn layer_geometry_with_percent_viewport() {
    let svg = load_svg(
        br#"<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%">
  <rect id="foo" x="10" y="20" width="30" height="40"/>
</svg>
"#,
    );

    let renderer = CairoRenderer::new(&svg);

    let viewport = cairo::Rectangle {
        x: 0.0,
        y: 0.0,
        width: 100.0,
        height: 100.0,
    };

    let (ink_r, logical_r) = renderer
        .geometry_for_layer(Some("#foo"), &viewport)
        .unwrap();

    let rect = cairo::Rectangle {
        x: 10.0,
        y: 20.0,
        width: 30.0,
        height: 40.0,
    };

    assert_eq!((ink_r, logical_r), (rect, rect));
}

#[test]
fn layer_geometry_viewport_viewbox() {
    let svg = load_svg(
        br#"<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="400" viewBox="0 0 100 400">
  <rect id="one" x="0" y="0" width="100" height="200" fill="rgb(0,255,0)"/>
  <rect id="two" x="0" y="200" width="100" height="200" fill="rgb(0,0,255)"/>
</svg>
"#,
    );

    let renderer = CairoRenderer::new(&svg);

    let viewport = cairo::Rectangle {
        x: 0.0,
        y: 0.0,
        width: 100.0,
        height: 400.0,
    };

    let (ink_r, logical_r) = renderer
        .geometry_for_layer(Some("#two"), &viewport)
        .unwrap();

    let rect = cairo::Rectangle {
        x: 0.0,
        y: 200.0,
        width: 100.0,
        height: 200.0,
    };

    assert_eq!((ink_r, logical_r), (rect, rect));
}

#[test]
fn layer_geometry_for_nonexistent_element() {
    let svg = load_svg(
        br#"<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%"/>
"#,
    );

    let viewport = cairo::Rectangle {
        x: 0.0,
        y: 0.0,
        width: 100.0,
        height: 100.0,
    };

    let renderer = CairoRenderer::new(&svg);

    match renderer.geometry_for_layer(Some("#foo"), &viewport) {
        Err(RenderingError::InvalidId(DefsLookupErrorKind::NotFound)) => (),
        _ => panic!(),
    }
}

#[test]
fn layer_geometry_for_invalid_id() {
    let svg = load_svg(
        br#"<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%"/>
"#,
    );

    let viewport = cairo::Rectangle {
        x: 0.0,
        y: 0.0,
        width: 100.0,
        height: 100.0,
    };

    let renderer = CairoRenderer::new(&svg);
    match renderer.geometry_for_layer(Some("foo"), &viewport) {
        Err(RenderingError::InvalidId(DefsLookupErrorKind::CannotLookupExternalReferences)) => (),
        _ => panic!(),
    }

    match renderer.geometry_for_layer(Some("foo.svg#foo"), &viewport) {
        Err(RenderingError::InvalidId(DefsLookupErrorKind::CannotLookupExternalReferences)) => (),
        _ => panic!(),
    }

    match renderer.geometry_for_layer(Some(""), &viewport) {
        Err(RenderingError::InvalidId(DefsLookupErrorKind::HrefError(HrefError::ParseError))) => (),
        _ => panic!(),
    }
}
<|endoftext|>


<commit_before>extern crate feldspar;
extern crate typed_arena;

use feldspar::bytecode::Inst;
use feldspar::check::Check;
use feldspar::check;
use feldspar::codegen::Codegen;
use feldspar::lex::Lexer;
use feldspar::parse;
use feldspar::thread::Thread;
use feldspar::value::GC;
use std::collections::HashMap;
use std::env;
use std::error::Error;
use std::fs::File;
use std::io::{Read, Write};
use std::io;
use std::process;
use typed_arena::Arena;

struct AnyError(String);

impl From<io::Error> for AnyError {
  fn from(other: io::Error) -> Self {
    AnyError(other.description().to_string())
  }
}

impl From<parse::Error> for AnyError {
  fn from(other: parse::Error) -> Self {
    AnyError(other.1.to_string())
  }
}

fn main() {
  unsafe {
    main_();
  }
}

unsafe fn main_() {
  if let Err(err) = main__() {
    let _ = writeln!(io::stderr(), "feldspar: {}", err.0);
    process::exit(1);
  }
}

unsafe fn main__() -> Result<(), AnyError>{
  let args: Vec<_> = env::args().collect();
  if args.len() < 2 {
    usage(&mut io::stderr())?;
    process::exit(1);
  }

  let mut source = String::new();
  File::open(&args[1])?.read_to_string(&mut source)?;

  let expr_arena = Arena::new();
  let mut lexer = Lexer::new(&source);
  let expr = parse::read_expr(&expr_arena, &mut lexer)?;
  println!("{:?}", expr);

  let type_arena = Arena::new();
  let mut check = Check::new(&type_arena);
  let ty = check.infer(&HashMap::new(), &expr).map_err(|err| {
    AnyError(match err {
      check::Error::Unify(a, b) =>
        "cannot unify type\n  ".to_string() +
        &a.pretty_string(&|t| check.purge(t)) +
        "\nwith type\n  " +
        &b.pretty_string(&|t| check.purge(t)),
      check::Error::Var(name) =>
        "cannot find variable\n  ".to_string() +
        name,
    })
  })?;
  println!("{}", ty.pretty_string(&|t| check.purge(t)));

  let mut codegen = Codegen::new();
  let mut insts = vec![];
  codegen.codegen_expr(&HashMap::new(), &expr, &mut insts);
  insts.push(Inst::New(0, 0));
  insts.push(Inst::Call);
  insts.push(Inst::Return);

  let gc = GC::new();
  let mut thread = Thread::new(
    &gc,
    |id| &codegen.str(id),
    |id| &codegen.chunk(id),
    &insts,
    0,
  );

  thread.resume();

  Ok(())
}

fn usage<W>(w: &mut W) -> io::Result<()> where W: Write {
  writeln!(w, "usage: feldspar <src> [arg1 [arg2 [...]]]")
}
<commit_msg>Drop ASTs and types after compilation<commit_after>extern crate feldspar;
extern crate typed_arena;

use feldspar::bytecode::Inst;
use feldspar::check::Check;
use feldspar::check;
use feldspar::codegen::Codegen;
use feldspar::lex::Lexer;
use feldspar::parse;
use feldspar::thread::Thread;
use feldspar::value::GC;
use std::collections::HashMap;
use std::env;
use std::error::Error;
use std::fs::File;
use std::io::{Read, Write};
use std::io;
use std::process;
use typed_arena::Arena;

struct AnyError(String);

impl From<io::Error> for AnyError {
  fn from(other: io::Error) -> Self {
    AnyError(other.description().to_string())
  }
}

impl From<parse::Error> for AnyError {
  fn from(other: parse::Error) -> Self {
    AnyError(other.1.to_string())
  }
}

fn main() {
  unsafe {
    main_();
  }
}

unsafe fn main_() {
  if let Err(err) = main__() {
    let _ = writeln!(io::stderr(), "feldspar: {}", err.0);
    process::exit(1);
  }
}

unsafe fn main__() -> Result<(), AnyError>{
  let args: Vec<_> = env::args().collect();
  if args.len() < 2 {
    usage(&mut io::stderr())?;
    process::exit(1);
  }

  let mut source = String::new();
  File::open(&args[1])?.read_to_string(&mut source)?;

  let (codegen, insts) = {
    let expr_arena = Arena::new();
    let mut lexer = Lexer::new(&source);
    let expr = parse::read_expr(&expr_arena, &mut lexer)?;
    println!("{:?}", expr);

    let type_arena = Arena::new();
    let mut check = Check::new(&type_arena);
    let ty = check.infer(&HashMap::new(), &expr).map_err(|err| {
      AnyError(match err {
        check::Error::Unify(a, b) =>
          "cannot unify type\n  ".to_string() +
          &a.pretty_string(&|t| check.purge(t)) +
          "\nwith type\n  " +
          &b.pretty_string(&|t| check.purge(t)),
        check::Error::Var(name) =>
          "cannot find variable\n  ".to_string() +
          name,
      })
    })?;
    println!("{}", ty.pretty_string(&|t| check.purge(t)));

    let mut codegen = Codegen::new();
    let mut insts = vec![];
    codegen.codegen_expr(&HashMap::new(), &expr, &mut insts);
    insts.push(Inst::New(0, 0));
    insts.push(Inst::Call);
    insts.push(Inst::Return);

    (codegen, insts)
  };

  let gc = GC::new();
  let mut thread = Thread::new(
    &gc,
    |id| &codegen.str(id),
    |id| &codegen.chunk(id),
    &insts,
    0,
  );

  thread.resume();

  Ok(())
}

fn usage<W>(w: &mut W) -> io::Result<()> where W: Write {
  writeln!(w, "usage: feldspar <src> [arg1 [arg2 [...]]]")
}
<|endoftext|>


<commit_before>extern crate "cargo-registry" as cargo_registry;
extern crate postgres;
extern crate time;

use std::os;
use std::time::Duration;
use std::rand::{StdRng, Rng};

fn main() {
    let conn = postgres::Connection::connect(env("DATABASE_URL").as_slice(),
                                             &postgres::SslMode::None).unwrap();
    {
        let tx = conn.transaction().unwrap();
        update(&tx).unwrap();
        tx.set_commit();
        tx.finish().unwrap();
    }
}

fn env(s: &str) -> String {
    match os::getenv(s) {
        Some(s) => s,
        None => panic!("must have `{}` defined", s),
    }
}

fn update(tx: &postgres::Transaction) -> postgres::Result<()> {
    for &id in [48i32, 49, 50, 51, 52, 53].iter() {
        let now = time::now_utc().to_timespec();
        let mut rng = StdRng::new().unwrap();
        let mut dls = rng.gen_range(5000i32, 10000);

        for day in range(0, 90) {
            let moment = now + Duration::days(-day);
            dls += rng.gen_range(-100, 100);
            try!(tx.execute("INSERT INTO version_downloads \
                              (version_id, downloads, counted, date, processed) \
                              VALUES ($1, $2, 0, $3, false)",
                            &[&id, &dls, &moment]));
        }
    }
    Ok(())
}
<commit_msg>Don't hardcode ids into the populate script<commit_after>// Populate a set of dummy download statistics for a specific version in the
// database.
//
// Usage:
//      cargo run --bin populate version_id1 version_id2 ...

extern crate "cargo-registry" as cargo_registry;
extern crate postgres;
extern crate time;

use std::os;
use std::time::Duration;
use std::rand::{StdRng, Rng};

fn main() {
    let conn = postgres::Connection::connect(env("DATABASE_URL").as_slice(),
                                             &postgres::SslMode::None).unwrap();
    {
        let tx = conn.transaction().unwrap();
        update(&tx).unwrap();
        tx.set_commit();
        tx.finish().unwrap();
    }
}

fn env(s: &str) -> String {
    match os::getenv(s) {
        Some(s) => s,
        None => panic!("must have `{}` defined", s),
    }
}

fn update(tx: &postgres::Transaction) -> postgres::Result<()> {
    let ids = os::args();
    let mut ids = ids.iter().skip(1).filter_map(|arg| {
        from_str::<i32>(arg.as_slice())
    });
    for id in ids {
        let now = time::now_utc().to_timespec();
        let mut rng = StdRng::new().unwrap();
        let mut dls = rng.gen_range(5000i32, 10000);

        for day in range(0, 90) {
            let moment = now + Duration::days(-day);
            dls += rng.gen_range(-100, 100);
            try!(tx.execute("INSERT INTO version_downloads \
                              (version_id, downloads, counted, date, processed) \
                              VALUES ($1, $2, 0, $3, false)",
                            &[&id, &dls, &moment]));
        }
    }
    Ok(())
}
<|endoftext|>


<commit_before>#![deny(warnings)]

extern crate coreutils;
extern crate extra;
extern crate syscall;

use std::env;
use std::fs;
use std::io::{stdout, stderr, Write};
use coreutils::ArgParser;
use extra::option::OptionalExt;

const MAN_PAGE: &'static str = /* @MANSTART{readlink} */ r#"
NAME
    readlink - read the contents of a symbolic link

SYNOPSIS
    readlink [ -h | --help ] FILE...

DESCRIPTION
    Read the contents of a symbolic link.

OPTIONS
    --help, -h
        print this message
"#; /* @MANEND */

fn main() {
    let stdout = stdout();
    let mut stdout = stdout.lock();
    let mut stderr = stderr();
    let mut parser = ArgParser::new(1)
        .add_flag(&["h", "help"]);
    parser.parse(env::args());

    if parser.found("help") {
        stdout.write_all(MAN_PAGE.as_bytes()).try(&mut stderr);
        stdout.flush().try(&mut stderr);
        return;
    }

    for path in &parser.args[0..] {
        println!("{}", fs::read_link(path).unwrap().display());
    }
}
<commit_msg>Remove unneeded 'extern crate'<commit_after>#![deny(warnings)]

extern crate coreutils;
extern crate extra;

use std::env;
use std::fs;
use std::io::{stdout, stderr, Write};
use coreutils::ArgParser;
use extra::option::OptionalExt;

const MAN_PAGE: &'static str = /* @MANSTART{readlink} */ r#"
NAME
    readlink - read the contents of a symbolic link

SYNOPSIS
    readlink [ -h | --help ] FILE...

DESCRIPTION
    Read the contents of a symbolic link.

OPTIONS
    --help, -h
        print this message
"#; /* @MANEND */

fn main() {
    let stdout = stdout();
    let mut stdout = stdout.lock();
    let mut stderr = stderr();
    let mut parser = ArgParser::new(1)
        .add_flag(&["h", "help"]);
    parser.parse(env::args());

    if parser.found("help") {
        stdout.write_all(MAN_PAGE.as_bytes()).try(&mut stderr);
        stdout.flush().try(&mut stderr);
        return;
    }

    for path in &parser.args[0..] {
        println!("{}", fs::read_link(path).unwrap().display());
    }
}
<|endoftext|>


<commit_before>use url::Url;
use url::form_urlencoded;
use hyper::Client;

use lib::{Bin, BinFeature, ManagesUrls, ManagesHtmlUrls, ManagesRawUrls, UploadsSingleFiles, HasClient, HasFeatures, PasteUrl};
use lib::Result;
use lib::error::*;
use lib::files::*;
use config::{Config, CommandLineOptions};

use std::io::Read;
use std::sync::Arc;

pub struct Sprunge {
  config: Arc<Config>,
  cli: Arc<CommandLineOptions>,
  client: Client
}

impl Sprunge {
  pub fn new(config: Arc<Config>, cli: Arc<CommandLineOptions>) -> Sprunge {
    Sprunge {
      config: config,
      cli: cli,
      client: Client::new()
    }
  }

  fn create_url(&self, id: &str) -> String {
    // sprunge has no HTTPS support
    format!("http://sprunge.us/{}", id)
  }

  fn id_from_url(&self, url: &str) -> Option<String> {
    let mut url = option!(Url::parse(url).ok());
    url.set_query(None);
    let segments = option!(url.path_segments());
    segments.last().map(|x| x.to_owned())
  }
}

impl Bin for Sprunge {
  fn name(&self) -> &str {
    "sprunge"
  }

  fn html_host(&self) -> &str {
    "sprunge.us"
  }

  fn raw_host(&self) -> &str {
    "sprunge.us"
  }
}

impl ManagesUrls for Sprunge {}

impl ManagesHtmlUrls for Sprunge {
  fn create_html_url(&self, id: &str, _: &[&str]) -> Result<Vec<PasteUrl>> {
    Ok(vec![PasteUrl::html(None, self.create_url(id))])
  }

  fn id_from_html_url(&self, url: &str) -> Option<String> {
    self.id_from_url(url)
  }
}

impl ManagesRawUrls for Sprunge {
  fn create_raw_url(&self, id: &str, _: &[&str]) -> Result<Vec<PasteUrl>> {
    Ok(vec![PasteUrl::raw(None, self.create_url(id))])
  }

  fn id_from_raw_url(&self, url: &str) -> Option<String> {
    self.id_from_url(url)
  }
}

impl HasFeatures for Sprunge {
  fn features(&self) -> Vec<BinFeature> {
    vec![BinFeature::Public, BinFeature::Anonymous]
  }
}

impl UploadsSingleFiles for Sprunge {
  fn upload_single(&self, contents: &UploadFile) -> Result<String> {
    debug!(target: "sprunge", "uploading single file");
    let mut res = self.client.post("http://sprunge.us")
      .body(&form_urlencoded::Serializer::new(String::new())
        .append_pair("sprunge", &contents.content)
        .finish())
      .send()
      .map_err(BinsError::Http)?;
    debug!(target: "sprunge", "response: {:?}", res);
    if res.status.class().default_code() != ::hyper::Ok {
      return Err(BinsError::Http(::hyper::Error::Status));
    }
    let mut content = String::new();
    res.read_to_string(&mut content).map_err(BinsError::Io)?;
    debug!(target: "sprunge", "content: {}", content);
    Ok(content.replace("\n", ""))
  }
}

impl HasClient for Sprunge {
  fn client(&self) -> &Client {
    &self.client
  }
}
<commit_msg>fix: provide proper error on bad status<commit_after>use url::Url;
use url::form_urlencoded;
use hyper::Client;

use lib::{Bin, BinFeature, ManagesUrls, ManagesHtmlUrls, ManagesRawUrls, UploadsSingleFiles, HasClient, HasFeatures, PasteUrl};
use lib::Result;
use lib::error::*;
use lib::files::*;
use config::{Config, CommandLineOptions};

use std::io::Read;
use std::sync::Arc;

pub struct Sprunge {
  config: Arc<Config>,
  cli: Arc<CommandLineOptions>,
  client: Client
}

impl Sprunge {
  pub fn new(config: Arc<Config>, cli: Arc<CommandLineOptions>) -> Sprunge {
    Sprunge {
      config: config,
      cli: cli,
      client: Client::new()
    }
  }

  fn create_url(&self, id: &str) -> String {
    // sprunge has no HTTPS support
    format!("http://sprunge.us/{}", id)
  }

  fn id_from_url(&self, url: &str) -> Option<String> {
    let mut url = option!(Url::parse(url).ok());
    url.set_query(None);
    let segments = option!(url.path_segments());
    segments.last().map(|x| x.to_owned())
  }
}

impl Bin for Sprunge {
  fn name(&self) -> &str {
    "sprunge"
  }

  fn html_host(&self) -> &str {
    "sprunge.us"
  }

  fn raw_host(&self) -> &str {
    "sprunge.us"
  }
}

impl ManagesUrls for Sprunge {}

impl ManagesHtmlUrls for Sprunge {
  fn create_html_url(&self, id: &str, _: &[&str]) -> Result<Vec<PasteUrl>> {
    Ok(vec![PasteUrl::html(None, self.create_url(id))])
  }

  fn id_from_html_url(&self, url: &str) -> Option<String> {
    self.id_from_url(url)
  }
}

impl ManagesRawUrls for Sprunge {
  fn create_raw_url(&self, id: &str, _: &[&str]) -> Result<Vec<PasteUrl>> {
    Ok(vec![PasteUrl::raw(None, self.create_url(id))])
  }

  fn id_from_raw_url(&self, url: &str) -> Option<String> {
    self.id_from_url(url)
  }
}

impl HasFeatures for Sprunge {
  fn features(&self) -> Vec<BinFeature> {
    vec![BinFeature::Public, BinFeature::Anonymous]
  }
}

impl UploadsSingleFiles for Sprunge {
  fn upload_single(&self, contents: &UploadFile) -> Result<String> {
    debug!(target: "sprunge", "uploading single file");
    let mut res = self.client.post("http://sprunge.us")
      .body(&form_urlencoded::Serializer::new(String::new())
        .append_pair("sprunge", &contents.content)
        .finish())
      .send()
      .map_err(BinsError::Http)?;
    debug!(target: "sprunge", "response: {:?}", res);
    let mut content = String::new();
    res.read_to_string(&mut content).map_err(BinsError::Io)?;
    debug!(target: "sprunge", "content: {}", content);
    if res.status.class().default_code() != ::hyper::Ok {
      debug!("bad status code");
      return Err(BinsError::InvalidStatus(res.status_raw().0, Some(content)));
    }
    Ok(content.replace("\n", ""))
  }
}

impl HasClient for Sprunge {
  fn client(&self) -> &Client {
    &self.client
  }
}
<|endoftext|>


<commit_before>use std::io;

pub static CFF_FORMAT_TAG: u32 = 0x4F54544F;

pub static FONT_HEADER_TAG: u32 = 0x68656164;
pub static FONT_HEADER_MAGIC_NUMBER: u32 = 0x5F0F3CF5;

pub static MAXIMAL_PROFILE_TAG: u32 = 0x6d617870;
pub static MAXIMAL_PROFILE_VERSION_0_5: u32 = 0x00005000;

trait Spec {
    fn read(stream: &mut io::Reader) -> io::IoResult<Self>;
}

#[inline(always)]
pub fn read<S:Spec, R: io::Reader>(stream: &mut R) -> io::IoResult<S> {
    Spec::read(stream)
}

macro_rules! read_field(
    ($stream:ident, i16) => (try!($stream.read_be_i16()));
    ($stream:ident, u16) => (try!($stream.read_be_u16()));
    ($stream:ident, i32) => (try!($stream.read_be_i32()));
    ($stream:ident, u32) => (try!($stream.read_be_u32()));
    ($stream:ident, f32) => ({
        let value = try!($stream.read_be_u32()) as f32;
        (value * 0.0000152587890625 * 1000.0).round() / 1000.0
    });
    ($stream:ident, i64) => (try!($stream.read_be_i64()));
)

macro_rules! implement_spec(
    ($subject:ident, $($field:ident as $class:ident,)+) => (
        impl Spec for $subject {
            fn read(stream: &mut ::std::io::Reader)
                -> ::std::io::IoResult<$subject> {

                Ok($subject {
                    $($field: read_field!(stream, $class),)+
                })
            }
        }
    )
)

macro_rules! define_spec(
    ($name:ident, $($field:ident as $class:ident,)+) => (
        #[deriving(Default, Show)]
        pub struct $name { $(pub $field: $class,)+ }
        implement_spec!($name, $($field as $class,)+)
    )
)

define_spec!(OffsetTable,
    tag           as u32,
    numTables     as u16,
    searchRange   as u16,
    entrySelector as u16,
    rangeShift    as u16,
)

define_spec!(TableRecord,
    tag      as u32,
    checkSum as u32,
    offset   as u32,
    length   as u32,
)

define_spec!(FontHeader,
    version            as f32,
    fontRevision       as f32,
    checkSumAdjustment as u32,
    magicNumber        as u32,
    flags              as u16,
    unitsPerEm         as u16,
    created            as i64,
    modified           as i64,
    xMin               as i16,
    yMin               as i16,
    xMax               as i16,
    yMax               as i16,
    macStyle           as u16,
    lowestRecPPEM      as u16,
    fontDirectionHint  as i16,
    indexToLocFormat   as i16,
    glyphDataFormat    as i16,
)

define_spec!(MaximumProfile,
    version   as u32,
    numGlyphs as u16,
)
<commit_msg>Updated the code to compile with nightly<commit_after>#![allow(non_snake_case)]

use std::io;

pub const CFF_FORMAT_TAG: u32 = 0x4F54544F;

pub const FONT_HEADER_TAG: u32 = 0x68656164;
pub const FONT_HEADER_MAGIC_NUMBER: u32 = 0x5F0F3CF5;

pub const MAXIMAL_PROFILE_TAG: u32 = 0x6d617870;
pub const MAXIMAL_PROFILE_VERSION_0_5: u32 = 0x00005000;

pub trait Spec {
    fn read(stream: &mut io::Reader) -> io::IoResult<Self>;
}

#[inline(always)]
pub fn read<S: Spec, R: io::Reader>(stream: &mut R) -> io::IoResult<S> {
    Spec::read(stream)
}

macro_rules! read_field(
    ($stream:ident, i16) => (try!($stream.read_be_i16()));
    ($stream:ident, u16) => (try!($stream.read_be_u16()));
    ($stream:ident, i32) => (try!($stream.read_be_i32()));
    ($stream:ident, u32) => (try!($stream.read_be_u32()));
    ($stream:ident, f32) => ({
        let value = try!($stream.read_be_u32()) as f32;
        (value * 0.0000152587890625 * 1000.0).round() / 1000.0
    });
    ($stream:ident, i64) => (try!($stream.read_be_i64()));
)

macro_rules! implement_spec(
    ($subject:ident, $($field:ident as $class:ident,)+) => (
        impl Spec for $subject {
            fn read(stream: &mut ::std::io::Reader)
                -> ::std::io::IoResult<$subject> {

                Ok($subject {
                    $($field: read_field!(stream, $class),)+
                })
            }
        }
    )
)

macro_rules! define_spec(
    ($name:ident, $($field:ident as $class:ident,)+) => (
        #[deriving(Default, Show)]
        pub struct $name { $(pub $field: $class,)+ }
        implement_spec!($name, $($field as $class,)+)
    )
)

define_spec!(OffsetTable,
    tag           as u32,
    numTables     as u16,
    searchRange   as u16,
    entrySelector as u16,
    rangeShift    as u16,
)

define_spec!(TableRecord,
    tag      as u32,
    checkSum as u32,
    offset   as u32,
    length   as u32,
)

define_spec!(FontHeader,
    version            as f32,
    fontRevision       as f32,
    checkSumAdjustment as u32,
    magicNumber        as u32,
    flags              as u16,
    unitsPerEm         as u16,
    created            as i64,
    modified           as i64,
    xMin               as i16,
    yMin               as i16,
    xMax               as i16,
    yMax               as i16,
    macStyle           as u16,
    lowestRecPPEM      as u16,
    fontDirectionHint  as i16,
    indexToLocFormat   as i16,
    glyphDataFormat    as i16,
)

define_spec!(MaximumProfile,
    version   as u32,
    numGlyphs as u16,
)
<|endoftext|>


<commit_before>//! Repo branches interface
//!
//! For more information, visit the official
//! [Github docs](https://developer.github.com/v3/repos/branches/)
extern crate futures;
extern crate serde_json;

use hyper::Method;
use hyper::client::Connect;
use futures::future;

use {/*Iter,*/ Github, Future, Stream, streamed};

fn identity<T>(x: T) -> T {
    x
}

/// reference to gists associated with a github user
pub struct Branches<C>
where
    C: Clone + Connect,
{
    github: Github<C>,
    owner: String,
    repo: String,
}

impl<C: Clone + Connect> Branches<C> {
    #[doc(hidden)]
    pub fn new<U, R>(github: Github<C>, owner: U, repo: R) -> Self
    where
        U: Into<String>,
        R: Into<String>,
    {
        Branches {
            github: github,
            owner: owner.into(),
            repo: repo.into(),
        }
    }

    /// list of branches for this repo
    pub fn list(&self) -> Future<Vec<Branch>> {
        self.github.get(&format!(
            "/repos/{owner}/{repo}/branches",
            owner = self.owner,
            repo = self.repo
        ))
    }

    /// provides an stream over branches for this repo
    pub fn iter(&self) -> Stream<Branch> {
        streamed(
            self.github.clone(),
            self.github.request(
                Method::Get,
                format!(
                    "{host}/repos/{owner}/{repo}/branches",
                    host = self.github.host.clone(),
                    owner = self.owner,
                    repo = self.repo
                ),
                Default::default(),
                Default::default(),
            ),
            identity,
        )
    }

    /// gets a branch for this repo by name
    pub fn get<B>(&self, branch: B) -> Future<Branch>
    where
        B: Into<String>,
    {
        self.github.get(&format!(
            "/repos/{owner}/{repo}/branches/{branch}",
            owner = self.owner,
            repo = self.repo,
            branch = branch.into()
        ))
    }

    /// update branch production for a given branch
    ///
    /// https://developer.github.com/v3/repos/branches/#update-branch-protection
    pub fn protection<B>(&self, branch: B, pro: &Protection) -> Future<ProtectionState>
    where
        B: Into<String>,
    {
        let bytes = match serde_json::to_vec(&pro) {
            Ok(data) => data,
            Err(err) => return Box::new(future::err(err.into())),
        };
        self.github.put(
            &format!(
                "/repos/{owner}/{repo}/branches/{branch}/protection",
                owner = self.owner,
                repo = self.repo,
                branch = branch.into()
            ),
            bytes,
        )
    }
}

// representations

#[derive(Debug, Deserialize)]
pub struct Branch {
    pub name: String,
    pub protected: Option<bool>,
    pub protection_url: Option<String>,
    // todo: commit ref
}

#[derive(Debug, Deserialize, Serialize)]
pub struct ProtectionState {
    pub required_status_checks: Option<StatusChecks>,
    pub enforce_admins: Option<EnforceAdmins>,
    //pub required_pull_request_reviews: Option<RequiredPullRequestReviews>,
    //pub restrictions: Option<Restrictions>,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct EnforceAdmins {
    pub url: String,
    pub enabled: bool,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct Protection {
    pub required_status_checks: Option<StatusChecks>,
    pub enforce_admins: bool,
    pub required_pull_request_reviews: Option<RequiredPullRequestReviews>,
    pub restrictions: Option<Restrictions>,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct Restrictions {
    pub users: Vec<String>,
    pub teams: Vec<String>,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct RequiredPullRequestReviews {
    pub dismissal_restrictions: Restrictions,
    pub dismiss_stale_reviews: bool,
    pub require_code_owner_reviews: bool,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct StatusChecks {
    pub strict: bool,
    pub contexts: Vec<String>,
}
<commit_msg>use macro<commit_after>//! Repo branches interface
//!
//! For more information, visit the official
//! [Github docs](https://developer.github.com/v3/repos/branches/)
extern crate futures;
extern crate serde_json;

use hyper::Method;
use hyper::client::Connect;
use futures::future;

use {/*Iter,*/ Github, Future, Stream, streamed};

fn identity<T>(x: T) -> T {
    x
}

/// reference to gists associated with a github user
pub struct Branches<C>
where
    C: Clone + Connect,
{
    github: Github<C>,
    owner: String,
    repo: String,
}

impl<C: Clone + Connect> Branches<C> {
    #[doc(hidden)]
    pub fn new<U, R>(github: Github<C>, owner: U, repo: R) -> Self
    where
        U: Into<String>,
        R: Into<String>,
    {
        Branches {
            github: github,
            owner: owner.into(),
            repo: repo.into(),
        }
    }

    /// list of branches for this repo
    pub fn list(&self) -> Future<Vec<Branch>> {
        self.github.get(&format!(
            "/repos/{owner}/{repo}/branches",
            owner = self.owner,
            repo = self.repo
        ))
    }

    /// provides an stream over branches for this repo
    pub fn iter(&self) -> Stream<Branch> {
        streamed(
            self.github.clone(),
            self.github.request(
                Method::Get,
                format!(
                    "{host}/repos/{owner}/{repo}/branches",
                    host = self.github.host.clone(),
                    owner = self.owner,
                    repo = self.repo
                ),
                Default::default(),
                Default::default(),
            ),
            identity,
        )
    }

    /// gets a branch for this repo by name
    pub fn get<B>(&self, branch: B) -> Future<Branch>
    where
        B: Into<String>,
    {
        self.github.get(&format!(
            "/repos/{owner}/{repo}/branches/{branch}",
            owner = self.owner,
            repo = self.repo,
            branch = branch.into()
        ))
    }

    /// update branch production for a given branch
    ///
    /// https://developer.github.com/v3/repos/branches/#update-branch-protection
    pub fn protection<B>(&self, branch: B, pro: &Protection) -> Future<ProtectionState>
    where
        B: Into<String>,
    {
        self.github.put(
            &format!(
                "/repos/{owner}/{repo}/branches/{branch}/protection",
                owner = self.owner,
                repo = self.repo,
                branch = branch.into()
            ),
            json!(pro),
        )
    }
}

// representations

#[derive(Debug, Deserialize)]
pub struct Branch {
    pub name: String,
    pub protected: Option<bool>,
    pub protection_url: Option<String>,
    // todo: commit ref
}

#[derive(Debug, Deserialize, Serialize)]
pub struct ProtectionState {
    pub required_status_checks: Option<StatusChecks>,
    pub enforce_admins: Option<EnforceAdmins>,
    //pub required_pull_request_reviews: Option<RequiredPullRequestReviews>,
    //pub restrictions: Option<Restrictions>,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct EnforceAdmins {
    pub url: String,
    pub enabled: bool,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct Protection {
    pub required_status_checks: Option<StatusChecks>,
    pub enforce_admins: bool,
    pub required_pull_request_reviews: Option<RequiredPullRequestReviews>,
    pub restrictions: Option<Restrictions>,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct Restrictions {
    pub users: Vec<String>,
    pub teams: Vec<String>,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct RequiredPullRequestReviews {
    pub dismissal_restrictions: Restrictions,
    pub dismiss_stale_reviews: bool,
    pub require_code_owner_reviews: bool,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct StatusChecks {
    pub strict: bool,
    pub contexts: Vec<String>,
}
<|endoftext|>


<commit_before>#[macro_use] extern crate html5ever_atoms;
extern crate html5ever;
extern crate orbclient;
extern crate orbfont;
extern crate tendril;

use std::{cmp, env, str};
use std::iter::repeat;
use std::default::Default;
use std::fs::File;
use std::io::{stderr, Read, Write};
use std::net::TcpStream;
use std::string::String;

use html5ever::parse_document;
use html5ever::rcdom::{Document, Doctype, Text, Comment, Element, RcDom, Handle};
use orbclient::{Color, Window, EventOption, K_ESC, K_DOWN, K_UP};
use orbfont::Font;
use tendril::TendrilSink;

#[derive(Clone, Debug)]
struct Url {
    scheme: String,
    host: String,
    port: u16,
    path: Vec<String>
}

impl Url {
    fn new(url: &str) -> Url {
        let (scheme, reference) = url.split_at(url.find(':').unwrap_or(0));

        let mut parts = reference.split('/').skip(2); //skip first two slashes
        let remote = parts.next().unwrap_or("");
        let mut remote_parts = remote.split(':');
        let host = remote_parts.next().unwrap_or("");
        let port = remote_parts.next().unwrap_or("").parse::<u16>().unwrap_or(80);

        let mut path = Vec::new();
        for part in parts {
            path.push(part.to_string());
        }

        Url {
            scheme: scheme.to_string(),
            host: host.to_string(),
            port: port,
            path: path
        }
    }
}

struct Block<'a> {
    x: i32,
    y: i32,
    w: i32,
    h: i32,
    color: Color,
    string: String,
    link: Option<String>,
    text: orbfont::Text<'a>
}

impl<'a> Block<'a> {
    fn contains(&self, m_x: i32, m_y: i32, offset: i32) -> bool {
        let x = self.x;
        let y = self.y - offset;

        m_x >= x && m_x < x + self.w && m_y >= y && m_y < y + self.h
    }

    fn draw(&self, window: &mut Window, offset: i32) {
        let x = self.x;
        let y = self.y - offset;
        if x + self.w > 0 && x < window.width() as i32 && y + self.h > 0 && y < window.height() as i32 {
            self.text.draw(window, x, y, self.color);
        }
    }
}

fn walk<'a>(handle: Handle, indent: usize, x: &mut i32, y: &mut i32, mut size: f32, mut bold: bool, mut color: Color, mut ignore: bool, whitespace: &mut bool, mut link: Option<String>, font: &'a Font, font_bold: &'a Font, blocks: &mut Vec<Block<'a>>) {
    let node = handle.borrow();

    let mut new_line = false;

    print!("{}", repeat(" ").take(indent).collect::<String>());
    match node.node {
        Document
            => {
                println!("#Document")
            },

        Doctype(ref name, ref public, ref system)
            => {
                println!("<!DOCTYPE {} \"{}\" \"{}\">", *name, *public, *system);
            },

        Text(ref text)
            => {
                let mut block_text = String::new();

                for c in text.chars() {
                    match c {
                        ' ' | '\n' | '\r' => if *whitespace {
                            // Ignore
                        } else {
                            // Set whitespace
                            *whitespace = true;
                            block_text.push(' ');
                        },
                        _ => {
                            if *whitespace {
                                *whitespace = false;
                            }
                            block_text.push(c);
                        }
                    }
                }

                if ! block_text.is_empty() {
                    if ignore {
                        println!("#text: ignored");
                    } else {
                        let trimmed_left = block_text.trim_left();
                        let left_margin = block_text.len() as i32 - trimmed_left.len() as i32;
                        let trimmed_right = trimmed_left.trim_right();
                        let right_margin = trimmed_left.len() as i32 - trimmed_right.len() as i32;

                        let escaped_text = escape_default(&trimmed_right);
                        println!("#text: block {} at {}, {}: '{}'", blocks.len(), *x, *y, escaped_text);

                        *x += left_margin * 8;

                        for (word_i, word) in trimmed_right.split(' ').enumerate() {
                            if word_i > 0 {
                                *x += 8;
                            }

                            let text = if bold {
                                font_bold.render(word, size)
                            } else {
                                font.render(word, size)
                            };

                            let w = text.width() as i32;
                            let h = text.height() as i32;

                            if *x + w >= 640 && *x > 0 {
                                *x = 0;
                                *y += size.ceil() as i32;
                            }

                            blocks.push(Block {
                                x: *x,
                                y: *y,
                                w: w,
                                h: h,
                                color: color,
                                string: word.to_string(),
                                link: link.clone(),
                                text: text
                            });

                            *x += w;
                        }

                        *x += right_margin * 8;
                    }
                } else {
                    println!("#text: empty");
                }
            },

        Comment(ref text)
            => {
                println!("<!-- {} -->", escape_default(text))
            },

        Element(ref name, _, ref attrs) => {
            assert!(name.ns == ns!(html));
            print!("<{}", name.local);
            for attr in attrs.iter() {
                assert!(attr.name.ns == ns!());
                print!(" {}=\"{}\"", attr.name.local, attr.value);
            }
            println!(">");

            match &*name.local {
                "a" => {
                    color = Color::rgb(0, 0, 255);
                    for attr in attrs.iter() {
                        match &*attr.name.local {
                            "href" => link = Some(attr.value.to_string()),
                            _ => ()
                        }
                    }
                },
                "b" => {
                    bold = true;
                },
                "br" => {
                    ignore = true;
                    new_line = true;
                },
                "div" => {
                    new_line = true;
                },
                "h1" => {
                    size = 32.0;
                    bold = true;
                    new_line = true;
                },
                "h2" => {
                    size = 24.0;
                    bold = true;
                    new_line = true;
                },
                "h3" => {
                    size = 18.0;
                    bold = true;
                    new_line = true;
                }
                "h4" => {
                    size = 16.0;
                    bold = true;
                    new_line = true;
                }
                "h5" => {
                    size = 14.0;
                    bold = true;
                    new_line = true;
                }
                "h6" => {
                    size = 10.0;
                    bold = true;
                    new_line = true;
                },
                "hr" => {
                    new_line = true;
                },
                "li" => {
                    new_line = true;
                },
                "p" => {
                    new_line = true;
                },

                "head" => ignore = true,
                "title" => ignore = true, //TODO: Grab title
                "link" => ignore = true,
                "meta" => ignore = true,
                "script" => ignore = true,
                "style" => ignore = true,
                _ => ()
            }
        }
    }

    for child in node.children.iter() {
        walk(child.clone(), indent + 4, x, y, size, bold, color, ignore, whitespace, link.clone(), font, font_bold, blocks);
    }

    if new_line {
        *whitespace = true;
        *x = 0;
        *y += size.ceil() as i32;
    }
}

// FIXME: Copy of str::escape_default from std, which is currently unstable
pub fn escape_default(s: &str) -> String {
    s.chars().flat_map(|c| c.escape_default()).collect()
}

fn read_blocks<'a, R: Read>(r: &mut R, font: &'a Font, font_bold: &'a Font) -> Vec<Block<'a>> {
    let mut blocks = vec![];

    let dom = parse_document(RcDom::default(), Default::default())
        .from_utf8()
        .read_from(r)
        .unwrap();

    let mut x = 0;
    let mut y = 0;
    let mut whitespace = false;
    walk(dom.document, 0, &mut x, &mut y, 16.0, false, Color::rgb(0, 0, 0), false, &mut whitespace, None, font, font_bold, &mut blocks);

    if !dom.errors.is_empty() {
        /*
        println!("\nParse errors:");
        for err in dom.errors.into_iter() {
            println!("    {}", err);
        }
        */
    }

    blocks
}

fn file_blocks<'a>(url: &Url, font: &'a Font, font_bold: &'a Font) -> Vec<Block<'a>> {
    let mut parts = url.path.iter();
    let mut path = parts.next().map_or(String::new(), |s| s.clone());
    for part in parts {
        path.push('/');
        path.push_str(part);
    }

    if let Ok(mut file) = File::open(&path) {
        read_blocks(&mut file, &font, &font_bold)
    } else {
        vec![]
    }
}

fn http_blocks<'a>(url: &Url, font: &'a Font, font_bold: &'a Font) -> Vec<Block<'a>> {
    let mut parts = url.path.iter();
    let mut path = parts.next().map_or(String::new(), |s| s.clone());
    for part in parts {
        path.push('/');
        path.push_str(part);
    }

    write!(stderr(), "* Connecting to {}:{}\n", url.host, url.port).unwrap();

    let mut stream = TcpStream::connect((url.host.as_str(), url.port)).unwrap();

    write!(stderr(), "* Requesting {}\n", path).unwrap();

    let request = format!("GET /{} HTTP/1.1\r\nHost: {}\r\nConnection: close\r\n\r\n", path, url.host);
    stream.write(request.as_bytes()).unwrap();
    stream.flush().unwrap();

    write!(stderr(), "* Waiting for response\n").unwrap();

    let mut response = Vec::new();

    loop {
        let mut buf = [0; 65536];
        let count = stream.read(&mut buf).unwrap();
        if count == 0 {
            break;
        }
        response.extend_from_slice(&buf[.. count]);
    }

    write!(stderr(), "* Received {} bytes\n", response.len()).unwrap();

    let mut header_end = 0;
    while header_end < response.len() {
        if response[header_end..].starts_with(b"\r\n\r\n") {
            break;
        }
        header_end += 1;
    }

    for line in unsafe { str::from_utf8_unchecked(&response[..header_end]) }.lines() {
        write!(stderr(), "> {}\n", line).unwrap();
    }

    read_blocks(&mut &response[header_end + 4 ..], font, font_bold)
}

fn url_blocks<'a>(url: &Url, font: &'a Font, font_bold: &'a Font) -> Vec<Block<'a>> {
    if url.scheme == "http" {
        http_blocks(url, font, font_bold)
    } else if url.scheme == "file" || url.scheme.is_empty() {
        file_blocks(url, font, font_bold)
    } else {
        vec![]
    }
}

fn main_window(arg: &str, font: &Font, font_bold: &Font) {
    let mut url = Url::new(arg);

    let mut window = Window::new(-1, -1, 640, 480,  &format!("Browser ({})", arg)).unwrap();

    let mut blocks = url_blocks(&url, &font, &font_bold);

    let mut offset = 0;
    let mut max_offset = 0;
    for block in blocks.iter() {
        if block.y + block.h > max_offset {
            max_offset = block.y + block.h;
        }
    }

    let mut mouse_down = false;

    let mut redraw = true;
    loop {
        if redraw {
            redraw = false;

            window.set(Color::rgb(255, 255, 255));

            for block in blocks.iter() {
                block.draw(&mut window, offset);
            }

            window.sync();
        }

        for event in window.events() {
            match event.to_option() {
                EventOption::Key(key_event) => if key_event.pressed {
                    match key_event.scancode {
                        K_ESC => return,
                        K_UP => {
                            redraw = true;
                            offset = cmp::max(0, offset - 128);
                        },
                        K_DOWN => {
                            redraw = true;
                            offset = cmp::min(max_offset, offset + 128);
                        },
                        _ => ()
                    }
                },
                EventOption::Mouse(mouse_event) => if mouse_event.left_button {
                    mouse_down = true;
                } else if mouse_down {
                    mouse_down = false;

                    let mut link_opt = None;
                    for block in blocks.iter() {
                        if block.contains(mouse_event.x, mouse_event.y, offset) {
                            println!("Click {}", block.string);
                            if let Some(ref link) = block.link {
                                link_opt = Some(link.clone());
                                break;
                            }
                        }
                    }

                    if let Some(link) = link_opt {
                        if link.starts_with('#') {
                            println!("Find anchor {}", link);
                        } else {
                            if link.find(':').is_some() {
                                url = Url::new(&link);
                            } else if link.starts_with('/') {
                                url.path.clear();
                                for part in link[1..].split('/') {
                                    url.path.push(part.to_string());
                                }
                            } else {
                                url.path.push(link.clone());
                            };

                            println!("Navigate {}: {:#?}", link, url);

                            blocks = url_blocks(&url, &font, &font_bold);

                            offset = 0;
                            max_offset = 0;
                            for block in blocks.iter() {
                                if block.y + block.h > max_offset {
                                    max_offset = block.y + block.h;
                                }
                            }

                            redraw = true;
                        }
                    }
                },
                EventOption::Quit(_) => return,
                _ => ()
            }
        }
    }
}

fn main() {
    let err_window = |msg: &str| {
        let mut window = Window::new(-1, -1, 320, 32, "Browser").unwrap();

        window.set(Color::rgb(0, 0, 0));

        let mut x = 0;
        for c in msg.chars() {
            window.char(x, 0, c, Color::rgb(255, 255, 255));
            x += 8;
        }

        window.sync();

        loop {
            for event in window.events() {
                if let EventOption::Key(key_event) = event.to_option() {
                    if key_event.pressed && key_event.scancode == K_ESC {
                        return;
                    }
                }
                if let EventOption::Quit(_) = event.to_option() {
                    return;
                }
            }
        }
    };

    match env::args().nth(1) {
        Some(path) => match Font::find(None, None, None) {
            Ok(font) => match Font::find(None, None, Some("Bold")) {
                Ok(font_bold) => main_window(&path, &font, &font_bold),
                Err(err) => err_window(&format!("{}", err))
            },
            Err(err) => err_window(&format!("{}", err))
        },
        None => err_window("no file argument")
    }
}
<commit_msg>New line on tr<commit_after>#[macro_use] extern crate html5ever_atoms;
extern crate html5ever;
extern crate orbclient;
extern crate orbfont;
extern crate tendril;

use std::{cmp, env, str};
use std::iter::repeat;
use std::default::Default;
use std::fs::File;
use std::io::{stderr, Read, Write};
use std::net::TcpStream;
use std::string::String;

use html5ever::parse_document;
use html5ever::rcdom::{Document, Doctype, Text, Comment, Element, RcDom, Handle};
use orbclient::{Color, Window, EventOption, K_ESC, K_DOWN, K_UP};
use orbfont::Font;
use tendril::TendrilSink;

#[derive(Clone, Debug)]
struct Url {
    scheme: String,
    host: String,
    port: u16,
    path: Vec<String>
}

impl Url {
    fn new(url: &str) -> Url {
        let (scheme, reference) = url.split_at(url.find(':').unwrap_or(0));

        let mut parts = reference.split('/').skip(2); //skip first two slashes
        let remote = parts.next().unwrap_or("");
        let mut remote_parts = remote.split(':');
        let host = remote_parts.next().unwrap_or("");
        let port = remote_parts.next().unwrap_or("").parse::<u16>().unwrap_or(80);

        let mut path = Vec::new();
        for part in parts {
            path.push(part.to_string());
        }

        Url {
            scheme: scheme.to_string(),
            host: host.to_string(),
            port: port,
            path: path
        }
    }
}

struct Block<'a> {
    x: i32,
    y: i32,
    w: i32,
    h: i32,
    color: Color,
    string: String,
    link: Option<String>,
    text: orbfont::Text<'a>
}

impl<'a> Block<'a> {
    fn contains(&self, m_x: i32, m_y: i32, offset: i32) -> bool {
        let x = self.x;
        let y = self.y - offset;

        m_x >= x && m_x < x + self.w && m_y >= y && m_y < y + self.h
    }

    fn draw(&self, window: &mut Window, offset: i32) {
        let x = self.x;
        let y = self.y - offset;
        if x + self.w > 0 && x < window.width() as i32 && y + self.h > 0 && y < window.height() as i32 {
            self.text.draw(window, x, y, self.color);
        }
    }
}

fn walk<'a>(handle: Handle, indent: usize, x: &mut i32, y: &mut i32, mut size: f32, mut bold: bool, mut color: Color, mut ignore: bool, whitespace: &mut bool, mut link: Option<String>, font: &'a Font, font_bold: &'a Font, blocks: &mut Vec<Block<'a>>) {
    let node = handle.borrow();

    let mut new_line = false;

    print!("{}", repeat(" ").take(indent).collect::<String>());
    match node.node {
        Document
            => {
                println!("#Document")
            },

        Doctype(ref name, ref public, ref system)
            => {
                println!("<!DOCTYPE {} \"{}\" \"{}\">", *name, *public, *system);
            },

        Text(ref text)
            => {
                let mut block_text = String::new();

                for c in text.chars() {
                    match c {
                        ' ' | '\n' | '\r' => if *whitespace {
                            // Ignore
                        } else {
                            // Set whitespace
                            *whitespace = true;
                            block_text.push(' ');
                        },
                        _ => {
                            if *whitespace {
                                *whitespace = false;
                            }
                            block_text.push(c);
                        }
                    }
                }

                if ! block_text.is_empty() {
                    if ignore {
                        println!("#text: ignored");
                    } else {
                        let trimmed_left = block_text.trim_left();
                        let left_margin = block_text.len() as i32 - trimmed_left.len() as i32;
                        let trimmed_right = trimmed_left.trim_right();
                        let right_margin = trimmed_left.len() as i32 - trimmed_right.len() as i32;

                        let escaped_text = escape_default(&trimmed_right);
                        println!("#text: block {} at {}, {}: '{}'", blocks.len(), *x, *y, escaped_text);

                        *x += left_margin * 8;

                        for (word_i, word) in trimmed_right.split(' ').enumerate() {
                            if word_i > 0 {
                                *x += 8;
                            }

                            let text = if bold {
                                font_bold.render(word, size)
                            } else {
                                font.render(word, size)
                            };

                            let w = text.width() as i32;
                            let h = text.height() as i32;

                            if *x + w >= 640 && *x > 0 {
                                *x = 0;
                                *y += size.ceil() as i32;
                            }

                            blocks.push(Block {
                                x: *x,
                                y: *y,
                                w: w,
                                h: h,
                                color: color,
                                string: word.to_string(),
                                link: link.clone(),
                                text: text
                            });

                            *x += w;
                        }

                        *x += right_margin * 8;
                    }
                } else {
                    println!("#text: empty");
                }
            },

        Comment(ref text)
            => {
                println!("<!-- {} -->", escape_default(text))
            },

        Element(ref name, _, ref attrs) => {
            assert!(name.ns == ns!(html));
            print!("<{}", name.local);
            for attr in attrs.iter() {
                assert!(attr.name.ns == ns!());
                print!(" {}=\"{}\"", attr.name.local, attr.value);
            }
            println!(">");

            match &*name.local {
                "a" => {
                    color = Color::rgb(0, 0, 255);
                    for attr in attrs.iter() {
                        match &*attr.name.local {
                            "href" => link = Some(attr.value.to_string()),
                            _ => ()
                        }
                    }
                },
                "b" => {
                    bold = true;
                },
                "br" => {
                    ignore = true;
                    new_line = true;
                },
                "div" => {
                    new_line = true;
                },
                "h1" => {
                    size = 32.0;
                    bold = true;
                    new_line = true;
                },
                "h2" => {
                    size = 24.0;
                    bold = true;
                    new_line = true;
                },
                "h3" => {
                    size = 18.0;
                    bold = true;
                    new_line = true;
                }
                "h4" => {
                    size = 16.0;
                    bold = true;
                    new_line = true;
                }
                "h5" => {
                    size = 14.0;
                    bold = true;
                    new_line = true;
                }
                "h6" => {
                    size = 10.0;
                    bold = true;
                    new_line = true;
                },
                "hr" => {
                    new_line = true;
                },
                "li" => {
                    new_line = true;
                },
                "p" => {
                    new_line = true;
                },
                "tr" => {
                    new_line = true;
                }

                "head" => ignore = true,
                "title" => ignore = true, //TODO: Grab title
                "link" => ignore = true,
                "meta" => ignore = true,
                "script" => ignore = true,
                "style" => ignore = true,
                _ => ()
            }
        }
    }

    for child in node.children.iter() {
        walk(child.clone(), indent + 4, x, y, size, bold, color, ignore, whitespace, link.clone(), font, font_bold, blocks);
    }

    if new_line {
        *whitespace = true;
        *x = 0;
        *y += size.ceil() as i32;
    }
}

// FIXME: Copy of str::escape_default from std, which is currently unstable
pub fn escape_default(s: &str) -> String {
    s.chars().flat_map(|c| c.escape_default()).collect()
}

fn read_blocks<'a, R: Read>(r: &mut R, font: &'a Font, font_bold: &'a Font) -> Vec<Block<'a>> {
    let mut blocks = vec![];

    let dom = parse_document(RcDom::default(), Default::default())
        .from_utf8()
        .read_from(r)
        .unwrap();

    let mut x = 0;
    let mut y = 0;
    let mut whitespace = false;
    walk(dom.document, 0, &mut x, &mut y, 16.0, false, Color::rgb(0, 0, 0), false, &mut whitespace, None, font, font_bold, &mut blocks);

    if !dom.errors.is_empty() {
        /*
        println!("\nParse errors:");
        for err in dom.errors.into_iter() {
            println!("    {}", err);
        }
        */
    }

    blocks
}

fn file_blocks<'a>(url: &Url, font: &'a Font, font_bold: &'a Font) -> Vec<Block<'a>> {
    let mut parts = url.path.iter();
    let mut path = parts.next().map_or(String::new(), |s| s.clone());
    for part in parts {
        path.push('/');
        path.push_str(part);
    }

    if let Ok(mut file) = File::open(&path) {
        read_blocks(&mut file, &font, &font_bold)
    } else {
        vec![]
    }
}

fn http_blocks<'a>(url: &Url, font: &'a Font, font_bold: &'a Font) -> Vec<Block<'a>> {
    let mut parts = url.path.iter();
    let mut path = parts.next().map_or(String::new(), |s| s.clone());
    for part in parts {
        path.push('/');
        path.push_str(part);
    }

    write!(stderr(), "* Connecting to {}:{}\n", url.host, url.port).unwrap();

    let mut stream = TcpStream::connect((url.host.as_str(), url.port)).unwrap();

    write!(stderr(), "* Requesting {}\n", path).unwrap();

    let request = format!("GET /{} HTTP/1.1\r\nHost: {}\r\nConnection: close\r\n\r\n", path, url.host);
    stream.write(request.as_bytes()).unwrap();
    stream.flush().unwrap();

    write!(stderr(), "* Waiting for response\n").unwrap();

    let mut response = Vec::new();

    loop {
        let mut buf = [0; 65536];
        let count = stream.read(&mut buf).unwrap();
        if count == 0 {
            break;
        }
        response.extend_from_slice(&buf[.. count]);
    }

    write!(stderr(), "* Received {} bytes\n", response.len()).unwrap();

    let mut header_end = 0;
    while header_end < response.len() {
        if response[header_end..].starts_with(b"\r\n\r\n") {
            break;
        }
        header_end += 1;
    }

    for line in unsafe { str::from_utf8_unchecked(&response[..header_end]) }.lines() {
        write!(stderr(), "> {}\n", line).unwrap();
    }

    read_blocks(&mut &response[header_end + 4 ..], font, font_bold)
}

fn url_blocks<'a>(url: &Url, font: &'a Font, font_bold: &'a Font) -> Vec<Block<'a>> {
    if url.scheme == "http" {
        http_blocks(url, font, font_bold)
    } else if url.scheme == "file" || url.scheme.is_empty() {
        file_blocks(url, font, font_bold)
    } else {
        vec![]
    }
}

fn main_window(arg: &str, font: &Font, font_bold: &Font) {
    let mut url = Url::new(arg);

    let mut window = Window::new(-1, -1, 640, 480,  &format!("Browser ({})", arg)).unwrap();

    let mut blocks = url_blocks(&url, &font, &font_bold);

    let mut offset = 0;
    let mut max_offset = 0;
    for block in blocks.iter() {
        if block.y + block.h > max_offset {
            max_offset = block.y + block.h;
        }
    }

    let mut mouse_down = false;

    let mut redraw = true;
    loop {
        if redraw {
            redraw = false;

            window.set(Color::rgb(255, 255, 255));

            for block in blocks.iter() {
                block.draw(&mut window, offset);
            }

            window.sync();
        }

        for event in window.events() {
            match event.to_option() {
                EventOption::Key(key_event) => if key_event.pressed {
                    match key_event.scancode {
                        K_ESC => return,
                        K_UP => {
                            redraw = true;
                            offset = cmp::max(0, offset - 128);
                        },
                        K_DOWN => {
                            redraw = true;
                            offset = cmp::min(max_offset, offset + 128);
                        },
                        _ => ()
                    }
                },
                EventOption::Mouse(mouse_event) => if mouse_event.left_button {
                    mouse_down = true;
                } else if mouse_down {
                    mouse_down = false;

                    let mut link_opt = None;
                    for block in blocks.iter() {
                        if block.contains(mouse_event.x, mouse_event.y, offset) {
                            println!("Click {}", block.string);
                            if let Some(ref link) = block.link {
                                link_opt = Some(link.clone());
                                break;
                            }
                        }
                    }

                    if let Some(link) = link_opt {
                        if link.starts_with('#') {
                            println!("Find anchor {}", link);
                        } else {
                            if link.find(':').is_some() {
                                url = Url::new(&link);
                            } else if link.starts_with('/') {
                                url.path.clear();
                                for part in link[1..].split('/') {
                                    url.path.push(part.to_string());
                                }
                            } else {
                                url.path.push(link.clone());
                            };

                            println!("Navigate {}: {:#?}", link, url);

                            blocks = url_blocks(&url, &font, &font_bold);

                            offset = 0;
                            max_offset = 0;
                            for block in blocks.iter() {
                                if block.y + block.h > max_offset {
                                    max_offset = block.y + block.h;
                                }
                            }

                            redraw = true;
                        }
                    }
                },
                EventOption::Quit(_) => return,
                _ => ()
            }
        }
    }
}

fn main() {
    let err_window = |msg: &str| {
        let mut window = Window::new(-1, -1, 320, 32, "Browser").unwrap();

        window.set(Color::rgb(0, 0, 0));

        let mut x = 0;
        for c in msg.chars() {
            window.char(x, 0, c, Color::rgb(255, 255, 255));
            x += 8;
        }

        window.sync();

        loop {
            for event in window.events() {
                if let EventOption::Key(key_event) = event.to_option() {
                    if key_event.pressed && key_event.scancode == K_ESC {
                        return;
                    }
                }
                if let EventOption::Quit(_) = event.to_option() {
                    return;
                }
            }
        }
    };

    match env::args().nth(1) {
        Some(path) => match Font::find(None, None, None) {
            Ok(font) => match Font::find(None, None, Some("Bold")) {
                Ok(font_bold) => main_window(&path, &font, &font_bold),
                Err(err) => err_window(&format!("{}", err))
            },
            Err(err) => err_window(&format!("{}", err))
        },
        None => err_window("no file argument")
    }
}
<|endoftext|>


<commit_before>use std::mem;

use futures::{Async, Future, Poll, Stream};
use futures::future::Shared;
use futures::sync::{mpsc, oneshot};

use super::Never;

pub fn channel() -> (Signal, Watch) {
    let (tx, rx) = oneshot::channel();
    let (drained_tx, drained_rx) = mpsc::channel(0);
    (
        Signal {
            drained_rx,
            tx,
        },
        Watch {
            drained_tx,
            rx: rx.shared(),
        },
    )
}

pub struct Signal {
    drained_rx: mpsc::Receiver<Never>,
    tx: oneshot::Sender<()>,
}

pub struct Draining {
    drained_rx: mpsc::Receiver<Never>,
}

#[derive(Clone)]
pub struct Watch {
    drained_tx: mpsc::Sender<Never>,
    rx: Shared<oneshot::Receiver<()>>,
}

#[allow(missing_debug_implementations)]
pub struct Watching<F, FN> {
    future: F,
    state: State<FN>,
    watch: Watch,
}

enum State<F> {
    Watch(F),
    Draining,
}

impl Signal {
    pub fn drain(self) -> Draining {
        let _ = self.tx.send(());
        Draining {
            drained_rx: self.drained_rx,
        }
    }
}

impl Future for Draining {
    type Item = ();
    type Error = ();

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        match try_ready!(self.drained_rx.poll()) {
            Some(never) => match never {},
            None => Ok(Async::Ready(())),
        }
    }
}

impl Watch {
    pub fn watch<F, FN>(self, future: F, on_drain: FN) -> Watching<F, FN>
    where
        F: Future,
        FN: FnOnce(&mut F),
    {
        Watching {
            future,
            state: State::Watch(on_drain),
            watch: self,
        }
    }
}

impl<F, FN> Future for Watching<F, FN>
where
    F: Future,
    FN: FnOnce(&mut F),
{
    type Item = F::Item;
    type Error = F::Error;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        loop {
            match mem::replace(&mut self.state, State::Draining) {
                State::Watch(on_drain) => {
                    match self.watch.rx.poll() {
                        Ok(Async::Ready(_)) | Err(_) => {
                            // Drain has been triggered!
                            on_drain(&mut self.future);
                        },
                        Ok(Async::NotReady) => {
                            self.state = State::Watch(on_drain);
                            return self.future.poll();
                        },
                    }
                },
                State::Draining => {
                    return self.future.poll();
                },
            }
        }
    }
}

<commit_msg>test(drain): add tests for futures drain utility<commit_after>use std::mem;

use futures::{Async, Future, Poll, Stream};
use futures::future::Shared;
use futures::sync::{mpsc, oneshot};

use super::Never;

pub fn channel() -> (Signal, Watch) {
    let (tx, rx) = oneshot::channel();
    let (drained_tx, drained_rx) = mpsc::channel(0);
    (
        Signal {
            drained_rx,
            tx,
        },
        Watch {
            drained_tx,
            rx: rx.shared(),
        },
    )
}

pub struct Signal {
    drained_rx: mpsc::Receiver<Never>,
    tx: oneshot::Sender<()>,
}

pub struct Draining {
    drained_rx: mpsc::Receiver<Never>,
}

#[derive(Clone)]
pub struct Watch {
    drained_tx: mpsc::Sender<Never>,
    rx: Shared<oneshot::Receiver<()>>,
}

#[allow(missing_debug_implementations)]
pub struct Watching<F, FN> {
    future: F,
    state: State<FN>,
    watch: Watch,
}

enum State<F> {
    Watch(F),
    Draining,
}

impl Signal {
    pub fn drain(self) -> Draining {
        let _ = self.tx.send(());
        Draining {
            drained_rx: self.drained_rx,
        }
    }
}

impl Future for Draining {
    type Item = ();
    type Error = ();

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        match try_ready!(self.drained_rx.poll()) {
            Some(never) => match never {},
            None => Ok(Async::Ready(())),
        }
    }
}

impl Watch {
    pub fn watch<F, FN>(self, future: F, on_drain: FN) -> Watching<F, FN>
    where
        F: Future,
        FN: FnOnce(&mut F),
    {
        Watching {
            future,
            state: State::Watch(on_drain),
            watch: self,
        }
    }
}

impl<F, FN> Future for Watching<F, FN>
where
    F: Future,
    FN: FnOnce(&mut F),
{
    type Item = F::Item;
    type Error = F::Error;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        loop {
            match mem::replace(&mut self.state, State::Draining) {
                State::Watch(on_drain) => {
                    match self.watch.rx.poll() {
                        Ok(Async::Ready(_)) | Err(_) => {
                            // Drain has been triggered!
                            on_drain(&mut self.future);
                        },
                        Ok(Async::NotReady) => {
                            self.state = State::Watch(on_drain);
                            return self.future.poll();
                        },
                    }
                },
                State::Draining => {
                    return self.future.poll();
                },
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use futures::{future, Async, Future, Poll};
    use super::*;

    struct TestMe {
        draining: bool,
        finished: bool,
        poll_cnt: usize,
    }

    impl Future for TestMe {
        type Item = ();
        type Error = ();

        fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
            self.poll_cnt += 1;
            if self.finished {
                Ok(Async::Ready(()))
            } else {
                Ok(Async::NotReady)
            }
        }
    }

    #[test]
    fn watch() {
        future::lazy(|| {
            let (tx, rx) = channel();
            let fut = TestMe {
                draining: false,
                finished: false,
                poll_cnt: 0,
            };

            let mut watch = rx.watch(fut, |fut| {
                fut.draining = true;
            });

            assert_eq!(watch.future.poll_cnt, 0);

            // First poll should poll the inner future
            assert!(watch.poll().unwrap().is_not_ready());
            assert_eq!(watch.future.poll_cnt, 1);

            // Second poll should poll the inner future again
            assert!(watch.poll().unwrap().is_not_ready());
            assert_eq!(watch.future.poll_cnt, 2);

            let mut draining = tx.drain();
            // Drain signaled, but needs another poll to be noticed.
            assert!(!watch.future.draining);
            assert_eq!(watch.future.poll_cnt, 2);

            // Now, poll after drain has been signaled.
            assert!(watch.poll().unwrap().is_not_ready());
            assert_eq!(watch.future.poll_cnt, 3);
            assert!(watch.future.draining);

            // Draining is not ready until watcher completes
            assert!(draining.poll().unwrap().is_not_ready());

            // Finishing up the watch future
            watch.future.finished = true;
            assert!(watch.poll().unwrap().is_ready());
            assert_eq!(watch.future.poll_cnt, 4);
            drop(watch);

            assert!(draining.poll().unwrap().is_ready());

            Ok::<_, ()>(())
        }).wait().unwrap();
    }

    #[test]
    fn watch_clones() {
        future::lazy(|| {
            let (tx, rx) = channel();

            let fut1 = TestMe {
                draining: false,
                finished: false,
                poll_cnt: 0,
            };
            let fut2 = TestMe {
                draining: false,
                finished: false,
                poll_cnt: 0,
            };

            let watch1 = rx.clone().watch(fut1, |fut| {
                fut.draining = true;
            });
            let watch2 = rx.watch(fut2, |fut| {
                fut.draining = true;
            });

            let mut draining = tx.drain();

            // Still 2 outstanding watchers
            assert!(draining.poll().unwrap().is_not_ready());

            // drop 1 for whatever reason
            drop(watch1);

            // Still not ready, 1 other watcher still pending
            assert!(draining.poll().unwrap().is_not_ready());

            drop(watch2);

            // Now all watchers are gone, draining is complete
            assert!(draining.poll().unwrap().is_ready());

            Ok::<_, ()>(())
        }).wait().unwrap();
    }
}

<|endoftext|>


<commit_before>pub use self::peekable_buffer::PeekableBuffer;
pub use self::lexer::Lexer;
pub use self::token::Token;

pub mod lexer;
pub mod token;
mod peekable_buffer;
<commit_msg>Remove export modules in compiler<commit_after>pub use self::peekable_buffer::PeekableBuffer;
pub use self::lexer::Lexer;
pub use self::token::Token;

mod lexer;
mod peekable_buffer;
mod token;
<|endoftext|>


<commit_before>pub use self::peekable_buffer::PeekableBuffer;

pub mod lexer;
pub mod parser;
mod peekable_buffer;
<commit_msg>Remove partial parser work<commit_after>pub use self::peekable_buffer::PeekableBuffer;

pub mod lexer;
mod peekable_buffer;
<|endoftext|>


<commit_before>mod tree;
use std::collections::HashMap;
use parser::tree::ParseTree;

pub struct BodyParser<'a>
{
	pub variables: HashMap<Variable<'a>, &'a str>,
	pub body: ParseTree<'a>,
}

impl<'a> BodyParser<'a>
{
	fn parse() -> Option<ParseResult<'a>>
	{
		None
	}
}

pub struct ParseResult<'a>
{
	end_index: usize,
	tree: ParseTree<'a>,
}

pub struct Variable<'a>
{
	pub name: &'a str,
	pub vtype: &'a str,
}

pub fn get_start_symbols<'a>() -> Vec<&'a str>
{
	// TODO: Read symbols from rules file
    let mut start_symbols: Vec<&str> = Vec::new();

	start_symbols.push("");

	start_symbols
}

pub fn get_invalid_token_values<'a>() -> Vec<&'a str>
{
    // TODO: Read invalid types from rules file
    let mut invalid_tokens: Vec<&str> = Vec::new();

    invalid_tokens.push("enum");
    invalid_tokens.push("interface");

    invalid_tokens
}

pub fn get_invalid_token_types<'a>() -> Vec<&'a str>
{
    // TODO: Read invalid types from rules file
    let mut invalid_types: Vec<&str> = Vec::new();

    invalid_types.push("literal.null");
    invalid_types.push("block.generics.args");
    invalid_types.push("literal.string");
    invalid_types.push("literal.char");
    invalid_types.push("literal.float");
    invalid_types.push("literal.double");
    invalid_types.push("special.reserved");
    invalid_types.push("construct.conditional");
    invalid_types.push("construct.handles");
    invalid_types.push("construct.switch");
    invalid_types.push("construct.loop");

    invalid_types
}
<commit_msg>Clean unused function<commit_after>mod tree;
use std::collections::HashMap;
use parser::tree::ParseTree;

pub struct BodyParser<'a>
{
	pub variables: HashMap<Variable<'a>, &'a str>,
	pub body: ParseTree<'a>,
}

impl<'a> BodyParser<'a>
{
	fn parse() -> Option<ParseResult<'a>>
	{
		None
	}
}

pub struct ParseResult<'a>
{
	end_index: usize,
	tree: ParseTree<'a>,
}

pub struct Variable<'a>
{
	pub name: &'a str,
	pub vtype: &'a str,
}

pub fn get_invalid_token_values<'a>() -> Vec<&'a str>
{
    // TODO: Read invalid types from rules file
    let mut invalid_tokens: Vec<&str> = Vec::new();

    invalid_tokens.push("enum");
    invalid_tokens.push("interface");

    invalid_tokens
}

pub fn get_invalid_token_types<'a>() -> Vec<&'a str>
{
    // TODO: Read invalid types from rules file
    let mut invalid_types: Vec<&str> = Vec::new();

    invalid_types.push("literal.null");
    invalid_types.push("block.generics.args");
    invalid_types.push("literal.string");
    invalid_types.push("literal.char");
    invalid_types.push("literal.float");
    invalid_types.push("literal.double");
    invalid_types.push("special.reserved");
    invalid_types.push("construct.conditional");
    invalid_types.push("construct.handles");
    invalid_types.push("construct.switch");
    invalid_types.push("construct.loop");

    invalid_types
}
<|endoftext|>