<commit_before>#![deny(warnings)]

// This is using the `tokio` runtime. You'll need the following dependency:
//
// `tokio = { version = "0.2", features = ["macros"] }`
#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
    // Make sure you are running tor and this is your socks port
    let proxy = reqwest::Proxy::all("socks5://127.0.0.1:9050").expect("tor proxy should be there");
    let client = reqwest::Client::builder()
        .proxy(proxy)
        .build()
        .expect("should be able to build reqwest client");

    let res = client.get("https://check.torproject.org").send().await?;
    println!("Status: {}", res.status());

    let text = res.text().await?;
    let is_tor = text.contains("Congratulations. This browser is configured to use Tor.");
    println!("Is Tor: {}", is_tor);
    assert!(is_tor);

    Ok(())
}
<commit_msg>Use proxy's DNS in TOR example (#1003)<commit_after>#![deny(warnings)]

// This is using the `tokio` runtime. You'll need the following dependency:
//
// `tokio = { version = "0.2", features = ["macros"] }`
#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
    // Make sure you are running tor and this is your socks port
    let proxy = reqwest::Proxy::all("socks5h://127.0.0.1:9050").expect("tor proxy should be there");
    let client = reqwest::Client::builder()
        .proxy(proxy)
        .build()
        .expect("should be able to build reqwest client");

    let res = client.get("https://check.torproject.org").send().await?;
    println!("Status: {}", res.status());

    let text = res.text().await?;
    let is_tor = text.contains("Congratulations. This browser is configured to use Tor.");
    println!("Is Tor: {}", is_tor);
    assert!(is_tor);

    Ok(())
}
<|endoftext|>


<commit_before>//use std::str::Split;
use std::rc::Rc;

struct NestedInteger {
    value: i32,
    next: Rc<NestedInteger>,
}

fn split_it(s: &str) -> Vec<&str> {
    let result = s.splitn(2, ",").collect();
    result
}

fn generator(s: &str) -> Rc<NestedInteger> {
    //let mut result = NestedInteger {};
    if s == "" {
        Rc::new()
    }

    let temp = split_it(s);

    if let Some(c) = temp[0].chars().next() {
        let mut temp_value: i32;
        if c != "[" {
            temp_value = temp[0].parse::<i32>().unwrap();
        } else {
            temp_value = temp[1..].parse::<i32>().unwrap();
        }
        //result.next = temp_value;
    }

    let result = NestedInteger {
        value : temp_value,
        next : generator(temp[1]),
    }
    //result.next = generator(temp[1]);

    return Rc::new(result);
}

fn main() {
    let test1 = "111";
    let test2 = "[111,[222,[333]]]";
    println!("{:?}", split_it(&test1));
    println!("{:?}", split_it(&test2));

    println!("{:?}", generator(test2));
}
<commit_msg>finish<commit_after>//use std::str::Split;
use std::rc::Rc;

#[derive(Debug)]
struct NestedInteger {
    value: i32,
    next: Option<Rc<NestedInteger>>,
}

fn clean_tail(s: &str) -> &str {
    s.split(']').collect::<Vec<&str>>()[0]
}

fn split_it(s: &str) -> Vec<&str> {
    let result = s.splitn(2, ",").collect();
    result
}

fn generator(s: &str) -> Option<Rc<NestedInteger>> {
    //let mut result = NestedInteger {};
    if s == "" {
        return None;
    }

    let temp = split_it(s);
    let mut temp_value: i32 = 0;

    if let Some(c) = temp[0].chars().next() {
        if c != '[' {
            temp_value = temp[0].parse::<i32>().unwrap();
        } else {
            temp_value = temp[0][1..].parse::<i32>().unwrap();
        }
    }

    let result = Rc::new(NestedInteger {
        value: temp_value,
        next: if temp.len() > 1 {
            generator(temp[1])
        } else {
            None
        },
    });
    //result.next = generator(temp[1]);

    return Some(result);
}

fn main() {
    let test1 = "[111]]]";
    let test2 = "[111,[222,[333]]]";
    println!("{:?}", clean_tail(split_it(&test1)[0]));
    println!("{:?}", split_it(&test2));

    println!("{:?}", generator(clean_tail(test2)));
}
<|endoftext|>


<commit_before>use super::collect_versions;
use crate::{config::Config, env::Env, file_saver::save_to_file, nameutil, version::Version};
use log::info;
use std::{collections::HashMap, fs::File, io::prelude::*};
use toml::{self, value::Table, Value};

pub fn generate(env: &Env) -> String {
    info!("Generating sys Cargo.toml for {}", env.config.library_name);

    let path = env.config.target_path.join("Cargo.toml");

    let mut toml_str = String::new();
    if let Ok(mut file) = File::open(&path) {
        file.read_to_string(&mut toml_str).unwrap();
    }
    let empty = toml_str.trim().is_empty();
    let mut root_table = toml::from_str(&toml_str).unwrap_or_else(|_| Table::new());
    let crate_name = get_crate_name(&env.config, &root_table);

    if empty {
        fill_empty(&mut root_table, env, &crate_name);
    }
    fill_in(&mut root_table, env);

    save_to_file(&path, env.config.make_backup, |w| {
        w.write_all(toml::to_string(&root_table).unwrap().as_bytes())
    });

    crate_name
}

fn fill_empty(root: &mut Table, env: &Env, crate_name: &str) {
    let package_name = nameutil::exported_crate_name(crate_name);

    {
        let package = upsert_table(root, "package");
        set_string(package, "name", package_name);
        set_string(package, "version", "0.0.1");
        set_string(package, "edition", "2021");
    }

    {
        let lib = upsert_table(root, "lib");
        set_string(lib, "name", crate_name);
    }

    let deps = upsert_table(root, "dependencies");
    for ext_lib in &env.config.external_libraries {
        let dep = upsert_table(deps, &ext_lib.crate_name);
        let ext_package = if ext_lib.crate_name == "cairo" {
            format!("{}-sys-rs", ext_lib.crate_name)
        } else if ext_lib.crate_name == "gdk_pixbuf" {
            "gdk-pixbuf-sys".into()
        } else {
            format!("{}-sys", ext_lib.crate_name)
        };
        let repo_url = match ext_package.as_str() {
            "cairo-sys-rs" | "gdk-pixbuf-sys" | "gio-sys" | "gobject-sys" | "glib-sys"
            | "graphene-sys" | "pango-sys" | "pangocairo-sys" => {
                "https://github.com/gtk-rs/gtk-rs-core"
            }
            "atk-sys" | "gdk-sys" | "gdkwayland-sys" | "gdkx11-sys" | "gtk-sys" | "gtk-macros" => {
                "https://github.com/gtk-rs/gtk3-rs"
            }
            "gdk4-wayland-sys" | "gdk4-x11-sys" | "gdk4-sys" | "gsk4-sys" | "gtk4-sys" => {
                "https://github.com/gtk-rs/gtk4-rs"
            }
            "gstreamer-sys"
            | "gstreamer-app-sys"
            | "gstreamer-audio-sys"
            | "gstreamer-base-sys"
            | "gstreamer-check-sys"
            | "gstreamer-controller-sys"
            | "gstreamer-editing-services-sys"
            | "gstreamer-gl-sys"
            | "gstreamer-gl/egl-sys"
            | "gstreamer-gl/wayland-sys"
            | "gstreamer-gl/x11-sys"
            | "gstreamer-mpegts-sys"
            | "gstreamer-net-sys"
            | "gstreamer-pbutils-sys"
            | "gstreamer-player-sys"
            | "gstreamer-rtp-sys"
            | "gstreamer-rtsp-sys"
            | "gstreamer-rtsp-server-sys"
            | "gstreamer-sdp-sys"
            | "gstreamer-tag-sys"
            | "gstreamer-video-sys"
            | "gstreamer-webrtc-sys"
            | "gstreamer-allocators-sys" => "https://gitlab.freedesktop.org/gstreamer/gstreamer-rs",
            &_ => "ADD GIT REPOSITORY URL HERE",
        };
        set_string(dep, "package", ext_package);
        set_string(dep, "git", repo_url);
    }
}

fn fill_in(root: &mut Table, env: &Env) {
    {
        let package = upsert_table(root, "package");
        set_string(package, "build", "build.rs");
        //set_string(package, "version", "0.2.0");
    }

    {
        let deps = upsert_table(root, "dependencies");
        set_string(deps, "libc", "0.2");
    }

    {
        let build_deps = upsert_table(root, "build-dependencies");
        set_string(build_deps, "system-deps", "6");
    }

    {
        let dev_deps = upsert_table(root, "dev-dependencies");
        set_string(dev_deps, "shell-words", "1.0.0");
        set_string(dev_deps, "tempfile", "3");
        unset(dev_deps, "tempdir");
    }

    {
        let features = upsert_table(root, "features");
        let versions = collect_versions(env);
        versions.keys().fold(None::<Version>, |prev, &version| {
            let prev_array: Vec<Value> =
                get_feature_dependencies(version, prev, &env.config.feature_dependencies)
                    .iter()
                    .map(|s| Value::String(s.clone()))
                    .collect();
            features.insert(version.to_feature(), Value::Array(prev_array));
            Some(version)
        });
        features.insert(
            "dox".to_string(),
            Value::Array(
                env.config
                    .dox_feature_dependencies
                    .iter()
                    .map(|s| Value::String(s.clone()))
                    .collect(),
            ),
        );
    }

    {
        let meta = upsert_table(root, "package");
        let meta = upsert_table(meta, "metadata");
        let meta = upsert_table(meta, "system-deps");

        let ns = env.namespaces.main();
        let lib_name = ns.package_name.as_ref().unwrap();

        let meta = upsert_table(meta, nameutil::lib_name_to_toml(lib_name));
        // Allow both the name and version of a system dep to be overridden by hand
        meta.entry("name")
            .or_insert_with(|| Value::String(lib_name.to_owned()));
        meta.entry("version")
            .or_insert_with(|| Value::String(env.config.min_cfg_version.to_string()));

        // Old version API
        unset(meta, "feature-versions");

        collect_versions(env)
            .iter()
            .filter(|(&v, _)| v > env.config.min_cfg_version)
            .for_each(|(v, lib_version)| {
                let version_section = upsert_table(meta, &v.to_feature());
                // Allow system-deps version for this feature level to be overridden by hand
                version_section
                    .entry("version")
                    .or_insert_with(|| Value::String(lib_version.to_string()));
            });
    }

    {
        // Small trick to prevent having double quotes around it since toml doesn't like having '.'
        let docs_rs_metadata = upsert_table(root, "package");
        let docs_rs_metadata = upsert_table(docs_rs_metadata, "metadata");
        let docs_rs_metadata = upsert_table(docs_rs_metadata, "docs");
        let docs_rs_metadata = upsert_table(docs_rs_metadata, "rs");
        let mut docs_rs_features = env.config.docs_rs_features.clone();
        docs_rs_features.push("dox".to_owned());
        docs_rs_metadata.insert(
            "features".to_string(),
            Value::Array(
                docs_rs_features
                    .into_iter()
                    .map(Value::String)
                    .collect::<Vec<_>>(),
            ),
        );
    }
}

fn get_feature_dependencies(
    version: Version,
    prev_version: Option<Version>,
    feature_dependencies: &HashMap<Version, Vec<String>>,
) -> Vec<String> {
    let mut vec = Vec::with_capacity(10);
    if let Some(v) = prev_version {
        vec.push(v.to_feature());
    }
    if let Some(dependencies) = feature_dependencies.get(&version) {
        vec.extend_from_slice(dependencies);
    }
    vec
}

/// Returns the name of crate being currently generated.
fn get_crate_name(config: &Config, root: &Table) -> String {
    if let Some(Value::Table(lib)) = root.get("lib") {
        if let Some(Value::String(lib_name)) = lib.get("name") {
            //Converting don't needed as library target names cannot contain hyphens
            return lib_name.to_owned();
        }
    }
    if let Some(Value::Table(package)) = root.get("package") {
        if let Some(Value::String(package_name)) = package.get("name") {
            return nameutil::crate_name(package_name);
        }
    }
    return format!("{}_sys", nameutil::crate_name(&config.library_name));
}

fn set_string<S: Into<String>>(table: &mut Table, name: &str, new_value: S) {
    table.insert(name.into(), Value::String(new_value.into()));
}

fn unset(table: &mut Table, name: &str) {
    table.remove(name);
}

fn upsert_table<S: Into<String>>(parent: &mut Table, name: S) -> &mut Table {
    if let Value::Table(table) = parent
        .entry(name.into())
        .or_insert_with(|| Value::Table(toml::map::Map::new()))
    {
        table
    } else {
        unreachable!()
    }
}
<commit_msg>Removed gtk-macros<commit_after>use super::collect_versions;
use crate::{config::Config, env::Env, file_saver::save_to_file, nameutil, version::Version};
use log::info;
use std::{collections::HashMap, fs::File, io::prelude::*};
use toml::{self, value::Table, Value};

pub fn generate(env: &Env) -> String {
    info!("Generating sys Cargo.toml for {}", env.config.library_name);

    let path = env.config.target_path.join("Cargo.toml");

    let mut toml_str = String::new();
    if let Ok(mut file) = File::open(&path) {
        file.read_to_string(&mut toml_str).unwrap();
    }
    let empty = toml_str.trim().is_empty();
    let mut root_table = toml::from_str(&toml_str).unwrap_or_else(|_| Table::new());
    let crate_name = get_crate_name(&env.config, &root_table);

    if empty {
        fill_empty(&mut root_table, env, &crate_name);
    }
    fill_in(&mut root_table, env);

    save_to_file(&path, env.config.make_backup, |w| {
        w.write_all(toml::to_string(&root_table).unwrap().as_bytes())
    });

    crate_name
}

fn fill_empty(root: &mut Table, env: &Env, crate_name: &str) {
    let package_name = nameutil::exported_crate_name(crate_name);

    {
        let package = upsert_table(root, "package");
        set_string(package, "name", package_name);
        set_string(package, "version", "0.0.1");
        set_string(package, "edition", "2021");
    }

    {
        let lib = upsert_table(root, "lib");
        set_string(lib, "name", crate_name);
    }

    let deps = upsert_table(root, "dependencies");
    for ext_lib in &env.config.external_libraries {
        let dep = upsert_table(deps, &ext_lib.crate_name);
        let ext_package = if ext_lib.crate_name == "cairo" {
            format!("{}-sys-rs", ext_lib.crate_name)
        } else if ext_lib.crate_name == "gdk_pixbuf" {
            "gdk-pixbuf-sys".into()
        } else {
            format!("{}-sys", ext_lib.crate_name)
        };
        let repo_url = match ext_package.as_str() {
            "cairo-sys-rs" | "gdk-pixbuf-sys" | "gio-sys" | "gobject-sys" | "glib-sys"
            | "graphene-sys" | "pango-sys" | "pangocairo-sys" => {
                "https://github.com/gtk-rs/gtk-rs-core"
            }
            "atk-sys" | "gdk-sys" | "gdkwayland-sys" | "gdkx11-sys" | "gtk-sys" => {
                "https://github.com/gtk-rs/gtk3-rs"
            }
            "gdk4-wayland-sys" | "gdk4-x11-sys" | "gdk4-sys" | "gsk4-sys" | "gtk4-sys" => {
                "https://github.com/gtk-rs/gtk4-rs"
            }
            "gstreamer-sys"
            | "gstreamer-app-sys"
            | "gstreamer-audio-sys"
            | "gstreamer-base-sys"
            | "gstreamer-check-sys"
            | "gstreamer-controller-sys"
            | "gstreamer-editing-services-sys"
            | "gstreamer-gl-sys"
            | "gstreamer-gl/egl-sys"
            | "gstreamer-gl/wayland-sys"
            | "gstreamer-gl/x11-sys"
            | "gstreamer-mpegts-sys"
            | "gstreamer-net-sys"
            | "gstreamer-pbutils-sys"
            | "gstreamer-player-sys"
            | "gstreamer-rtp-sys"
            | "gstreamer-rtsp-sys"
            | "gstreamer-rtsp-server-sys"
            | "gstreamer-sdp-sys"
            | "gstreamer-tag-sys"
            | "gstreamer-video-sys"
            | "gstreamer-webrtc-sys"
            | "gstreamer-allocators-sys" => "https://gitlab.freedesktop.org/gstreamer/gstreamer-rs",
            &_ => "ADD GIT REPOSITORY URL HERE",
        };
        set_string(dep, "package", ext_package);
        set_string(dep, "git", repo_url);
    }
}

fn fill_in(root: &mut Table, env: &Env) {
    {
        let package = upsert_table(root, "package");
        set_string(package, "build", "build.rs");
        //set_string(package, "version", "0.2.0");
    }

    {
        let deps = upsert_table(root, "dependencies");
        set_string(deps, "libc", "0.2");
    }

    {
        let build_deps = upsert_table(root, "build-dependencies");
        set_string(build_deps, "system-deps", "6");
    }

    {
        let dev_deps = upsert_table(root, "dev-dependencies");
        set_string(dev_deps, "shell-words", "1.0.0");
        set_string(dev_deps, "tempfile", "3");
        unset(dev_deps, "tempdir");
    }

    {
        let features = upsert_table(root, "features");
        let versions = collect_versions(env);
        versions.keys().fold(None::<Version>, |prev, &version| {
            let prev_array: Vec<Value> =
                get_feature_dependencies(version, prev, &env.config.feature_dependencies)
                    .iter()
                    .map(|s| Value::String(s.clone()))
                    .collect();
            features.insert(version.to_feature(), Value::Array(prev_array));
            Some(version)
        });
        features.insert(
            "dox".to_string(),
            Value::Array(
                env.config
                    .dox_feature_dependencies
                    .iter()
                    .map(|s| Value::String(s.clone()))
                    .collect(),
            ),
        );
    }

    {
        let meta = upsert_table(root, "package");
        let meta = upsert_table(meta, "metadata");
        let meta = upsert_table(meta, "system-deps");

        let ns = env.namespaces.main();
        let lib_name = ns.package_name.as_ref().unwrap();

        let meta = upsert_table(meta, nameutil::lib_name_to_toml(lib_name));
        // Allow both the name and version of a system dep to be overridden by hand
        meta.entry("name")
            .or_insert_with(|| Value::String(lib_name.to_owned()));
        meta.entry("version")
            .or_insert_with(|| Value::String(env.config.min_cfg_version.to_string()));

        // Old version API
        unset(meta, "feature-versions");

        collect_versions(env)
            .iter()
            .filter(|(&v, _)| v > env.config.min_cfg_version)
            .for_each(|(v, lib_version)| {
                let version_section = upsert_table(meta, &v.to_feature());
                // Allow system-deps version for this feature level to be overridden by hand
                version_section
                    .entry("version")
                    .or_insert_with(|| Value::String(lib_version.to_string()));
            });
    }

    {
        // Small trick to prevent having double quotes around it since toml doesn't like having '.'
        let docs_rs_metadata = upsert_table(root, "package");
        let docs_rs_metadata = upsert_table(docs_rs_metadata, "metadata");
        let docs_rs_metadata = upsert_table(docs_rs_metadata, "docs");
        let docs_rs_metadata = upsert_table(docs_rs_metadata, "rs");
        let mut docs_rs_features = env.config.docs_rs_features.clone();
        docs_rs_features.push("dox".to_owned());
        docs_rs_metadata.insert(
            "features".to_string(),
            Value::Array(
                docs_rs_features
                    .into_iter()
                    .map(Value::String)
                    .collect::<Vec<_>>(),
            ),
        );
    }
}

fn get_feature_dependencies(
    version: Version,
    prev_version: Option<Version>,
    feature_dependencies: &HashMap<Version, Vec<String>>,
) -> Vec<String> {
    let mut vec = Vec::with_capacity(10);
    if let Some(v) = prev_version {
        vec.push(v.to_feature());
    }
    if let Some(dependencies) = feature_dependencies.get(&version) {
        vec.extend_from_slice(dependencies);
    }
    vec
}

/// Returns the name of crate being currently generated.
fn get_crate_name(config: &Config, root: &Table) -> String {
    if let Some(Value::Table(lib)) = root.get("lib") {
        if let Some(Value::String(lib_name)) = lib.get("name") {
            //Converting don't needed as library target names cannot contain hyphens
            return lib_name.to_owned();
        }
    }
    if let Some(Value::Table(package)) = root.get("package") {
        if let Some(Value::String(package_name)) = package.get("name") {
            return nameutil::crate_name(package_name);
        }
    }
    return format!("{}_sys", nameutil::crate_name(&config.library_name));
}

fn set_string<S: Into<String>>(table: &mut Table, name: &str, new_value: S) {
    table.insert(name.into(), Value::String(new_value.into()));
}

fn unset(table: &mut Table, name: &str) {
    table.remove(name);
}

fn upsert_table<S: Into<String>>(parent: &mut Table, name: S) -> &mut Table {
    if let Value::Table(table) = parent
        .entry(name.into())
        .or_insert_with(|| Value::Table(toml::map::Map::new()))
    {
        table
    } else {
        unreachable!()
    }
}
<|endoftext|>


<commit_before>use alloc::boxed::Box;
use collections::string::String;
use collections::vec::Vec;
use collections::btree_map::BTreeMap;

use super::AmlError;
use super::parser::{AmlParseType, ParseResult, AmlExecutionContext};
use super::namespace::{AmlValue, ObjectReference};
use super::pkglength::parse_pkg_length;
use super::termlist::{parse_term_arg, parse_term_list};
use super::namestring::{parse_name_string, parse_super_name};

pub fn parse_type1_opcode(data: &[u8],
                          ctx: &mut AmlExecutionContext) -> ParseResult {
    parser_selector! {
        data, ctx,
        parse_def_break,
        parse_def_breakpoint,
        parse_def_continue,
        parse_def_noop,
        parse_def_fatal,
        parse_def_if_else,
        parse_def_load,
        parse_def_notify,
        parse_def_release,
        parse_def_reset,
        parse_def_signal,
        parse_def_sleep,
        parse_def_stall,
        parse_def_return,
        parse_def_unload,
        parse_def_while
    };

    Err(AmlError::AmlInvalidOpCode)
}

fn parse_def_break(data: &[u8],
                   ctx: &mut AmlExecutionContext) -> ParseResult {
    // TODO: Implement
    parser_opcode!(data, 0xA5);

    Ok(AmlParseType {
        val: AmlValue::None,
        len: 1 as usize
    })
}

fn parse_def_breakpoint(data: &[u8],
                        ctx: &mut AmlExecutionContext) -> ParseResult {
    // TODO: Implement
    parser_opcode!(data, 0xCC);

    Ok(AmlParseType {
        val: AmlValue::None,
        len: 1 as usize
    })
}

fn parse_def_continue(data: &[u8],
                      ctx: &mut AmlExecutionContext) -> ParseResult {
    // TODO: Implement
    parser_opcode!(data, 0x9F);

    Ok(AmlParseType {
        val: AmlValue::None,
        len: 1 as usize
    })
}

fn parse_def_noop(data: &[u8],
                  ctx: &mut AmlExecutionContext) -> ParseResult {
    parser_opcode!(data, 0xA3);

    Ok(AmlParseType {
        val: AmlValue::None,
        len: 1 as usize
    })
}

fn parse_def_fatal(data: &[u8],
                   ctx: &mut AmlExecutionContext) -> ParseResult {
    parser_opcode_extended!(data, 0x32);

    let fatal_type = data[2];
    let fatal_code: u16 = (data[3] as u16) + ((data[4] as u16) << 8);
    let fatal_arg = parse_term_arg(&data[5..], ctx)?;

    Err(AmlError::AmlFatalError(fatal_type, fatal_code, fatal_arg.val))
}

fn parse_def_load(data: &[u8],
                  ctx: &mut AmlExecutionContext) -> ParseResult {
    // TODO: Load in the table pointed to by `name`
    // TODO: Set DDB_Handle to the handle returned by loading in the table
    // TODO: Run the AML parser on the table, in a secondary namespace
    parser_opcode_extended!(data, 0x20);

    let name = parse_name_string(&data[2..], ctx)?;
    let ddb_handle_object = parse_super_name(&data[2 + name.len..], ctx)?;

    Ok(AmlParseType {
        val: AmlValue::None,
        len: 2 + name.len + ddb_handle_object.len
    })
}

fn parse_def_notify(data: &[u8],
                    ctx: &mut AmlExecutionContext) -> ParseResult {
    // TODO: This requires significantly more infrastructure from the OS itself, see 5.6.6
    parser_opcode!(data, 0x86);

    let object = parse_super_name(&data[1..], ctx)?;
    let value = parse_term_arg(&data[1 + object.len..], ctx)?;

    Ok(AmlParseType {
        val: AmlValue::None,
        len: 1 + object.len + value.len
    })
}

fn parse_def_release(data: &[u8],
                     ctx: &mut AmlExecutionContext) -> ParseResult {
    // TODO: Check ownership of the mutex pointed to
    // TODO: FATAL if not owned
    // TODO: Release if it is
    parser_opcode_extended!(data, 0x27);

    let object = parse_super_name(&data[2..], ctx)?;

    Ok(AmlParseType {
        val: AmlValue::None,
        len: 2 + object.len
    })
}

fn parse_def_reset(data: &[u8],
                   ctx: &mut AmlExecutionContext) -> ParseResult {
    // TODO: object (of type Event) is a semaphore. Reset the resource count to 0
    parser_opcode_extended!(data, 0x26);

    let object = parse_super_name(&data[2..], ctx)?;

    Ok(AmlParseType {
        val: AmlValue::None,
        len: 2 + object.len
    })
}

fn parse_def_signal(data: &[u8],
                    ctx: &mut AmlExecutionContext) -> ParseResult {
    // TODO: Increment the resource count of the semaphore
    parser_opcode_extended!(data, 0x24);

    let object = parse_super_name(&data[2..], ctx)?;

    Ok(AmlParseType {
        val: AmlValue::None,
        len: 2 + object.len
    })
}

fn parse_def_sleep(data: &[u8],
                   ctx: &mut AmlExecutionContext) -> ParseResult {
    // TODO: Sleep the processor for the specified number of milliseconds (minimum)
    parser_opcode_extended!(data, 0x22);

    let time = parse_term_arg(&data[2..], ctx)?;

    Ok(AmlParseType {
        val: AmlValue::None,
        len: 2 + time.len
    })
}

fn parse_def_stall(data: &[u8],
                   ctx: &mut AmlExecutionContext) -> ParseResult {
    // TODO: Sleep the processor for the specified number of microseconds (minimum)
    parser_opcode_extended!(data, 0x21);

    let time = parse_term_arg(&data[2..], ctx)?;

    Ok(AmlParseType {
        val: AmlValue::None,
        len: 2 + time.len
    })
}

fn parse_def_unload(data: &[u8],
                    ctx: &mut AmlExecutionContext) -> ParseResult {
    // TODO: remove from namespace all values added when `object` was loaded
    // TODO: globally synchronous (how?)
    parser_opcode_extended!(data, 0x2A);

    let object = parse_super_name(&data[2..], ctx)?;

    Ok(AmlParseType {
        val: AmlValue::None,
        len: 2 + object.len
    })
}

fn parse_def_if_else(data: &[u8],
                     ctx: &mut AmlExecutionContext) -> ParseResult {
    parser_opcode!(data, 0xA0);

    let (pkg_length, pkg_length_len) = parse_pkg_length(&data[1..])?;
    let if_condition = parse_term_arg(&data[1 + pkg_length_len .. 1 + pkg_length], ctx)?;

    let (else_length, else_length_len) = if data.len() > 1 + pkg_length && data[1 + pkg_length] == 0xA1 {
        parse_pkg_length(&data[2 + pkg_length..])?
    } else {
        (0 as usize, 0 as usize)
    };

    if if_condition.val.get_as_integer()? > 0 {
        parse_term_list(&data[1 + pkg_length_len + if_condition.len .. 1 + pkg_length], ctx)?;
    } else if else_length > 0 {
        parse_term_list(&data[2 + pkg_length + else_length_len .. 2 + pkg_length + else_length], ctx)?;
    }

    Ok(AmlParseType {
        val: AmlValue::None,
        len: 1 + pkg_length + if else_length > 0 { 1 + else_length } else { 0 }
    })
}

fn parse_def_while(data: &[u8],
                   ctx: &mut AmlExecutionContext) -> ParseResult {
    parser_opcode!(data, 0xA2);

    let (pkg_length, pkg_length_len) = parse_pkg_length(&data[1..])?;

    loop {
        let predicate = parse_term_arg(&data[1 + pkg_length_len..], ctx)?;
        if predicate.val.get_as_integer()? == 0 {
            break;
        }

        parse_term_list(&data[1 + pkg_length_len + predicate.len .. 1 + pkg_length], ctx)?;
    }

    Ok(AmlParseType {
        val: AmlValue::None,
        len: 1 + pkg_length
    })
}

fn parse_def_return(data: &[u8],
                    ctx: &mut AmlExecutionContext) -> ParseResult {
    // TODO: Return to the calling context
    // TODO: We need contexts for that
    parser_opcode!(data, 0xA4);

    let arg_object = parse_term_arg(&data[1..], ctx)?;

    Ok(AmlParseType {
        val: AmlValue::None,
        len: 1 + arg_object.len
    })
}
<commit_msg>Implemented opcodes<commit_after>use alloc::boxed::Box;
use collections::string::String;
use collections::vec::Vec;
use collections::btree_map::BTreeMap;

use super::AmlError;
use super::parser::{AmlParseType, ParseResult, AmlExecutionContext};
use super::namespace::{AmlValue, ObjectReference};
use super::pkglength::parse_pkg_length;
use super::termlist::{parse_term_arg, parse_term_list};
use super::namestring::{parse_name_string, parse_super_name};

pub fn parse_type1_opcode(data: &[u8],
                          ctx: &mut AmlExecutionContext) -> ParseResult {
    parser_selector! {
        data, ctx,
        parse_def_break,
        parse_def_breakpoint,
        parse_def_continue,
        parse_def_noop,
        parse_def_fatal,
        parse_def_if_else,
        parse_def_load,
        parse_def_notify,
        parse_def_release,
        parse_def_reset,
        parse_def_signal,
        parse_def_sleep,
        parse_def_stall,
        parse_def_return,
        parse_def_unload,
        parse_def_while
    };

    Err(AmlError::AmlInvalidOpCode)
}

fn parse_def_break(data: &[u8],
                   ctx: &mut AmlExecutionContext) -> ParseResult {
    // TODO: Implement
    parser_opcode!(data, 0xA5);

    Ok(AmlParseType {
        val: AmlValue::None,
        len: 1 as usize
    })
}

fn parse_def_breakpoint(data: &[u8],
                        ctx: &mut AmlExecutionContext) -> ParseResult {
    parser_opcode!(data, 0xCC);

    Ok(AmlParseType {
        val: AmlValue::None,
        len: 1 as usize
    })
}

fn parse_def_continue(data: &[u8],
                      ctx: &mut AmlExecutionContext) -> ParseResult {
    // TODO: Implement
    parser_opcode!(data, 0x9F);

    Ok(AmlParseType {
        val: AmlValue::None,
        len: 1 as usize
    })
}

fn parse_def_noop(data: &[u8],
                  ctx: &mut AmlExecutionContext) -> ParseResult {
    parser_opcode!(data, 0xA3);

    Ok(AmlParseType {
        val: AmlValue::None,
        len: 1 as usize
    })
}

fn parse_def_fatal(data: &[u8],
                   ctx: &mut AmlExecutionContext) -> ParseResult {
    parser_opcode_extended!(data, 0x32);

    let fatal_type = data[2];
    let fatal_code: u16 = (data[3] as u16) + ((data[4] as u16) << 8);
    let fatal_arg = parse_term_arg(&data[5..], ctx)?;

    Err(AmlError::AmlFatalError(fatal_type, fatal_code, fatal_arg.val))
}

fn parse_def_load(data: &[u8],
                  ctx: &mut AmlExecutionContext) -> ParseResult {
    // TODO: Load in the table pointed to by `name`
    // TODO: Set DDB_Handle to the handle returned by loading in the table
    // TODO: Run the AML parser on the table, in a secondary namespace
    parser_opcode_extended!(data, 0x20);

    let name = parse_name_string(&data[2..], ctx)?;
    let ddb_handle_object = parse_super_name(&data[2 + name.len..], ctx)?;

    Ok(AmlParseType {
        val: AmlValue::None,
        len: 2 + name.len + ddb_handle_object.len
    })
}

fn parse_def_notify(data: &[u8],
                    ctx: &mut AmlExecutionContext) -> ParseResult {
    // TODO: This requires significantly more infrastructure from the OS itself, see 5.6.6
    parser_opcode!(data, 0x86);

    let object = parse_super_name(&data[1..], ctx)?;
    let value = parse_term_arg(&data[1 + object.len..], ctx)?;

    Ok(AmlParseType {
        val: AmlValue::None,
        len: 1 + object.len + value.len
    })
}

fn parse_def_release(data: &[u8],
                     ctx: &mut AmlExecutionContext) -> ParseResult {
    // TODO: Check ownership of the mutex pointed to
    // TODO: FATAL if not owned
    // TODO: Release if it is
    parser_opcode_extended!(data, 0x27);

    let object = parse_super_name(&data[2..], ctx)?;

    Ok(AmlParseType {
        val: AmlValue::None,
        len: 2 + object.len
    })
}

fn parse_def_reset(data: &[u8],
                   ctx: &mut AmlExecutionContext) -> ParseResult {
    // TODO: object (of type Event) is a semaphore. Reset the resource count to 0
    parser_opcode_extended!(data, 0x26);

    let object = parse_super_name(&data[2..], ctx)?;

    Ok(AmlParseType {
        val: AmlValue::None,
        len: 2 + object.len
    })
}

fn parse_def_signal(data: &[u8],
                    ctx: &mut AmlExecutionContext) -> ParseResult {
    // TODO: Increment the resource count of the semaphore
    parser_opcode_extended!(data, 0x24);

    let object = parse_super_name(&data[2..], ctx)?;

    Ok(AmlParseType {
        val: AmlValue::None,
        len: 2 + object.len
    })
}

fn parse_def_sleep(data: &[u8],
                   ctx: &mut AmlExecutionContext) -> ParseResult {
    // TODO: Sleep the processor for the specified number of milliseconds (minimum)
    parser_opcode_extended!(data, 0x22);

    let time = parse_term_arg(&data[2..], ctx)?;

    Ok(AmlParseType {
        val: AmlValue::None,
        len: 2 + time.len
    })
}

fn parse_def_stall(data: &[u8],
                   ctx: &mut AmlExecutionContext) -> ParseResult {
    // TODO: Sleep the processor for the specified number of microseconds (minimum)
    parser_opcode_extended!(data, 0x21);

    let time = parse_term_arg(&data[2..], ctx)?;

    Ok(AmlParseType {
        val: AmlValue::None,
        len: 2 + time.len
    })
}

fn parse_def_unload(data: &[u8],
                    ctx: &mut AmlExecutionContext) -> ParseResult {
    // TODO: remove from namespace all values added when `object` was loaded
    // TODO: globally synchronous (how?)
    parser_opcode_extended!(data, 0x2A);

    let object = parse_super_name(&data[2..], ctx)?;

    Ok(AmlParseType {
        val: AmlValue::None,
        len: 2 + object.len
    })
}

fn parse_def_if_else(data: &[u8],
                     ctx: &mut AmlExecutionContext) -> ParseResult {
    parser_opcode!(data, 0xA0);

    let (pkg_length, pkg_length_len) = parse_pkg_length(&data[1..])?;
    let if_condition = parse_term_arg(&data[1 + pkg_length_len .. 1 + pkg_length], ctx)?;

    let (else_length, else_length_len) = if data.len() > 1 + pkg_length && data[1 + pkg_length] == 0xA1 {
        parse_pkg_length(&data[2 + pkg_length..])?
    } else {
        (0 as usize, 0 as usize)
    };

    if if_condition.val.get_as_integer()? > 0 {
        parse_term_list(&data[1 + pkg_length_len + if_condition.len .. 1 + pkg_length], ctx)?;
    } else if else_length > 0 {
        parse_term_list(&data[2 + pkg_length + else_length_len .. 2 + pkg_length + else_length], ctx)?;
    }

    Ok(AmlParseType {
        val: AmlValue::None,
        len: 1 + pkg_length + if else_length > 0 { 1 + else_length } else { 0 }
    })
}

fn parse_def_while(data: &[u8],
                   ctx: &mut AmlExecutionContext) -> ParseResult {
    parser_opcode!(data, 0xA2);

    let (pkg_length, pkg_length_len) = parse_pkg_length(&data[1..])?;

    loop {
        let predicate = parse_term_arg(&data[1 + pkg_length_len..], ctx)?;
        if predicate.val.get_as_integer()? == 0 {
            break;
        }

        parse_term_list(&data[1 + pkg_length_len + predicate.len .. 1 + pkg_length], ctx)?;
    }

    Ok(AmlParseType {
        val: AmlValue::None,
        len: 1 + pkg_length
    })
}

fn parse_def_return(data: &[u8],
                    ctx: &mut AmlExecutionContext) -> ParseResult {
    // TODO: Return to the calling context
    // TODO: We need contexts for that
    parser_opcode!(data, 0xA4);

    let arg_object = parse_term_arg(&data[1..], ctx)?;

    Ok(AmlParseType {
        val: AmlValue::None,
        len: 1 + arg_object.len
    })
}
<|endoftext|>


<commit_before>use Parameter;
use fa::VFunction;
use agents::PredictionAgent;
use geometry::{Space, NullSpace};
use std::marker::PhantomData;

pub struct TD<S: Space, V: VFunction<S>>
{
    v_func: V,

    alpha: Parameter,
    gamma: Parameter,

    phantom: PhantomData<S>,
}

impl<S: Space, V: VFunction<S>> TD<S, V>
{
    pub fn new<T1, T2>(v_func: V, alpha: T1, gamma: T2) -> Self
        where T1: Into<Parameter>,
              T2: Into<Parameter>
    {
        TD {
            v_func: v_func,

            alpha: alpha.into(),
            gamma: gamma.into(),

            phantom: PhantomData,
        }
    }
}

impl<S: Space, V: VFunction<S>> PredictionAgent<S> for TD<S, V>
{
    fn handle_transition(&mut self, s: &S::Repr, ns: &S::Repr, r: f64) -> Option<f64> {
        let v = self.v_func.evaluate(s);
        let nv = self.v_func.evaluate(ns);

        let td_error = self.alpha*(r + self.gamma*nv - v);
        self.v_func.update(&s, td_error);

        Some(td_error)
    }

    fn handle_terminal(&mut self, _: &S::Repr) {
        self.alpha = self.alpha.step();
        self.gamma = self.gamma.step();
    }
}
<commit_msg>Correct return value in TD type<commit_after>use Parameter;
use fa::{VFunction, Linear};
use agents::PredictionAgent;
use geometry::{Space, NullSpace};
use std::marker::PhantomData;

pub struct TD<S: Space, V: VFunction<S>>
{
    v_func: V,

    alpha: Parameter,
    gamma: Parameter,

    phantom: PhantomData<S>,
}

impl<S: Space, V: VFunction<S>> TD<S, V>
{
    pub fn new<T1, T2>(v_func: V, alpha: T1, gamma: T2) -> Self
        where T1: Into<Parameter>,
              T2: Into<Parameter>
    {
        TD {
            v_func: v_func,

            alpha: alpha.into(),
            gamma: gamma.into(),

            phantom: PhantomData,
        }
    }
}

impl<S: Space, V: VFunction<S>> PredictionAgent<S> for TD<S, V>
{
    fn handle_transition(&mut self, s: &S::Repr, ns: &S::Repr, r: f64) -> Option<f64> {
        let v = self.v_func.evaluate(s);
        let nv = self.v_func.evaluate(ns);

        let td_error = r + self.gamma*nv - v;
        self.v_func.update(&s, self.alpha*td_error);

        Some(td_error)
    }

    fn handle_terminal(&mut self, _: &S::Repr) {
        self.alpha = self.alpha.step();
        self.gamma = self.gamma.step();
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate clap;

// [Macro clap::clap_app](https://docs.rs/clap/2.33.0/clap/macro.clap_app.html)

fn main() {
    let matches = clap_app!(gf =>
        (version: "0.1")
        (author: "Alexander Samoilov <alexander.samoilov@gmail.com>")
        (about: "ARM Android cross-compile sample project")
        (@arg AVAILABLE: -a --available "display available frequencies")
        (@arg SET_GPU: -g --gpu +takes_value "set GPU frequency")
        (@arg LOCK_FREQ: -l --lock ... +takes_value "lock GPU/DDR/CPU frequencies as GPU/DDR/CPUlittle/CPUmiddle/CPUbig")
        (@arg VERBOSE: -v --verbose "be verbose")
    ).get_matches();

    if matches.is_present("VERBOSE") {
        println!("gf_freq command line args matches: {:?}", matches);
    }

    if let Ok(gpu_freq) = value_t!(matches, "SET_GPU", u64) {
        println!("Set GPU frequency to: {}", gpu_freq);
    }

    if let Ok(freq_vec) = values_t!(matches, "LOCK_FREQ", u64) {
        println!("freq_vec: {:?}", freq_vec);
        for v in freq_vec {
            println!("Set frequency to: {}", v);
        }
    }

}
<commit_msg>expand on gf_arm_android.<commit_after>#[macro_use]
extern crate clap;

use std::fs::File;
use std::io::{Read,Write};
use std::str::from_utf8;

// [Macro clap::clap_app](https://docs.rs/clap/2.33.0/clap/macro.clap_app.html)

fn gpu_freq_stat(tail: &str) -> String {
    format!("/sys/class/devfreq/gpufreq/{}", tail)
}

fn ddr_freq_stat(tail: &str) -> String {
    format!("/sys/class/devfreq/ddrfreq/{}", tail)
}

fn cpu_freq_stat(id: usize, tail: &str) -> String {
    format!("/sys/devices/system/cpu/cpu{}/cpufreq/{}", id, tail)
}

struct AvailableFrequencies
{
    gpu: Vec<u64>,
    ddr: Vec<u64>,
    cpu_little: Vec<u64>,
    cpu_medium: Vec<u64>,
    cpu_big: Vec<u64>,
}

struct ActualFrequencies
{
    gpu: u64,
    ddr: u64,
    cpu_little: u64,
    cpu_medium: u64,
    cpu_big: u64,
}

impl ActualFrequencies {
    fn cons() -> ActualFrequencies {
        ActualFrequencies { gpu: 0, ddr: 0, cpu_little: 0, cpu_medium: 0, cpu_big: 0, }
    }

    fn init(gpu: u64, ddr: u64, cpu_l: u64, cpu_m: u64, cpu_b: u64) -> ActualFrequencies {
        ActualFrequencies { gpu: gpu, ddr: ddr, cpu_little: cpu_l, cpu_medium: cpu_m, cpu_big: cpu_b, }
    }
}

fn read_sys_record(sys_path: &str) -> String {
    let mut read_buf = String::new();
    if let Ok(mut file) = File::open(sys_path) {
        let sz = file.read_to_string(&mut read_buf).expect("cannot read sysfs");
        assert!(sz > 0);
    }
    read_buf.trim_right().to_string()
}

fn read_sys_as_u64(sys_path: &str) -> u64 {
    let str_buf = read_sys_record(sys_path);
    str_buf.parse().expect("cannot parse to u64")
}

fn read_gpu_frequency() -> u64 {
    read_sys_as_u64(&gpu_freq_stat("cur_freq"))
}

fn main() {
    let matches = clap_app!(gf =>
        (version: "0.1")
        (author: "Alexander Samoilov <alexander.samoilov@gmail.com>")
        (about: "ARM Android cross-compile sample project")
        (@arg AVAILABLE: -a --available "display available frequencies")
        (@arg SHOW: -s --show "show current frequencies")
        (@arg SET_GPU: -g --gpu +takes_value "set GPU frequency")
        (@arg LOCK_FREQ: -l --lock ... +takes_value "lock GPU/DDR/CPU frequencies")
        (@arg VERBOSE: -v --verbose "be verbose")
    ).get_matches();

    if matches.is_present("VERBOSE") {
        println!("gf_freq command line args matches: {:?}", matches);
    }

    if matches.is_present("SHOW") {
        println!("show device current frequencies: gpu: {}", read_gpu_frequency());
    }

    if let Ok(gpu_freq) = value_t!(matches, "SET_GPU", u64) {
        println!("Set GPU frequency to: {}", gpu_freq);
    }

    if let Ok(freq_vec) = values_t!(matches, "LOCK_FREQ", u64) {
        println!("freq_vec: {:?}", freq_vec);
        for v in freq_vec {
            println!("Set frequency to: {}", v);
        }
    }

}
<|endoftext|>


<commit_before>use neb::ram::schema::Field;
use neb::ram::types::{TypeId, Id, key_hash, Map, Value};
use neb::ram::cell::{Cell, WriteError};
use neb::client::{Client as NebClient};
use bifrost::rpc::RPCError;

use server::schema::{MorpheusSchema, SchemaType, SchemaContainer, SchemaError};
use graph::vertex::Vertex;

use std::sync::Arc;
use serde::Serialize;

pub mod vertex;
pub mod edge;

pub enum NewVertexError {
    SchemaNotFound,
    SchemaNotVertex,
    CannotGenerateCellByData,
    DataNotMap,
    RPCError(RPCError),
    WriteError(WriteError),
}
pub enum RemoveVertexError {
    WriteError(WriteError),
    RPCError(RPCError)
}

#[derive(Clone, Copy, Serialize, Deserialize)]
pub enum CellType {
    Vertex,
    Edge(edge::EdgeType)
}

lazy_static! {
    pub static ref ID_LINKED_LIST: Vec<Field> = vec![
            Field::new(&String::from("next"), TypeId::Id as u32, true, false, None),
            Field::new(&String::from("list"), TypeId::Id as u32, false, true, None)
        ];
}

pub fn cell_to_vertex (cell: Cell) -> Vertex {
    Vertex {
        id: cell.header.id(),
        schema: cell.header.schema,
        data: cell.data
    }
}

pub struct Graph {
    schema: Arc<SchemaContainer>,
    neb_client: Arc<NebClient>
}

impl Graph {
    pub fn new_vertex_group(&self, schema: &mut MorpheusSchema) -> Result<(), SchemaError> {
        schema.schema_type = SchemaType::Vertex;
        self.schema.new_schema(schema)
    }
    pub fn new_edge_group(&self, schema: &mut MorpheusSchema, edge_type: edge::EdgeType) -> Result<(), SchemaError> {
        if edge_type == edge::EdgeType::Simple {
            return Err(SchemaError::SimpleEdgeShouldNotHaveSchema)
        }
        schema.schema_type = SchemaType::Edge(edge_type);
        self.schema.new_schema(schema)
    }
    pub fn new_vertex(&self, mut vertex: Vertex) -> Result<Vertex, NewVertexError> {
        let schema_id = vertex.schema;
        if let Some(stype) = self.schema.schema_type(schema_id) {
            if stype != SchemaType::Vertex {
                return Err(NewVertexError::SchemaNotVertex)
            }
        } else {
            return Err(NewVertexError::SchemaNotFound)
        }
        let neb_schema = match self.schema.get_neb_schema(schema_id) {
            Some(schema) => schema,
            None => return Err(NewVertexError::SchemaNotFound)
        };
        let mut data = {
            match vertex.data {
                Value::Map(mut map) => map,
                _ => return Err(NewVertexError::DataNotMap)
            }
        };
        data.insert_key_id(*vertex::INBOUND_KEY_ID, Value::Id(Id::unit_id()));
        data.insert_key_id(*vertex::OUTBOUND_KEY_ID, Value::Id(Id::unit_id()));
        data.insert_key_id(*vertex::INDIRECTED_KEY_ID, Value::Id(Id::unit_id()));
        let mut cell = match Cell::new(&neb_schema, Value::Map(data)) {
            Some(cell) => cell,
            None => return Err(NewVertexError::CannotGenerateCellByData)
        };
        let header = match self.neb_client.write_cell(&cell) {
            Ok(Ok(header)) => header,
            Ok(Err(e)) => return Err(NewVertexError::WriteError(e)),
            Err(e) => return Err(NewVertexError::RPCError(e))
        };
        cell.header = header;
        Ok(cell_to_vertex(cell))
    }
    pub fn remove_vertex(&self, id: &Id) -> Result<(), RemoveVertexError> {
        match self.neb_client.remove_cell(id) {
            Err(e) => Err(RemoveVertexError::RPCError(e)),
            Ok(Err(e)) => Err(RemoveVertexError::WriteError(e)),
            Ok(Ok(())) => Ok(())
        }
    }
    pub fn remove_vertex_by_key<K>(&self, schema_id: u32, key: &K) -> Result<(), RemoveVertexError>
        where K: Serialize {
        let id = Cell::encode_cell_key(schema_id, key);
        self.remove_vertex(&id)
    }
}<commit_msg>update vertex by transaction<commit_after>use neb::ram::schema::Field;
use neb::ram::types::{TypeId, Id, key_hash, Map, Value};
use neb::ram::cell::{Cell, WriteError};
use neb::client::{Client as NebClient};
use neb::client::transaction::TxnError;
use bifrost::rpc::RPCError;

use server::schema::{MorpheusSchema, SchemaType, SchemaContainer, SchemaError};
use graph::vertex::Vertex;

use std::sync::Arc;
use serde::Serialize;

pub mod vertex;
pub mod edge;

pub enum NewVertexError {
    SchemaNotFound,
    SchemaNotVertex,
    CannotGenerateCellByData,
    DataNotMap,
    RPCError(RPCError),
    WriteError(WriteError),
}
pub enum RemoveVertexError {
    WriteError(WriteError),
    RPCError(RPCError)
}

#[derive(Clone, Copy, Serialize, Deserialize)]
pub enum CellType {
    Vertex,
    Edge(edge::EdgeType)
}

lazy_static! {
    pub static ref ID_LINKED_LIST: Vec<Field> = vec![
            Field::new(&String::from("next"), TypeId::Id as u32, true, false, None),
            Field::new(&String::from("list"), TypeId::Id as u32, false, true, None)
        ];
}

pub fn cell_to_vertex(cell: Cell) -> Vertex {
    Vertex {
        id: cell.header.id(),
        schema: cell.header.schema,
        data: cell.data
    }
}

pub fn vertex_to_cell(vertex: Vertex) -> Cell {
    Cell::new_with_id(vertex.schema, &vertex.id, vertex.data)
}

pub struct Graph {
    schema: Arc<SchemaContainer>,
    neb_client: Arc<NebClient>
}

impl Graph {
    pub fn new_vertex_group(&self, schema: &mut MorpheusSchema) -> Result<(), SchemaError> {
        schema.schema_type = SchemaType::Vertex;
        self.schema.new_schema(schema)
    }
    pub fn new_edge_group(&self, schema: &mut MorpheusSchema, edge_type: edge::EdgeType) -> Result<(), SchemaError> {
        if edge_type == edge::EdgeType::Simple {
            return Err(SchemaError::SimpleEdgeShouldNotHaveSchema)
        }
        schema.schema_type = SchemaType::Edge(edge_type);
        self.schema.new_schema(schema)
    }
    pub fn new_vertex(&self, mut vertex: Vertex) -> Result<Vertex, NewVertexError> {
        let schema_id = vertex.schema;
        if let Some(stype) = self.schema.schema_type(schema_id) {
            if stype != SchemaType::Vertex {
                return Err(NewVertexError::SchemaNotVertex)
            }
        } else {
            return Err(NewVertexError::SchemaNotFound)
        }
        let neb_schema = match self.schema.get_neb_schema(schema_id) {
            Some(schema) => schema,
            None => return Err(NewVertexError::SchemaNotFound)
        };
        let mut data = {
            match vertex.data {
                Value::Map(mut map) => map,
                _ => return Err(NewVertexError::DataNotMap)
            }
        };
        data.insert_key_id(*vertex::INBOUND_KEY_ID, Value::Id(Id::unit_id()));
        data.insert_key_id(*vertex::OUTBOUND_KEY_ID, Value::Id(Id::unit_id()));
        data.insert_key_id(*vertex::INDIRECTED_KEY_ID, Value::Id(Id::unit_id()));
        let mut cell = match Cell::new(&neb_schema, Value::Map(data)) {
            Some(cell) => cell,
            None => return Err(NewVertexError::CannotGenerateCellByData)
        };
        let header = match self.neb_client.write_cell(&cell) {
            Ok(Ok(header)) => header,
            Ok(Err(e)) => return Err(NewVertexError::WriteError(e)),
            Err(e) => return Err(NewVertexError::RPCError(e))
        };
        cell.header = header;
        Ok(cell_to_vertex(cell))
    }
    pub fn remove_vertex(&self, id: &Id) -> Result<(), RemoveVertexError> {
        match self.neb_client.remove_cell(id) {
            Err(e) => Err(RemoveVertexError::RPCError(e)),
            Ok(Err(e)) => Err(RemoveVertexError::WriteError(e)),
            Ok(Ok(())) => Ok(())
        }
    }
    pub fn remove_vertex_by_key<K>(&self, schema_id: u32, key: &K) -> Result<(), RemoveVertexError>
        where K: Serialize {
        let id = Cell::encode_cell_key(schema_id, key);
        self.remove_vertex(&id)
    }
    pub fn update_vertex<U>(&self, id: &Id, update: U) -> Result<(), TxnError>
        where U: Fn(Vertex) -> Option<Vertex> {
        let update_cell = |cell| {
            match update(cell_to_vertex(cell)) {
                Some(vertex) => Some(vertex_to_cell(vertex)),
                None => None
            }
        };
        self.neb_client.transaction(|txn|{
            let cell = txn.read(id)?;
            match cell {
                Some(cell) => {
                    match update_cell(cell) {
                        Some(cell) => txn.update(&cell),
                        None => txn.abort()
                    }
                },
                None => txn.abort()
            }
        })
    }
}<|endoftext|>


<commit_before>use std::ops;
use std::mem;

use self::Node::*;

/// A `Node` in the `Rope`'s tree.
///
/// A `Node` is either a `Leaf` holding a `String`, or a
/// a `Branch` concatenating together two `Node`s.
#[derive(Debug, Clone)]
pub enum Node {
    /// A leaf node
    Leaf(String)
  , /// A branch concatenating together `l`eft and `r`ight nodes.
    Branch(BranchNode)
}

#[derive(Debug, Clone)]
pub struct BranchNode {
    /// The length of this node
    len: usize
  , /// The weight of a node is the summed weight of its left subtree
    weight: usize
  , /// The left branch node
    pub left: Box<Node>
  , /// The right branch node
    pub right: Box<Node>
}

impl Default for Node {
    fn default() -> Self { Node::empty() }
}

/// Returns the _n_th fibonacci number.
// TODO: replace with an iterative implementation and/or lookup table?
fn fibonacci(n: usize) -> usize {
    match n { 0 => 1
            , 1 => 1
            , _ => fibonacci(n - 1) + fibonacci(n - 2)
            }
}

impl BranchNode {

    #[inline]
    fn new(left: Node, right: Node) -> Self {
        BranchNode { len: left.len() + right.len()
                   , weight: left.subtree_weight()
                   , left: box left
                   , right: box right
                   }
    }

    #[inline]
    fn take_left(&mut self) -> Node {
        mem::replace(self.left.as_mut(), Node::empty())
    }

    #[inline]
    fn take_right(&mut self) -> Node {
        mem::replace(self.right.as_mut(), Node::empty())
    }

    fn split(&mut self, index: usize) -> &mut Node {
        if index < self.weight {
            // split the left node
            let mut left = self.take_left();
            left.split(index);
            // replacing *self with a new BranchNode will update the
            // node's weight automagically
            *self = BranchNode::new(left, self.take_right());
            self.left.as_mut()
        } else {
            // split the right node
            let mut right = self.take_right();
            right.split(index);
            // replacing *self with a new BranchNode will update the
            // node's weight automagically
            *self = BranchNode::new(self.take_left(), right);
            self.left.as_mut()
        }
    }

}

impl Node {
    fn split_leaf(&mut self, index: usize) -> bool {
        // we mutably borrow `self` here. This precludes us from changing it
        // directly as in `*self = ...`, because the borrow checker won't allow
        // it. Therefore, the assignment to `self` must be outside the `if let`
        // clause.
        *self = if let Leaf(ref mut s) = *self {

            // if this node is a Leaf, take the String out of it
            // (note that empty strings don't allocate).
            let string = mem::replace(s, String::new());
            // split the string into left and right parts...
            let left = Leaf(string[index..].to_string());
            let right = Leaf(string[..index].to_string());
            // construct the new Branch node that will be reassigned to `self`
            Node::new_branch(left, right)
        } else {
            // if this node is not a Leaf, we return immediately, thus skipping
            // the assignment
            return false
        };
        return true
    }

    pub fn split(&mut self, index: usize) -> &mut Node {
        if self.split_leaf(index) == true {
            self
        } else {
            if let &mut Branch(ref mut node) = self {
                node.split(index)
            } else {
                unreachable!()
            }
        }
    }

    pub fn empty() -> Self {
        Leaf(String::new())
    }

    /// Concatenate two `Node`s to return a new `Branch` node.
    #[inline]
    pub fn new_branch(left: Self, right: Self) -> Self {
        Branch(BranchNode::new(left, right))
    }

    #[inline]
    pub fn concat(&mut self, right: Self) {
        *self = Node::new_branch(mem::replace(self, Node::empty()), right)
    }

    #[inline]
    pub const fn new_leaf(string: String) -> Self {
        Leaf(string)
    }

    /// Returns true if this node is balanced
    ///
    /// "We define the depth of a leaf to be 0, and the depth of a
    /// concatenation to be one plus the maximum depth of its children. Let
    /// _Fn_ be the _n_th Fibonacci number. A rope of depth _n_ is balanced if
    /// its length is at least _Fn_+2, e.g. a balanced rope of depth 1 must
    /// have length at least 2. Note that balanced ropes may contain unbalanced
    /// subropes."
    /// – from "Ropes: An Alternative to Strings"
    #[inline]
    pub fn is_balanced(&self) -> bool {
        self.len() >= fibonacci(self.depth() + 2)
    }

    /// Returns the depth in the tree of a node
    #[inline]
    fn depth(&self) -> usize {
        use std::cmp::max;

        match self {
            &Node::Leaf(_) => 0
          , &Node::Branch(BranchNode { ref left, ref right, .. }) =>
                max(left.depth(), right.depth()) + 1
            }
    }

    /// Returns the length of a node
    //  TODO: do we want to cache this?
    pub fn len(&self) -> usize {
        match self { &Leaf(ref s) => s.len()
                   , &Branch(BranchNode { ref left, ref right, .. }) =>
                        left.len() + right.len()
                    }
    }

    /// Calculates the weight of a node
    #[inline]
    fn subtree_weight (&self) -> usize {
        match self { &Leaf(ref s) => s.len()
                   , &Branch(BranchNode { ref left, .. }) =>
                        left.subtree_weight()
                    }
    }

    /// Rebalance the subrope starting at this `Node`, returning a new `Node`
    ///
    /// From "Ropes: An Alternative to Strings":
    /// > "The rebalancing operation maintains an ordered sequence of (empty
    /// > or) balanced ropes, one for each length interval [_Fn_, _Fn_+1), for
    /// > _n_ >= 2. We traverse the rope from left to right, inserting each
    /// > leaf into the appropriate sequence position, depending on its length.
    ///
    /// > The concatenation of the sequence of ropes in order of decreasing
    /// > length is equivalent to the prefix of the rope we have traversed so
    /// > far. Each new leaf _x_ is with_insert_ropeed into the appropriate entry of the
    /// > sequence. Assume that _x_’s length is in the interval [_Fn_, _Fn_+1),
    /// > and thus it should be put in slot _n_ (which also corresponds to
    /// > maximum depth _n_ − 2). If all lower and equal numbered levels are
    /// > empty, then this can be done directly. If not, then we concatenate
    /// > ropes in slots 2, ... ,(_n_ − 1) (concatenating onto the left), and
    /// > concatenate _x_ to the right of the result. We then continue to
    /// > concatenate ropes from the sequence in increasing order to the left
    /// > of this result, until the result fits into an empty slot in the
    /// > sequence."
    pub fn rebalance(self) -> Self {
        // TODO: this is a huge mess, I based it on the IBM Java implementation
        //       please refactor until it stops being ugly!
        //        - eliza, 12/17/2016

        if self.is_balanced() {
            // the subrope is already balanced, do nothing
            self
        } else {
            let mut leaves: Vec<Option<Node>> =
                self.into_leaves().map(Option::Some).collect();
            let len = leaves.len();
            fn _rebalance(l: &mut Vec<Option<Node>>, start: usize, end: usize)
                          -> Node {
                match end - start {
                    1 => l[start].take().unwrap()
                  , 2 => l[start].take().unwrap() + l[start + 1].take().unwrap()
                  , n => {
                        let mid = start + (n / 2);
                        _rebalance(l, start, mid) + _rebalance(l, mid, end)

                    }
                }
            };
            _rebalance(&mut leaves, 0, len)
        }
    }

    /// Returns an iterator over all leaf nodes in this `Node`'s subrope
    fn leaves<'a>(&'a self) -> Leaves<'a> {
        Leaves(vec![self])
    }

    /// Returns a move iterator over all leaf nodes in this `Node`'s subrope
    fn into_leaves(self) -> IntoLeaves {
        IntoLeaves(vec![self])
    }

    /// Returns an iterator over all the strings in this `Node`s subrope'
    #[inline]
    pub fn strings<'a>(&'a self) -> impl Iterator<Item=&'a str> {
        box self.leaves().map(|n| match n {
            &Leaf(ref s) => s.as_ref()
          , _ => unreachable!("Node.leaves() iterator contained something \
                               that wasn't a leaf. Barring _force majeure_, \
                               this should be impossible. Something's broken.")
        })
    }

    /// Returns a move iterator over all the strings in this `Node`s subrope'
    ///
    /// Consumes `self`.
    #[inline]
    pub fn into_strings(self) -> impl Iterator<Item=String> {
        box self.into_leaves().map(|n| match n {
            Leaf(s) => s
            , _ => unreachable!("Node.into_leaves() iterator contained \
                                 something  that wasn't a leaf. Barring _force \
                                 majeure_, this should be impossible. \
                                 Something's broken.")
        })
    }

    str_iters! {
        #[doc="Returns an iterator over all the bytes in this `Node`'s \
               subrope \n\

               \nAs a Rope consists of a sequence of bytes, we can iterate \
               through a rope by byte. This method returns such an iterator."]
        #[inline]
        impl bytes<u8> for Node {}
        #[doc="Returns an iterator over all the characters in this `Node`'s \
               subrope \n\

               \nAs a `Rope` consists of valid UTF-8, we can iterate through a \
               `Rope` by `char`. This method returns such an iterator. \n\

               \nIt's important to remember that `char` represents a Unicode \
               Scalar Value, and may not match your idea of what a \
               'character' is. Iteration over grapheme clusters may be what \
               you actually want."]
        #[inline]
        impl chars<char> for Node {}
        // TODO: this is actually Wrong, the indices will wrap around once we
        //       iterate into the next leaf node. we'll need to write our own
        //       char_indices iterator that tracks the character's index in the
        //       global Rope. shouldn't be too hard, just a fold...
        //          - eliza, 12/18/2016
        // #[inline]
        // impl char_indices<(usize, char)> for Node {}
        #[inline]
        impl split_whitespace<&'a str> for Node {}
        #[inline]
        impl lines<&'a str> for Node {}
    }

    // /// Returns n iterator over the bytes of this `Node`'s subrope
    // ///
    // ///
    // #[inline]
    // pub fn bytes<'a>(&'a self) -> impl Iterator<Item=u8> + 'a {
    //     self.strings().flat_map(str::bytes)
    // }

    /// Returns an iterator over the grapheme clusters of this `Node`'s subrope'
    ///
    /// This is the iterator returned by `Node::into_iter`.
    #[inline]
    pub fn graphemes<'a>(&'a self) -> impl Iterator<Item=&'a str> {
        // the compiler won't let me mark this as unimplemented using the
        // unimplemented!() macro, due to Reasons (i suspect relating to
        // returning `impl Trait`)
        //  - eliza, 12/18/2016
        panic!("Unimplemented!");
        self.strings()
    }

}

/// An iterator over a series of leaf `Node`s
struct Leaves<'a>(Vec<&'a Node>);

impl<'a> Iterator for Leaves<'a> {
    type Item = &'a Node;
    fn next(&mut self) -> Option<Self::Item> {
        match self.0.pop() {
            None => None
          , Some(leaf @ &Leaf(_)) => Some(leaf)
          , Some(&Branch(BranchNode { ref left, ref right, .. })) => {
                self.0.push(left);
                self.0.push(right);
                self.next()
            }
        }
    }
}

/// A move iterator over a series of leaf `Node`s
struct IntoLeaves(Vec<Node>);

impl Iterator for IntoLeaves {
    type Item = Node;
    fn next(&mut self) -> Option<Self::Item> {
        match self.0.pop() {
            None => None
          , Some(leaf @ Leaf(_)) => Some(leaf)
          , Some(Branch(BranchNode { box left, box right, .. })) => {
                self.0.push(right);
                self.0.push(left);
                self.next()
            }
        }
    }
}

impl ops::Add for Node {
    type Output = Self;
    /// Concatenate two `Node`s, returning a `Branch` node.
    fn add(self, right: Self) -> Self { Node::new_branch(self, right) }
}
<commit_msg>rope: fix incorrect push order in Leaves iterator<commit_after>use std::ops;
use std::mem;

use self::Node::*;

/// A `Node` in the `Rope`'s tree.
///
/// A `Node` is either a `Leaf` holding a `String`, or a
/// a `Branch` concatenating together two `Node`s.
#[derive(Debug, Clone)]
pub enum Node {
    /// A leaf node
    Leaf(String)
  , /// A branch concatenating together `l`eft and `r`ight nodes.
    Branch(BranchNode)
}

#[derive(Debug, Clone)]
pub struct BranchNode {
    /// The length of this node
    len: usize
  , /// The weight of a node is the summed weight of its left subtree
    weight: usize
  , /// The left branch node
    pub left: Box<Node>
  , /// The right branch node
    pub right: Box<Node>
}

impl Default for Node {
    fn default() -> Self { Node::empty() }
}

/// Returns the _n_th fibonacci number.
// TODO: replace with an iterative implementation and/or lookup table?
fn fibonacci(n: usize) -> usize {
    match n { 0 => 1
            , 1 => 1
            , _ => fibonacci(n - 1) + fibonacci(n - 2)
            }
}

impl BranchNode {

    #[inline]
    fn new(left: Node, right: Node) -> Self {
        BranchNode { len: left.len() + right.len()
                   , weight: left.subtree_weight()
                   , left: box left
                   , right: box right
                   }
    }

    #[inline]
    fn take_left(&mut self) -> Node {
        mem::replace(self.left.as_mut(), Node::empty())
    }

    #[inline]
    fn take_right(&mut self) -> Node {
        mem::replace(self.right.as_mut(), Node::empty())
    }

    fn split(&mut self, index: usize) -> &mut Node {
        if index < self.weight {
            // split the left node
            let mut left = self.take_left();
            left.split(index);
            // replacing *self with a new BranchNode will update the
            // node's weight automagically
            *self = BranchNode::new(left, self.take_right());
            self.left.as_mut()
        } else {
            // split the right node
            let mut right = self.take_right();
            right.split(index);
            // replacing *self with a new BranchNode will update the
            // node's weight automagically
            *self = BranchNode::new(self.take_left(), right);
            self.left.as_mut()
        }
    }

}

impl Node {
    fn split_leaf(&mut self, index: usize) -> bool {
        // we mutably borrow `self` here. This precludes us from changing it
        // directly as in `*self = ...`, because the borrow checker won't allow
        // it. Therefore, the assignment to `self` must be outside the `if let`
        // clause.
        *self = if let Leaf(ref mut s) = *self {

            // if this node is a Leaf, take the String out of it
            // (note that empty strings don't allocate).
            let string = mem::replace(s, String::new());
            // split the string into left and right parts...
            let left = Leaf(string[index..].to_string());
            let right = Leaf(string[..index].to_string());
            // construct the new Branch node that will be reassigned to `self`
            Node::new_branch(left, right)
        } else {
            // if this node is not a Leaf, we return immediately, thus skipping
            // the assignment
            return false
        };
        return true
    }

    pub fn split(&mut self, index: usize) -> &mut Node {
        if self.split_leaf(index) == true {
            self
        } else {
            if let &mut Branch(ref mut node) = self {
                node.split(index)
            } else {
                unreachable!()
            }
        }
    }

    pub fn empty() -> Self {
        Leaf(String::new())
    }

    /// Concatenate two `Node`s to return a new `Branch` node.
    #[inline]
    pub fn new_branch(left: Self, right: Self) -> Self {
        Branch(BranchNode::new(left, right))
    }

    #[inline]
    pub fn concat(&mut self, right: Self) {
        *self = Node::new_branch(mem::replace(self, Node::empty()), right)
    }

    #[inline]
    pub const fn new_leaf(string: String) -> Self {
        Leaf(string)
    }

    /// Returns true if this node is balanced
    ///
    /// "We define the depth of a leaf to be 0, and the depth of a
    /// concatenation to be one plus the maximum depth of its children. Let
    /// _Fn_ be the _n_th Fibonacci number. A rope of depth _n_ is balanced if
    /// its length is at least _Fn_+2, e.g. a balanced rope of depth 1 must
    /// have length at least 2. Note that balanced ropes may contain unbalanced
    /// subropes."
    /// – from "Ropes: An Alternative to Strings"
    #[inline]
    pub fn is_balanced(&self) -> bool {
        self.len() >= fibonacci(self.depth() + 2)
    }

    /// Returns the depth in the tree of a node
    #[inline]
    fn depth(&self) -> usize {
        use std::cmp::max;

        match self {
            &Node::Leaf(_) => 0
          , &Node::Branch(BranchNode { ref left, ref right, .. }) =>
                max(left.depth(), right.depth()) + 1
            }
    }

    /// Returns the length of a node
    //  TODO: do we want to cache this?
    pub fn len(&self) -> usize {
        match self { &Leaf(ref s) => s.len()
                   , &Branch(BranchNode { ref left, ref right, .. }) =>
                        left.len() + right.len()
                    }
    }

    /// Calculates the weight of a node
    #[inline]
    fn subtree_weight (&self) -> usize {
        match self { &Leaf(ref s) => s.len()
                   , &Branch(BranchNode { ref left, .. }) =>
                        left.subtree_weight()
                    }
    }

    /// Rebalance the subrope starting at this `Node`, returning a new `Node`
    ///
    /// From "Ropes: An Alternative to Strings":
    /// > "The rebalancing operation maintains an ordered sequence of (empty
    /// > or) balanced ropes, one for each length interval [_Fn_, _Fn_+1), for
    /// > _n_ >= 2. We traverse the rope from left to right, inserting each
    /// > leaf into the appropriate sequence position, depending on its length.
    ///
    /// > The concatenation of the sequence of ropes in order of decreasing
    /// > length is equivalent to the prefix of the rope we have traversed so
    /// > far. Each new leaf _x_ is with_insert_ropeed into the appropriate entry of the
    /// > sequence. Assume that _x_’s length is in the interval [_Fn_, _Fn_+1),
    /// > and thus it should be put in slot _n_ (which also corresponds to
    /// > maximum depth _n_ − 2). If all lower and equal numbered levels are
    /// > empty, then this can be done directly. If not, then we concatenate
    /// > ropes in slots 2, ... ,(_n_ − 1) (concatenating onto the left), and
    /// > concatenate _x_ to the right of the result. We then continue to
    /// > concatenate ropes from the sequence in increasing order to the left
    /// > of this result, until the result fits into an empty slot in the
    /// > sequence."
    pub fn rebalance(self) -> Self {
        // TODO: this is a huge mess, I based it on the IBM Java implementation
        //       please refactor until it stops being ugly!
        //        - eliza, 12/17/2016

        if self.is_balanced() {
            // the subrope is already balanced, do nothing
            self
        } else {
            let mut leaves: Vec<Option<Node>> =
                self.into_leaves().map(Option::Some).collect();
            let len = leaves.len();
            fn _rebalance(l: &mut Vec<Option<Node>>, start: usize, end: usize)
                          -> Node {
                match end - start {
                    1 => l[start].take().unwrap()
                  , 2 => l[start].take().unwrap() + l[start + 1].take().unwrap()
                  , n => {
                        let mid = start + (n / 2);
                        _rebalance(l, start, mid) + _rebalance(l, mid, end)

                    }
                }
            };
            _rebalance(&mut leaves, 0, len)
        }
    }

    /// Returns an iterator over all leaf nodes in this `Node`'s subrope
    fn leaves<'a>(&'a self) -> Leaves<'a> {
        Leaves(vec![self])
    }

    /// Returns a move iterator over all leaf nodes in this `Node`'s subrope
    fn into_leaves(self) -> IntoLeaves {
        IntoLeaves(vec![self])
    }

    /// Returns an iterator over all the strings in this `Node`s subrope'
    #[inline]
    pub fn strings<'a>(&'a self) -> impl Iterator<Item=&'a str> {
        box self.leaves().map(|n| match n {
            &Leaf(ref s) => s.as_ref()
          , _ => unreachable!("Node.leaves() iterator contained something \
                               that wasn't a leaf. Barring _force majeure_, \
                               this should be impossible. Something's broken.")
        })
    }

    /// Returns a move iterator over all the strings in this `Node`s subrope'
    ///
    /// Consumes `self`.
    #[inline]
    pub fn into_strings(self) -> impl Iterator<Item=String> {
        box self.into_leaves().map(|n| match n {
            Leaf(s) => s
            , _ => unreachable!("Node.into_leaves() iterator contained \
                                 something  that wasn't a leaf. Barring _force \
                                 majeure_, this should be impossible. \
                                 Something's broken.")
        })
    }

    str_iters! {
        #[doc="Returns an iterator over all the bytes in this `Node`'s \
               subrope \n\

               \nAs a Rope consists of a sequence of bytes, we can iterate \
               through a rope by byte. This method returns such an iterator."]
        #[inline]
        impl bytes<u8> for Node {}
        #[doc="Returns an iterator over all the characters in this `Node`'s \
               subrope \n\

               \nAs a `Rope` consists of valid UTF-8, we can iterate through a \
               `Rope` by `char`. This method returns such an iterator. \n\

               \nIt's important to remember that `char` represents a Unicode \
               Scalar Value, and may not match your idea of what a \
               'character' is. Iteration over grapheme clusters may be what \
               you actually want."]
        #[inline]
        impl chars<char> for Node {}
        // TODO: this is actually Wrong, the indices will wrap around once we
        //       iterate into the next leaf node. we'll need to write our own
        //       char_indices iterator that tracks the character's index in the
        //       global Rope. shouldn't be too hard, just a fold...
        //          - eliza, 12/18/2016
        // #[inline]
        // impl char_indices<(usize, char)> for Node {}
        #[inline]
        impl split_whitespace<&'a str> for Node {}
        #[inline]
        impl lines<&'a str> for Node {}
    }

    // /// Returns n iterator over the bytes of this `Node`'s subrope
    // ///
    // ///
    // #[inline]
    // pub fn bytes<'a>(&'a self) -> impl Iterator<Item=u8> + 'a {
    //     self.strings().flat_map(str::bytes)
    // }

    /// Returns an iterator over the grapheme clusters of this `Node`'s subrope'
    ///
    /// This is the iterator returned by `Node::into_iter`.
    #[inline]
    pub fn graphemes<'a>(&'a self) -> impl Iterator<Item=&'a str> {
        // the compiler won't let me mark this as unimplemented using the
        // unimplemented!() macro, due to Reasons (i suspect relating to
        // returning `impl Trait`)
        //  - eliza, 12/18/2016
        panic!("Unimplemented!");
        self.strings()
    }

}

/// An iterator over a series of leaf `Node`s
struct Leaves<'a>(Vec<&'a Node>);

impl<'a> Iterator for Leaves<'a> {
    type Item = &'a Node;
    fn next(&mut self) -> Option<Self::Item> {
        match self.0.pop() {
            None => None
          , Some(leaf @ &Leaf(_)) => Some(leaf)
          , Some(&Branch(BranchNode { ref left, ref right, .. })) => {
                self.0.push(right);
                self.0.push(left);
                self.next()
            }
        }
    }
}

/// A move iterator over a series of leaf `Node`s
struct IntoLeaves(Vec<Node>);

impl Iterator for IntoLeaves {
    type Item = Node;
    fn next(&mut self) -> Option<Self::Item> {
        match self.0.pop() {
            None => None
          , Some(leaf @ Leaf(_)) => Some(leaf)
          , Some(Branch(BranchNode { box left, box right, .. })) => {
                self.0.push(right);
                self.0.push(left);
                self.next()
            }
        }
    }
}

impl ops::Add for Node {
    type Output = Self;
    /// Concatenate two `Node`s, returning a `Branch` node.
    fn add(self, right: Self) -> Self { Node::new_branch(self, right) }
}
<|endoftext|>


<commit_before>// Copyright (c) 2017 Jason White
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
use std::fs;
use std::io::{self, Write};
use std::path::PathBuf;

use button::build_graph::{BuildGraph, FromRules};
use button::graph::Graphviz;
use button::rules::Rules;
use opts::{rules_path, Edges};

use failure::{Error, ResultExt};

#[derive(StructOpt, Debug)]
pub struct Graph {
    /// Path to the build description. If not specified, finds "button.json"
    /// in the current directory or parent directories.
    #[structopt(long = "file", short = "f", parse(from_os_str))]
    file: Option<PathBuf>,

    /// Path to the output file. If not specified, writes to standard output.
    #[structopt(long = "output", short = "o", parse(from_os_str))]
    output: Option<PathBuf>,

    /// Only display the subgraph that will be traversed on an update. This
    /// has to query the file system for changes to resources.
    #[structopt(long = "changes")]
    changes: bool,

    /// Display the cached graph from the previous build.
    #[structopt(long = "cached")]
    cached: bool,

    /// Display the full name for each node instead of the abbreviated name.
    #[structopt(long = "full")]
    full: bool,

    /// Type of edges to show in the graph.
    #[structopt(
        long = "edges",
        default_value = "explicit",
        raw(
            possible_values = "&Edges::variants()",
            case_insensitive = "true"
        )
    )]
    edges: Edges,
}

impl Graph {
    /// Shows a pretty graph of the build.
    pub fn main(&self) -> Result<(), Error> {
        let file = rules_path(&self.file);

        let rules = Rules::from_path(&file).with_context(|_| {
            format!("Failed loading rules from file {:?}", file)
        })?;

        let build_graph = BuildGraph::from_rules(rules)?;

        if let Some(output) = &self.output {
            let mut stream =
                io::BufWriter::new(fs::File::create(&output).with_context(
                    |_| format!("Failed creating {:?}", output),
                )?);
            build_graph.graphviz(&mut stream)?;
            stream.flush() // Flush to catch write errors
        } else {
            let mut stdout = io::stdout();
            // build_graph.graphviz(&mut stdout.lock())?;
            stdout.flush() // Flush to catch write errors
        }.context("Failed writing GraphViz DOT file")?;

        Ok(())
    }
}
<commit_msg>Fix `button graph`<commit_after>// Copyright (c) 2017 Jason White
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
use std::fs;
use std::io::{self, Write};
use std::path::PathBuf;

use button::build_graph::{BuildGraph, FromRules};
use button::graph::Graphviz;
use button::rules::Rules;
use opts::{rules_path, Edges};

use failure::{Error, ResultExt};

#[derive(StructOpt, Debug)]
pub struct Graph {
    /// Path to the build description. If not specified, finds "button.json"
    /// in the current directory or parent directories.
    #[structopt(long = "file", short = "f", parse(from_os_str))]
    file: Option<PathBuf>,

    /// Path to the output file. If not specified, writes to standard output.
    #[structopt(long = "output", short = "o", parse(from_os_str))]
    output: Option<PathBuf>,

    /// Only display the subgraph that will be traversed on an update. This
    /// has to query the file system for changes to resources.
    #[structopt(long = "changes")]
    changes: bool,

    /// Display the cached graph from the previous build.
    #[structopt(long = "cached")]
    cached: bool,

    /// Display the full name for each node instead of the abbreviated name.
    #[structopt(long = "full")]
    full: bool,

    /// Type of edges to show in the graph.
    #[structopt(
        long = "edges",
        default_value = "explicit",
        raw(
            possible_values = "&Edges::variants()",
            case_insensitive = "true"
        )
    )]
    edges: Edges,
}

impl Graph {
    /// Shows a pretty graph of the build.
    pub fn main(&self) -> Result<(), Error> {
        let file = rules_path(&self.file);

        let rules = Rules::from_path(&file).with_context(|_| {
            format!("Failed loading rules from file {:?}", file)
        })?;

        let build_graph = BuildGraph::from_rules(rules)?;

        if let Some(output) = &self.output {
            let mut stream =
                io::BufWriter::new(fs::File::create(&output).with_context(
                    |_| format!("Failed creating {:?}", output),
                )?);
            build_graph.graphviz(&mut stream)?;
            stream.flush() // Flush to catch write errors
        } else {
            let mut stdout = io::stdout();
            build_graph.graphviz(&mut stdout.lock())?;
            stdout.flush() // Flush to catch write errors
        }.context("Failed writing GraphViz DOT file")?;

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


<commit_before>use anyhow::{anyhow, Result};
use std::convert::TryInto;

#[derive(Debug, Clone)]
pub struct Entry {
    input: [String; 10],
    output: [String; 4],
}

pub fn parse(input: &str) -> Result<Vec<Entry>> {
    let mut entries = Vec::new();
    for line in input.lines() {
        if line.trim().is_empty() {
            continue;
        }
        let (i, o) = line
            .split_once("|")
            .ok_or_else(|| anyhow!("line did not contain a |: {}", line))?;
        let i_vec: Vec<String> = i
            .trim()
            .split_ascii_whitespace()
            .map(|i| i.to_owned())
            .collect();
        let o_vec: Vec<String> = o
            .trim()
            .split_ascii_whitespace()
            .map(|i| i.to_owned())
            .collect();
        let input = i_vec
            .try_into()
            .map_err(|v: Vec<_>| anyhow!("{}: expected 10 values but got {}", i, v.len()))?;
        let output = o_vec
            .try_into()
            .map_err(|v: Vec<_>| anyhow!("{}: expected 10 values but got {}", i, v.len()))?;
        entries.push(Entry { input, output });
    }
    Ok(entries)
}

pub fn part1(input: &[Entry]) -> usize {
    input
        .iter()
        .flat_map(|e| e.output.iter())
        .filter(|signal| [2, 4, 3, 7].contains(&signal.len()))
        .count()
}

pub fn part2(_input: &[Entry]) -> &'static str {
    "<TODO>"
}

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

    const INPUT: &str = include_str!("test-data/day08.txt");

    #[test]
    fn test_parse() {
        let parsed = parse(INPUT).unwrap();
        assert_eq!(parsed.len(), 10);
        assert_eq!(
            parsed[0].input,
            [
                "be", "cfbegad", "cbdgef", "fgaecd", "cgeb", "fdcge", "agebfd", "fecdb", "fabcd",
                "edb"
            ]
        );
        assert_eq!(parsed[0].output, ["fdgacbe", "cefdb", "cefbgd", "gcbe"]);
    }

    #[test]
    fn test_part1() {
        let parsed = parse(INPUT).unwrap();
        assert_eq!(part1(&parsed), 26);
    }
}
<commit_msg>2021 day 08 part 2<commit_after>use anyhow::{anyhow, Result};
use itertools::Itertools;
use std::convert::TryInto;

type AsciiChar = u8;

#[derive(Debug, Clone)]
pub struct Entry {
    input: [Vec<AsciiChar>; 10],
    output: [Vec<AsciiChar>; 4],
}

#[derive(Debug, Clone, Copy)]
#[allow(dead_code)] // since we don't technically need the input
/// fields represent the reconstructed numbers
pub struct Decoded {
    input: [u8; 10],
    output: [u8; 4],
}

impl Decoded {
    fn read_output(&self) -> u32 {
        let mut result: u32 = 0;
        for n in self.output.iter() {
            result *= 10;
            result += *n as u32;
        }
        result
    }
}

#[derive(Debug, Clone, Copy)]
/// Represents the possibilities of what letter can represent what, effectively mapping input
/// segment -> possible output segments
///
/// The ith entry's jth least-significant-bit represents is 1 if the ith encoded segment can
/// represent the jth decoded segment, 0 if it cannot. Here, letters are encoded as 'a' -> 0,
/// 'b' -> 1, ... 'g' -> 6.
///
/// Example: if input segment 0 (='a') could possibly be decoded segment 1 (='b'), then
/// self.0[0] has bit 1 set.
struct Segments([u8; 7]);

impl Segments {
    fn zero_knowledge() -> Self {
        Segments([0x7f; 7])
    }

    /// checks that every output can be assigned from at least one input
    fn is_consistent(&self) -> bool {
        self.0
            .iter()
            .copied()
            .reduce(|acc, b| acc | b)
            .unwrap()
            .count_ones()
            == 7
    }
}

fn segments(digit: u8) -> &'static [u8] {
    match digit {
        0 => &[0, 1, 2, 4, 5, 6],
        1 => &[2, 5],
        2 => &[0, 2, 3, 4, 6],
        3 => &[0, 2, 3, 5, 6],
        4 => &[1, 2, 3, 5],
        5 => &[0, 1, 3, 5, 6],
        6 => &[0, 1, 3, 4, 5, 6],
        7 => &[1, 2, 5],
        8 => &[0, 1, 2, 3, 4, 5, 6],
        9 => &[0, 1, 2, 3, 5, 6],
        _ => panic!("invalid digit {}", digit),
    }
}

fn possibilities(segments_count: usize) -> &'static [u8] {
    match segments_count {
        2 => &[1],
        3 => &[7],
        4 => &[4],
        5 => &[2, 3, 5],
        6 => &[0, 6, 9],
        7 => &[8],
        _ => panic!("invalid segment count: {}", segments_count),
    }
}

#[derive(Debug, Clone, Copy)]
struct ProblemState<'a> {
    entry: &'a Entry,
    // input segment -> decoded segment
    segments: Segments,
    // input number index -> decoded number. 255 if unassigned
    numbers: [u8; 10],
}

impl<'a> ProblemState<'a> {
    fn zero_knowledge(entry: &'a Entry) -> Self {
        ProblemState {
            entry,
            segments: Segments::zero_knowledge(),
            numbers: [255; 10],
        }
    }

    /// identify the number at `idx` as representing `digit`
    fn identify(&self, idx: usize, digit: u8) -> Self {
        let mut result = *self;

        result.numbers[idx] = digit;

        // encoded segments at `idx` can only correspond to decoded segments from `digit`
        let mask = segments(digit)
            .iter()
            .fold(0, |mask, seg| mask | (1 << seg));
        for encoded_segment in &self.entry.input[idx] {
            let seg_idx = (encoded_segment - b'a') as usize;
            // set all bits not in `mask` to zero
            result.segments.0[seg_idx] &= mask;
        }
        result
    }

    fn decode(&self) -> Decoded {
        assert!(self.numbers.iter().copied().all(|n| n <= 9));
        let mut decoded_output = <[u8; 4]>::default();

        let mut sorted_inputs = self.entry.input.clone();
        for unsorted in sorted_inputs.iter_mut() {
            unsorted.sort_unstable();
        }

        for (encoded, decoded) in self.entry.output.iter().zip(decoded_output.iter_mut()) {
            let mut sorted = encoded.clone();
            sorted.sort_unstable();
            let input_idx = sorted_inputs
                .iter()
                .position(|e| *e == sorted)
                .unwrap_or_else(|| {
                    panic!(
                        "could not output {} in inputs [{}]",
                        std::str::from_utf8(&sorted).unwrap(),
                        sorted_inputs
                            .iter()
                            .map(|v| std::str::from_utf8(v).unwrap())
                            .join(", ")
                    )
                });
            *decoded = self.numbers[input_idx];
        }

        Decoded {
            input: self.numbers,
            output: decoded_output,
        }
    }
}

fn solve_helper(state: &ProblemState, input: &[Vec<AsciiChar>; 10], idx: usize) -> Option<Decoded> {
    if idx >= input.len() {
        return Some(state.decode());
    }

    for possibility in possibilities(input[idx].len()) {
        if state.numbers.contains(possibility) {
            continue; // already assigned
        }
        let updated = state.identify(idx, *possibility);
        if !updated.segments.is_consistent() {
            continue;
        }
        if let Some(solution) = solve_helper(&updated, input, idx + 1) {
            return Some(solution);
        }
    }
    None
}

fn solve(entry: &Entry) -> Decoded {
    let state = ProblemState::zero_knowledge(entry);
    solve_helper(&state, &entry.input, 0)
        .unwrap_or_else(|| panic!("no valid solution found for entry {:?}", entry))
}

pub fn parse(input: &str) -> Result<Vec<Entry>> {
    let mut entries = Vec::new();
    for line in input.lines() {
        if line.trim().is_empty() {
            continue;
        }
        let (i, o) = line
            .split_once("|")
            .ok_or_else(|| anyhow!("line did not contain a |: {}", line))?;
        // split lines and collect into vec of vec of bytes
        let i_vec: Vec<Vec<AsciiChar>> = i
            .trim()
            .split_ascii_whitespace()
            .map(|i| i.bytes().collect())
            .collect();
        let o_vec: Vec<Vec<AsciiChar>> = o
            .trim()
            .split_ascii_whitespace()
            .map(|i| i.bytes().collect())
            .collect();
        // turn those into arrays of vecs of bytes of the correct length
        let input = i_vec
            .try_into()
            .map_err(|v: Vec<_>| anyhow!("{}: expected 10 values but got {}", i, v.len()))?;
        let output = o_vec
            .try_into()
            .map_err(|v: Vec<_>| anyhow!("{}: expected 10 values but got {}", i, v.len()))?;
        entries.push(Entry { input, output });
    }
    Ok(entries)
}

pub fn part1(input: &[Entry]) -> usize {
    input
        .iter()
        .flat_map(|e| e.output.iter())
        .filter(|signal| [2, 4, 3, 7].contains(&signal.len()))
        .count()
}

pub fn part2(input: &[Entry]) -> u32 {
    input.iter().map(|entry| solve(entry).read_output()).sum()
}

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

    const INPUT: &str = include_str!("test-data/day08.txt");

    #[test]
    fn test_parse() {
        let parsed = parse(INPUT).unwrap();
        assert_eq!(parsed.len(), 10);
        assert_eq!(
            parsed[0].input,
            [
                b"be".to_vec(),
                b"cfbegad".to_vec(),
                b"cbdgef".to_vec(),
                b"fgaecd".to_vec(),
                b"cgeb".to_vec(),
                b"fdcge".to_vec(),
                b"agebfd".to_vec(),
                b"fecdb".to_vec(),
                b"fabcd".to_vec(),
                b"edb".to_vec()
            ]
        );
        assert_eq!(
            parsed[0].output,
            [
                b"fdgacbe".to_vec(),
                b"cefdb".to_vec(),
                b"cefbgd".to_vec(),
                b"gcbe".to_vec()
            ]
        );
    }

    #[test]
    fn test_part1() {
        let parsed = parse(INPUT).unwrap();
        assert_eq!(part1(&parsed), 26);
    }

    #[test]
    fn test_solve() {
        let input = "acedgfb cdfbe gcdfa fbcad dab cefabd cdfgeb eafb cagedb ab | \
            cdfeb fcadb cdfeb cdbaf";
        let parsed = parse(input).unwrap();
        let decoded = solve(&parsed[0]);
        assert_eq!(decoded.input, [8, 5, 2, 3, 7, 9, 6, 4, 0, 1]);
        assert_eq!(decoded.output, [5, 3, 5, 3]);
        assert_eq!(decoded.read_output(), 5353);
    }

    #[test]
    fn test_part2() {
        let parsed = parse(INPUT).unwrap();
        assert_eq!(part2(&parsed), 61229);
    }
}
<|endoftext|>