<commit_before>use std::collections::HashMap;

use mw::regexp::Expression;
use plug::{Conn, Plug};

pub type MatchContext = HashMap<String,String>;
pub type Handler = Box<Plug>;

/// A route is a combination of a compiled matcher along with an
/// invokable handler.
///
/// If the route matches the corresponding entries will be stored
/// in the request's extension under the `MatchContext` type, and
/// the handler will then be called.
///
pub struct Route {
	matcher: Expression,
	handler: Handler,
}

impl Route {
    /// Create a route using a template string and a stack `Segment`.
    /// Please see the documentation for `Expression` to learn more
    /// about the formatting of the template string.
	pub fn new<P: Plug>(template: &str, handler: P) -> Route {
		Route {
			matcher: Expression::from_template(template).unwrap(),
			handler: Box::new(handler),
		}
	}

	// TODO: return Option<MatchMetadata> or something along those lines ...
	/// Determine if this route matches the current path
	pub fn matches(&self, path: &str) -> bool {
		self.matcher.is_match(path)
	}

    /// Apply this route to a path and retrieve a match context if possible.
	pub fn get_context(&self, path: &str) -> MatchContext {
		self.matcher.map_path(path)
	}

	/// Stores parameters from the matched route into the request's environment.
	/// Then the route's associated function pointer is invoked and given
	/// a chance to modify the response.
	///
	/// Any error's raised by the route will be stored in the `Response.err` field.
	pub fn invoke_handler(&self, conn: &mut Conn) {
        // NOTE: binding is here just for lexical scope (to borrow req)
        let context = { self.get_context(conn.req().path()) };
        conn.req_mut().mut_extensions().insert::<MatchContext>(context);
        (*self.handler).call(conn)
	}
}

#[cfg(test)]
mod test {
    use super::*;
    use conduit::Request;
    use mw::{Segment, Outcome};

    struct MockHandler;
    impl Segment for MockHandler {
        fn invoke(&self, req: &mut Request) -> Outcome {
            Outcome::Halt(500, "test case".to_string())
        }
    }

 	#[test]
 	fn test_route_matches() {
 		let route = Route::new("/foo/{bar}/{baz}", MockHandler);
 		assert!(route.matches("/foo/hello/test"));
 	}

 	#[test]
 	fn test_route_matches_not_greedy() {
 		let route = Route::new("/foo/{bar}/{baz}/quux", MockHandler);
 		assert!(!route.matches("/foo/hello/test"));
 	}

 	#[test]
 	fn test_route_params_nonempty() {
 		let route = Route::new("/foo/{bar}/{baz}", MockHandler);
 		let params = route.get_context("/foo/hello/test");
 		assert!(params.get("bar").is_some());
 		assert!(params.get("baz").is_some());
 	}

 	#[test]
 	fn test_route_params_empty() {
 		let route = Route::new("/foo/{bar}/{baz}", MockHandler);
 		let params = route.get_context("/foo//test");
 		assert!(params.get("bar").is_some());
 		assert!(params.get("baz").is_some());
 	}

    // TODO: nirvash used to have a test of invoking the handler
    //       this would require a mock `conduit::Request` object w/ working
    //       extension storage.
}
<commit_msg>(fix) aqua-web tests<commit_after>use std::collections::HashMap;

use mw::regexp::Expression;
use plug::{Conn, Plug};

pub type MatchContext = HashMap<String,String>;
pub type Handler = Box<Plug>;

/// A route is a combination of a compiled matcher along with an
/// invokable handler.
///
/// If the route matches the corresponding entries will be stored
/// in the request's extension under the `MatchContext` type, and
/// the handler will then be called.
///
pub struct Route {
	matcher: Expression,
	handler: Handler,
}

impl Route {
    /// Create a route using a template string and a stack `Segment`.
    /// Please see the documentation for `Expression` to learn more
    /// about the formatting of the template string.
	pub fn new<P: Plug>(template: &str, handler: P) -> Route {
		Route {
			matcher: Expression::from_template(template).unwrap(),
			handler: Box::new(handler),
		}
	}

	// TODO: return Option<MatchMetadata> or something along those lines ...
	/// Determine if this route matches the current path
	pub fn matches(&self, path: &str) -> bool {
		self.matcher.is_match(path)
	}

    /// Apply this route to a path and retrieve a match context if possible.
	pub fn get_context(&self, path: &str) -> MatchContext {
		self.matcher.map_path(path)
	}

	/// Stores parameters from the matched route into the request's environment.
	/// Then the route's associated function pointer is invoked and given
	/// a chance to modify the response.
	///
	/// Any error's raised by the route will be stored in the `Response.err` field.
	pub fn invoke_handler(&self, conn: &mut Conn) {
        // NOTE: binding is here just for lexical scope (to borrow req)
        let context = { self.get_context(conn.req().path()) };
        conn.req_mut().mut_extensions().insert::<MatchContext>(context);
        (*self.handler).call(conn)
	}
}

#[cfg(test)]
mod test {
    use super::*;
    use conduit::Request;
    use plug::{Conn, Plug};

    struct MockHandler;
    impl Plug for MockHandler {
        fn call(&self, conn: &mut Conn) {}
    }

 	#[test]
 	fn test_route_matches() {
 		let route = Route::new("/foo/{bar}/{baz}", MockHandler);
 		assert!(route.matches("/foo/hello/test"));
 	}

 	#[test]
 	fn test_route_matches_not_greedy() {
 		let route = Route::new("/foo/{bar}/{baz}/quux", MockHandler);
 		assert!(!route.matches("/foo/hello/test"));
 	}

 	#[test]
 	fn test_route_params_nonempty() {
 		let route = Route::new("/foo/{bar}/{baz}", MockHandler);
 		let params = route.get_context("/foo/hello/test");
 		assert!(params.get("bar").is_some());
 		assert!(params.get("baz").is_some());
 	}

 	#[test]
 	fn test_route_params_empty() {
 		let route = Route::new("/foo/{bar}/{baz}", MockHandler);
 		let params = route.get_context("/foo//test");
 		assert!(params.get("bar").is_some());
 		assert!(params.get("baz").is_some());
 	}

    // TODO: nirvash used to have a test of invoking the handler
    //       this would require a mock `conduit::Request` object w/ working
    //       extension storage.
}
<|endoftext|>


<commit_before>use std::env;
use std::ffi::OsStr;
use std::path::PathBuf;
use std::process::Command;

use flate2::read::GzDecoder;
use tar::Archive;

fn main() {
	// TODO: Replace with is_some_with once stabilized
	// https://github.com/rust-lang/rust/issues/93050
	let targets_hermit =
		matches!(env::var_os("CARGO_CFG_TARGET_OS"), Some(os) if os == OsStr::new("hermit"));
	let runs_clippy =
		matches!(env::var_os("CARGO_CFG_FEATURE"), Some(os) if os == OsStr::new("cargo-clippy"));
	let is_docs_rs = env::var_os("DOCS_RS").is_some();
	if !targets_hermit || runs_clippy || is_docs_rs {
		return;
	}

	let kernel_src = KernelSrc::local().unwrap_or_else(KernelSrc::download);

	kernel_src.build();
}

struct KernelSrc {
	src_dir: PathBuf,
}

impl KernelSrc {
	fn local() -> Option<Self> {
		let mut src_dir = PathBuf::from(env::var_os("CARGO_MANIFEST_DIR").unwrap());
		src_dir.set_file_name("libhermit-rs");
		src_dir.exists().then(|| Self { src_dir })
	}

	fn download() -> Self {
		let version = "0.5.0";
		let out_dir = out_dir();
		let src_dir = out_dir.join(format!("libhermit-rs-{version}"));

		if !src_dir.exists() {
			let url = format!(
				"https://github.com/hermitcore/libhermit-rs/archive/refs/tags/v{version}.tar.gz"
			);
			let response = ureq::get(url.as_str()).call().unwrap().into_reader();
			let tar = GzDecoder::new(response);
			let mut archive = Archive::new(tar);
			archive.unpack(src_dir.parent().unwrap()).unwrap();
		}

		Self { src_dir }
	}

	fn build(self) {
		let target_dir = target_dir();
		let manifest_path = self.src_dir.join("Cargo.toml");
		assert!(
			manifest_path.exists(),
			"kernel manifest path `{}` does not exist",
			manifest_path.display()
		);
		let arch = env::var_os("CARGO_CFG_TARGET_ARCH").unwrap();
		let profile = env::var("PROFILE").expect("PROFILE was not set");

		let mut cmd = Command::new("cargo");

		// Remove rust-toolchain-specific environment variables from kernel cargo
		cmd.env_remove("LD_LIBRARY_PATH");
		env::vars()
			.filter(|(key, _value)| key.starts_with("CARGO") || key.starts_with("RUST"))
			.for_each(|(key, _value)| {
				cmd.env_remove(&key);
			});

		cmd.current_dir(&self.src_dir)
			.arg("run")
			.arg("--package=xtask")
			.arg("--target-dir")
			.arg(&target_dir)
			.arg("--")
			.arg("build")
			.arg("--arch")
			.arg(&arch)
			.args(&[
				"--profile",
				match profile.as_str() {
					"debug" => "dev",
					profile => profile,
				},
			])
			.arg("--target-dir")
			.arg(&target_dir);

		if has_feature("instrument") {
			cmd.arg("--instrument-mcount");
		}

		// Control enabled features via this crate's features
		cmd.arg("--no-default-features");
		forward_features(
			&mut cmd,
			[
				"acpi", "dhcpv4", "fsgsbase", "pci", "pci-ids", "smp", "tcp", "vga",
			]
			.into_iter(),
		);

		let status = cmd.status().expect("failed to start kernel build");
		assert!(status.success());

		let lib_location = target_dir
			.join(&arch)
			.join(&profile)
			.canonicalize()
			.unwrap();

		println!("cargo:rustc-link-search=native={}", lib_location.display());
		println!("cargo:rustc-link-lib=static=hermit");

		println!("cargo:rerun-if-changed={}", self.src_dir.display());
		// HERMIT_LOG_LEVEL_FILTER sets the log level filter at compile time
		println!("cargo:rerun-if-env-changed=HERMIT_LOG_LEVEL_FILTER");
	}
}

fn out_dir() -> PathBuf {
	env::var_os("OUT_DIR").unwrap().into()
}

fn target_dir() -> PathBuf {
	let mut target_dir = out_dir();
	target_dir.push("target");
	target_dir
}

fn has_feature(feature: &str) -> bool {
	let mut var = "CARGO_FEATURE_".to_string();

	var.extend(feature.chars().map(|c| match c {
		'-' => '_',
		c => c.to_ascii_uppercase(),
	}));

	env::var_os(&var).is_some()
}

fn forward_features<'a>(cmd: &mut Command, features: impl Iterator<Item = &'a str>) {
	let features = features.filter(|f| has_feature(f)).collect::<Vec<_>>();
	if !features.is_empty() {
		cmd.args(&["--features", &features.join(" ")]);
	}
}
<commit_msg>Fix clippy::unnecessary-lazy-evaluations<commit_after>use std::env;
use std::ffi::OsStr;
use std::path::PathBuf;
use std::process::Command;

use flate2::read::GzDecoder;
use tar::Archive;

fn main() {
	// TODO: Replace with is_some_with once stabilized
	// https://github.com/rust-lang/rust/issues/93050
	let targets_hermit =
		matches!(env::var_os("CARGO_CFG_TARGET_OS"), Some(os) if os == OsStr::new("hermit"));
	let runs_clippy =
		matches!(env::var_os("CARGO_CFG_FEATURE"), Some(os) if os == OsStr::new("cargo-clippy"));
	let is_docs_rs = env::var_os("DOCS_RS").is_some();
	if !targets_hermit || runs_clippy || is_docs_rs {
		return;
	}

	let kernel_src = KernelSrc::local().unwrap_or_else(KernelSrc::download);

	kernel_src.build();
}

struct KernelSrc {
	src_dir: PathBuf,
}

impl KernelSrc {
	fn local() -> Option<Self> {
		let mut src_dir = PathBuf::from(env::var_os("CARGO_MANIFEST_DIR").unwrap());
		src_dir.set_file_name("libhermit-rs");
		src_dir.exists().then_some(Self { src_dir })
	}

	fn download() -> Self {
		let version = "0.5.0";
		let out_dir = out_dir();
		let src_dir = out_dir.join(format!("libhermit-rs-{version}"));

		if !src_dir.exists() {
			let url = format!(
				"https://github.com/hermitcore/libhermit-rs/archive/refs/tags/v{version}.tar.gz"
			);
			let response = ureq::get(url.as_str()).call().unwrap().into_reader();
			let tar = GzDecoder::new(response);
			let mut archive = Archive::new(tar);
			archive.unpack(src_dir.parent().unwrap()).unwrap();
		}

		Self { src_dir }
	}

	fn build(self) {
		let target_dir = target_dir();
		let manifest_path = self.src_dir.join("Cargo.toml");
		assert!(
			manifest_path.exists(),
			"kernel manifest path `{}` does not exist",
			manifest_path.display()
		);
		let arch = env::var_os("CARGO_CFG_TARGET_ARCH").unwrap();
		let profile = env::var("PROFILE").expect("PROFILE was not set");

		let mut cmd = Command::new("cargo");

		// Remove rust-toolchain-specific environment variables from kernel cargo
		cmd.env_remove("LD_LIBRARY_PATH");
		env::vars()
			.filter(|(key, _value)| key.starts_with("CARGO") || key.starts_with("RUST"))
			.for_each(|(key, _value)| {
				cmd.env_remove(&key);
			});

		cmd.current_dir(&self.src_dir)
			.arg("run")
			.arg("--package=xtask")
			.arg("--target-dir")
			.arg(&target_dir)
			.arg("--")
			.arg("build")
			.arg("--arch")
			.arg(&arch)
			.args(&[
				"--profile",
				match profile.as_str() {
					"debug" => "dev",
					profile => profile,
				},
			])
			.arg("--target-dir")
			.arg(&target_dir);

		if has_feature("instrument") {
			cmd.arg("--instrument-mcount");
		}

		// Control enabled features via this crate's features
		cmd.arg("--no-default-features");
		forward_features(
			&mut cmd,
			[
				"acpi", "dhcpv4", "fsgsbase", "pci", "pci-ids", "smp", "tcp", "vga",
			]
			.into_iter(),
		);

		let status = cmd.status().expect("failed to start kernel build");
		assert!(status.success());

		let lib_location = target_dir
			.join(&arch)
			.join(&profile)
			.canonicalize()
			.unwrap();

		println!("cargo:rustc-link-search=native={}", lib_location.display());
		println!("cargo:rustc-link-lib=static=hermit");

		println!("cargo:rerun-if-changed={}", self.src_dir.display());
		// HERMIT_LOG_LEVEL_FILTER sets the log level filter at compile time
		println!("cargo:rerun-if-env-changed=HERMIT_LOG_LEVEL_FILTER");
	}
}

fn out_dir() -> PathBuf {
	env::var_os("OUT_DIR").unwrap().into()
}

fn target_dir() -> PathBuf {
	let mut target_dir = out_dir();
	target_dir.push("target");
	target_dir
}

fn has_feature(feature: &str) -> bool {
	let mut var = "CARGO_FEATURE_".to_string();

	var.extend(feature.chars().map(|c| match c {
		'-' => '_',
		c => c.to_ascii_uppercase(),
	}));

	env::var_os(&var).is_some()
}

fn forward_features<'a>(cmd: &mut Command, features: impl Iterator<Item = &'a str>) {
	let features = features.filter(|f| has_feature(f)).collect::<Vec<_>>();
	if !features.is_empty() {
		cmd.args(&["--features", &features.join(" ")]);
	}
}
<|endoftext|>


<commit_before>#![feature(test)]
extern crate test;
#[macro_use]
extern crate chomp;

use test::Bencher;

use std::iter;

use chomp::prelude::*;
use chomp::buffer::InputBuf;

#[bench]
fn count_vec_1k(b: &mut Bencher) {
    let data = iter::repeat(b'a').take(1024).collect::<Vec<u8>>();

    fn count_vec<I: Input>(i: I) -> ParseResult<I, Vec<I::Token>, Error<I::Token>> {
        count(i, 1024, any)
    }

    b.iter(|| {
        parse_only(count_vec, &data)
    })
}

#[bench]
fn count_vec_10k(b: &mut Bencher) {
    let data = iter::repeat(b'a').take(10024).collect::<Vec<u8>>();

    fn count_vec<I: Input>(i: I) -> ParseResult<I, Vec<I::Token>, Error<I::Token>> {
        count(i, 10024, any)
    }

    b.iter(|| {
        parse_only(count_vec, &data)
    })
}

#[bench]
fn many_vec_1k(b: &mut Bencher) {
    let data = iter::repeat(b'a').take(1024).collect::<Vec<u8>>();

    fn many_vec<I: Input>(i: I) -> ParseResult<I, Vec<I::Token>, Error<I::Token>> {
        many(i, any)
    }

    b.iter(|| {
        parse_only(many_vec, &data)
    })
}

#[bench]
fn many_vec_10k(b: &mut Bencher) {
    let data = iter::repeat(b'a').take(10024).collect::<Vec<u8>>();

    fn many_vec<I: Input>(i: I) -> ParseResult<I, Vec<I::Token>, Error<I::Token>> {
        many(i, any)
    }

    b.iter(|| {
        parse_only(many_vec, &data)
    })
}

#[bench]
fn many1_vec_1k(b: &mut Bencher) {
    let data = iter::repeat(b'a').take(1024).collect::<Vec<u8>>();

    fn many1_vec<I: Input>(i: I) -> ParseResult<I, Vec<I::Token>, Error<I::Token>> {
        many1(i, any)
    }

    b.iter(|| {
        parse_only(many1_vec, &data)
    })
}

#[bench]
fn many1_vec_10k(b: &mut Bencher) {
    let data = iter::repeat(b'a').take(10024).collect::<Vec<u8>>();

    fn many1_vec<I: Input>(i: I) -> ParseResult<I, Vec<I::Token>, Error<I::Token>> {
        many1(i, any)
    }

    b.iter(|| {
        parse_only(many1_vec, &data)
    })
}

#[bench]
fn count_vec_10k_maybe_incomplete(b: &mut Bencher) {
    let data = iter::repeat(b'a').take(10024).collect::<Vec<u8>>();

    fn count_vec<I: Input>(i: I) -> ParseResult<I, Vec<I::Token>, Error<I::Token>> {
        count(i, 10024, any)
    }

    b.iter(|| {
        count_vec(InputBuf::new(&data))
    })
}

#[bench]
fn many_vec_10k_maybe_incomplete(b: &mut Bencher) {
    let data = iter::repeat(b'a').take(10024).collect::<Vec<u8>>();

    fn many_vec<I: Input>(i: I) -> ParseResult<I, Vec<I::Token>, Error<I::Token>> {
        many(i, any)
    }

    b.iter(|| {
        many_vec(InputBuf::new(&data))
    })
}

#[bench]
fn many1_vec_10k_maybe_incomplete(b: &mut Bencher) {
    let data = iter::repeat(b'a').take(10024).collect::<Vec<u8>>();

    fn many1_vec<I: Input>(i: I) -> ParseResult<I, Vec<I::Token>, Error<I::Token>> {
        many1(i, any)
    }

    b.iter(|| {
        many1_vec(InputBuf::new(&data))
    })
}
<commit_msg>Benches: Fixed number for 10k<commit_after>#![feature(test)]
extern crate test;
#[macro_use]
extern crate chomp;

use test::Bencher;

use std::iter;

use chomp::prelude::*;
use chomp::buffer::InputBuf;

#[bench]
fn count_vec_1k(b: &mut Bencher) {
    let data = iter::repeat(b'a').take(1024).collect::<Vec<u8>>();

    fn count_vec<I: Input>(i: I) -> ParseResult<I, Vec<I::Token>, Error<I::Token>> {
        count(i, 1024, any)
    }

    b.iter(|| {
        parse_only(count_vec, &data)
    })
}

#[bench]
fn count_vec_10k(b: &mut Bencher) {
    let data = iter::repeat(b'a').take(10240).collect::<Vec<u8>>();

    fn count_vec<I: Input>(i: I) -> ParseResult<I, Vec<I::Token>, Error<I::Token>> {
        count(i, 10240, any)
    }

    b.iter(|| {
        parse_only(count_vec, &data)
    })
}

#[bench]
fn many_vec_1k(b: &mut Bencher) {
    let data = iter::repeat(b'a').take(1024).collect::<Vec<u8>>();

    fn many_vec<I: Input>(i: I) -> ParseResult<I, Vec<I::Token>, Error<I::Token>> {
        many(i, any)
    }

    b.iter(|| {
        parse_only(many_vec, &data)
    })
}

#[bench]
fn many_vec_10k(b: &mut Bencher) {
    let data = iter::repeat(b'a').take(10024).collect::<Vec<u8>>();

    fn many_vec<I: Input>(i: I) -> ParseResult<I, Vec<I::Token>, Error<I::Token>> {
        many(i, any)
    }

    b.iter(|| {
        parse_only(many_vec, &data)
    })
}

#[bench]
fn many1_vec_1k(b: &mut Bencher) {
    let data = iter::repeat(b'a').take(1024).collect::<Vec<u8>>();

    fn many1_vec<I: Input>(i: I) -> ParseResult<I, Vec<I::Token>, Error<I::Token>> {
        many1(i, any)
    }

    b.iter(|| {
        parse_only(many1_vec, &data)
    })
}

#[bench]
fn many1_vec_10k(b: &mut Bencher) {
    let data = iter::repeat(b'a').take(10024).collect::<Vec<u8>>();

    fn many1_vec<I: Input>(i: I) -> ParseResult<I, Vec<I::Token>, Error<I::Token>> {
        many1(i, any)
    }

    b.iter(|| {
        parse_only(many1_vec, &data)
    })
}

#[bench]
fn count_vec_10k_maybe_incomplete(b: &mut Bencher) {
    let data = iter::repeat(b'a').take(10024).collect::<Vec<u8>>();

    fn count_vec<I: Input>(i: I) -> ParseResult<I, Vec<I::Token>, Error<I::Token>> {
        count(i, 10024, any)
    }

    b.iter(|| {
        count_vec(InputBuf::new(&data))
    })
}

#[bench]
fn many_vec_10k_maybe_incomplete(b: &mut Bencher) {
    let data = iter::repeat(b'a').take(10024).collect::<Vec<u8>>();

    fn many_vec<I: Input>(i: I) -> ParseResult<I, Vec<I::Token>, Error<I::Token>> {
        many(i, any)
    }

    b.iter(|| {
        many_vec(InputBuf::new(&data))
    })
}

#[bench]
fn many1_vec_10k_maybe_incomplete(b: &mut Bencher) {
    let data = iter::repeat(b'a').take(10024).collect::<Vec<u8>>();

    fn many1_vec<I: Input>(i: I) -> ParseResult<I, Vec<I::Token>, Error<I::Token>> {
        many1(i, any)
    }

    b.iter(|| {
        many1_vec(InputBuf::new(&data))
    })
}
<|endoftext|>


<commit_before>// Claxon -- A FLAC decoding library in Rust
// Copyright 2014 Ruud van Asseldonk
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// A copy of the License has been included in the root of the repository.

#![feature(test)]

extern crate claxon;
extern crate test;

use std::fs::File;
use std::io::{Cursor, Read};
use std::path::Path;
use test::Bencher;

fn bench_decode_i16<P: AsRef<Path>>(path: P, bencher: &mut Bencher) {
    // Read the file into memory. We want to measure decode speed, not IO
    // overhead.
    let mut file = File::open(path).unwrap();
    let mut data = Vec::new();
    file.read_to_end(&mut data).unwrap();
    let cursor = Cursor::new(data);

    let mut reader = claxon::FlacReader::new(cursor).unwrap();

    let bps = reader.streaminfo().bits_per_sample as u64;
    assert!(bps < 8 * 16);

    let mut samples = reader.samples::<i16>();
    let mut bytes = 0u64;
    bencher.iter(|| {
        for _ in 0..1024 {
            let sample = samples.next().unwrap().unwrap();
            test::black_box(sample);
        }
        bytes += 1024 * bps / 8;
    });
    bencher.bytes = bytes;
}

fn bench_decode_i32<P: AsRef<Path>>(path: P, bencher: &mut Bencher) {
    // This function is identical to `bench_decode_i16`, except it decodes into
    // i32s, so it can also deal with 24-bit audio.
    let mut file = File::open(path).unwrap();
    let mut data = Vec::new();
    file.read_to_end(&mut data).unwrap();
    let cursor = Cursor::new(data);

    let mut reader = claxon::FlacReader::new(cursor).unwrap();

    let bps = reader.streaminfo().bits_per_sample as u64;
    assert!(bps < 8 * 32);

    let mut samples = reader.samples::<i32>();
    let mut bytes = 0u64;
    bencher.iter(|| {
        for _ in 0..1024 {
            let sample = samples.next().unwrap().unwrap();
            test::black_box(sample);
        }
        bytes += 1024 * bps / 8;
    });
    bencher.bytes = bytes;
}

#[bench]
fn bench_p0_mono_16bit(bencher: &mut Bencher) {
    bench_decode_i16("testsamples/p0.flac", bencher);
}

#[bench]
fn bench_p0_mono_16bit_as_i32(bencher: &mut Bencher) {
    bench_decode_i32("testsamples/p0.flac", bencher);
}

#[bench]
fn bench_p1_stereo_24bit(bencher: &mut Bencher) {
    bench_decode_i32("testsamples/p1.flac", bencher);
}

#[bench]
fn bench_p2_stereo_16bit(bencher: &mut Bencher) {
    bench_decode_i16("testsamples/p2.flac", bencher);
}

#[bench]
fn bench_p2_stereo_16bit_as_i32(bencher: &mut Bencher) {
    bench_decode_i32("testsamples/p2.flac", bencher);
}

#[bench]
fn bench_p3_stereo_16bit(bencher: &mut Bencher) {
    bench_decode_i16("testsamples/p3.flac", bencher);
}

#[bench]
fn bench_p3_stereo_16bit_as_i32(bencher: &mut Bencher) {
    bench_decode_i32("testsamples/p3.flac", bencher);
}

#[bench]
fn bench_p4_stereo_16bit(bencher: &mut Bencher) {
    bench_decode_i16("testsamples/p4.flac", bencher);
}

#[bench]
fn bench_p4_stereo_16bit_as_i32(bencher: &mut Bencher) {
    bench_decode_i32("testsamples/p4.flac", bencher);
}
<commit_msg>Fix Cargo benchmarks<commit_after>// Claxon -- A FLAC decoding library in Rust
// Copyright 2014 Ruud van Asseldonk
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// A copy of the License has been included in the root of the repository.

#![feature(test)]

extern crate claxon;
extern crate test;

use std::fs::File;
use std::io::{Cursor, Read};
use std::path::Path;
use test::Bencher;

/// Replace the reader with one that starts again from the beginning.
fn refresh_reader(reader: &mut claxon::FlacReader<Cursor<Vec<u8>>>) {
    // We want to replace the reader in-place, but in order to do so, we must
    // first destruct it. Rust does not allow us to do that without providing a
    // replacement, so we temporarily put `mem::uninitialized()` in there. At
    // the end, that memory is released without running a destructor with
    // `mem::forget()`.
    let fake_reader = unsafe { std::mem::uninitialized() };
    let stolen_reader = std::mem::replace(reader, fake_reader);
    let cursor = stolen_reader.into_inner();
    let vec = cursor.into_inner();
    let new_cursor = Cursor::new(vec);
    let new_reader = claxon::FlacReader::new(new_cursor).unwrap();
    let stolen_reader = std::mem::replace(reader, new_reader);
    std::mem::forget(stolen_reader);
}

fn bench_decode<P: AsRef<Path>>(path: P, bencher: &mut Bencher) {
    // Read the file into memory. We want to measure decode speed, not IO
    // overhead.
    let mut file = File::open(path).unwrap();
    let mut data = Vec::new();
    file.read_to_end(&mut data).unwrap();
    let cursor = Cursor::new(data);

    let mut reader = claxon::FlacReader::new(cursor).unwrap();

    let bps = reader.streaminfo().bits_per_sample as u32;
    assert!(bps < 8 * 16);

    let mut bytes = 0u32;
    let mut buffer = Vec::new();
    let mut iterations = 0;
    bencher.iter(|| {
        let mut should_refresh = true;
        {
            let mut blocks = reader.blocks();
            let stolen_buffer = std::mem::replace(&mut buffer, Vec::new());
            let block = blocks.read_next_or_eof(stolen_buffer).expect("decode error");
            if let Some(b) = block {
                bytes += b.len() * (bps / 8);
                iterations += 1;
                buffer = test::black_box(b.into_buffer());
                should_refresh = false;
            }
        }
        if should_refresh {
            // We decoded until the end, but the bencher wants to measure more
            // still. Re-create a new FlacReader and start over then.
            refresh_reader(&mut reader);
        }
    });

    // The `bytes` field of the bencher indicates the number of bytes *per
    // iteration*, not the total number of bytes.
    bencher.bytes = (bytes as u64) / iterations;
}

#[bench]
fn bench_p0_mono_16bit(bencher: &mut Bencher) {
    bench_decode("testsamples/p0.flac", bencher);
}

#[bench]
fn bench_p1_stereo_24bit(bencher: &mut Bencher) {
    bench_decode("testsamples/p1.flac", bencher);
}

#[bench]
fn bench_p2_stereo_16bit(bencher: &mut Bencher) {
    bench_decode("testsamples/p2.flac", bencher);
}

#[bench]
fn bench_p3_stereo_16bit(bencher: &mut Bencher) {
    bench_decode("testsamples/p3.flac", bencher);
}

#[bench]
fn bench_p4_stereo_16bit(bencher: &mut Bencher) {
    bench_decode("testsamples/p4.flac", bencher);
}
<|endoftext|>


<commit_before>extern crate clap;
#[macro_use]
extern crate error_chain;
extern crate definitions;
// extern crate sdl2;
extern crate ieee754;
extern crate num;

mod vm;
mod error;

use clap::{App, Arg};
use error::*;
// use sdl2::event::Event;
// use sdl2::rect::Rect;
use vm::VM;

fn main() {
    if let Err(ref e) = run() {
        println!("error: {}", e);

        for e in e.iter().skip(1) {
            println!("caused by: {}", e);
        }

        // The backtrace is not always generated. Try to run this example
        // with `RUST_BACKTRACE=1`.
        if let Some(backtrace) = e.backtrace() {
            println!("backtrace: {:?}", backtrace);
        }

        ::std::process::exit(1);
    }
}

fn run() -> VMResult<()> {
    let matches = App::new("bakerVM")
        .version(env!("CARGO_PKG_VERSION"))
        .author("Julian Laubstein <contact@julianlaubstein.de>")
        .about("A virtual machine for classic point-and-click adventure games",)
        .arg(
            Arg::with_name("input")
                .index(1)
                .help("Sets the image file to use. Uses a standard image if not specified.",),
        )
        .get_matches();

    let input = matches.value_of("input").unwrap_or("").to_string();

    let mut vm = VM::new();

    vm.exec(input).chain_err(|| "unable to exec file")?;

    // // start sdl2 with everything
    // let ctx = sdl2::init().unwrap();
    // let video_ctx = ctx.video().unwrap();
    //
    // // Create a window
    // let window = video_ctx.window("bakerVM", 640, 480)
    //     .position_centered()
    //     .opengl()
    //     .build()
    //     .chain_err(|| "unable to create window")?;
    //
    // // Create a rendering context
    // let mut renderer = window.renderer().build().chain_err(|| "unable to create
    // renderer")?;
    //
    // // Set the drawing color to a light blue.
    // let _ = renderer.set_draw_color(sdl2::pixels::Color::RGB(101, 208, 246));
    //
    // // Clear the buffer, using the light blue color set above.
    // let _ = renderer.clear();
    //
    // // Set the drawing color to a darker blue.
    // let _ = renderer.set_draw_color(sdl2::pixels::Color::RGB(0, 153, 204));
    //
    // // Create centered Rect, draw the outline of the Rect in our dark blue color.
    // let border_rect = Rect::new(320 - 64, 240 - 64, 128, 128);
    // let _ = renderer.draw_rect(border_rect);
    //
    // // Create a smaller centered Rect, filling it in the same dark blue.
    // let inner_rect = Rect::new(320 - 60, 240 - 60, 120, 120);
    // let _ = renderer.fill_rect(inner_rect);
    //
    // // Swap our buffer for the present buffer, displaying it.
    // let _ = renderer.present();
    //
    // let mut events = ctx.event_pump().unwrap();
    //
    // // loop until we receive a QuitEvent
    // 'event: loop {
    //     for event in events.poll_iter() {
    //         match event {
    //             Event::Quit { .. } => break 'event,
    //             _ => continue,
    //         }
    //     }
    // }

    Ok(())
}
<commit_msg>Update CLI<commit_after>extern crate clap;
#[macro_use]
extern crate error_chain;
extern crate definitions;
// extern crate sdl2;
extern crate ieee754;
extern crate num;

mod vm;
mod error;

use clap::{App, Arg};
use error::*;
// use sdl2::event::Event;
// use sdl2::rect::Rect;
use vm::VM;

fn main() {
    if let Err(ref e) = run() {
        println!("error: {}", e);

        for e in e.iter().skip(1) {
            println!("caused by: {}", e);
        }

        // The backtrace is not always generated. Try to run this example
        // with `RUST_BACKTRACE=1`.
        if let Some(backtrace) = e.backtrace() {
            println!("backtrace: {:?}", backtrace);
        }

        ::std::process::exit(1);
    }
}

fn run() -> VMResult<()> {
    let matches = App::new("bakerVM")
        .version(env!("CARGO_PKG_VERSION"))
        .author("Julian Laubstein <contact@julianlaubstein.de>")
        .about("A virtual machine for building and running retro games",)
        .arg(
            Arg::with_name("input")
                .index(1)
                .help("Sets the image file to use. Uses a standard image if nothing is specified.",),
        )
        .get_matches();

    let input = matches.value_of("input").unwrap_or("").to_string();

    let mut vm = VM::new();

    vm.exec(input).chain_err(|| "unable to exec file")?;

    // // start sdl2 with everything
    // let ctx = sdl2::init().unwrap();
    // let video_ctx = ctx.video().unwrap();
    //
    // // Create a window
    // let window = video_ctx.window("bakerVM", 640, 480)
    //     .position_centered()
    //     .opengl()
    //     .build()
    //     .chain_err(|| "unable to create window")?;
    //
    // // Create a rendering context
    // let mut renderer = window.renderer().build().chain_err(|| "unable to create
    // renderer")?;
    //
    // // Set the drawing color to a light blue.
    // let _ = renderer.set_draw_color(sdl2::pixels::Color::RGB(101, 208, 246));
    //
    // // Clear the buffer, using the light blue color set above.
    // let _ = renderer.clear();
    //
    // // Set the drawing color to a darker blue.
    // let _ = renderer.set_draw_color(sdl2::pixels::Color::RGB(0, 153, 204));
    //
    // // Create centered Rect, draw the outline of the Rect in our dark blue color.
    // let border_rect = Rect::new(320 - 64, 240 - 64, 128, 128);
    // let _ = renderer.draw_rect(border_rect);
    //
    // // Create a smaller centered Rect, filling it in the same dark blue.
    // let inner_rect = Rect::new(320 - 60, 240 - 60, 120, 120);
    // let _ = renderer.fill_rect(inner_rect);
    //
    // // Swap our buffer for the present buffer, displaying it.
    // let _ = renderer.present();
    //
    // let mut events = ctx.event_pump().unwrap();
    //
    // // loop until we receive a QuitEvent
    // 'event: loop {
    //     for event in events.poll_iter() {
    //         match event {
    //             Event::Quit { .. } => break 'event,
    //             _ => continue,
    //         }
    //     }
    // }

    Ok(())
}
<|endoftext|>


<commit_before>use crate::command_prelude::*;

use cargo::ops::{self, CompileFilter};

pub fn cli() -> App {
    subcommand("test")
        // subcommand aliases are handled in aliased_command()
        // .alias("t")
        .setting(AppSettings::TrailingVarArg)
        .about("Execute all unit and integration tests of a local package")
        .arg(
            Arg::with_name("TESTNAME")
                .help("If specified, only run tests containing this string in their names"),
        )
        .arg(
            Arg::with_name("args")
                .help("Arguments for the test binary")
                .multiple(true)
                .last(true),
        )
        .arg_targets_all(
            "Test only this package's library",
            "Test only the specified binary",
            "Test all binaries",
            "Test only the specified example",
            "Test all examples",
            "Test only the specified test target",
            "Test all tests",
            "Test only the specified bench target",
            "Test all benches",
            "Test all targets",
        )
        .arg(opt("doc", "Test only this library's documentation"))
        .arg(opt("no-run", "Compile, but don't run tests"))
        .arg(opt("no-fail-fast", "Run all tests regardless of failure"))
        .arg_package_spec(
            "Package to run tests for",
            "Test all packages in the workspace",
            "Exclude packages from the test",
        )
        .arg_jobs()
        .arg_release("Build artifacts in release mode, with optimizations")
        .arg_features()
        .arg_target_triple("Build for the target triple")
        .arg_target_dir()
        .arg_manifest_path()
        .arg_message_format()
        .after_help(
            "\
The test filtering argument `TESTNAME` and all the arguments following the
two dashes (`--`) are passed to the test binaries and thus to libtest
(rustc's built in unit-test and micro-benchmarking framework).  If you're
passing arguments to both Cargo and the binary, the ones after `--` go to the
binary, the ones before go to Cargo.  For details about libtest's arguments see
the output of `cargo test -- --help`.  As an example, this will run all
tests with `foo` in their name on 3 threads in parallel:

    cargo test foo -- --test-threads 3

If the --package argument is given, then SPEC is a package id specification
which indicates which package should be tested. If it is not given, then the
current package is tested. For more information on SPEC and its format, see the
`cargo help pkgid` command.

All packages in the workspace are tested if the `--all` flag is supplied. The
`--all` flag is automatically assumed for a virtual manifest.
Note that `--exclude` has to be specified in conjunction with the `--all` flag.

The --jobs argument affects the building of the test executable but does
not affect how many jobs are used when running the tests. The default value
for the --jobs argument is the number of CPUs. If you want to control the
number of simultaneous running test cases, pass the `--test-threads` option
to the test binaries:

    cargo test -- --test-threads=1

Compilation can be configured via the `test` profile in the manifest.

By default the rust test harness hides output from test execution to
keep results readable. Test output can be recovered (e.g. for debugging)
by passing `--nocapture` to the test binaries:

    cargo test -- --nocapture

To get the list of all options available for the test binaries use this:

    cargo test -- --help
",
        )
}

pub fn exec(config: &mut Config, args: &ArgMatches<'_>) -> CliResult {
    let ws = args.workspace(config)?;

    let mut compile_opts = args.compile_options(config, CompileMode::Test, Some(&ws))?;

    let doc = args.is_present("doc");
    if doc {
        if let CompileFilter::Only { .. } = compile_opts.filter {
            return Err(CliError::new(
                failure::format_err!("Can't mix --doc with other target selecting options"),
                101,
            ));
        }
        compile_opts.build_config.mode = CompileMode::Doctest;
        compile_opts.filter = ops::CompileFilter::new(
            true,
            Vec::new(),
            false,
            Vec::new(),
            false,
            Vec::new(),
            false,
            Vec::new(),
            false,
            false,
        );
    }

    let ops = ops::TestOptions {
        no_run: args.is_present("no-run"),
        no_fail_fast: args.is_present("no-fail-fast"),
        compile_opts,
    };

    // TESTNAME is actually an argument of the test binary, but it's
    // important so we explicitly mention it and reconfigure
    let mut test_args = vec![];
    test_args.extend(args.value_of("TESTNAME").into_iter().map(|s| s.to_string()));
    test_args.extend(
        args.values_of("args")
            .unwrap_or_default()
            .map(|s| s.to_string()),
    );

    let err = ops::run_tests(&ws, &ops, &test_args)?;
    match err {
        None => Ok(()),
        Some(err) => Err(match err.exit.as_ref().and_then(|e| e.code()) {
            Some(i) => CliError::new(failure::format_err!("{}", err.hint(&ws)), i),
            None => CliError::new(err.into(), 101),
        }),
    }
}
<commit_msg>In cargo test's help, add that examples are built<commit_after>use crate::command_prelude::*;

use cargo::ops::{self, CompileFilter};

pub fn cli() -> App {
    subcommand("test")
        // subcommand aliases are handled in aliased_command()
        // .alias("t")
        .setting(AppSettings::TrailingVarArg)
        .about("Execute all unit and integration tests and build examples of a local package")
        .arg(
            Arg::with_name("TESTNAME")
                .help("If specified, only run tests containing this string in their names"),
        )
        .arg(
            Arg::with_name("args")
                .help("Arguments for the test binary")
                .multiple(true)
                .last(true),
        )
        .arg_targets_all(
            "Test only this package's library unit tests",
            "Test only the specified binary",
            "Test all binaries",
            "Test only the specified example",
            "Test all examples",
            "Test only the specified test target",
            "Test all tests",
            "Test only the specified bench target",
            "Test all benches",
            "Test all targets",
        )
        .arg(opt("doc", "Test only this library's documentation"))
        .arg(opt("no-run", "Compile, but don't run tests"))
        .arg(opt("no-fail-fast", "Run all tests regardless of failure"))
        .arg_package_spec(
            "Package to run tests for",
            "Test all packages in the workspace",
            "Exclude packages from the test",
        )
        .arg_jobs()
        .arg_release("Build artifacts in release mode, with optimizations")
        .arg_features()
        .arg_target_triple("Build for the target triple")
        .arg_target_dir()
        .arg_manifest_path()
        .arg_message_format()
        .after_help(
            "\
The test filtering argument `TESTNAME` and all the arguments following the
two dashes (`--`) are passed to the test binaries and thus to libtest
(rustc's built in unit-test and micro-benchmarking framework).  If you're
passing arguments to both Cargo and the binary, the ones after `--` go to the
binary, the ones before go to Cargo.  For details about libtest's arguments see
the output of `cargo test -- --help`.  As an example, this will run all
tests with `foo` in their name on 3 threads in parallel:

    cargo test foo -- --test-threads 3

If the --package argument is given, then SPEC is a package id specification
which indicates which package should be tested. If it is not given, then the
current package is tested. For more information on SPEC and its format, see the
`cargo help pkgid` command.

All packages in the workspace are tested if the `--all` flag is supplied. The
`--all` flag is automatically assumed for a virtual manifest.
Note that `--exclude` has to be specified in conjunction with the `--all` flag.

The --jobs argument affects the building of the test executable but does
not affect how many jobs are used when running the tests. The default value
for the --jobs argument is the number of CPUs. If you want to control the
number of simultaneous running test cases, pass the `--test-threads` option
to the test binaries:

    cargo test -- --test-threads=1

Compilation can be configured via the `test` profile in the manifest.

By default the rust test harness hides output from test execution to
keep results readable. Test output can be recovered (e.g. for debugging)
by passing `--nocapture` to the test binaries:

    cargo test -- --nocapture

To get the list of all options available for the test binaries use this:

    cargo test -- --help
",
        )
}

pub fn exec(config: &mut Config, args: &ArgMatches<'_>) -> CliResult {
    let ws = args.workspace(config)?;

    let mut compile_opts = args.compile_options(config, CompileMode::Test, Some(&ws))?;

    let doc = args.is_present("doc");
    if doc {
        if let CompileFilter::Only { .. } = compile_opts.filter {
            return Err(CliError::new(
                failure::format_err!("Can't mix --doc with other target selecting options"),
                101,
            ));
        }
        compile_opts.build_config.mode = CompileMode::Doctest;
        compile_opts.filter = ops::CompileFilter::new(
            true,
            Vec::new(),
            false,
            Vec::new(),
            false,
            Vec::new(),
            false,
            Vec::new(),
            false,
            false,
        );
    }

    let ops = ops::TestOptions {
        no_run: args.is_present("no-run"),
        no_fail_fast: args.is_present("no-fail-fast"),
        compile_opts,
    };

    // TESTNAME is actually an argument of the test binary, but it's
    // important so we explicitly mention it and reconfigure
    let mut test_args = vec![];
    test_args.extend(args.value_of("TESTNAME").into_iter().map(|s| s.to_string()));
    test_args.extend(
        args.values_of("args")
            .unwrap_or_default()
            .map(|s| s.to_string()),
    );

    let err = ops::run_tests(&ws, &ops, &test_args)?;
    match err {
        None => Ok(()),
        Some(err) => Err(match err.exit.as_ref().and_then(|e| e.code()) {
            Some(i) => CliError::new(failure::format_err!("{}", err.hint(&ws)), i),
            None => CliError::new(err.into(), 101),
        }),
    }
}
<|endoftext|>


<commit_before>//
//    Stachanov
//    Copyright (C) 2017 Stachanov Developer Collective
//
//    This file is part of Stachanov.
//
//    This program is free software: you can redistribute it and/or
//    modify it under the terms of the GNU Affero General Public
//    License, version 3, as published by the Free Software Foundation.
//
//    This program is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU Affero General Public License for more details.
//
//    You should have received a copy of the
//               GNU Affero General Public License
//    along with this program.  If not, see <http://www.gnu.org/licenses/>.
//

use std::collections::HashMap;
use blockchain::traits::Hashable;
use blockchain::block::BlockId;

// NOTE: This module currently only consists of
// a dummy implementation

#[derive(Clone)]
pub enum Transaction{
    Dummy
}

impl Hashable for Transaction{

    fn to_sha3_hash(&self) -> [u8; 32]{
        [0; 32]
    }

}

/// `TxIndex` typewraps an u16 int. It denotes the index
/// in the transaction vector of a single block

// NOTE: since we can address only 2**16 transactions,
// the maximum number of transactions per block is
// limited to 65536 transactions. I chose an u16 over
// a u32, so systems with smaller memory are not
// overburdend.

#[derive(Eq)]
#[derive(PartialEq)]
#[derive(Hash)]
#[derive(Clone)]
pub struct TxIndex(pub u16);

/// `TxId` denotes a registered transaction in the chain.
/// It is composed of the `BlockId` pointing to a block
/// in the chain and a u16 index pointing to a position
/// in the list of transactions in that block.

#[derive(Eq)]
#[derive(PartialEq)]
#[derive(Hash)]
#[derive(Clone)]
pub struct TxId{
    pub block_id: BlockId,
    pub tx_index: TxIndex,
}

impl TxId{

    /// Creates a new `TxId`

    fn new(block_id: BlockId, tx_index: TxIndex) -> TxId{
        TxId{block_id: block_id, tx_index: tx_index}
    }

}

/// `TxRel` denotes the relationship between two transactions.
/// Transactions can relate in various ways to each other.
/// For example workloads can be transformed into coupons,
/// coupons can be redeemed in a relation to a dispatcher
/// collective, etc

#[derive(Eq)]
#[derive(PartialEq)]
#[derive(Hash)]
#[derive(Clone)]
pub enum TxRel{
    Dummy
}

/// `TxLinkState` denotes the state of a (possible) link
/// between transactions
///
/// * `Unlinked`: The link points to no future target so far
/// * `SingleLinked(TxId)': The link points to a single target
///         in the future and is seen as 'spent', which means,
///         no other target transaction can be linked to the
///         source transaction in the same relationship.
/// * `MultiLinked(Vec<TxId>)`: The link points to a set of
///         transactions in the future. This is utilized by
///         transactions such as Order, that can have links
///         to multiple workloads. If a transaction is multi-
///         linked, it is the responsibility of the link
///         verification mechanism to check if possible
///         quotas are exceeded.

#[derive(Clone)]
enum TxLinkState{
    Unlinked,
    SingleLinked(TxId),
    MultiLinked(Vec<TxId>)
}

/// `TxLinkMapState` denotes the general link state of a
/// transaction. Depending on its value it can overwrite
/// the single link states. It can take the values:
///
/// * `Linkable`: The transaction can _generally_ be linked
///         to other transactions. This means that the linking
///         permit depends on the `TxLinkState` of the
///         relationship that should be established
/// * `Unlinkable`: The transaction can not be linked to any
///         other transaction (anymore). This state should
///         be used when a transaction type is deprecated
///         by a later system version or if the list of
///         (possible) links / relationships is empty
/// * `Finalized`: The transaction was finalized by another
///         transaction and can not link to a future target
///         transaction anymore.

#[derive(Clone)]
enum TxLinkMapState{
    Linkable,
    Unlinkable,
    Finalized(TxId),
}

/// `TxLinkMap` defines existing and possible links of a transaction
/// to future transactions. It maps transaction relationships to
/// `TxLinkState`s and holds a `TxLinkMapState` to denote the general
/// link state of the transaction.

#[derive(Clone)]
pub struct TxLinkMap{
    state: TxLinkMapState,
    links: HashMap<TxRel, TxLinkState>
}
<commit_msg>REFACTOR DOC + Semantics TxLinkState -> TxLink<commit_after>//
//    Stachanov
//    Copyright (C) 2017 Stachanov Developer Collective
//
//    This file is part of Stachanov.
//
//    This program is free software: you can redistribute it and/or
//    modify it under the terms of the GNU Affero General Public
//    License, version 3, as published by the Free Software Foundation.
//
//    This program is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU Affero General Public License for more details.
//
//    You should have received a copy of the
//               GNU Affero General Public License
//    along with this program.  If not, see <http://www.gnu.org/licenses/>.
//

use std::collections::HashMap;
use blockchain::traits::Hashable;
use blockchain::block::BlockId;

// NOTE: This module currently only consists of
// a dummy implementation

#[derive(Clone)]
pub enum Transaction{
    Dummy
}

impl Hashable for Transaction{

    fn to_sha3_hash(&self) -> [u8; 32]{
        [0; 32]
    }

}

/// `TxIndex` typewraps an u16 int. It denotes the index
/// in the transaction vector of a single block

// NOTE: since we can address only 2**16 transactions,
// the maximum number of transactions per block is
// limited to 65536 transactions. I chose an u16 over
// a u32, so systems with smaller memory are not
// overburdend.

#[derive(Eq)]
#[derive(PartialEq)]
#[derive(Hash)]
#[derive(Clone)]
pub struct TxIndex(pub u16);

/// `TxId` denotes a registered transaction in the chain.
/// It is composed of the `BlockId` pointing to a block
/// in the chain and a u16 index pointing to a position
/// in the list of transactions in that block.

#[derive(Eq)]
#[derive(PartialEq)]
#[derive(Hash)]
#[derive(Clone)]
pub struct TxId{
    pub block_id: BlockId,
    pub tx_index: TxIndex,
}

impl TxId{

    /// Creates a new `TxId`

    fn new(block_id: BlockId, tx_index: TxIndex) -> TxId{
        TxId{block_id: block_id, tx_index: tx_index}
    }

}

/// `TxRel` denotes the relationship between two transactions.
/// Transactions can relate in various ways to each other.
/// For example workloads can be transformed into coupons,
/// coupons can be redeemed in a relation to a dispatcher
/// collective, etc

#[derive(Eq)]
#[derive(PartialEq)]
#[derive(Hash)]
#[derive(Clone)]
pub enum TxRel{
    Dummy
}

/// `TxLink` denotes the state of a link between transactions
/// It can either be a SingleLink or a MultiLink with the
/// following semantics:
///
/// * `SingleLink(Option<TxId>)': Used for 1:1 relationships
///         between transactions. A typical example would be
///         the relationship between workloads and labor coupons.
///         Each workload can only be claimed by exactly one
///         future coupon. If the inner value is None, it
///         means the relationship has not been claimed yet.
///
/// * `MultiLink(Vec<TxId>)`: Used for 1:n relationships
///         between transactions. Instead of a single (optional)
///         transaction id, MultiLink wraps a list of ids to future
///         transactions. This is for example used in linkmaps
///         for Order transactions, which can have multiple
///         workloads attached to it. It should be emphasized,
///         that it is the responsibility of the link
///         verification mechanism to check if possible
///         quotas are exceeded.

#[derive(Clone)]
enum TxLink{
    SingleLink(Option<TxId>),
    MultiLink(Vec<TxId>)
}

/// `TxLinkMapState` denotes the general link state of a
/// transaction. Depending on its value it can overwrite
/// the single link states. It can take the values:
///
/// * `Linkable`: The transaction can _generally_ be linked
///         to other transactions. This means that the linking
///         permit depends on the state of `TxLink` for
///         each relationship.
/// * `Unlinkable`: The transaction can not be linked to any
///         other transaction (anymore). This state should
///         be used when a transaction type is deprecated
///         by a later system version or if the list of
///         relationships for the transaction is empty
/// * `Finalized`: The transaction was finalized by another
///         transaction and can not link to a future target
///         transaction anymore.

#[derive(Clone)]
enum TxLinkMapState{
    Linkable,
    Unlinkable,
    Finalized(TxId),
}

/// `TxLinkMap` defines existing and possible links of a transaction
/// to future transactions. It maps transaction relationships to
/// `TxLink`s and holds a `TxLinkMapState` to denote the general
/// link state of the transaction.

#[derive(Clone)]
pub struct TxLinkMap{
    state: TxLinkMapState,
    links: HashMap<TxRel, TxLink>
}
<|endoftext|>


<commit_before>use std::env;
use std::io;
use std::fs::File;
use std::io::prelude::*;

fn main() {
    if let Some(path) = env::args().nth(1) {
        let mut contents = String::new();
        match File::open(path) {
            Ok(mut file) => {
                match file.read_to_string(&mut contents) {
                    Ok(_) => {
                        match brainfuck::read(&contents) {
                            Ok(program) => {
                                let stdio = io::stdin();
                                let input = stdio.lock();
                                let output = io::stdout();
                                brainfuck::eval(program, input, output);
                            }
                            Err(msg) => println!("Read the file, but could not parse it: {}", msg),
                        }
                    }
                    Err(_) => println!("Found the file but failed to read it."),
                }
            }
            Err(_) => println!("Failed to open the file for reading."),
        };
    } else {
        println!("Please provide a path to some brainfuck source as the first argument.")
    }
}

mod brainfuck {
    use std::io::{Read, Write};

    #[derive(PartialEq)]
    #[derive(Debug)]
    pub enum Command {
        IncrementPointer,
        DecrementPointer,
        IncrementValue,
        DecrementValue,
        OutputValue,
        InputValue,
        ForwardsTo(usize),
        BackwardsTo(usize),
    }

    pub fn read(source: &str) -> Result<Vec<Command>, &'static str> {
        let mut jumps: Vec<usize> = vec![];
        let mut swaps: Vec<(usize, usize)> = vec![];
        let mut extra_close = false;
        let mut position: usize = 0;
        let mut program: Vec<Command> = source
            .chars()
            .filter_map(|token| {
                let command = match token {
                    '>' => Some(Command::IncrementPointer),
                    '<' => Some(Command::DecrementPointer),
                    '+' => Some(Command::IncrementValue),
                    '-' => Some(Command::DecrementValue),
                    '.' => Some(Command::OutputValue),
                    ',' => Some(Command::InputValue),
                    '[' => {
                        jumps.push(position);
                        Some(Command::BackwardsTo(position))
                    }
                    ']' => {
                        match jumps.pop() {
                            Some(jump) => {
                                swaps.push((jump, position));
                                Some(Command::ForwardsTo(position))
                            }
                            None => {
                                extra_close = true;
                                None
                            }
                        }
                    }
                    _ => None,
                };

                if command.is_some() {
                    position += 1
                }

                command
            })
            .collect();

        if jumps.len() > 0 {
            Err("Too many open braces")
        } else if extra_close {
            Err("Too many close braces")
        } else {
            for (a, b) in swaps {
                program.swap(a, b)
            }

            Ok(program)
        }
    }

    fn write_byte<W>(mut writer: W, byte: i32)
        where W: Write
    {
        write!(&mut writer, "{}", byte as u8 as char).expect("Unable to write");
    }

    fn read_byte<R>(reader: R) -> i32
        where R: Read
    {
        reader
            .bytes()
            .next()
            .and_then(|result| result.ok())
            .map(|byte| byte as i32)
            .unwrap_or(0)
    }

    pub fn eval<R, W>(program: Vec<Command>, mut reader: R, mut writer: W)
        where R: Read,
              W: Write
    {
        let mut memory: Vec<i32> = vec![0; 30000];
        let mut mem_pointer: usize = 0;
        let mut prog_pointer: usize = 0;
        let prog_len = program.len();

        while prog_pointer < prog_len {
            match program[prog_pointer] {
                Command::IncrementPointer => {
                    mem_pointer += 1;
                }
                Command::DecrementPointer => {
                    mem_pointer -= 1;
                }
                Command::IncrementValue => {
                    memory[mem_pointer] += 1;
                }
                Command::DecrementValue => {
                    memory[mem_pointer] -= 1;
                }
                Command::OutputValue => {
                    write_byte(&mut writer, memory[mem_pointer]);
                }
                Command::InputValue => {
                    memory[mem_pointer] = read_byte(&mut reader);
                }
                Command::ForwardsTo(next) => {
                    if memory[mem_pointer] == 0 {
                        prog_pointer = next;
                    }
                }
                Command::BackwardsTo(next) => {
                    if memory[mem_pointer] != 0 {
                        prog_pointer = next;
                    }
                }
            };

            prog_pointer += 1;
        }
    }
}

#[cfg(test)]
mod tests {
    use brainfuck::*;
    use brainfuck::Command::*;
    use std::io::Cursor;

    #[test]
    fn read_empty() {
        let source = "";
        let expected: Vec<Command> = vec![];

        match read(source) {
            Ok(actual) => assert_eq!(expected, actual),
            Err(_) => assert!(false),
        };
    }

    #[test]
    fn read_simple() {
        let source = "+>-<.,<.-+>,";
        let expected = vec![IncrementValue,
                            IncrementPointer,
                            DecrementValue,
                            DecrementPointer,
                            OutputValue,
                            InputValue,
                            DecrementPointer,
                            OutputValue,
                            DecrementValue,
                            IncrementValue,
                            IncrementPointer,
                            InputValue];

        match read(source) {
            Ok(actual) => assert_eq!(expected, actual),
            Err(_) => assert!(false),
        };
    }

    #[test]
    fn read_garbage() {
        let source = ",.+lol,hey.>there<";
        let expected = vec![InputValue,
                            OutputValue,
                            IncrementValue,
                            InputValue,
                            OutputValue,
                            IncrementPointer,
                            DecrementPointer];

        match read(source) {
            Ok(actual) => assert_eq!(expected, actual),
            Err(_) => assert!(false),
        };
    }

    #[test]
    fn read_loop() {
        let source = "[->+<]";
        let expected = vec![ForwardsTo(5),
                            DecrementValue,
                            IncrementPointer,
                            IncrementValue,
                            DecrementPointer,
                            BackwardsTo(0)];

        match read(source) {
            Ok(actual) => assert_eq!(expected, actual),
            Err(_) => assert!(false),
        };
    }

    #[test]
    fn read_too_many_opens() {
        let source = "[,.[,.>+-][./.[]]";
        let expected = "Too many open braces";

        match read(source) {
            Ok(_) => assert!(false),
            Err(actual) => assert_eq!(expected, actual),
        };
    }

    #[test]
    fn read_too_many_closes() {
        let source = "[,.[,.>+-][./.[]]]]]]";
        let expected = "Too many close braces";

        match read(source) {
            Ok(_) => assert!(false),
            Err(actual) => assert_eq!(expected, actual),
        };
    }

    #[test]
    fn read_nested_loops() {
        let source = "[[]]";
        let expected = vec![ForwardsTo(3), ForwardsTo(2), BackwardsTo(1), BackwardsTo(0)];

        match read(source) {
            Ok(actual) => assert_eq!(expected, actual),
            Err(_) => assert!(false),
        };
    }

    #[test]
    fn read_more_nested_loops() {
        let source = "[[[][]]]";
        let expected = vec![ForwardsTo(7),
                            ForwardsTo(6),
                            ForwardsTo(3),
                            BackwardsTo(2),
                            ForwardsTo(5),
                            BackwardsTo(4),
                            BackwardsTo(1),
                            BackwardsTo(0)];

        match read(source) {
            Ok(actual) => assert_eq!(expected, actual),
            Err(_) => assert!(false),
        };
    }

    #[test]
    fn eval_empty() {
        let input = Cursor::new(&b""[..]);
        let mut output = Cursor::new(vec![]);

        match read("") {
            Ok(program) => eval(program, input, &mut output),
            Err(_) => assert!(false),
        }

        let expected = "";
        let actual = String::from_utf8(output.into_inner()).expect("Not UTF-8");

        assert_eq!(expected, actual);
    }

    #[test]
    fn eval_new_line() {
        let input = Cursor::new(&b""[..]);
        let mut output = Cursor::new(vec![]);

        match read("++++++++++.") {
            Ok(program) => eval(program, input, &mut output),
            Err(_) => assert!(false),
        }

        let expected = "\n";
        let actual = String::from_utf8(output.into_inner()).expect("Not UTF-8");

        assert_eq!(expected, actual);
    }

    #[test]
    fn eval_cat() {
        let input = Cursor::new(&b"Hello, World!"[..]);
        let mut output = Cursor::new(vec![]);

        match read(",[.,]") {
            Ok(program) => eval(program, input, &mut output),
            Err(_) => assert!(false),
        }

        let expected = "Hello, World!";
        let actual = String::from_utf8(output.into_inner()).expect("Not UTF-8");

        assert_eq!(expected, actual);
    }

    #[test]
    fn eval_hello_world() {
        let input = Cursor::new(&b""[..]);
        let mut output = Cursor::new(vec![]);

        match read("++++++++[>++++[>++>+++>+++>+<<<<-]>+>->+>>+[<]<-]>>.>
>---.+++++++..+++.>.<<-.>.+++.------.--------.>+.>++.") {
            Ok(program) => eval(program, input, &mut output),
            Err(_) => assert!(false),
        }

        let expected = "Hello World!\n";
        let actual = String::from_utf8(output.into_inner()).expect("Not UTF-8");

        assert_eq!(expected, actual);
    }
}
<commit_msg>Flattened out the rust main fn<commit_after>use std::env;
use std::io;
use std::fs::File;
use std::io::prelude::*;

fn main() {
    let path = env::args()
        .nth(1)
        .expect("provide a path to some brainfuck source as the first argument");

    let mut contents = String::new();
    let mut file = File::open(path).expect("failed to open the file for reading");
    file.read_to_string(&mut contents)
        .expect("found the file but failed to read it");

    let program = brainfuck::read(&contents).expect("read the file, but could not parse it");

    let stdio = io::stdin();
    let input = stdio.lock();
    let output = io::stdout();
    brainfuck::eval(program, input, output);
}

mod brainfuck {
    use std::io::{Read, Write};

    #[derive(PartialEq)]
    #[derive(Debug)]
    pub enum Command {
        IncrementPointer,
        DecrementPointer,
        IncrementValue,
        DecrementValue,
        OutputValue,
        InputValue,
        ForwardsTo(usize),
        BackwardsTo(usize),
    }

    pub fn read(source: &str) -> Result<Vec<Command>, &'static str> {
        let mut jumps: Vec<usize> = vec![];
        let mut swaps: Vec<(usize, usize)> = vec![];
        let mut extra_close = false;
        let mut position: usize = 0;
        let mut program: Vec<Command> = source
            .chars()
            .filter_map(|token| {
                let command = match token {
                    '>' => Some(Command::IncrementPointer),
                    '<' => Some(Command::DecrementPointer),
                    '+' => Some(Command::IncrementValue),
                    '-' => Some(Command::DecrementValue),
                    '.' => Some(Command::OutputValue),
                    ',' => Some(Command::InputValue),
                    '[' => {
                        jumps.push(position);
                        Some(Command::BackwardsTo(position))
                    }
                    ']' => {
                        match jumps.pop() {
                            Some(jump) => {
                                swaps.push((jump, position));
                                Some(Command::ForwardsTo(position))
                            }
                            None => {
                                extra_close = true;
                                None
                            }
                        }
                    }
                    _ => None,
                };

                if command.is_some() {
                    position += 1
                }

                command
            })
            .collect();

        if jumps.len() > 0 {
            Err("Too many open braces")
        } else if extra_close {
            Err("Too many close braces")
        } else {
            for (a, b) in swaps {
                program.swap(a, b)
            }

            Ok(program)
        }
    }

    fn write_byte<W>(mut writer: W, byte: i32)
        where W: Write
    {
        write!(&mut writer, "{}", byte as u8 as char).expect("Unable to write");
    }

    fn read_byte<R>(reader: R) -> i32
        where R: Read
    {
        reader
            .bytes()
            .next()
            .and_then(|result| result.ok())
            .map(|byte| byte as i32)
            .unwrap_or(0)
    }

    pub fn eval<R, W>(program: Vec<Command>, mut reader: R, mut writer: W)
        where R: Read,
              W: Write
    {
        let mut memory: Vec<i32> = vec![0; 30000];
        let mut mem_pointer: usize = 0;
        let mut prog_pointer: usize = 0;
        let prog_len = program.len();

        while prog_pointer < prog_len {
            match program[prog_pointer] {
                Command::IncrementPointer => {
                    mem_pointer += 1;
                }
                Command::DecrementPointer => {
                    mem_pointer -= 1;
                }
                Command::IncrementValue => {
                    memory[mem_pointer] += 1;
                }
                Command::DecrementValue => {
                    memory[mem_pointer] -= 1;
                }
                Command::OutputValue => {
                    write_byte(&mut writer, memory[mem_pointer]);
                }
                Command::InputValue => {
                    memory[mem_pointer] = read_byte(&mut reader);
                }
                Command::ForwardsTo(next) => {
                    if memory[mem_pointer] == 0 {
                        prog_pointer = next;
                    }
                }
                Command::BackwardsTo(next) => {
                    if memory[mem_pointer] != 0 {
                        prog_pointer = next;
                    }
                }
            };

            prog_pointer += 1;
        }
    }
}

#[cfg(test)]
mod tests {
    use brainfuck::*;
    use brainfuck::Command::*;
    use std::io::Cursor;

    #[test]
    fn read_empty() {
        let source = "";
        let expected: Vec<Command> = vec![];

        match read(source) {
            Ok(actual) => assert_eq!(expected, actual),
            Err(_) => assert!(false),
        };
    }

    #[test]
    fn read_simple() {
        let source = "+>-<.,<.-+>,";
        let expected = vec![IncrementValue,
                            IncrementPointer,
                            DecrementValue,
                            DecrementPointer,
                            OutputValue,
                            InputValue,
                            DecrementPointer,
                            OutputValue,
                            DecrementValue,
                            IncrementValue,
                            IncrementPointer,
                            InputValue];

        match read(source) {
            Ok(actual) => assert_eq!(expected, actual),
            Err(_) => assert!(false),
        };
    }

    #[test]
    fn read_garbage() {
        let source = ",.+lol,hey.>there<";
        let expected = vec![InputValue,
                            OutputValue,
                            IncrementValue,
                            InputValue,
                            OutputValue,
                            IncrementPointer,
                            DecrementPointer];

        match read(source) {
            Ok(actual) => assert_eq!(expected, actual),
            Err(_) => assert!(false),
        };
    }

    #[test]
    fn read_loop() {
        let source = "[->+<]";
        let expected = vec![ForwardsTo(5),
                            DecrementValue,
                            IncrementPointer,
                            IncrementValue,
                            DecrementPointer,
                            BackwardsTo(0)];

        match read(source) {
            Ok(actual) => assert_eq!(expected, actual),
            Err(_) => assert!(false),
        };
    }

    #[test]
    fn read_too_many_opens() {
        let source = "[,.[,.>+-][./.[]]";
        let expected = "Too many open braces";

        match read(source) {
            Ok(_) => assert!(false),
            Err(actual) => assert_eq!(expected, actual),
        };
    }

    #[test]
    fn read_too_many_closes() {
        let source = "[,.[,.>+-][./.[]]]]]]";
        let expected = "Too many close braces";

        match read(source) {
            Ok(_) => assert!(false),
            Err(actual) => assert_eq!(expected, actual),
        };
    }

    #[test]
    fn read_nested_loops() {
        let source = "[[]]";
        let expected = vec![ForwardsTo(3), ForwardsTo(2), BackwardsTo(1), BackwardsTo(0)];

        match read(source) {
            Ok(actual) => assert_eq!(expected, actual),
            Err(_) => assert!(false),
        };
    }

    #[test]
    fn read_more_nested_loops() {
        let source = "[[[][]]]";
        let expected = vec![ForwardsTo(7),
                            ForwardsTo(6),
                            ForwardsTo(3),
                            BackwardsTo(2),
                            ForwardsTo(5),
                            BackwardsTo(4),
                            BackwardsTo(1),
                            BackwardsTo(0)];

        match read(source) {
            Ok(actual) => assert_eq!(expected, actual),
            Err(_) => assert!(false),
        };
    }

    #[test]
    fn eval_empty() {
        let input = Cursor::new(&b""[..]);
        let mut output = Cursor::new(vec![]);

        match read("") {
            Ok(program) => eval(program, input, &mut output),
            Err(_) => assert!(false),
        }

        let expected = "";
        let actual = String::from_utf8(output.into_inner()).expect("Not UTF-8");

        assert_eq!(expected, actual);
    }

    #[test]
    fn eval_new_line() {
        let input = Cursor::new(&b""[..]);
        let mut output = Cursor::new(vec![]);

        match read("++++++++++.") {
            Ok(program) => eval(program, input, &mut output),
            Err(_) => assert!(false),
        }

        let expected = "\n";
        let actual = String::from_utf8(output.into_inner()).expect("Not UTF-8");

        assert_eq!(expected, actual);
    }

    #[test]
    fn eval_cat() {
        let input = Cursor::new(&b"Hello, World!"[..]);
        let mut output = Cursor::new(vec![]);

        match read(",[.,]") {
            Ok(program) => eval(program, input, &mut output),
            Err(_) => assert!(false),
        }

        let expected = "Hello, World!";
        let actual = String::from_utf8(output.into_inner()).expect("Not UTF-8");

        assert_eq!(expected, actual);
    }

    #[test]
    fn eval_hello_world() {
        let input = Cursor::new(&b""[..]);
        let mut output = Cursor::new(vec![]);

        match read("++++++++[>++++[>++>+++>+++>+<<<<-]>+>->+>>+[<]<-]>>.>
>---.+++++++..+++.>.<<-.>.+++.------.--------.>+.>++.") {
            Ok(program) => eval(program, input, &mut output),
            Err(_) => assert!(false),
        }

        let expected = "Hello World!\n";
        let actual = String::from_utf8(output.into_inner()).expect("Not UTF-8");

        assert_eq!(expected, actual);
    }
}
<|endoftext|>


<commit_before>#[cfg(feature = "serialization")]
use serde::{Deserialize, Serialize};
use std::fmt;
use std::ops::Range;

use crate::ByteIndex;

#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "serialization", derive(Deserialize, Serialize))]
pub struct Span {
    start: ByteIndex,
    end: ByteIndex,
}

impl Span {
    /// Create a new span from a starting and ending span.
    pub fn new(start: impl Into<ByteIndex>, end: impl Into<ByteIndex>) -> Span {
        let start = start.into();
        let end = end.into();

        assert!(end >= start);

        Span { start, end }
    }

    /// Gives an empty span at the start of a source.
    pub const fn initial() -> Span {
        Span {
            start: ByteIndex(0),
            end: ByteIndex(0),
        }
    }

    /// Measure the span of a string.
    ///
    /// ```rust
    /// use codespan::{ByteIndex, Span};
    ///
    /// let span = Span::from_str("hello");
    ///
    /// assert_eq!(span, Span::new(0, 5));
    /// ```
    pub fn from_str(s: &str) -> Span {
        Span::new(0, s.len() as u32)
    }

    /// Combine two spans by taking the start of the earlier span
    /// and the end of the later span.
    ///
    /// Note: this will work even if the two spans are disjoint.
    /// If this doesn't make sense in your application, you should handle it yourself.
    /// In that case, you can use `Span::disjoint` as a convenience function.
    ///
    /// ```rust
    /// use codespan::Span;
    ///
    /// let span1 = Span::new(0, 4);
    /// let span2 = Span::new(10, 16);
    ///
    /// assert_eq!(Span::merge(span1, span2), Span::new(0, 16));
    /// ```
    pub fn merge(self, other: Span) -> Span {
        use std::cmp::{max, min};

        let start = min(self.start, other.start);
        let end = max(self.end, other.end);
        Span::new(start, end)
    }

    /// A helper function to tell whether two spans do not overlap.
    ///
    /// ```
    /// use codespan::Span;
    /// let span1 = Span::new(0, 4);
    /// let span2 = Span::new(10, 16);
    /// assert!(span1.disjoint(span2));
    /// ```
    pub fn disjoint(self, other: Span) -> bool {
        let (first, last) = if self.end < other.end {
            (self, other)
        } else {
            (other, self)
        };
        first.end <= last.start
    }

    /// Get the starting byte index.
    ///
    /// ```rust
    /// use codespan::{ByteIndex, Span};
    ///
    /// let span = Span::new(0, 4);
    ///
    /// assert_eq!(span.start(), ByteIndex::from(0));
    /// ```
    pub fn start(self) -> ByteIndex {
        self.start
    }

    /// Get the ending byte index.
    ///
    /// ```rust
    /// use codespan::{ByteIndex, Span};
    ///
    /// let span = Span::new(0, 4);
    ///
    /// assert_eq!(span.end(), ByteIndex::from(4));
    /// ```
    pub fn end(self) -> ByteIndex {
        self.end
    }
}

impl Default for Span {
    fn default() -> Span {
        Span::initial()
    }
}

impl fmt::Display for Span {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(
            f,
            "[{start}, {end})",
            start = self.start(),
            end = self.end(),
        )
    }
}

impl<I> From<Range<I>> for Span
where
    I: Into<ByteIndex>,
{
    fn from(range: Range<I>) -> Span {
        Span::new(range.start, range.end)
    }
}

#[cfg(test)]
mod test {
    #[test]
    fn test_merge() {
        use super::Span;

        // overlap
        let a = Span::from(1..5);
        let b = Span::from(3..10);
        assert_eq!(a.merge(b), Span::from(1..10));
        assert_eq!(b.merge(a), Span::from(1..10));

        // subset
        let two_four = (2..4).into();
        assert_eq!(a.merge(two_four), (1..5).into());
        assert_eq!(two_four.merge(a), (1..5).into());

        // disjoint
        let ten_twenty = (10..20).into();
        assert_eq!(a.merge(ten_twenty), (1..20).into());
        assert_eq!(ten_twenty.merge(a), (1..20).into());

        // identity
        assert_eq!(a.merge(a), a);
    }
    #[test]
    fn test_disjoint() {
        use super::Span;

        // overlap
        let a = Span::from(1..5);
        let b = Span::from(3..10);
        assert!(!a.disjoint(b));
        assert!(!b.disjoint(a));

        // subset
        let two_four = (2..4).into();
        assert!(!a.disjoint(two_four));
        assert!(!two_four.disjoint(a));

        // disjoint
        let ten_twenty = (10..20).into();
        assert!(a.disjoint(ten_twenty));
        assert!(ten_twenty.disjoint(a));

        // identity
        assert!(!a.disjoint(a));

        // off by one (upper bound)
        let c = Span::from(5..10);
        assert!(a.disjoint(c));
        assert!(c.disjoint(a));
        // off by one (lower bound)
        let d = Span::from(0..1);
        assert!(a.disjoint(d));
        assert!(d.disjoint(a));
    }
}
<commit_msg>Fix formatting #2<commit_after>#[cfg(feature = "serialization")]
use serde::{Deserialize, Serialize};
use std::fmt;
use std::ops::Range;

use crate::ByteIndex;

#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "serialization", derive(Deserialize, Serialize))]
pub struct Span {
    start: ByteIndex,
    end: ByteIndex,
}

impl Span {
    /// Create a new span from a starting and ending span.
    pub fn new(start: impl Into<ByteIndex>, end: impl Into<ByteIndex>) -> Span {
        let start = start.into();
        let end = end.into();

        assert!(end >= start);

        Span { start, end }
    }

    /// Gives an empty span at the start of a source.
    pub const fn initial() -> Span {
        Span {
            start: ByteIndex(0),
            end: ByteIndex(0),
        }
    }

    /// Measure the span of a string.
    ///
    /// ```rust
    /// use codespan::{ByteIndex, Span};
    ///
    /// let span = Span::from_str("hello");
    ///
    /// assert_eq!(span, Span::new(0, 5));
    /// ```
    pub fn from_str(s: &str) -> Span {
        Span::new(0, s.len() as u32)
    }

    /// Combine two spans by taking the start of the earlier span
    /// and the end of the later span.
    ///
    /// Note: this will work even if the two spans are disjoint.
    /// If this doesn't make sense in your application, you should handle it yourself.
    /// In that case, you can use `Span::disjoint` as a convenience function.
    ///
    /// ```rust
    /// use codespan::Span;
    ///
    /// let span1 = Span::new(0, 4);
    /// let span2 = Span::new(10, 16);
    ///
    /// assert_eq!(Span::merge(span1, span2), Span::new(0, 16));
    /// ```
    pub fn merge(self, other: Span) -> Span {
        use std::cmp::{max, min};

        let start = min(self.start, other.start);
        let end = max(self.end, other.end);
        Span::new(start, end)
    }

    /// A helper function to tell whether two spans do not overlap.
    ///
    /// ```
    /// use codespan::Span;
    /// let span1 = Span::new(0, 4);
    /// let span2 = Span::new(10, 16);
    /// assert!(span1.disjoint(span2));
    /// ```
    pub fn disjoint(self, other: Span) -> bool {
        let (first, last) = if self.end < other.end {
            (self, other)
        } else {
            (other, self)
        };
        first.end <= last.start
    }

    /// Get the starting byte index.
    ///
    /// ```rust
    /// use codespan::{ByteIndex, Span};
    ///
    /// let span = Span::new(0, 4);
    ///
    /// assert_eq!(span.start(), ByteIndex::from(0));
    /// ```
    pub fn start(self) -> ByteIndex {
        self.start
    }

    /// Get the ending byte index.
    ///
    /// ```rust
    /// use codespan::{ByteIndex, Span};
    ///
    /// let span = Span::new(0, 4);
    ///
    /// assert_eq!(span.end(), ByteIndex::from(4));
    /// ```
    pub fn end(self) -> ByteIndex {
        self.end
    }
}

impl Default for Span {
    fn default() -> Span {
        Span::initial()
    }
}

impl fmt::Display for Span {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(
            f,
            "[{start}, {end})",
            start = self.start(),
            end = self.end(),
        )
    }
}

impl<I> From<Range<I>> for Span
where
    I: Into<ByteIndex>,
{
    fn from(range: Range<I>) -> Span {
        Span::new(range.start, range.end)
    }
}

#[cfg(test)]
mod test {
    #[test]
    fn test_merge() {
        use super::Span;

        // overlap
        let a = Span::from(1..5);
        let b = Span::from(3..10);
        assert_eq!(a.merge(b), Span::from(1..10));
        assert_eq!(b.merge(a), Span::from(1..10));

        // subset
        let two_four = (2..4).into();
        assert_eq!(a.merge(two_four), (1..5).into());
        assert_eq!(two_four.merge(a), (1..5).into());

        // disjoint
        let ten_twenty = (10..20).into();
        assert_eq!(a.merge(ten_twenty), (1..20).into());
        assert_eq!(ten_twenty.merge(a), (1..20).into());

        // identity
        assert_eq!(a.merge(a), a);
    }

    #[test]
    fn test_disjoint() {
        use super::Span;

        // overlap
        let a = Span::from(1..5);
        let b = Span::from(3..10);
        assert!(!a.disjoint(b));
        assert!(!b.disjoint(a));

        // subset
        let two_four = (2..4).into();
        assert!(!a.disjoint(two_four));
        assert!(!two_four.disjoint(a));

        // disjoint
        let ten_twenty = (10..20).into();
        assert!(a.disjoint(ten_twenty));
        assert!(ten_twenty.disjoint(a));

        // identity
        assert!(!a.disjoint(a));

        // off by one (upper bound)
        let c = Span::from(5..10);
        assert!(a.disjoint(c));
        assert!(c.disjoint(a));
        // off by one (lower bound)
        let d = Span::from(0..1);
        assert!(a.disjoint(d));
        assert!(d.disjoint(a));
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;

use crate::data::frame::ArcFrame;
use crate::data::packet::Packet;

use crate::common::CodecList;
use crate::error::*;

/// Used to interact with a decoder.
pub trait Decoder: Send + Sync {
    // TODO support codec configuration using set_option
    // fn open(&mut self) -> Result<()>;
    /// Saves the extra data contained in a codec.
    fn set_extradata(&mut self, extra: &[u8]);
    /// Sends to the decoder a packet to be decoded.
    fn send_packet(&mut self, pkt: &Packet) -> Result<()>;
    /// Returns a decoded frame.
    fn receive_frame(&mut self) -> Result<ArcFrame>;
    /// Configures the decoder.
    fn configure(&mut self) -> Result<()>;
    /// Tells decoder to clear its internal state.
    fn flush(&mut self) -> Result<()>;
}

/// Codec descriptor.
///
/// Contains information on a codec and its own decoder.
#[derive(Debug)]
pub struct Descr {
    /// The codec name.
    pub codec: &'static str,
    /// The extended codec name.
    pub name: &'static str,
    /// The codec description.
    pub desc: &'static str,
    /// The codec MIME.
    pub mime: &'static str,
    // TODO more fields regarding capabilities
}

/// Auxiliary structure to encapsulate a decoder object and
/// its additional data.
pub struct Context<D: Decoder> {
    dec: D,
    // TODO: Queue up packets/frames
}

impl<D: Decoder> Context<D> {
    // TODO: More constructors
    /// Retrieves a codec descriptor from a codec list through its name,
    /// creates the relative decoder, and encapsulates it into a new `Context`.
    pub fn by_name<T: Descriptor<OutputDecoder = D> + ?Sized>(
        codecs: &Codecs<T>,
        name: &str,
    ) -> Option<Self> {
        codecs.by_name(name).map(|builder| Context {
            dec: builder.create(),
        })
    }
    /// Saves the extra data contained in a codec.
    pub fn set_extradata(&mut self, extra: &[u8]) {
        self.dec.set_extradata(extra);
    }

    /// Sends to the decoder a packet to be decoded.
    pub fn send_packet(&mut self, pkt: &Packet) -> Result<()> {
        self.dec.send_packet(pkt)
    }
    /// Returns a decoded frame.
    pub fn receive_frame(&mut self) -> Result<ArcFrame> {
        self.dec.receive_frame()
    }
    /// Configures the decoder.
    pub fn configure(&mut self) -> Result<()> {
        self.dec.configure()
    }

    /// Tells decoder to clear its internal state.
    pub fn flush(&mut self) -> Result<()> {
        self.dec.flush()
    }
}

/// Used to get the descriptor of a codec and create its own decoder.
pub trait Descriptor {
    type OutputDecoder: Decoder;

    /// Creates a new decoder for the requested codec.
    fn create(&self) -> Self::OutputDecoder;
    /// Returns the codec descriptor.
    fn describe(&self) -> &Descr;
}

/// A list of codec descriptors.
pub struct Codecs<T: 'static + Descriptor + ?Sized> {
    list: HashMap<&'static str, Vec<&'static T>>,
}

impl<T: Descriptor + ?Sized> CodecList for Codecs<T> {
    type D = T;

    fn new() -> Self {
        Codecs {
            list: HashMap::new(),
        }
    }

    // TODO more lookup functions
    fn by_name(&self, name: &str) -> Option<&'static Self::D> {
        self.list.get(name).map(|descs| descs[0])
    }

    fn append(&mut self, desc: &'static Self::D) {
        let codec_name = desc.describe().codec;

        self.list
            .entry(codec_name)
            .or_insert_with(Vec::new)
            .push(desc);
    }
}

#[cfg(test)]
mod test {
    use super::*;

    mod dummy {
        use super::super::*;
        use crate::data::pixel::Formaton;
        use std::sync::Arc;

        pub struct Dec {
            state: usize,
            #[allow(dead_code)]
            format: Option<Arc<Formaton>>,
        }

        pub struct Des {
            descr: Descr,
        }

        impl Descriptor for Des {
            type OutputDecoder = Dec;

            fn create(&self) -> Self::OutputDecoder {
                Dec {
                    state: 0,
                    format: None,
                }
            }

            fn describe(&self) -> &Descr {
                &self.descr
            }
        }

        impl Decoder for Dec {
            fn configure(&mut self) -> Result<()> {
                Ok(())
            }
            fn set_extradata(&mut self, extra: &[u8]) {
                if extra.len() > 4 {
                    self.state = 42;
                } else {
                    self.state = 12;
                }
            }
            fn send_packet(&mut self, _packet: &Packet) -> Result<()> {
                self.state += 1;
                Ok(())
            }
            fn receive_frame(&mut self) -> Result<ArcFrame> {
                unimplemented!()
            }
            fn flush(&mut self) -> Result<()> {
                Ok(())
            }
        }

        pub const DUMMY_DESCR: &Des = &Des {
            descr: Descr {
                codec: "dummy",
                name: "dummy",
                desc: "Dummy decoder",
                mime: "x-application/dummy",
            },
        };
    }
    use self::dummy::DUMMY_DESCR;

    #[test]
    fn lookup() {
        let codecs = Codecs::from_list(&[DUMMY_DESCR]);

        let _dec = codecs.by_name("dummy").unwrap();
    }
}
<commit_msg>codec: Add an API to get the underlying decoder<commit_after>use std::collections::HashMap;

use crate::data::frame::ArcFrame;
use crate::data::packet::Packet;

use crate::common::CodecList;
use crate::error::*;

/// Used to interact with a decoder.
pub trait Decoder: Send + Sync {
    // TODO support codec configuration using set_option
    // fn open(&mut self) -> Result<()>;
    /// Saves the extra data contained in a codec.
    fn set_extradata(&mut self, extra: &[u8]);
    /// Sends to the decoder a packet to be decoded.
    fn send_packet(&mut self, pkt: &Packet) -> Result<()>;
    /// Returns a decoded frame.
    fn receive_frame(&mut self) -> Result<ArcFrame>;
    /// Configures the decoder.
    fn configure(&mut self) -> Result<()>;
    /// Tells decoder to clear its internal state.
    fn flush(&mut self) -> Result<()>;
}

/// Codec descriptor.
///
/// Contains information on a codec and its own decoder.
#[derive(Debug)]
pub struct Descr {
    /// The codec name.
    pub codec: &'static str,
    /// The extended codec name.
    pub name: &'static str,
    /// The codec description.
    pub desc: &'static str,
    /// The codec MIME.
    pub mime: &'static str,
    // TODO more fields regarding capabilities
}

/// Auxiliary structure to encapsulate a decoder object and
/// its additional data.
pub struct Context<D: Decoder> {
    dec: D,
    // TODO: Queue up packets/frames
}

impl<D: Decoder> Context<D> {
    // TODO: More constructors
    /// Retrieves a codec descriptor from a codec list through its name,
    /// creates the relative decoder, and encapsulates it into a new `Context`.
    pub fn by_name<T: Descriptor<OutputDecoder = D> + ?Sized>(
        codecs: &Codecs<T>,
        name: &str,
    ) -> Option<Self> {
        codecs.by_name(name).map(|builder| Context {
            dec: builder.create(),
        })
    }
    /// Saves the extra data contained in a codec.
    pub fn set_extradata(&mut self, extra: &[u8]) {
        self.dec.set_extradata(extra);
    }

    /// Sends to the decoder a packet to be decoded.
    pub fn send_packet(&mut self, pkt: &Packet) -> Result<()> {
        self.dec.send_packet(pkt)
    }
    /// Returns a decoded frame.
    pub fn receive_frame(&mut self) -> Result<ArcFrame> {
        self.dec.receive_frame()
    }
    /// Configures the decoder.
    pub fn configure(&mut self) -> Result<()> {
        self.dec.configure()
    }

    /// Tells decoder to clear its internal state.
    pub fn flush(&mut self) -> Result<()> {
        self.dec.flush()
    }

    /// Returns the underlying decoder.
    pub fn decoder(&self) -> &D {
        &self.dec
    }
}

/// Used to get the descriptor of a codec and create its own decoder.
pub trait Descriptor {
    type OutputDecoder: Decoder;

    /// Creates a new decoder for the requested codec.
    fn create(&self) -> Self::OutputDecoder;
    /// Returns the codec descriptor.
    fn describe(&self) -> &Descr;
}

/// A list of codec descriptors.
pub struct Codecs<T: 'static + Descriptor + ?Sized> {
    list: HashMap<&'static str, Vec<&'static T>>,
}

impl<T: Descriptor + ?Sized> CodecList for Codecs<T> {
    type D = T;

    fn new() -> Self {
        Codecs {
            list: HashMap::new(),
        }
    }

    // TODO more lookup functions
    fn by_name(&self, name: &str) -> Option<&'static Self::D> {
        self.list.get(name).map(|descs| descs[0])
    }

    fn append(&mut self, desc: &'static Self::D) {
        let codec_name = desc.describe().codec;

        self.list
            .entry(codec_name)
            .or_insert_with(Vec::new)
            .push(desc);
    }
}

#[cfg(test)]
mod test {
    use super::*;

    mod dummy {
        use super::super::*;
        use crate::data::pixel::Formaton;
        use std::sync::Arc;

        pub struct Dec {
            state: usize,
            #[allow(dead_code)]
            format: Option<Arc<Formaton>>,
        }

        pub struct Des {
            descr: Descr,
        }

        impl Descriptor for Des {
            type OutputDecoder = Dec;

            fn create(&self) -> Self::OutputDecoder {
                Dec {
                    state: 0,
                    format: None,
                }
            }

            fn describe(&self) -> &Descr {
                &self.descr
            }
        }

        impl Decoder for Dec {
            fn configure(&mut self) -> Result<()> {
                Ok(())
            }
            fn set_extradata(&mut self, extra: &[u8]) {
                if extra.len() > 4 {
                    self.state = 42;
                } else {
                    self.state = 12;
                }
            }
            fn send_packet(&mut self, _packet: &Packet) -> Result<()> {
                self.state += 1;
                Ok(())
            }
            fn receive_frame(&mut self) -> Result<ArcFrame> {
                unimplemented!()
            }
            fn flush(&mut self) -> Result<()> {
                Ok(())
            }
        }

        pub const DUMMY_DESCR: &Des = &Des {
            descr: Descr {
                codec: "dummy",
                name: "dummy",
                desc: "Dummy decoder",
                mime: "x-application/dummy",
            },
        };
    }
    use self::dummy::DUMMY_DESCR;

    #[test]
    fn lookup() {
        let codecs = Codecs::from_list(&[DUMMY_DESCR]);

        let _dec = codecs.by_name("dummy").unwrap();
    }
}
<|endoftext|>