<commit_before>use std::io::prelude::*;

use crate::core::{resolver, Resolve, ResolveVersion, Workspace};
use crate::util::errors::CargoResult;
use crate::util::toml as cargo_toml;
use crate::util::Filesystem;

use anyhow::Context as _;
use toml_edit::easy as toml;

pub fn load_pkg_lockfile(ws: &Workspace<'_>) -> CargoResult<Option<Resolve>> {
    if !ws.root().join("Cargo.lock").exists() {
        return Ok(None);
    }

    let root = Filesystem::new(ws.root().to_path_buf());
    let mut f = root.open_ro("Cargo.lock", ws.config(), "Cargo.lock file")?;

    let mut s = String::new();
    f.read_to_string(&mut s)
        .with_context(|| format!("failed to read file: {}", f.path().display()))?;

    let resolve = (|| -> CargoResult<Option<Resolve>> {
        let resolve: toml::Value = cargo_toml::parse(&s, f.path(), ws.config())?;
        let v: resolver::EncodableResolve = resolve.try_into()?;
        Ok(Some(v.into_resolve(&s, ws)?))
    })()
    .with_context(|| format!("failed to parse lock file at: {}", f.path().display()))?;
    Ok(resolve)
}

/// Generate a toml String of Cargo.lock from a Resolve.
pub fn resolve_to_string(ws: &Workspace<'_>, resolve: &mut Resolve) -> CargoResult<String> {
    let (_orig, out, _ws_root) = resolve_to_string_orig(ws, resolve);
    Ok(out)
}

pub fn write_pkg_lockfile(ws: &Workspace<'_>, resolve: &mut Resolve) -> CargoResult<()> {
    let (orig, mut out, ws_root) = resolve_to_string_orig(ws, resolve);

    // If the lock file contents haven't changed so don't rewrite it. This is
    // helpful on read-only filesystems.
    if let Some(orig) = &orig {
        if are_equal_lockfiles(orig, &out, ws) {
            return Ok(());
        }
    }

    if !ws.config().lock_update_allowed() {
        let flag = if ws.config().network_allowed() {
            "--locked"
        } else {
            "--frozen"
        };
        anyhow::bail!(
            "the lock file {} needs to be updated but {} was passed to prevent this\n\
             If you want to try to generate the lock file without accessing the network, \
             remove the {} flag and use --offline instead.",
            ws.root().to_path_buf().join("Cargo.lock").display(),
            flag,
            flag
        );
    }

    // While we're updating the lock file anyway go ahead and update its
    // encoding to whatever the latest default is. That way we can slowly roll
    // out lock file updates as they're otherwise already updated, and changes
    // which don't touch dependencies won't seemingly spuriously update the lock
    // file.
    if resolve.version() < ResolveVersion::default() {
        resolve.set_version(ResolveVersion::default());
        out = serialize_resolve(resolve, orig.as_deref());
    }

    // Ok, if that didn't work just write it out
    ws_root
        .open_rw("Cargo.lock", ws.config(), "Cargo.lock file")
        .and_then(|mut f| {
            f.file().set_len(0)?;
            f.write_all(out.as_bytes())?;
            Ok(())
        })
        .with_context(|| format!("failed to write {}", ws.root().join("Cargo.lock").display()))?;
    Ok(())
}

fn resolve_to_string_orig(
    ws: &Workspace<'_>,
    resolve: &mut Resolve,
) -> (Option<String>, String, Filesystem) {
    // Load the original lock file if it exists.
    let ws_root = Filesystem::new(ws.root().to_path_buf());
    let orig = ws_root.open_ro("Cargo.lock", ws.config(), "Cargo.lock file");
    let orig = orig.and_then(|mut f| {
        let mut s = String::new();
        f.read_to_string(&mut s)?;
        Ok(s)
    });
    let out = serialize_resolve(resolve, orig.as_deref().ok());
    (orig.ok(), out, ws_root)
}

fn serialize_resolve(resolve: &Resolve, orig: Option<&str>) -> String {
    let toml = toml_edit::ser::to_item(resolve).unwrap();

    let mut out = String::new();

    // At the start of the file we notify the reader that the file is generated.
    // Specifically Phabricator ignores files containing "@generated", so we use that.
    let marker_line = "# This file is automatically @generated by Cargo.";
    let extra_line = "# It is not intended for manual editing.";
    out.push_str(marker_line);
    out.push('\n');
    out.push_str(extra_line);
    out.push('\n');
    // and preserve any other top comments
    if let Some(orig) = orig {
        let mut comments = orig.lines().take_while(|line| line.starts_with('#'));
        if let Some(first) = comments.next() {
            if first != marker_line {
                out.push_str(first);
                out.push('\n');
            }
            if let Some(second) = comments.next() {
                if second != extra_line {
                    out.push_str(second);
                    out.push('\n');
                }
                for line in comments {
                    out.push_str(line);
                    out.push('\n');
                }
            }
        }
    }

    if let Some(version) = toml.get("version") {
        out.push_str(&format!("version = {}\n\n", version));
    }

    let deps = toml["package"].as_array().unwrap();
    for dep in deps {
        let dep = dep.as_inline_table().unwrap();

        out.push_str("[[package]]\n");
        emit_package(dep, &mut out);
    }

    if let Some(patch) = toml.get("patch") {
        let list = patch["unused"].as_array().unwrap();
        for entry in list {
            out.push_str("[[patch.unused]]\n");
            emit_package(entry.as_inline_table().unwrap(), &mut out);
            out.push('\n');
        }
    }

    if let Some(meta) = toml.get("metadata") {
        // 1. We need to ensure we print the entire tree, not just the direct members of `metadata`
        //    (which `toml_edit::Table::to_string` only shows)
        // 2. We need to ensure all children tables have `metadata.` prefix
        let meta_table = meta
            .clone()
            .into_table()
            .expect("validation ensures this is a table");
        let mut meta_doc = toml_edit::Document::new();
        meta_doc["metadata"] = toml_edit::Item::Table(meta_table);

        out.push_str(&meta_doc.to_string());
    }

    // Historical versions of Cargo in the old format accidentally left trailing
    // blank newlines at the end of files, so we just leave that as-is. For all
    // encodings going forward, though, we want to be sure that our encoded lock
    // file doesn't contain any trailing newlines so trim out the extra if
    // necessary.
    if resolve.version() >= ResolveVersion::V2 {
        while out.ends_with("\n\n") {
            out.pop();
        }
    }
    out
}

fn are_equal_lockfiles(orig: &str, current: &str, ws: &Workspace<'_>) -> bool {
    // If we want to try and avoid updating the lock file, parse both and
    // compare them; since this is somewhat expensive, don't do it in the
    // common case where we can update lock files.
    if !ws.config().lock_update_allowed() {
        let res: CargoResult<bool> = (|| {
            let old: resolver::EncodableResolve = toml::from_str(orig)?;
            let new: resolver::EncodableResolve = toml::from_str(current)?;
            Ok(old.into_resolve(orig, ws)? == new.into_resolve(current, ws)?)
        })();
        if let Ok(true) = res {
            return true;
        }
    }

    orig.lines().eq(current.lines())
}

fn emit_package(dep: &toml_edit::InlineTable, out: &mut String) {
    out.push_str(&format!("name = {}\n", &dep["name"]));
    out.push_str(&format!("version = {}\n", &dep["version"]));

    if dep.contains_key("source") {
        out.push_str(&format!("source = {}\n", &dep["source"]));
    }
    if dep.contains_key("checksum") {
        out.push_str(&format!("checksum = {}\n", &dep["checksum"]));
    }

    if let Some(s) = dep.get("dependencies") {
        let slice = s.as_array().unwrap();

        if !slice.is_empty() {
            out.push_str("dependencies = [\n");

            for child in slice.iter() {
                out.push_str(&format!(" {},\n", child));
            }

            out.push_str("]\n");
        }
        out.push('\n');
    } else if dep.contains_key("replace") {
        out.push_str(&format!("replace = {}\n\n", &dep["replace"]));
    }
}
<commit_msg>Use the correct the flag in --locked --offline error message<commit_after>use std::io::prelude::*;

use crate::core::{resolver, Resolve, ResolveVersion, Workspace};
use crate::util::errors::CargoResult;
use crate::util::toml as cargo_toml;
use crate::util::Filesystem;

use anyhow::Context as _;
use toml_edit::easy as toml;

pub fn load_pkg_lockfile(ws: &Workspace<'_>) -> CargoResult<Option<Resolve>> {
    if !ws.root().join("Cargo.lock").exists() {
        return Ok(None);
    }

    let root = Filesystem::new(ws.root().to_path_buf());
    let mut f = root.open_ro("Cargo.lock", ws.config(), "Cargo.lock file")?;

    let mut s = String::new();
    f.read_to_string(&mut s)
        .with_context(|| format!("failed to read file: {}", f.path().display()))?;

    let resolve = (|| -> CargoResult<Option<Resolve>> {
        let resolve: toml::Value = cargo_toml::parse(&s, f.path(), ws.config())?;
        let v: resolver::EncodableResolve = resolve.try_into()?;
        Ok(Some(v.into_resolve(&s, ws)?))
    })()
    .with_context(|| format!("failed to parse lock file at: {}", f.path().display()))?;
    Ok(resolve)
}

/// Generate a toml String of Cargo.lock from a Resolve.
pub fn resolve_to_string(ws: &Workspace<'_>, resolve: &mut Resolve) -> CargoResult<String> {
    let (_orig, out, _ws_root) = resolve_to_string_orig(ws, resolve);
    Ok(out)
}

pub fn write_pkg_lockfile(ws: &Workspace<'_>, resolve: &mut Resolve) -> CargoResult<()> {
    let (orig, mut out, ws_root) = resolve_to_string_orig(ws, resolve);

    // If the lock file contents haven't changed so don't rewrite it. This is
    // helpful on read-only filesystems.
    if let Some(orig) = &orig {
        if are_equal_lockfiles(orig, &out, ws) {
            return Ok(());
        }
    }

    if !ws.config().lock_update_allowed() {
        let flag = if ws.config().locked() {
            "--locked"
        } else {
            "--frozen"
        };
        anyhow::bail!(
            "the lock file {} needs to be updated but {} was passed to prevent this\n\
             If you want to try to generate the lock file without accessing the network, \
             remove the {} flag and use --offline instead.",
            ws.root().to_path_buf().join("Cargo.lock").display(),
            flag,
            flag
        );
    }

    // While we're updating the lock file anyway go ahead and update its
    // encoding to whatever the latest default is. That way we can slowly roll
    // out lock file updates as they're otherwise already updated, and changes
    // which don't touch dependencies won't seemingly spuriously update the lock
    // file.
    if resolve.version() < ResolveVersion::default() {
        resolve.set_version(ResolveVersion::default());
        out = serialize_resolve(resolve, orig.as_deref());
    }

    // Ok, if that didn't work just write it out
    ws_root
        .open_rw("Cargo.lock", ws.config(), "Cargo.lock file")
        .and_then(|mut f| {
            f.file().set_len(0)?;
            f.write_all(out.as_bytes())?;
            Ok(())
        })
        .with_context(|| format!("failed to write {}", ws.root().join("Cargo.lock").display()))?;
    Ok(())
}

fn resolve_to_string_orig(
    ws: &Workspace<'_>,
    resolve: &mut Resolve,
) -> (Option<String>, String, Filesystem) {
    // Load the original lock file if it exists.
    let ws_root = Filesystem::new(ws.root().to_path_buf());
    let orig = ws_root.open_ro("Cargo.lock", ws.config(), "Cargo.lock file");
    let orig = orig.and_then(|mut f| {
        let mut s = String::new();
        f.read_to_string(&mut s)?;
        Ok(s)
    });
    let out = serialize_resolve(resolve, orig.as_deref().ok());
    (orig.ok(), out, ws_root)
}

fn serialize_resolve(resolve: &Resolve, orig: Option<&str>) -> String {
    let toml = toml_edit::ser::to_item(resolve).unwrap();

    let mut out = String::new();

    // At the start of the file we notify the reader that the file is generated.
    // Specifically Phabricator ignores files containing "@generated", so we use that.
    let marker_line = "# This file is automatically @generated by Cargo.";
    let extra_line = "# It is not intended for manual editing.";
    out.push_str(marker_line);
    out.push('\n');
    out.push_str(extra_line);
    out.push('\n');
    // and preserve any other top comments
    if let Some(orig) = orig {
        let mut comments = orig.lines().take_while(|line| line.starts_with('#'));
        if let Some(first) = comments.next() {
            if first != marker_line {
                out.push_str(first);
                out.push('\n');
            }
            if let Some(second) = comments.next() {
                if second != extra_line {
                    out.push_str(second);
                    out.push('\n');
                }
                for line in comments {
                    out.push_str(line);
                    out.push('\n');
                }
            }
        }
    }

    if let Some(version) = toml.get("version") {
        out.push_str(&format!("version = {}\n\n", version));
    }

    let deps = toml["package"].as_array().unwrap();
    for dep in deps {
        let dep = dep.as_inline_table().unwrap();

        out.push_str("[[package]]\n");
        emit_package(dep, &mut out);
    }

    if let Some(patch) = toml.get("patch") {
        let list = patch["unused"].as_array().unwrap();
        for entry in list {
            out.push_str("[[patch.unused]]\n");
            emit_package(entry.as_inline_table().unwrap(), &mut out);
            out.push('\n');
        }
    }

    if let Some(meta) = toml.get("metadata") {
        // 1. We need to ensure we print the entire tree, not just the direct members of `metadata`
        //    (which `toml_edit::Table::to_string` only shows)
        // 2. We need to ensure all children tables have `metadata.` prefix
        let meta_table = meta
            .clone()
            .into_table()
            .expect("validation ensures this is a table");
        let mut meta_doc = toml_edit::Document::new();
        meta_doc["metadata"] = toml_edit::Item::Table(meta_table);

        out.push_str(&meta_doc.to_string());
    }

    // Historical versions of Cargo in the old format accidentally left trailing
    // blank newlines at the end of files, so we just leave that as-is. For all
    // encodings going forward, though, we want to be sure that our encoded lock
    // file doesn't contain any trailing newlines so trim out the extra if
    // necessary.
    if resolve.version() >= ResolveVersion::V2 {
        while out.ends_with("\n\n") {
            out.pop();
        }
    }
    out
}

fn are_equal_lockfiles(orig: &str, current: &str, ws: &Workspace<'_>) -> bool {
    // If we want to try and avoid updating the lock file, parse both and
    // compare them; since this is somewhat expensive, don't do it in the
    // common case where we can update lock files.
    if !ws.config().lock_update_allowed() {
        let res: CargoResult<bool> = (|| {
            let old: resolver::EncodableResolve = toml::from_str(orig)?;
            let new: resolver::EncodableResolve = toml::from_str(current)?;
            Ok(old.into_resolve(orig, ws)? == new.into_resolve(current, ws)?)
        })();
        if let Ok(true) = res {
            return true;
        }
    }

    orig.lines().eq(current.lines())
}

fn emit_package(dep: &toml_edit::InlineTable, out: &mut String) {
    out.push_str(&format!("name = {}\n", &dep["name"]));
    out.push_str(&format!("version = {}\n", &dep["version"]));

    if dep.contains_key("source") {
        out.push_str(&format!("source = {}\n", &dep["source"]));
    }
    if dep.contains_key("checksum") {
        out.push_str(&format!("checksum = {}\n", &dep["checksum"]));
    }

    if let Some(s) = dep.get("dependencies") {
        let slice = s.as_array().unwrap();

        if !slice.is_empty() {
            out.push_str("dependencies = [\n");

            for child in slice.iter() {
                out.push_str(&format!(" {},\n", child));
            }

            out.push_str("]\n");
        }
        out.push('\n');
    } else if dep.contains_key("replace") {
        out.push_str(&format!("replace = {}\n\n", &dep["replace"]));
    }
}
<|endoftext|>


<commit_before>#[cfg(target_arch = "aarch64")]
use aarch64::regs::*;
use std::env;
use std::f64::consts::{E, PI};
use std::fs::File;
use std::hint::black_box;
use std::io::Read;
use std::io::Write;
use std::net::{TcpListener, TcpStream};
use std::str;
use std::thread;
use std::time::Instant;
use std::vec;
#[cfg(target_os = "linux")]
use syscalls::SYS_getpid;

const NR_RUNS: usize = 1000;

#[cfg(target_arch = "x86_64")]
#[inline]
fn get_timestamp() -> u64 {
	unsafe {
		let mut _aux = 0;
		let value = core::arch::x86_64::__rdtscp(&mut _aux);
		core::arch::x86_64::_mm_lfence();
		value
	}
}

#[cfg(target_arch = "aarch64")]
#[inline]
fn get_timestamp() -> u64 {
	CNTPCT_EL0.get()
}

extern "C" {
	#[cfg(target_os = "hermit")]
	fn sys_getpid() -> u32;
}

pub fn bench_syscall() -> Result<(), ()> {
	let n = 1000000;

	let ticks = unsafe {
		// cache warmup
		#[cfg(target_os = "hermit")]
		let _ = sys_getpid();
		#[cfg(target_os = "linux")]
		let _ = syscall!(SYS_getpid);
		let _ = get_timestamp();

		let start = get_timestamp();
		for _ in 0..n {
			#[cfg(target_os = "hermit")]
			let _ = sys_getpid();
			#[cfg(target_os = "linux")]
			let _ = syscall!(SYS_getpid);
		}
		get_timestamp() - start
	};

	println!("Time {} for a system call (in ticks)", ticks / n);

	Ok(())
}

pub fn bench_sched_one_thread() -> Result<(), ()> {
	let n = 1000000;

	// cache warmup
	thread::yield_now();
	thread::yield_now();
	let _ = get_timestamp();

	let start = get_timestamp();
	for _ in 0..n {
		thread::yield_now();
	}
	let ticks = get_timestamp() - start;

	println!("Scheduling time {} ticks (1 thread)", ticks / n);

	Ok(())
}

pub fn bench_sched_two_threads() -> Result<(), ()> {
	let n = 1000000;
	let nthreads = 2;

	// cache warmup
	thread::yield_now();
	thread::yield_now();
	let _ = get_timestamp();

	let start = get_timestamp();
	let threads: Vec<_> = (0..nthreads - 1)
		.map(|_| {
			thread::spawn(move || {
				for _ in 0..n {
					thread::yield_now();
				}
			})
		})
		.collect();

	for _ in 0..n {
		thread::yield_now();
	}

	let ticks = get_timestamp() - start;

	for t in threads {
		t.join().unwrap();
	}

	println!(
		"Scheduling time {} ticks (2 threads)",
		ticks / (nthreads * n)
	);

	Ok(())
}

fn memcpy_builtin(n: usize) {
	let v1 = vec![1u8; n];
	let mut v2 = vec![0u8; n];

	let now = Instant::now();
	for _i in 0..NR_RUNS {
		let src: &[u8] = black_box(&v1);
		let dst: &mut [u8] = black_box(&mut v2);
		dst.copy_from_slice(src);
	}

	println!(
		"memcpy_builtin:  {} block size, {} MByte/s",
		n,
		(NR_RUNS * n) as f64 / (1024.0 * 1024.0 * now.elapsed().as_secs_f64())
	);
}

fn memset_builtin(n: usize) {
	let mut v1 = vec![0u8; n];
	let now = Instant::now();
	for _i in 0..NR_RUNS {
		let dst: &mut [u8] = black_box(&mut v1);
		let val: u8 = black_box(27);
		for b in dst {
			*b = val;
		}
	}

	println!(
		"memset_builtin:  {} block, {} MByte/s",
		n,
		((NR_RUNS * n) >> 20) as f64 / now.elapsed().as_secs_f64()
	);
}

pub fn bench_mem() -> Result<(), ()> {
	memcpy_builtin(4096);
	memcpy_builtin(1048576);
	memset_builtin(4096);
	memset_builtin(1048576);

	Ok(())
}
<commit_msg>add benchmark for memcpy and memset<commit_after>#[cfg(target_arch = "aarch64")]
use aarch64::regs::*;
use std::env;
use std::f64::consts::{E, PI};
use std::fs::File;
use std::ffi::c_void;
use std::hint::black_box;
use std::io::Read;
use std::io::Write;
use std::net::{TcpListener, TcpStream};
use std::str;
use std::thread;
use std::time::Instant;
use std::vec;
#[cfg(target_os = "linux")]
use syscalls::SYS_getpid;

extern "C" {
	pub fn memcpy(
        dest: *mut c_void,
        src: *const c_void,
        n: usize,
	) -> *mut c_void;
	pub fn memset(dest: *mut c_void, c: u8, n: usize) -> *mut c_void;
}

const NR_RUNS: usize = 1000;

#[cfg(target_arch = "x86_64")]
#[inline]
fn get_timestamp() -> u64 {
	unsafe {
		let mut _aux = 0;
		let value = core::arch::x86_64::__rdtscp(&mut _aux);
		core::arch::x86_64::_mm_lfence();
		value
	}
}

#[cfg(target_arch = "aarch64")]
#[inline]
fn get_timestamp() -> u64 {
	CNTPCT_EL0.get()
}

extern "C" {
	#[cfg(target_os = "hermit")]
	fn sys_getpid() -> u32;
}

pub fn bench_syscall() -> Result<(), ()> {
	let n = 1000000;

	let ticks = unsafe {
		// cache warmup
		#[cfg(target_os = "hermit")]
		let _ = sys_getpid();
		#[cfg(target_os = "linux")]
		let _ = syscall!(SYS_getpid);
		let _ = get_timestamp();

		let start = get_timestamp();
		for _ in 0..n {
			#[cfg(target_os = "hermit")]
			let _ = sys_getpid();
			#[cfg(target_os = "linux")]
			let _ = syscall!(SYS_getpid);
		}
		get_timestamp() - start
	};

	println!("Time {} for a system call (in ticks)", ticks / n);

	Ok(())
}

pub fn bench_sched_one_thread() -> Result<(), ()> {
	let n = 1000000;

	// cache warmup
	thread::yield_now();
	thread::yield_now();
	let _ = get_timestamp();

	let start = get_timestamp();
	for _ in 0..n {
		thread::yield_now();
	}
	let ticks = get_timestamp() - start;

	println!("Scheduling time {} ticks (1 thread)", ticks / n);

	Ok(())
}

pub fn bench_sched_two_threads() -> Result<(), ()> {
	let n = 1000000;
	let nthreads = 2;

	// cache warmup
	thread::yield_now();
	thread::yield_now();
	let _ = get_timestamp();

	let start = get_timestamp();
	let threads: Vec<_> = (0..nthreads - 1)
		.map(|_| {
			thread::spawn(move || {
				for _ in 0..n {
					thread::yield_now();
				}
			})
		})
		.collect();

	for _ in 0..n {
		thread::yield_now();
	}

	let ticks = get_timestamp() - start;

	for t in threads {
		t.join().unwrap();
	}

	println!(
		"Scheduling time {} ticks (2 threads)",
		ticks / (nthreads * n)
	);

	Ok(())
}

// derived from
// https://github.com/rust-lang/compiler-builtins/blob/master/testcrate/benches/mem.rs
fn memcpy_builtin(n: usize) {
	let v1 = vec![1u8; n];
	let mut v2 = vec![0u8; n];

	let now = Instant::now();
	for _i in 0..NR_RUNS {
		let src: &[u8] = black_box(&v1);
		let dst: &mut [u8] = black_box(&mut v2);
		dst.copy_from_slice(src);
	}

	println!(
		"memcpy_builtin:  {} block size, {} MByte/s",
		n,
		(NR_RUNS * n) as f64 / (1024.0 * 1024.0 * now.elapsed().as_secs_f64())
	);
}

// derived from
// https://github.com/rust-lang/compiler-builtins/blob/master/testcrate/benches/mem.rs
fn memset_builtin(n: usize) {
	let mut v1 = vec![0u8; n];
	let now = Instant::now();
	for _i in 0..NR_RUNS {
		let dst: &mut [u8] = black_box(&mut v1);
		let val: u8 = black_box(27);
		for b in dst {
			*b = val;
		}
	}

	println!(
		"memset_builtin:  {} block, {} MByte/s",
		n,
		((NR_RUNS * n) >> 20) as f64 / now.elapsed().as_secs_f64()
	);
}

// derived from
// https://github.com/rust-lang/compiler-builtins/blob/master/testcrate/benches/mem.rs
fn memcpy_rust(n: usize) {
    let v1 = vec![1u8; n];
	let mut v2 = vec![0u8; n];
	let now = Instant::now();
    for _i in 0..NR_RUNS {
        let src: &[u8] = black_box(&v1[0..]);
        let dst: &mut [u8] = black_box(&mut v2[0..]);
        unsafe { memcpy(dst.as_mut_ptr() as *mut c_void, src.as_ptr() as *mut c_void, n); }
	}

	println!(
		"memcpy_rust:  {} block, {} MByte/s",
		n,
		((NR_RUNS * n) >> 20) as f64 / now.elapsed().as_secs_f64()
	);
}

// derived from
// https://github.com/rust-lang/compiler-builtins/blob/master/testcrate/benches/mem.rs
fn memset_rust(n: usize) {
	let mut v1 = vec![0u8; n];
	let now = Instant::now();
    for _i in 0..NR_RUNS {
        let dst: &mut [u8] = black_box(&mut v1[0..]);
        let val = black_box(27);
        unsafe { memset(dst.as_mut_ptr() as *mut c_void, val, n); }
	}

	println!(
		"memset_rust:  {} block, {} MByte/s",
		n,
		((NR_RUNS * n) >> 20) as f64 / now.elapsed().as_secs_f64()
	);
}

pub fn bench_mem() -> Result<(), ()> {
	memcpy_builtin(4096);
	memcpy_builtin(1048576);
	memset_builtin(4096);
	memset_builtin(1048576);
	memcpy_rust(4096);
	memcpy_rust(1048576);
	memset_rust(4096);
	memset_rust(1048576);

	Ok(())
}
<|endoftext|>


<commit_before>/// This is a small server which is intended to run inside of an emulator or
/// on a remote test device. This server pairs with the `remote-test-client`
/// program in this repository. The `remote-test-client` connects to this
/// server over a TCP socket and performs work such as:
///
/// 1. Pushing shared libraries to the server
/// 2. Running tests through the server
///
/// The server supports running tests concurrently and also supports tests
/// themselves having support libraries. All data over the TCP sockets is in a
/// basically custom format suiting our needs.

use std::cmp;
use std::env;
use std::fs::{self, File, Permissions};
use std::io::prelude::*;
use std::io::{self, BufReader};
use std::net::{TcpListener, TcpStream};
use std::os::unix::prelude::*;
use std::path::{Path, PathBuf};
use std::process::{Command, Stdio};
use std::str;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::{Arc, Mutex};
use std::thread;

macro_rules! t {
    ($e:expr) => (match $e {
        Ok(e) => e,
        Err(e) => panic!("{} failed with {}", stringify!($e), e),
    })
}

static TEST: AtomicUsize = AtomicUsize::new(0);

struct Config {
    pub remote: bool,
    pub verbose: bool,
}

impl Config {
    pub fn default() -> Config {
        Config {
            remote: false,
            verbose: false,
        }
    }

    pub fn parse_args() -> Config {
        let mut config = Config::default();

        let args = env::args().skip(1);
        for argument in args {
            match &argument[..] {
                "remote" => {
                    config.remote = true;
                },
                "verbose" | "-v" => {
                    config.verbose = true;
                }
                arg => panic!("unknown argument: {}", arg),
            }
        }

        config
    }
}

fn main() {
    println!("starting test server");

    let config = Config::parse_args();

    let bind_addr = if cfg!(target_os = "android") || config.remote {
        "0.0.0.0:12345"
    } else {
        "10.0.2.15:12345"
    };

    let (listener, work) = if cfg!(target_os = "android") {
        (t!(TcpListener::bind(bind_addr)), "/data/tmp/work")
    } else {
        (t!(TcpListener::bind(bind_addr)), "/tmp/work")
    };
    println!("listening!");

    let work = Path::new(work);
    t!(fs::create_dir_all(work));

    let lock = Arc::new(Mutex::new(()));

    for socket in listener.incoming() {
        let mut socket = t!(socket);
        let mut buf = [0; 4];
        if socket.read_exact(&mut buf).is_err() {
            continue
        }
        if &buf[..] == b"ping" {
            t!(socket.write_all(b"pong"));
        } else if &buf[..] == b"push" {
            handle_push(socket, work);
        } else if &buf[..] == b"run " {
            let lock = lock.clone();
            thread::spawn(move || handle_run(socket, work, &lock));
        } else {
            panic!("unknown command {:?}", buf);
        }
    }
}

fn handle_push(socket: TcpStream, work: &Path) {
    let mut reader = BufReader::new(socket);
    recv(&work, &mut reader);

    let mut socket = reader.into_inner();
    t!(socket.write_all(b"ack "));
}

struct RemoveOnDrop<'a> {
    inner: &'a Path,
}

impl<'a> Drop for RemoveOnDrop<'a> {
    fn drop(&mut self) {
        t!(fs::remove_dir_all(self.inner));
    }
}

fn handle_run(socket: TcpStream, work: &Path, lock: &Mutex<()>) {
    let mut arg = Vec::new();
    let mut reader = BufReader::new(socket);

    // Allocate ourselves a directory that we'll delete when we're done to save
    // space.
    let n = TEST.fetch_add(1, Ordering::SeqCst);
    let path = work.join(format!("test{}", n));
    t!(fs::create_dir(&path));
    let _a = RemoveOnDrop { inner: &path };

    // First up we'll get a list of arguments delimited with 0 bytes. An empty
    // argument means that we're done.
    let mut args = Vec::new();
    while t!(reader.read_until(0, &mut arg)) > 1 {
        args.push(t!(str::from_utf8(&arg[..arg.len() - 1])).to_string());
        arg.truncate(0);
    }

    // Next we'll get a bunch of env vars in pairs delimited by 0s as well
    let mut env = Vec::new();
    arg.truncate(0);
    while t!(reader.read_until(0, &mut arg)) > 1 {
        let key_len = arg.len() - 1;
        let val_len = t!(reader.read_until(0, &mut arg)) - 1;
        {
            let key = &arg[..key_len];
            let val = &arg[key_len + 1..][..val_len];
            let key = t!(str::from_utf8(key)).to_string();
            let val = t!(str::from_utf8(val)).to_string();
            env.push((key, val));
        }
        arg.truncate(0);
    }

    // The section of code from here down to where we drop the lock is going to
    // be a critical section for us. On Linux you can't execute a file which is
    // open somewhere for writing, as you'll receive the error "text file busy".
    // Now here we never have the text file open for writing when we spawn it,
    // so why do we still need a critical section?
    //
    // Process spawning first involves a `fork` on Unix, which clones all file
    // descriptors into the child process. This means that it's possible for us
    // to open the file for writing (as we're downloading it), then some other
    // thread forks, then we close the file and try to exec. At that point the
    // other thread created a child process with the file open for writing, and
    // we attempt to execute it, so we get an error.
    //
    // This race is resolve by ensuring that only one thread can writ ethe file
    // and spawn a child process at once. Kinda an unfortunate solution, but we
    // don't have many other choices with this sort of setup!
    //
    // In any case the lock is acquired here, before we start writing any files.
    // It's then dropped just after we spawn the child. That way we don't lock
    // the execution of the child, just the creation of its files.
    let lock = lock.lock();

    // Next there's a list of dynamic libraries preceded by their filenames.
    while t!(reader.fill_buf())[0] != 0 {
        recv(&path, &mut reader);
    }
    assert_eq!(t!(reader.read(&mut [0])), 1);

    // Finally we'll get the binary. The other end will tell us how big the
    // binary is and then we'll download it all to the exe path we calculated
    // earlier.
    let exe = recv(&path, &mut reader);

    let mut cmd = Command::new(&exe);
    for arg in args {
        cmd.arg(arg);
    }
    for (k, v) in env {
        cmd.env(k, v);
    }

    // Support libraries were uploaded to `work` earlier, so make sure that's
    // in `LD_LIBRARY_PATH`. Also include our own current dir which may have
    // had some libs uploaded.
    cmd.env("LD_LIBRARY_PATH",
            format!("{}:{}", work.display(), path.display()));

    // Spawn the child and ferry over stdout/stderr to the socket in a framed
    // fashion (poor man's style)
    let mut child = t!(cmd.stdin(Stdio::null())
                          .stdout(Stdio::piped())
                          .stderr(Stdio::piped())
                          .spawn());
    drop(lock);
    let mut stdout = child.stdout.take().unwrap();
    let mut stderr = child.stderr.take().unwrap();
    let socket = Arc::new(Mutex::new(reader.into_inner()));
    let socket2 = socket.clone();
    let thread = thread::spawn(move || my_copy(&mut stdout, 0, &*socket2));
    my_copy(&mut stderr, 1, &*socket);
    thread.join().unwrap();

    // Finally send over the exit status.
    let status = t!(child.wait());
    let (which, code) = match status.code() {
        Some(n) => (0, n),
        None => (1, status.signal().unwrap()),
    };
    t!(socket.lock().unwrap().write_all(&[
        which,
        (code >> 24) as u8,
        (code >> 16) as u8,
        (code >>  8) as u8,
        (code >>  0) as u8,
    ]));
}

fn recv<B: BufRead>(dir: &Path, io: &mut B) -> PathBuf {
    let mut filename = Vec::new();
    t!(io.read_until(0, &mut filename));

    // We've got some tests with *really* long names. We try to name the test
    // executable the same on the target as it is on the host to aid with
    // debugging, but the targets we're emulating are often more restrictive
    // than the hosts as well.
    //
    // To ensure we can run a maximum number of tests without modifications we
    // just arbitrarily truncate the filename to 50 bytes. That should
    // hopefully allow us to still identify what's running while staying under
    // the filesystem limits.
    let len = cmp::min(filename.len() - 1, 50);
    let dst = dir.join(t!(str::from_utf8(&filename[..len])));
    let amt = read_u32(io) as u64;
    t!(io::copy(&mut io.take(amt),
                &mut t!(File::create(&dst))));
    t!(fs::set_permissions(&dst, Permissions::from_mode(0o755)));
    dst
}

fn my_copy(src: &mut dyn Read, which: u8, dst: &Mutex<dyn Write>) {
    let mut b = [0; 1024];
    loop {
        let n = t!(src.read(&mut b));
        let mut dst = dst.lock().unwrap();
        t!(dst.write_all(&[
            which,
            (n >> 24) as u8,
            (n >> 16) as u8,
            (n >>  8) as u8,
            (n >>  0) as u8,
        ]));
        if n > 0 {
            t!(dst.write_all(&b[..n]));
        } else {
            break
        }
    }
}

fn read_u32(r: &mut dyn Read) -> u32 {
    let mut len = [0; 4];
    t!(r.read_exact(&mut len));
    ((len[0] as u32) << 24) |
    ((len[1] as u32) << 16) |
    ((len[2] as u32) <<  8) |
    ((len[3] as u32) <<  0)
}
<commit_msg>Auto merge of #58049 - king6cong:typo, r=oli-obk<commit_after>/// This is a small server which is intended to run inside of an emulator or
/// on a remote test device. This server pairs with the `remote-test-client`
/// program in this repository. The `remote-test-client` connects to this
/// server over a TCP socket and performs work such as:
///
/// 1. Pushing shared libraries to the server
/// 2. Running tests through the server
///
/// The server supports running tests concurrently and also supports tests
/// themselves having support libraries. All data over the TCP sockets is in a
/// basically custom format suiting our needs.

use std::cmp;
use std::env;
use std::fs::{self, File, Permissions};
use std::io::prelude::*;
use std::io::{self, BufReader};
use std::net::{TcpListener, TcpStream};
use std::os::unix::prelude::*;
use std::path::{Path, PathBuf};
use std::process::{Command, Stdio};
use std::str;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::{Arc, Mutex};
use std::thread;

macro_rules! t {
    ($e:expr) => (match $e {
        Ok(e) => e,
        Err(e) => panic!("{} failed with {}", stringify!($e), e),
    })
}

static TEST: AtomicUsize = AtomicUsize::new(0);

struct Config {
    pub remote: bool,
    pub verbose: bool,
}

impl Config {
    pub fn default() -> Config {
        Config {
            remote: false,
            verbose: false,
        }
    }

    pub fn parse_args() -> Config {
        let mut config = Config::default();

        let args = env::args().skip(1);
        for argument in args {
            match &argument[..] {
                "remote" => {
                    config.remote = true;
                },
                "verbose" | "-v" => {
                    config.verbose = true;
                }
                arg => panic!("unknown argument: {}", arg),
            }
        }

        config
    }
}

fn main() {
    println!("starting test server");

    let config = Config::parse_args();

    let bind_addr = if cfg!(target_os = "android") || config.remote {
        "0.0.0.0:12345"
    } else {
        "10.0.2.15:12345"
    };

    let (listener, work) = if cfg!(target_os = "android") {
        (t!(TcpListener::bind(bind_addr)), "/data/tmp/work")
    } else {
        (t!(TcpListener::bind(bind_addr)), "/tmp/work")
    };
    println!("listening!");

    let work = Path::new(work);
    t!(fs::create_dir_all(work));

    let lock = Arc::new(Mutex::new(()));

    for socket in listener.incoming() {
        let mut socket = t!(socket);
        let mut buf = [0; 4];
        if socket.read_exact(&mut buf).is_err() {
            continue
        }
        if &buf[..] == b"ping" {
            t!(socket.write_all(b"pong"));
        } else if &buf[..] == b"push" {
            handle_push(socket, work);
        } else if &buf[..] == b"run " {
            let lock = lock.clone();
            thread::spawn(move || handle_run(socket, work, &lock));
        } else {
            panic!("unknown command {:?}", buf);
        }
    }
}

fn handle_push(socket: TcpStream, work: &Path) {
    let mut reader = BufReader::new(socket);
    recv(&work, &mut reader);

    let mut socket = reader.into_inner();
    t!(socket.write_all(b"ack "));
}

struct RemoveOnDrop<'a> {
    inner: &'a Path,
}

impl<'a> Drop for RemoveOnDrop<'a> {
    fn drop(&mut self) {
        t!(fs::remove_dir_all(self.inner));
    }
}

fn handle_run(socket: TcpStream, work: &Path, lock: &Mutex<()>) {
    let mut arg = Vec::new();
    let mut reader = BufReader::new(socket);

    // Allocate ourselves a directory that we'll delete when we're done to save
    // space.
    let n = TEST.fetch_add(1, Ordering::SeqCst);
    let path = work.join(format!("test{}", n));
    t!(fs::create_dir(&path));
    let _a = RemoveOnDrop { inner: &path };

    // First up we'll get a list of arguments delimited with 0 bytes. An empty
    // argument means that we're done.
    let mut args = Vec::new();
    while t!(reader.read_until(0, &mut arg)) > 1 {
        args.push(t!(str::from_utf8(&arg[..arg.len() - 1])).to_string());
        arg.truncate(0);
    }

    // Next we'll get a bunch of env vars in pairs delimited by 0s as well
    let mut env = Vec::new();
    arg.truncate(0);
    while t!(reader.read_until(0, &mut arg)) > 1 {
        let key_len = arg.len() - 1;
        let val_len = t!(reader.read_until(0, &mut arg)) - 1;
        {
            let key = &arg[..key_len];
            let val = &arg[key_len + 1..][..val_len];
            let key = t!(str::from_utf8(key)).to_string();
            let val = t!(str::from_utf8(val)).to_string();
            env.push((key, val));
        }
        arg.truncate(0);
    }

    // The section of code from here down to where we drop the lock is going to
    // be a critical section for us. On Linux you can't execute a file which is
    // open somewhere for writing, as you'll receive the error "text file busy".
    // Now here we never have the text file open for writing when we spawn it,
    // so why do we still need a critical section?
    //
    // Process spawning first involves a `fork` on Unix, which clones all file
    // descriptors into the child process. This means that it's possible for us
    // to open the file for writing (as we're downloading it), then some other
    // thread forks, then we close the file and try to exec. At that point the
    // other thread created a child process with the file open for writing, and
    // we attempt to execute it, so we get an error.
    //
    // This race is resolve by ensuring that only one thread can write the file
    // and spawn a child process at once. Kinda an unfortunate solution, but we
    // don't have many other choices with this sort of setup!
    //
    // In any case the lock is acquired here, before we start writing any files.
    // It's then dropped just after we spawn the child. That way we don't lock
    // the execution of the child, just the creation of its files.
    let lock = lock.lock();

    // Next there's a list of dynamic libraries preceded by their filenames.
    while t!(reader.fill_buf())[0] != 0 {
        recv(&path, &mut reader);
    }
    assert_eq!(t!(reader.read(&mut [0])), 1);

    // Finally we'll get the binary. The other end will tell us how big the
    // binary is and then we'll download it all to the exe path we calculated
    // earlier.
    let exe = recv(&path, &mut reader);

    let mut cmd = Command::new(&exe);
    for arg in args {
        cmd.arg(arg);
    }
    for (k, v) in env {
        cmd.env(k, v);
    }

    // Support libraries were uploaded to `work` earlier, so make sure that's
    // in `LD_LIBRARY_PATH`. Also include our own current dir which may have
    // had some libs uploaded.
    cmd.env("LD_LIBRARY_PATH",
            format!("{}:{}", work.display(), path.display()));

    // Spawn the child and ferry over stdout/stderr to the socket in a framed
    // fashion (poor man's style)
    let mut child = t!(cmd.stdin(Stdio::null())
                          .stdout(Stdio::piped())
                          .stderr(Stdio::piped())
                          .spawn());
    drop(lock);
    let mut stdout = child.stdout.take().unwrap();
    let mut stderr = child.stderr.take().unwrap();
    let socket = Arc::new(Mutex::new(reader.into_inner()));
    let socket2 = socket.clone();
    let thread = thread::spawn(move || my_copy(&mut stdout, 0, &*socket2));
    my_copy(&mut stderr, 1, &*socket);
    thread.join().unwrap();

    // Finally send over the exit status.
    let status = t!(child.wait());
    let (which, code) = match status.code() {
        Some(n) => (0, n),
        None => (1, status.signal().unwrap()),
    };
    t!(socket.lock().unwrap().write_all(&[
        which,
        (code >> 24) as u8,
        (code >> 16) as u8,
        (code >>  8) as u8,
        (code >>  0) as u8,
    ]));
}

fn recv<B: BufRead>(dir: &Path, io: &mut B) -> PathBuf {
    let mut filename = Vec::new();
    t!(io.read_until(0, &mut filename));

    // We've got some tests with *really* long names. We try to name the test
    // executable the same on the target as it is on the host to aid with
    // debugging, but the targets we're emulating are often more restrictive
    // than the hosts as well.
    //
    // To ensure we can run a maximum number of tests without modifications we
    // just arbitrarily truncate the filename to 50 bytes. That should
    // hopefully allow us to still identify what's running while staying under
    // the filesystem limits.
    let len = cmp::min(filename.len() - 1, 50);
    let dst = dir.join(t!(str::from_utf8(&filename[..len])));
    let amt = read_u32(io) as u64;
    t!(io::copy(&mut io.take(amt),
                &mut t!(File::create(&dst))));
    t!(fs::set_permissions(&dst, Permissions::from_mode(0o755)));
    dst
}

fn my_copy(src: &mut dyn Read, which: u8, dst: &Mutex<dyn Write>) {
    let mut b = [0; 1024];
    loop {
        let n = t!(src.read(&mut b));
        let mut dst = dst.lock().unwrap();
        t!(dst.write_all(&[
            which,
            (n >> 24) as u8,
            (n >> 16) as u8,
            (n >>  8) as u8,
            (n >>  0) as u8,
        ]));
        if n > 0 {
            t!(dst.write_all(&b[..n]));
        } else {
            break
        }
    }
}

fn read_u32(r: &mut dyn Read) -> u32 {
    let mut len = [0; 4];
    t!(r.read_exact(&mut len));
    ((len[0] as u32) << 24) |
    ((len[1] as u32) << 16) |
    ((len[2] as u32) <<  8) |
    ((len[3] as u32) <<  0)
}
<|endoftext|>


<commit_before>///
/// This example parses, sorts and groups the iris dataset
/// and does some simple manipulations.
///
/// Iterators and itertools functionality are used throughout.
///
///

extern crate itertools;

use itertools::Itertools;
use std::collections::HashMap;
use std::iter::repeat;
use std::num::ParseFloatError;
use std::str::FromStr;

static DATA: &'static str = include_str!("iris.data");

#[derive(Clone, Debug)]
struct Iris {
    name: String,
    data: [f32; 4],
}

#[derive(Clone, Debug)]
enum ParseError {
    Numeric(ParseFloatError),
    Other(&'static str),
}

impl From<ParseFloatError> for ParseError {
    fn from(err: ParseFloatError) -> Self {
        ParseError::Numeric(err)
    }
}

/// Parse an Iris from a comma-separated line
impl FromStr for Iris {
    type Err = ParseError;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        let mut iris = Iris { name: "".into(), data: [0.; 4] };
        let mut parts = s.split(",").map(str::trim);

        // using Iterator::by_ref()
        for (index, part) in parts.by_ref().take(4).enumerate() {
            iris.data[index] = try!(part.parse::<f32>());
        }
        if let Some(name) = parts.next() {
            iris.name = name.into();
        } else {
            return Err(ParseError::Other("Missing name"))
        }
        Ok(iris)
    }
}

fn main() {
    // using Itertools::fold_results to create the result of parsing
    let irises = DATA.lines()
                     .map(str::parse)
                     .fold_results(Vec::new(), |mut v, iris: Iris| {
                         v.push(iris);
                         v
                     });
    let mut irises = match irises {
        Err(e) => {
            println!("Error parsing: {:?}", e);
            std::process::exit(1);
        }
        Ok(data) => data,
    };

    // Sort them and group them
    irises.sort_by(|a, b| Ord::cmp(&a.name, &b.name));

    // using Iterator::cycle()
    let mut plot_symbols = "+ox".chars().cycle();
    let mut symbolmap = HashMap::new();

    // using Itertools::group_by_lazy
    for (species, species_group) in &irises.iter().group_by_lazy(|iris| &iris.name) {
        // assign a plot symbol
        symbolmap.entry(species).or_insert_with(|| {
            plot_symbols.next().unwrap()
        });
        println!("{} (symbol={})", species, symbolmap[species]);

        for iris in species_group {
            // using Itertools::format for lazy formatting
            println!("{}",
                     iris.data.iter()
                     .format(", ", |elt, f| f(&format_args!("{:>3.1}", elt))));
        }

    }

    // Look at all combinations of the four columns
    //
    // See https://en.wikipedia.org/wiki/Iris_flower_data_set
    //
    let n = 30; // plot size
    let mut plot = vec![' '; n * n];

    // using Itertools::combinations
    for (a, b) in (0..4).combinations() {
        println!("Column {} vs {}:", a, b);

        // Clear plot
        //
        // using std::iter::repeat;
        // using Itertools::set_from
        plot.iter_mut().set_from(repeat(' '));

        // using Itertools::fold1
        let min_max = |data: &[Iris], col| {
            data.iter()
                .map(|iris| iris.data[col])
                .map(|x| (x, x))
                .fold1(|(min, max), (elt, _)|
                    (f32::min(min, elt), f32::max(max, elt))
                ).expect("Can't find min/max of empty iterator")
        };
        let (min_x, max_x) = min_max(&irises, a);
        let (min_y, max_y) = min_max(&irises, b);

        // Plot the data points
        let round_to_grid = |x, min, max| ((x - min) / (max - min) * ((n - 1) as f32)) as usize;
        let flip = |ix| n - 1 - ix; // reverse axis direction

        for iris in &irises {
            let ix = round_to_grid(iris.data[a], min_x, max_x);
            let iy = flip(round_to_grid(iris.data[b], min_y, max_y));
            plot[n * iy + ix] = symbolmap[&iris.name];
        }

        // render plot
        //
        // using Itertools::join
        for line in plot.chunks(n) {
            println!("{}", line.iter().join(" "))
        }
    }
}
<commit_msg>examples: Try to workaround mysterious From trait error in Rust.10<commit_after>///
/// This example parses, sorts and groups the iris dataset
/// and does some simple manipulations.
///
/// Iterators and itertools functionality are used throughout.
///
///

extern crate itertools;

use itertools::Itertools;
use std::collections::HashMap;
use std::iter::repeat;
use std::num::ParseFloatError;
use std::str::FromStr;

static DATA: &'static str = include_str!("iris.data");

#[derive(Clone, Debug)]
struct Iris {
    name: String,
    data: [f32; 4],
}

#[derive(Clone, Debug)]
enum ParseError {
    Numeric(ParseFloatError),
    Other(&'static str),
}

impl From<ParseFloatError> for ParseError {
    fn from(err: ParseFloatError) -> Self {
        ParseError::Numeric(err)
    }
}

/// Parse an Iris from a comma-separated line
impl FromStr for Iris {
    type Err = ParseError;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        let mut iris = Iris { name: "".into(), data: [0.; 4] };
        let mut parts = s.split(",").map(str::trim);

        // using Iterator::by_ref()
        for (index, part) in parts.by_ref().take(4).enumerate() {
            iris.data[index] = try!(part.parse::<f32>().map_err(ParseError::from));
        }
        if let Some(name) = parts.next() {
            iris.name = name.into();
        } else {
            return Err(ParseError::Other("Missing name"))
        }
        Ok(iris)
    }
}

fn main() {
    // using Itertools::fold_results to create the result of parsing
    let irises = DATA.lines()
                     .map(str::parse)
                     .fold_results(Vec::new(), |mut v, iris: Iris| {
                         v.push(iris);
                         v
                     });
    let mut irises = match irises {
        Err(e) => {
            println!("Error parsing: {:?}", e);
            std::process::exit(1);
        }
        Ok(data) => data,
    };

    // Sort them and group them
    irises.sort_by(|a, b| Ord::cmp(&a.name, &b.name));

    // using Iterator::cycle()
    let mut plot_symbols = "+ox".chars().cycle();
    let mut symbolmap = HashMap::new();

    // using Itertools::group_by_lazy
    for (species, species_group) in &irises.iter().group_by_lazy(|iris| &iris.name) {
        // assign a plot symbol
        symbolmap.entry(species).or_insert_with(|| {
            plot_symbols.next().unwrap()
        });
        println!("{} (symbol={})", species, symbolmap[species]);

        for iris in species_group {
            // using Itertools::format for lazy formatting
            println!("{}",
                     iris.data.iter()
                     .format(", ", |elt, f| f(&format_args!("{:>3.1}", elt))));
        }

    }

    // Look at all combinations of the four columns
    //
    // See https://en.wikipedia.org/wiki/Iris_flower_data_set
    //
    let n = 30; // plot size
    let mut plot = vec![' '; n * n];

    // using Itertools::combinations
    for (a, b) in (0..4).combinations() {
        println!("Column {} vs {}:", a, b);

        // Clear plot
        //
        // using std::iter::repeat;
        // using Itertools::set_from
        plot.iter_mut().set_from(repeat(' '));

        // using Itertools::fold1
        let min_max = |data: &[Iris], col| {
            data.iter()
                .map(|iris| iris.data[col])
                .map(|x| (x, x))
                .fold1(|(min, max), (elt, _)|
                    (f32::min(min, elt), f32::max(max, elt))
                ).expect("Can't find min/max of empty iterator")
        };
        let (min_x, max_x) = min_max(&irises, a);
        let (min_y, max_y) = min_max(&irises, b);

        // Plot the data points
        let round_to_grid = |x, min, max| ((x - min) / (max - min) * ((n - 1) as f32)) as usize;
        let flip = |ix| n - 1 - ix; // reverse axis direction

        for iris in &irises {
            let ix = round_to_grid(iris.data[a], min_x, max_x);
            let iy = flip(round_to_grid(iris.data[b], min_y, max_y));
            plot[n * iy + ix] = symbolmap[&iris.name];
        }

        // render plot
        //
        // using Itertools::join
        for line in plot.chunks(n) {
            println!("{}", line.iter().join(" "))
        }
    }
}
<|endoftext|>


<commit_before>extern crate rustylifx;

use rustylifx::colour;

use std::time::Duration;
use std::thread;

fn main() {
    println!("Started.");
    let resp = rustylifx::request::get_service().unwrap();
    println!("\nState service: {:?}", resp);
    println!("==========\n");
    //display_response(resp);

    thread::sleep(Duration::from_millis(1000));
    let resp2 = rustylifx::request::get_device_state().unwrap();
    println!("\nState: {:?}", resp2);
    println!("==========");
    //display_response(resp2);

    thread::sleep(Duration::from_millis(1000));
    rustylifx::request::set_device_state(colour::RED, 1000, 0);
    thread::sleep(Duration::from_millis(1000));
    rustylifx::request::set_device_state(colour::GREEN, 1000, 0);
    thread::sleep(Duration::from_millis(1000));
    rustylifx::request::set_device_state(colour::BLUE, 1000, 0);
    thread::sleep(Duration::from_millis(1000));

    rustylifx::request::set_device_state(colour::BEIGE, 1000, 0);
    thread::sleep(Duration::from_millis(1000));
    rustylifx::request::set_device_state(colour::CHARTREUSE, 1000, 0);
    thread::sleep(Duration::from_millis(1000));
    rustylifx::request::set_device_state(colour::CORAL, 1000, 0);
    thread::sleep(Duration::from_millis(1000));
    rustylifx::request::set_device_state(colour::CORNFLOWER, 1000, 0);
    thread::sleep(Duration::from_millis(1000));
    rustylifx::request::set_device_state(colour::CRIMSON, 1000, 0);
    thread::sleep(Duration::from_millis(1000));
    rustylifx::request::set_device_state(colour::DEEP_SKY_BLUE, 1000, 0);
    thread::sleep(Duration::from_millis(1000));
    rustylifx::request::set_device_state(colour::SLATE_GRAY, 1000, 0);
    thread::sleep(Duration::from_millis(1000));
    //rustylifx::request::set_device_state(colour::BEIGE, 65000, 65000, 1000, 0);

    println!("\nFinished.");
}

fn display_response(resp: rustylifx::response::Response) {
    println!("Response:");
    println!("Size: {}", resp.size);
    println!("Source: {:?}", resp.source);
    println!("Mac addr: {:?}", resp.mac_address);
    println!("Firmware: {:?}", resp.firmware);
    // packed byte
    println!("Sequence num: {:?}", resp.sequence_number);

    println!("Reserved_1 (timestamp?): {:?}", resp.reserved_1);

    println!("Message type: {:?}", resp.message_type);

    println!("Reserved_2: {:?}", resp.reserved_2);

    //println!("Service: {:?}", resp.service);
    //println!("Port: {:?}", resp.port);
    //println!("Unknown: {:?}", resp.unknown);

}
<commit_msg>Acknowledge responses.<commit_after>extern crate rustylifx;

use rustylifx::colour;

use std::time::Duration;
use std::thread;

fn main() {
    println!("Started.");
    let resp = rustylifx::request::get_service().unwrap();
    println!("\nState service:");
    display_response(resp);
    println!("==========\n");

    thread::sleep(Duration::from_millis(1000));
    let resp2 = rustylifx::request::get_device_state().unwrap();
    println!("\nState:");
    display_response(resp2);
    println!("==========");

    thread::sleep(Duration::from_millis(1000));
    let _ = rustylifx::request::set_device_state(colour::RED, 1000, 0);
    thread::sleep(Duration::from_millis(1000));
    let _ = rustylifx::request::set_device_state(colour::GREEN, 1000, 0);
    thread::sleep(Duration::from_millis(1000));
    let _ = rustylifx::request::set_device_state(colour::BLUE, 1000, 0);
    thread::sleep(Duration::from_millis(1000));

    let _ = rustylifx::request::set_device_state(colour::BEIGE, 1000, 0);
    thread::sleep(Duration::from_millis(1000));
    let _ = rustylifx::request::set_device_state(colour::CHARTREUSE, 1000, 0);
    thread::sleep(Duration::from_millis(1000));
    let _ = rustylifx::request::set_device_state(colour::CORAL, 1000, 0);
    thread::sleep(Duration::from_millis(1000));
    let _ = rustylifx::request::set_device_state(colour::CORNFLOWER, 1000, 0);
    thread::sleep(Duration::from_millis(1000));
    let _ = rustylifx::request::set_device_state(colour::CRIMSON, 1000, 0);
    thread::sleep(Duration::from_millis(1000));
    let _ = rustylifx::request::set_device_state(colour::DEEP_SKY_BLUE, 1000, 0);
    thread::sleep(Duration::from_millis(1000));
    let _ = rustylifx::request::set_device_state(colour::SLATE_GRAY, 1000, 0);
    thread::sleep(Duration::from_millis(1000));
    let resp = rustylifx::request::set_device_state(colour::BEIGE, 1000, 0);
    display_response(resp.unwrap());

    println!("\nFinished.");
}

fn display_response(resp: rustylifx::response::Response) {
    println!("Response:");
    println!("Size: {}", resp.size);
    println!("Source: {:?}", resp.source);
    println!("Mac addr: {:?}", resp.mac_address);
    println!("Firmware: {:?}", resp.firmware);
    // packed byte
    println!("Sequence num: {:?}", resp.sequence_number);
    println!("Reserved_1 (timestamp?): {:?}", resp.reserved_1);
    println!("Message type: {:?}", resp.message_type);
    println!("Reserved_2: {:?}", resp.reserved_2);

    //println!("Service: {:?}", resp.service);
    //println!("Port: {:?}", resp.port);
    //println!("Unknown: {:?}", resp.unknown);
}
<|endoftext|>


<commit_before>extern crate rustbox;
extern crate yoga;
extern crate yoga_rustbox;
extern crate yoga_wrapper;

use yoga::Backend;

use std::error::Error;
use std::default::Default;

use rustbox::RustBox;
use rustbox::Key;

fn main() {
    let rustbox = match RustBox::init(Default::default()) {
        Result::Ok(v) => v,
        Result::Err(e) => panic!("{}", e),
    };

    let mut root = yoga_wrapper::Node::new();
    root.set_width(50.0);
    root.set_height(12.0);
    root.set_flex_direction(yoga_wrapper::FlexDirection::Row);
    root.set_padding(yoga_wrapper::Edge::All, 2.0);

    let mut text = yoga_wrapper::Node::new();
    text.set_measure_func(yoga_wrapper::measure);
    text.set_context(&mut yoga_wrapper::Context::new("Yo!!!", &yoga_rustbox::Measurer {}));

    root.insert_child(&text, 0);

    root.calculate_layout();

    yoga_rustbox::Backend::new(&rustbox).render(&root);

    loop {
        match rustbox.poll_event(false) {
            Ok(rustbox::Event::KeyEvent(key)) => {
                match key {
                    Key::Char('q') => {
                        break;
                    }
                    _ => {}
                }
            }
            Err(e) => panic!("{}", e.description()),
            _ => {}
        }
    }
}
<commit_msg>feat(text): use create_context from be<commit_after>extern crate rustbox;
extern crate yoga;
extern crate yoga_rustbox;
extern crate yoga_wrapper;

use yoga::Backend;

use std::error::Error;
use std::default::Default;

use rustbox::RustBox;
use rustbox::Key;

fn main() {
    let rustbox = match RustBox::init(Default::default()) {
        Result::Ok(v) => v,
        Result::Err(e) => panic!("{}", e),
    };

    let be = yoga_rustbox::Backend::new(&rustbox);

    let mut root = yoga_wrapper::Node::new();
    root.set_width(50.0);
    root.set_height(12.0);
    root.set_flex_direction(yoga_wrapper::FlexDirection::Row);
    root.set_padding(yoga_wrapper::Edge::All, 2.0);

    let mut text = yoga_wrapper::Node::new();
    text.set_measure_func(yoga_wrapper::measure);
    text.set_context(&mut be.create_context("Yo!!!"));

    root.insert_child(&text, 0);

    root.calculate_layout();

    yoga_rustbox::Backend::new(&rustbox).render(&root);

    loop {
        match rustbox.poll_event(false) {
            Ok(rustbox::Event::KeyEvent(key)) => {
                match key {
                    Key::Char('q') => {
                        break;
                    }
                    _ => {}
                }
            }
            Err(e) => panic!("{}", e.description()),
            _ => {}
        }
    }
}
<|endoftext|>


<commit_before>use core::prelude::*;
use core::iter::range_step;
use core::intrinsics::set_memory;

use con::write;
use con::writeUInt;
use mboot;
use mboot::MemoryMapItem;
use start32::PhysAddr;
use start32::MutPhysAddr;
use util::abort;

use mem::framestack::*;

pub mod framestack {
	use core::prelude::*;

	struct FreeFrame {
		next : FreeFrameS
	}
	pub type FreeFrameS = *mut FreeFrame;
	pub type FreeFrameP = Option<*mut FreeFrame>;

	pub static none : FreeFrameS = 0 as *mut FreeFrame;

	fn from_option<T>(x : Option<T>, def : T) -> T {
		match x {
			Some(val) => val,
			None => def
		}
	}

	pub fn store(p : FreeFrameP) -> FreeFrameS {
		from_option(p, none)
	}

	pub fn push_frame<T>(head : &mut FreeFrameS, frame : *mut T) {
		let free = frame as *mut FreeFrame;
		unsafe { (*free).next = *head; }
		*head = free;
	}

	pub fn pop_frame(head : &mut FreeFrameS) -> FreeFrameP {
		if *head == none {
			None
		} else {
			let page = *head;
			unsafe {
				*head = (*page).next;
				(*page).next = none;
			}
			Some(page)
		}
	}

}

pub struct Global {
	// Frames that are uninitialized (except for the first word)
	garbage : FreeFrameS,
	// Frames that are all zeroes except for the first word
	free : FreeFrameS,
	num_used : uint,
	num_total : uint,
}

pub static empty_global : Global = Global { garbage : none, free : none, num_used : 0, num_total : 0 };
pub static mut global : Global = empty_global;

pub struct PerCpu {
	free : FreeFrameS
}

struct MemoryMap {
	addr : *u8,
	end : *u8
}

impl MemoryMap {
	fn new(addr : *u8, length : uint) -> MemoryMap {
		return MemoryMap { addr : addr, end : unsafe { addr.offset(length as int) } }
	}
}

impl Iterator<MemoryMapItem> for MemoryMap {
	fn next(&mut self) -> Option<MemoryMapItem> {
		if self.addr < self.end { unsafe {
			let item = *(self.addr as *MemoryMapItem);
			self.addr = self.addr.offset(4 + item.item_size as int);
			Some(item)
		} } else {
			None
		}
	}
}

fn clear<T>(page : *mut T) {
	unsafe { set_memory(page as *mut u8, 0, 4096); }
}

impl Global {
	pub fn init(&mut self, info : &mboot::Info, min_addr : uint) {
		if !info.has(mboot::MemoryMap) {
			return;
		}

		let mut mmap = MemoryMap::new(PhysAddr(info.mmap_addr as uint), info.mmap_length as uint);
		let mut count = 0;
		for item in mmap {
//			newline();
//			writePHex(item.start as uint);
//			newline();
//			writePHex(item.length as uint);
//			newline();
//			writeUInt(item.item_type as uint);
//			newline();
			for p in range_step(item.start, item.start + item.length, 4096) {
				if p as uint > min_addr {
					self.free_frame(MutPhysAddr(p as uint));
					count += 1;
				}
			}
		}
		self.num_used = 0;
		self.num_total = count;
	}

	pub fn free_frame(&mut self, vpaddr : *mut u8) {
		self.num_used -= 1;
		push_frame(&mut self.garbage, vpaddr);
	}

	pub fn alloc_frame(&mut self) -> FreeFrameP {
		match pop_frame(&mut self.free) {
			Some(page) => {
				self.num_used += 1;
				Some(page)
			},
			None => match pop_frame(&mut self.garbage) {
				Some(page) => {
					self.num_used += 1;
					clear(page);
					Some(page)
				},
				None => { None }
			}
		}
	}

	pub fn alloc_frame_panic(&mut self) -> *mut u8 {
		match self.alloc_frame() {
			Some(page) => page as *mut u8,
			None => abort()
		}
	}

	pub fn free_pages(&self) -> uint {
		self.num_total - self.num_used
	}

	pub fn used_pages(&self) -> uint {
		self.num_used
	}

	#[inline(never)]
	pub fn stat(&self) {
		write("Free: ");
		writeUInt(self.free_pages() * 4);
		write("KiB, Used: ");
		writeUInt(self.used_pages() * 4);
		write("KiB\n");
	}
}

#[inline(always)]
pub fn get() -> &mut Global {
	unsafe { &mut global }
}

impl PerCpu {
	pub fn new() -> PerCpu {
		PerCpu { free : none }
	}

	#[inline(never)]
	pub fn alloc_frame(&mut self) -> Option<*mut u8> {
		match pop_frame(&mut self.free) {
			Some(page) => { return Some(page as *mut u8); }
			None => {}
		}
		self.free = store(get().alloc_frame());
		return self.steal_frame();
	}

	pub fn steal_frame(&mut self) -> Option<*mut u8> {
		match get().alloc_frame() {
			Some(page) => Some(page as *mut u8),
			None => None
		}
	}

	pub fn alloc_frame_panic(&mut self) -> *mut u8 {
		match self.alloc_frame() {
			Some(page) => page,
			None => abort()
		}
	}

	pub fn free_frame(&mut self, page : *mut u8) {
		get().free_frame(page);
	}

	pub fn test(&mut self) {
		let mut head = none;
//		let mut count = 0;
		loop {
			let p = self.alloc_frame();
//			write("Allocation #");
//			writeUInt(count);
//			write(": ");
//			writePtr(from_option(p, 0 as *mut u8) as *u8);
//			newline();
//			get().stat();
			match p {
				Some(pp) => push_frame(&mut head, pp),
				None => break
			}
//			count += 1;
		}
//		write("Allocated everything: ");
//		writeUInt(count);
//		write(" pages\n");
//		get().stat();
		loop {
//			write("Allocation #");
//			writeUInt(count);
//			write(": ");
//			writePtr(from_option(head, 0 as *mut FreeFrame) as *u8);
//			newline();
//			get().stat();
			match pop_frame(&mut head) {
				Some(p) => self.free_frame(p as *mut u8),
				None => break
			}
		}
	}
}
<commit_msg>Only use "memory" memory ranges as memory...<commit_after>use core::prelude::*;
use core::iter::range_step;
use core::intrinsics::set_memory;

use con::write;
use con::writeUInt;
use mboot;
use mboot::MemoryMapItem;
use start32::PhysAddr;
use start32::MutPhysAddr;
use util::abort;

use mem::framestack::*;

pub mod framestack {
	use core::prelude::*;

	struct FreeFrame {
		next : FreeFrameS
	}
	pub type FreeFrameS = *mut FreeFrame;
	pub type FreeFrameP = Option<*mut FreeFrame>;

	pub static none : FreeFrameS = 0 as *mut FreeFrame;

	fn from_option<T>(x : Option<T>, def : T) -> T {
		match x {
			Some(val) => val,
			None => def
		}
	}

	pub fn store(p : FreeFrameP) -> FreeFrameS {
		from_option(p, none)
	}

	pub fn push_frame<T>(head : &mut FreeFrameS, frame : *mut T) {
		let free = frame as *mut FreeFrame;
		unsafe { (*free).next = *head; }
		*head = free;
	}

	pub fn pop_frame(head : &mut FreeFrameS) -> FreeFrameP {
		if *head == none {
			None
		} else {
			let page = *head;
			unsafe {
				*head = (*page).next;
				(*page).next = none;
			}
			Some(page)
		}
	}

}

pub struct Global {
	// Frames that are uninitialized (except for the first word)
	garbage : FreeFrameS,
	// Frames that are all zeroes except for the first word
	free : FreeFrameS,
	num_used : uint,
	num_total : uint,
}

pub static empty_global : Global = Global { garbage : none, free : none, num_used : 0, num_total : 0 };
pub static mut global : Global = empty_global;

pub struct PerCpu {
	free : FreeFrameS
}

struct MemoryMap {
	addr : *u8,
	end : *u8
}

impl MemoryMap {
	fn new(addr : *u8, length : uint) -> MemoryMap {
		return MemoryMap { addr : addr, end : unsafe { addr.offset(length as int) } }
	}
}

impl Iterator<MemoryMapItem> for MemoryMap {
	fn next(&mut self) -> Option<MemoryMapItem> {
		if self.addr < self.end { unsafe {
			let item = *(self.addr as *MemoryMapItem);
			self.addr = self.addr.offset(4 + item.item_size as int);
			Some(item)
		} } else {
			None
		}
	}
}

fn clear<T>(page : *mut T) {
	unsafe { set_memory(page as *mut u8, 0, 4096); }
}

impl Global {
	pub fn init(&mut self, info : &mboot::Info, min_addr : uint) {
		if !info.has(mboot::MemoryMap) {
			return;
		}

		let mut mmap = MemoryMap::new(PhysAddr(info.mmap_addr as uint), info.mmap_length as uint);
		let mut count = 0;
		for item in mmap {
			if item.item_type != mboot::MemoryTypeMemory as u32 {
				continue;
			}
//			newline();
//			writePHex(item.start as uint);
//			newline();
//			writePHex(item.length as uint);
//			newline();
//			writeUInt(item.item_type as uint);
//			newline();
			for p in range_step(item.start, item.start + item.length, 4096) {
				if p as uint > min_addr {
					self.free_frame(MutPhysAddr(p as uint));
					count += 1;
				}
			}
		}
		self.num_used = 0;
		self.num_total = count;
	}

	pub fn free_frame(&mut self, vpaddr : *mut u8) {
		self.num_used -= 1;
		push_frame(&mut self.garbage, vpaddr);
	}

	pub fn alloc_frame(&mut self) -> FreeFrameP {
		match pop_frame(&mut self.free) {
			Some(page) => {
				self.num_used += 1;
				Some(page)
			},
			None => match pop_frame(&mut self.garbage) {
				Some(page) => {
					self.num_used += 1;
					clear(page);
					Some(page)
				},
				None => { None }
			}
		}
	}

	pub fn alloc_frame_panic(&mut self) -> *mut u8 {
		match self.alloc_frame() {
			Some(page) => page as *mut u8,
			None => abort()
		}
	}

	pub fn free_pages(&self) -> uint {
		self.num_total - self.num_used
	}

	pub fn used_pages(&self) -> uint {
		self.num_used
	}

	#[inline(never)]
	pub fn stat(&self) {
		write("Free: ");
		writeUInt(self.free_pages() * 4);
		write("KiB, Used: ");
		writeUInt(self.used_pages() * 4);
		write("KiB\n");
	}
}

#[inline(always)]
pub fn get() -> &mut Global {
	unsafe { &mut global }
}

impl PerCpu {
	pub fn new() -> PerCpu {
		PerCpu { free : none }
	}

	#[inline(never)]
	pub fn alloc_frame(&mut self) -> Option<*mut u8> {
		match pop_frame(&mut self.free) {
			Some(page) => { return Some(page as *mut u8); }
			None => {}
		}
		self.free = store(get().alloc_frame());
		return self.steal_frame();
	}

	pub fn steal_frame(&mut self) -> Option<*mut u8> {
		match get().alloc_frame() {
			Some(page) => Some(page as *mut u8),
			None => None
		}
	}

	pub fn alloc_frame_panic(&mut self) -> *mut u8 {
		match self.alloc_frame() {
			Some(page) => page,
			None => abort()
		}
	}

	pub fn free_frame(&mut self, page : *mut u8) {
		get().free_frame(page);
	}

	pub fn test(&mut self) {
		let mut head = none;
//		let mut count = 0;
		loop {
			let p = self.alloc_frame();
//			write("Allocation #");
//			writeUInt(count);
//			write(": ");
//			writePtr(from_option(p, 0 as *mut u8) as *u8);
//			newline();
//			get().stat();
			match p {
				Some(pp) => push_frame(&mut head, pp),
				None => break
			}
//			count += 1;
		}
//		write("Allocated everything: ");
//		writeUInt(count);
//		write(" pages\n");
//		get().stat();
		loop {
//			write("Allocation #");
//			writeUInt(count);
//			write(": ");
//			writePtr(from_option(head, 0 as *mut FreeFrame) as *u8);
//			newline();
//			get().stat();
			match pop_frame(&mut head) {
				Some(p) => self.free_frame(p as *mut u8),
				None => break
			}
		}
	}
}
<|endoftext|>


<commit_before>use super::*;
use {tapa, Grid, X, Y};
use rand;

use std::sync::{Arc, Mutex};
use std::io::{stdout, Write};
use std::thread;
use super::getopts::{Matches, Options};

#[derive(Clone, Copy, Debug)]
struct GeneratorOption {
    height: i32,
    width: i32,
    jobs: i32,
    symmetry: bool,
    max_clue: Option<i32>,
    trial_and_error: bool,
}

fn parse_options(matches: &Matches) -> Result<GeneratorOption, CliError> {
    let height = parse_integer_argument(matches, "height", None, Some(1))?;
    let width = parse_integer_argument(matches, "width", None, Some(1))?;
    let jobs = parse_integer_argument(matches, "jobs", Some(1), Some(1))?;
    let symmetry = matches.opt_present("symmetry");
    let trial_and_error = matches.opt_present("trial-and-error");

    let max_clue = matches
        .opt_str("max-clue")
        .map(|s| {
            s.parse::<i32>()
                .map_err(|_| CliError::UnrecognizedArgument("max-clue"))
                .and_then(|arg| {
                    if arg > 0 {
                        Ok(Some(arg))
                    } else {
                        Err(CliError::UnrecognizedArgument("max-clue"))
                    }
                })
        })
        .unwrap_or(Ok(None))?;
    Ok(GeneratorOption {
        height,
        width,
        jobs,
        symmetry,
        max_clue,
        trial_and_error,
    })
}

fn run_generator(opts: GeneratorOption) -> Result<(), CliError> {
    let height = opts.height;
    let width = opts.width;
    let mut ths = vec![];
    let gen_probs = Arc::new(Mutex::new(0i64));

    for _ in 0..opts.jobs {
        let gen_probs = gen_probs.clone();

        let opts = opts;

        ths.push(thread::spawn(move || {
            let start = Instant::now();
            let dic = tapa::Dictionary::new();
            let consecutive_dic = tapa::ConsecutiveRegionDictionary::new(&dic);

            let opts = tapa::GeneratorOption {
                clue_constraint: Grid::new(opts.height, opts.width, tapa::ClueConstraint::Any),
                symmetry: opts.symmetry,
                max_clue: opts.max_clue,
                use_trial_and_error: opts.trial_and_error,
            };

            let mut rng = rand::thread_rng();
            loop {
                let res = tapa::generate(&opts, &dic, &consecutive_dic, &mut rng);

                if let Some(problem) = res {
                    let stdin = io::stdout();
                    let handle = &mut stdin.lock();

                    let end = start.elapsed();
                    let cost_time =
                        (end.as_secs() as f64 + end.subsec_nanos() as f64 / 1e9f64) / 60f64;
                    let mut cnt = gen_probs.lock().unwrap();
                    *cnt += 1;
                    eprintln!(
                        "{} problem(s) in {:.3}[min] ({:.3} [prob/min])",
                        *cnt,
                        cost_time,
                        (*cnt) as f64 / cost_time
                    );

                    writeln!(handle, "{} {}", height, width).unwrap();
                    for y in 0..height {
                        for x in 0..width {
                            let tapa::Clue(c) = problem[(Y(y), X(x))];
                            if c == 0 {
                                write!(handle, "0...").unwrap();
                            } else if c > 0 {
                                for i in 0..4 {
                                    let v = tapa::CLUE_VALUES[c as usize][i];
                                    if v > 0 {
                                        write!(handle, "{}", v).unwrap();
                                    } else {
                                        write!(handle, ".").unwrap();;
                                    }
                                }
                            } else {
                                write!(handle, "....").unwrap();
                            }
                            write!(handle, "{}", if x == width - 1 { '\n' } else { ' ' }).unwrap();
                        }
                    }
                    writeln!(handle).unwrap();
                }
            }
        }));
    }
    for th in ths {
        th.join().unwrap();
    }
    Ok(())
}

pub fn tapa_generator_frontend(args: &[String], program: &str) -> Result<(), CliError> {
    let mut options = Options::new();
    options.optflag("", "help", "Show this help menu");
    options.optopt("h", "height", "Height of desired problems", "10");
    options.optopt("w", "width", "Width of desired problems", "10");
    options.optopt("j", "jobs", "Number of workers (threads)", "2");
    options.optflag("s", "symmetry", "Force symmetry");
    options.optflag("t", "trial-and-error", "Use trial and error");
    options.optopt("x", "max-clue", "Maximum value of clues", "10");

    let matches = options.parse(&args[..])?;

    if matches.opt_present("help") {
        let brief = format!("Usage: {} tapa-gen [options]", program);
        print!("{}", options.usage(&brief));
        return Ok(());
    }

    let opts = parse_options(&matches)?;
    run_generator(opts)
}
<commit_msg>Tapa: CRLF -> LF in cli/tapa_generator.rs<commit_after>use super::*;
use {tapa, Grid, X, Y};
use rand;

use std::sync::{Arc, Mutex};
use std::io::{stdout, Write};
use std::thread;
use super::getopts::{Matches, Options};

#[derive(Clone, Copy, Debug)]
struct GeneratorOption {
    height: i32,
    width: i32,
    jobs: i32,
    symmetry: bool,
    max_clue: Option<i32>,
    trial_and_error: bool,
}

fn parse_options(matches: &Matches) -> Result<GeneratorOption, CliError> {
    let height = parse_integer_argument(matches, "height", None, Some(1))?;
    let width = parse_integer_argument(matches, "width", None, Some(1))?;
    let jobs = parse_integer_argument(matches, "jobs", Some(1), Some(1))?;
    let symmetry = matches.opt_present("symmetry");
    let trial_and_error = matches.opt_present("trial-and-error");

    let max_clue = matches
        .opt_str("max-clue")
        .map(|s| {
            s.parse::<i32>()
                .map_err(|_| CliError::UnrecognizedArgument("max-clue"))
                .and_then(|arg| {
                    if arg > 0 {
                        Ok(Some(arg))
                    } else {
                        Err(CliError::UnrecognizedArgument("max-clue"))
                    }
                })
        })
        .unwrap_or(Ok(None))?;
    Ok(GeneratorOption {
        height,
        width,
        jobs,
        symmetry,
        max_clue,
        trial_and_error,
    })
}

fn run_generator(opts: GeneratorOption) -> Result<(), CliError> {
    let height = opts.height;
    let width = opts.width;
    let mut ths = vec![];
    let gen_probs = Arc::new(Mutex::new(0i64));

    for _ in 0..opts.jobs {
        let gen_probs = gen_probs.clone();

        let opts = opts;

        ths.push(thread::spawn(move || {
            let start = Instant::now();
            let dic = tapa::Dictionary::new();
            let consecutive_dic = tapa::ConsecutiveRegionDictionary::new(&dic);

            let opts = tapa::GeneratorOption {
                clue_constraint: Grid::new(opts.height, opts.width, tapa::ClueConstraint::Any),
                symmetry: opts.symmetry,
                max_clue: opts.max_clue,
                use_trial_and_error: opts.trial_and_error,
            };

            let mut rng = rand::thread_rng();
            loop {
                let res = tapa::generate(&opts, &dic, &consecutive_dic, &mut rng);

                if let Some(problem) = res {
                    let stdin = io::stdout();
                    let handle = &mut stdin.lock();

                    let end = start.elapsed();
                    let cost_time =
                        (end.as_secs() as f64 + end.subsec_nanos() as f64 / 1e9f64) / 60f64;
                    let mut cnt = gen_probs.lock().unwrap();
                    *cnt += 1;
                    eprintln!(
                        "{} problem(s) in {:.3}[min] ({:.3} [prob/min])",
                        *cnt,
                        cost_time,
                        (*cnt) as f64 / cost_time
                    );

                    writeln!(handle, "{} {}", height, width).unwrap();
                    for y in 0..height {
                        for x in 0..width {
                            let tapa::Clue(c) = problem[(Y(y), X(x))];
                            if c == 0 {
                                write!(handle, "0...").unwrap();
                            } else if c > 0 {
                                for i in 0..4 {
                                    let v = tapa::CLUE_VALUES[c as usize][i];
                                    if v > 0 {
                                        write!(handle, "{}", v).unwrap();
                                    } else {
                                        write!(handle, ".").unwrap();;
                                    }
                                }
                            } else {
                                write!(handle, "....").unwrap();
                            }
                            write!(handle, "{}", if x == width - 1 { '\n' } else { ' ' }).unwrap();
                        }
                    }
                    writeln!(handle).unwrap();
                }
            }
        }));
    }
    for th in ths {
        th.join().unwrap();
    }
    Ok(())
}

pub fn tapa_generator_frontend(args: &[String], program: &str) -> Result<(), CliError> {
    let mut options = Options::new();
    options.optflag("", "help", "Show this help menu");
    options.optopt("h", "height", "Height of desired problems", "10");
    options.optopt("w", "width", "Width of desired problems", "10");
    options.optopt("j", "jobs", "Number of workers (threads)", "2");
    options.optflag("s", "symmetry", "Force symmetry");
    options.optflag("t", "trial-and-error", "Use trial and error");
    options.optopt("x", "max-clue", "Maximum value of clues", "10");

    let matches = options.parse(&args[..])?;

    if matches.opt_present("help") {
        let brief = format!("Usage: {} tapa-gen [options]", program);
        print!("{}", options.usage(&brief));
        return Ok(());
    }

    let opts = parse_options(&matches)?;
    run_generator(opts)
}
<|endoftext|>


<commit_before>//! An rope.
//!
//! A rope is an efficient data structure for large mutable strings. It's
//! essentially a binary tree whose leaves are strings.
//!
//! For more information, see the following resources:
//! + http://scienceblogs.com/goodmath/2009/01/26/ropes-twining-together-strings/
//! + https://www.ibm.com/developerworks/library/j-ropes/
//! + http://citeseer.ist.psu.edu/viewdoc/download?doi=10.1.1.14.9450&rep=rep1&type=pdf

#![feature(const_fn)]
#![feature(box_patterns)]

use std::cmp;
use std::ops;
use std::convert;

use self::Node::*;

#[derive(Debug)]
pub struct Rope {
    // can we get away with having these be of &str or will they need
    // to be string?
    root: Node
}

impl Rope {

    /// Returns a new empty Rope
    ///
    /// # Examples
    /// ```
    /// use an_rope::Rope;
    /// let mut an_rope = Rope::new();
    /// assert_eq!(an_rope.len(), 0);
    /// ```
    pub const fn new() -> Rope {
        Rope { root: Node::None }
    }

    /// Returns the length of this Rope
    ///
    /// # Examples
    /// ```
    /// use an_rope::Rope;
    /// let mut an_empty_rope = Rope::new();
    /// assert_eq!(an_empty_rope.len(), 0);
    /// ```
    /// ```
    /// use an_rope::Rope;
    /// let mut an_empty_rope = Rope::from(String::from(""));
    /// assert_eq!(an_empty_rope.len(), 0);
    /// ```
    /// ```
    /// use an_rope::Rope;
    /// let mut an_rope = Rope::from(String::from("a string"));
    /// assert_eq!(an_rope.len(), "a string".len());
    /// ```
    pub fn len(&self) -> usize {
        self.root.len()
    }

    /// Appends a rope to the end of this Rope
    ///
    /// # Examples
    /// ```
    /// use an_rope::Rope;
    /// let mut an_rope = Rope::from(String::from("abcd"));
    /// an_rope.append(Rope::from(String::from("efgh")))
    /// assert_eq!(an_rope, Rope::from(String::from("abcdefgh")));
    /// ```
    pub fn append(&mut self, other: Rope) {
        unimplemented!()
    }

    /// Prepends a rope to the front of this Rope
    ///
    /// # Examples
    /// ```
    /// use an_rope::Rope;
    /// let mut an_rope = Rope::from(String::from("efgh"));
    /// an_rope.preend(Rope::from(String::from("abcd")))
    /// assert_eq!(an_rope, Rope::from(String::from("abcdefgh")));
    /// ```
    pub fn prepend(&mut self, other: Rope) {
        unimplemented!()
    }

    /// Splits the rope into two ropes at the given index.
    ///
    /// Consumes this rope.
    ///
    /// # Examples
    /// ```
    /// use an_rope::Rope;
    /// let mut an_rope = Rope::from(String::from("abcd"));
    /// let (ab, cd) = an_rope.split(2);
    /// assert_eq!(ab, Rope::from(String::from("ab")));
    /// assert_eq!(cd, Rope::from(String::from("cd")));
    /// ```
    pub fn split(self, index: usize) -> (Rope, Rope) {
        unimplemented!()
    }
}

#[derive(Debug)]
enum Node { /// A leaf node
            // todo: is box<str> the right choice?
            Leaf(Box<str>)
          , /// A branch node
            Branch { l: Box<Node>, r: Box<Node> }
          , /// Nothing
            None
}

impl ops::Index<usize> for Node {
    type Output = str;

    fn index(&self, i: usize) -> &str {
        let len = self.len();
        match self { &Leaf(box ref s) => {
                        let slice: &str = s.as_ref();
                        &slice[i..i+1]
                    }
                    , &Branch { box ref r, .. } if len < i => &r[i - len]
                    , &Branch { box ref l, .. } => &l[i]
                    , &None => panic!("Index out of bounds!")
                    }
    }
}

impl Node {

    /// Returns the length of a node
    //  TODO: do we want to cache this?
    fn len(&self) -> usize {
        match *self { Leaf(box ref s) => s.len()
                    , Branch { box ref l, box ref r} => l.len() + r.len()
                    , None => 0
                    }
    }

    /// Returns the weight of a node
    #[inline]
    fn weight(&self) -> usize {
        match *self { Leaf(_) => 1
                    , Branch { box ref l, box ref r} =>
                        cmp::max(r.weight(), l.weight()) + 1
                    , None => 0
                    }
    }

}

trait Take {
    fn take(&mut self) -> Node;
}

impl Take for Box<Node> {

    /// Take the value out of a `Node`, replacing it with `None`
    #[inline]
    fn take(&mut self) -> Node {
        std::mem::replace(self, None)
    }
}

impl convert::From<String> for Rope {
    fn from(string: String) -> Rope {
        Rope {
            root: if string.len() == 0 { Node::None }
                  else { Node::Leaf(string.into_boxed_str()) }
        }
    }
}

//-- comparisons ----------------------------------------------------
impl cmp::PartialEq for Rope {
    fn eq(&self, other: &Rope) -> bool {
        unimplemented!()
    }
}

impl cmp::PartialEq<str> for Rope {
    fn eq(&self, other: &str) -> bool {
        unimplemented!()
    }
}

//-- concatenation --------------------------------------------------
impl ops::Add for Rope {
    type Output = Rope;

    // This is the concat operation.
    fn add(self, other: Rope) -> Rope {
        unimplemented!()
    }
}

impl ops::Index<usize> for Rope {
    type Output = str;

    /// Recursively index the Rope to return the `i` th character.
    ///
    /// # Examples
    /// ```
    /// use an_rope::Rope;
    /// let an_rope = Rope::from(String::from("abcd"));
    /// assert_eq!(&an_rope[0], "a");
    /// assert_eq!(&an_rope[1], "b");
    /// assert_eq!(&an_rope[2], "c");
    /// assert_eq!(&an_rope[3], "d");
    /// ```
    ///
    /// # Time complexity
    /// _O_(log _n_)
    ///
    #[inline]
    fn index(&self, i: usize) -> &str {
        &self.root[i]
    }
}

//-- slicing operators ----------------------------------------------
impl ops::Index<ops::Range<usize>> for Rope {
    type Output = str;

    // Index a substring
    fn index(&self, i: ops::Range<usize>) -> &str {
        unimplemented!()
    }
}

impl ops::Index<ops::RangeTo<usize>> for Rope {
    type Output = str;

    fn index(&self, i: ops::RangeTo<usize>) -> &str {
        unimplemented!()
    }
}

impl ops::Index<ops::RangeFrom<usize>> for Rope {
    type Output = str;

    fn index(&self, i: ops::RangeFrom<usize>) -> &str {
        unimplemented!()
    }
}

impl ops::IndexMut<ops::Range<usize>> for Rope {
    fn index_mut(&mut self, i: ops::Range<usize>) -> &mut str {
        unimplemented!()
    }
}

impl ops::IndexMut<ops::RangeTo<usize>> for Rope {
    fn index_mut(&mut self, i: ops::RangeTo<usize>) -> &mut str {
        unimplemented!()
    }
}

impl ops::IndexMut<ops::RangeFrom<usize>> for Rope {
    fn index_mut(&mut self, i: ops::RangeFrom<usize>) -> &mut str {
        unimplemented!()
    }
}

#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {
    }
}
<commit_msg>rope: changes to rope concatenation operators<commit_after>//! An rope.
//!
//! A rope is an efficient data structure for large mutable strings. It's
//! essentially a binary tree whose leaves are strings.
//!
//! For more information, see the following resources:
//! + http://scienceblogs.com/goodmath/2009/01/26/ropes-twining-together-strings/
//! + https://www.ibm.com/developerworks/library/j-ropes/
//! + http://citeseer.ist.psu.edu/viewdoc/download?doi=10.1.1.14.9450&rep=rep1&type=pdf

#![feature(const_fn)]
#![feature(box_patterns)]

use std::cmp;
use std::ops;
use std::convert;

use self::Node::*;

#[derive(Debug)]
pub struct Rope {
    // can we get away with having these be of &str or will they need
    // to be string?
    root: Node
}

impl Rope {

    /// Returns a new empty Rope
    ///
    /// # Examples
    /// ```
    /// use an_rope::Rope;
    /// let mut an_rope = Rope::new();
    /// assert_eq!(an_rope.len(), 0);
    /// ```
    pub const fn new() -> Rope {
        Rope { root: Node::None }
    }

    /// Returns the length of this Rope
    ///
    /// # Examples
    /// ```
    /// use an_rope::Rope;
    /// let mut an_empty_rope = Rope::new();
    /// assert_eq!(an_empty_rope.len(), 0);
    /// ```
    /// ```
    /// use an_rope::Rope;
    /// let mut an_empty_rope = Rope::from(String::from(""));
    /// assert_eq!(an_empty_rope.len(), 0);
    /// ```
    /// ```
    /// use an_rope::Rope;
    /// let mut an_rope = Rope::from(String::from("a string"));
    /// assert_eq!(an_rope.len(), "a string".len());
    /// ```
    pub fn len(&self) -> usize {
        self.root.len()
    }

    /// Appends a rope to the end of this Rope
    ///
    /// # Examples
    /// ```
    /// use an_rope::Rope;
    /// let mut an_rope = Rope::from(String::from("abcd"));
    /// an_rope.append(Rope::from(String::from("efgh")))
    /// assert_eq!(an_rope, Rope::from(String::from("abcdefgh")));
    /// ```
    pub fn append(&mut self, other: Rope) {
        unimplemented!()
    }

    /// Prepends a rope to the front of this Rope
    ///
    /// # Examples
    /// ```
    /// use an_rope::Rope;
    /// let mut an_rope = Rope::from(String::from("efgh"));
    /// an_rope.preend(Rope::from(String::from("abcd")))
    /// assert_eq!(an_rope, Rope::from(String::from("abcdefgh")));
    /// ```
    pub fn prepend(&mut self, other: Rope) {
        unimplemented!()
    }

    /// Splits the rope into two ropes at the given index.
    ///
    /// Consumes this rope.
    ///
    /// # Examples
    /// ```
    /// use an_rope::Rope;
    /// let mut an_rope = Rope::from(String::from("abcd"));
    /// let (ab, cd) = an_rope.split(2);
    /// assert_eq!(ab, Rope::from(String::from("ab")));
    /// assert_eq!(cd, Rope::from(String::from("cd")));
    /// ```
    pub fn split(self, index: usize) -> (Rope, Rope) {
        unimplemented!()
    }
}

#[derive(Debug)]
enum Node { /// A leaf node
            // todo: is box<str> the right choice?
            Leaf(Box<str>)
          , /// A branch node
            Branch { l: Box<Node>, r: Box<Node> }
          , /// Nothing
            None
}

impl ops::Index<usize> for Node {
    type Output = str;

    fn index(&self, i: usize) -> &str {
        let len = self.len();
        match self { &Leaf(box ref s) => {
                        let slice: &str = s.as_ref();
                        &slice[i..i+1]
                    }
                    , &Branch { box ref r, .. } if len < i => &r[i - len]
                    , &Branch { box ref l, .. } => &l[i]
                    , &None => panic!("Index out of bounds!")
                    }
    }
}

impl Node {

    /// Returns the length of a node
    //  TODO: do we want to cache this?
    fn len(&self) -> usize {
        match *self { Leaf(box ref s) => s.len()
                    , Branch { box ref l, box ref r} => l.len() + r.len()
                    , None => 0
                    }
    }

    /// Returns the weight of a node
    #[inline]
    fn weight(&self) -> usize {
        match *self { Leaf(_) => 1
                    , Branch { box ref l, box ref r} =>
                        cmp::max(r.weight(), l.weight()) + 1
                    , None => 0
                    }
    }

}

trait Take {
    fn take(&mut self) -> Node;
}

impl Take for Box<Node> {

    /// Take the value out of a `Node`, replacing it with `None`
    #[inline]
    fn take(&mut self) -> Node {
        std::mem::replace(self, None)
    }
}

impl convert::From<String> for Rope {
    fn from(string: String) -> Rope {
        Rope {
            root: if string.len() == 0 { Node::None }
                  else { Node::Leaf(string.into_boxed_str()) }
        }
    }
}

//-- comparisons ----------------------------------------------------
impl cmp::PartialEq for Rope {
    fn eq(&self, other: &Rope) -> bool {
        unimplemented!()
    }
}

impl cmp::PartialEq<str> for Rope {
    fn eq(&self, other: &str) -> bool {
        unimplemented!()
    }
}

//-- concatenation --------------------------------------------------
impl ops::AddAssign for Rope {

    /// Concatenate two `Rope`s.
    ///
    /// # Examples
    /// ```
    /// let mut rope = Rope::from(String::from("ab"));
    /// rope += Rope::from(String::from("cd"));
    /// assert_eq!(rope, Rope::from(String::from("abcd")));
    /// ````
    #[inline]
    fn add_assign(&mut self, other: Rope) {
        self.append(other)
    }
}

impl ops::AddAssign<String> for Rope {

    /// Concatenate a `String` onto a `Rope`
    ///
    /// # Examples
    /// ```
    /// let mut rope = Rope::from(String::from("ab"));
    /// rope += String::from("cd");
    /// assert_eq!(rope, Rope::from(String::from("abcd")));
    /// ````
    #[inline]
    fn add_assign(&mut self, string: String) {
        self.append(Rope::from(string))
    }
}

impl<'a> ops::AddAssign<&'a str> for Rope {

    /// Concatenate an `&str` onto a `Rope`
    ///
    /// # Examples
    /// ```
    /// let mut rope = Rope::from(String::from("ab"));
    /// rope += String::from("cd");
    /// assert_eq!(rope, Rope::from(String::from("abcd")));
    /// ````
    #[inline]
    fn add_assign(&mut self, string: &'a str) {
        self.append(Rope::from(string.to_owned()))
    }
}

impl ops::Index<usize> for Rope {
    type Output = str;

    /// Recursively index the Rope to return the `i` th character.
    ///
    /// # Examples
    /// ```
    /// use an_rope::Rope;
    /// let an_rope = Rope::from(String::from("abcd"));
    /// assert_eq!(&an_rope[0], "a");
    /// assert_eq!(&an_rope[1], "b");
    /// assert_eq!(&an_rope[2], "c");
    /// assert_eq!(&an_rope[3], "d");
    /// ```
    ///
    /// # Time complexity
    /// _O_(log _n_)
    ///
    #[inline]
    fn index(&self, i: usize) -> &str {
        &self.root[i]
    }
}

//-- slicing operators ----------------------------------------------
impl ops::Index<ops::Range<usize>> for Rope {
    type Output = str;

    // Index a substring
    fn index(&self, i: ops::Range<usize>) -> &str {
        unimplemented!()
    }
}

impl ops::Index<ops::RangeTo<usize>> for Rope {
    type Output = str;

    fn index(&self, i: ops::RangeTo<usize>) -> &str {
        unimplemented!()
    }
}

impl ops::Index<ops::RangeFrom<usize>> for Rope {
    type Output = str;

    fn index(&self, i: ops::RangeFrom<usize>) -> &str {
        unimplemented!()
    }
}

impl ops::IndexMut<ops::Range<usize>> for Rope {
    fn index_mut(&mut self, i: ops::Range<usize>) -> &mut str {
        unimplemented!()
    }
}

impl ops::IndexMut<ops::RangeTo<usize>> for Rope {
    fn index_mut(&mut self, i: ops::RangeTo<usize>) -> &mut str {
        unimplemented!()
    }
}

impl ops::IndexMut<ops::RangeFrom<usize>> for Rope {
    fn index_mut(&mut self, i: ops::RangeFrom<usize>) -> &mut str {
        unimplemented!()
    }
}

#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {
    }
}
<|endoftext|>


<commit_before>use tokenizer::TomlFragment;

#[derive(PartialEq, Debug)]
pub enum AstFragment {
    Boolean(bool),
}

pub fn parse_fragment(tokens: Vec<TomlFragment>) -> Result<Vec<AstFragment>, &str> {
    let mut fragments = Vec::with_capacity(tokens.len() / 2);

    for token in tokens.iter() {
        fragments.push(
            match token {
                &TomlFragment::Boolean("true") => AstFragment::Boolean(true),
                &TomlFragment::Boolean("false") => AstFragment::Boolean(false),
                _ => return Err("not implemented"),
            });
    }

    Ok(fragments)
}

#[test]
fn parse_fragment_boolean_true() {
    let expected = Ok(vec![AstFragment::Boolean(true)]);
    let input = vec![TomlFragment::Boolean("true")];
    assert_eq!(expected, parse_fragment(input));
}

#[test]
fn parse_fragment_boolean_false() {
    let expected = Ok(vec![AstFragment::Boolean(false)]);
    let input = vec![TomlFragment::Boolean("false")];
    assert_eq!(expected, parse_fragment(input));
}
<commit_msg>Add parsing for whitespace<commit_after>use tokenizer::TomlFragment;

#[derive(PartialEq, Debug)]
pub enum AstFragment<'a> {
    Boolean(bool),
    Whitespace(&'a str),
}

pub fn parse_fragment(tokens: Vec<TomlFragment>) -> Result<Vec<AstFragment>, &str> {
    let mut fragments = Vec::with_capacity(tokens.len() / 2);

    for token in tokens.iter() {
        fragments.push(
            match token {
                &TomlFragment::Boolean("true") => AstFragment::Boolean(true),
                &TomlFragment::Boolean("false") => AstFragment::Boolean(false),
                &TomlFragment::Whitespace(s) => AstFragment::Whitespace(s),
                _ => return Err("not implemented"),
            });
    }

    Ok(fragments)
}

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

    #[test]
    fn parse_fragment_whitespace() {
        let expected = Ok(vec![AstFragment::Whitespace("   ")]);
        let input = vec![TomlFragment::Whitespace("   ")];
        assert_eq!(expected, parse_fragment(input));
    }

    #[test]
    fn parse_fragment_boolean_true() {
        let expected = Ok(vec![AstFragment::Boolean(true)]);
        let input = vec![TomlFragment::Boolean("true")];
        assert_eq!(expected, parse_fragment(input));
    }

    #[test]
    fn parse_fragment_boolean_false() {
        let expected = Ok(vec![AstFragment::Boolean(false)]);
        let input = vec![TomlFragment::Boolean("false")];
        assert_eq!(expected, parse_fragment(input));
    }
}
<|endoftext|>