<commit_before>use crate::{
    env::Env,
    library::{self, Type, TypeId},
};
use imports::Imports;
use log::error;
use std::collections::BTreeMap;

pub mod bounds;
pub mod c_type;
pub mod child_properties;
pub mod class_builder;
pub mod class_hierarchy;
pub mod constants;
pub mod conversion_type;
pub mod enums;
pub mod ffi_type;
pub mod function_parameters;
pub mod functions;
pub mod general;
pub mod imports;
pub mod info_base;
pub mod namespaces;
pub mod object;
pub mod out_parameters;
mod override_string_type;
pub mod properties;
pub mod record;
pub mod record_type;
pub mod ref_mode;
pub mod return_value;
pub mod rust_type;
pub mod safety_assertion_mode;
pub mod signals;
pub mod signatures;
pub mod special_functions;
pub mod supertypes;
pub mod symbols;
pub mod trampoline_parameters;
pub mod trampolines;
pub mod types;

#[derive(Debug, Default)]
pub struct Analysis {
    pub objects: BTreeMap<String, object::Info>,
    pub records: BTreeMap<String, record::Info>,
    pub global_functions: Option<info_base::InfoBase>,
    pub constants: Vec<constants::Info>,
    pub enumerations: Vec<enums::Info>,
    pub enum_imports: Imports,
}

pub fn run(env: &mut Env) {
    let mut to_analyze: Vec<(TypeId, Vec<TypeId>)> = Vec::with_capacity(env.config.objects.len());
    for obj in env.config.objects.values() {
        if obj.status.ignored() {
            continue;
        }
        let tid = match env.library.find_type(0, &obj.name) {
            Some(x) => x,
            None => continue,
        };
        let deps = supertypes::dependencies(env, tid);
        to_analyze.push((tid, deps));
    }

    let mut enum_imports = Imports::new(&env.library);
    enum_imports.add("glib::translate::*");

    let mut analyzed = 1;
    while analyzed > 0 {
        analyzed = 0;
        let mut new_to_analyze: Vec<(TypeId, Vec<TypeId>)> = Vec::with_capacity(to_analyze.len());
        for &(tid, ref deps) in &to_analyze {
            if !is_all_deps_analyzed(env, deps) {
                new_to_analyze.push((tid, deps.clone()));
                continue;
            }
            analyze(env, tid, deps, &mut enum_imports);
            analyzed += 1;
        }

        to_analyze = new_to_analyze;
    }

    env.analysis.enum_imports = enum_imports;

    if !to_analyze.is_empty() {
        error!(
            "Not analyzed {} objects due unfinished dependencies",
            to_analyze.len()
        );
        return;
    }

    analyze_constants(env);

    // Analyze free functions as the last step once all types are analyzed
    analyze_global_functions(env);
}

fn analyze_global_functions(env: &mut Env) {
    let ns = env.library.namespace(library::MAIN_NAMESPACE);

    let full_name = format!("{}.*", ns.name);

    let obj = match env.config.objects.get(&*full_name) {
        Some(obj) if obj.status.need_generate() => obj,
        _ => return,
    };

    let functions: Vec<_> = ns
        .functions
        .iter()
        .filter(|f| f.kind == library::FunctionKind::Global)
        .collect();
    if functions.is_empty() {
        return;
    }

    let mut imports = imports::Imports::new(&env.library);
    imports.add("glib::translate::*");

    let functions = functions::analyze(
        env,
        &functions,
        TypeId::tid_none(),
        false,
        false,
        obj,
        &mut imports,
        None,
        None,
    );

    env.analysis.global_functions = Some(info_base::InfoBase {
        full_name,
        type_id: TypeId::tid_none(),
        name: "*".into(),
        functions,
        imports,
        ..Default::default()
    });
}

fn analyze_constants(env: &mut Env) {
    let ns = env.library.namespace(library::MAIN_NAMESPACE);

    let full_name = format!("{}.*", ns.name);

    let obj = match env.config.objects.get(&*full_name) {
        Some(obj) if obj.status.need_generate() => obj,
        _ => return,
    };

    let constants: Vec<_> = ns.constants.iter().collect();
    if constants.is_empty() {
        return;
    }

    env.analysis.constants = constants::analyze(env, &constants, obj);
}

fn analyze(env: &mut Env, tid: TypeId, deps: &[TypeId], enum_imports: &mut Imports) {
    let full_name = tid.full_name(&env.library);
    let obj = match env.config.objects.get(&*full_name) {
        Some(obj) => obj,
        None => return,
    };
    match *env.library.type_(tid) {
        Type::Class(_) => {
            if let Some(info) = object::class(env, obj, deps) {
                env.analysis.objects.insert(full_name, info);
            }
        }
        Type::Interface(_) => {
            if let Some(info) = object::interface(env, obj, deps) {
                env.analysis.objects.insert(full_name, info);
            }
        }
        Type::Record(_) => {
            if let Some(info) = record::new(env, obj) {
                env.analysis.records.insert(full_name, info);
            }
        }
        Type::Enumeration(_) => {
            // Cannot mutably borrow env.analysis.enum_imports here
            if let Some(info) = enums::new(env, obj, enum_imports) {
                env.analysis.enumerations.push(info);
            }
        }
        _ => {}
    }
}

fn is_all_deps_analyzed(env: &mut Env, deps: &[TypeId]) -> bool {
    for tid in deps {
        let full_name = tid.full_name(&env.library);
        if !env.analysis.objects.contains_key(&full_name) {
            return false;
        }
    }
    true
}

pub fn is_gpointer(s: &str) -> bool {
    s == "gpointer" || s == "void*"
}
<commit_msg>analysis: Move enum discovery out of generic analyze() function<commit_after>use crate::{
    env::Env,
    library::{self, Type, TypeId},
};
use imports::Imports;
use log::error;
use std::collections::BTreeMap;

pub mod bounds;
pub mod c_type;
pub mod child_properties;
pub mod class_builder;
pub mod class_hierarchy;
pub mod constants;
pub mod conversion_type;
pub mod enums;
pub mod ffi_type;
pub mod function_parameters;
pub mod functions;
pub mod general;
pub mod imports;
pub mod info_base;
pub mod namespaces;
pub mod object;
pub mod out_parameters;
mod override_string_type;
pub mod properties;
pub mod record;
pub mod record_type;
pub mod ref_mode;
pub mod return_value;
pub mod rust_type;
pub mod safety_assertion_mode;
pub mod signals;
pub mod signatures;
pub mod special_functions;
pub mod supertypes;
pub mod symbols;
pub mod trampoline_parameters;
pub mod trampolines;
pub mod types;

#[derive(Debug, Default)]
pub struct Analysis {
    pub objects: BTreeMap<String, object::Info>,
    pub records: BTreeMap<String, record::Info>,
    pub global_functions: Option<info_base::InfoBase>,
    pub constants: Vec<constants::Info>,
    pub enumerations: Vec<enums::Info>,
    pub enum_imports: Imports,
}

pub fn run(env: &mut Env) {
    let mut to_analyze: Vec<(TypeId, Vec<TypeId>)> = Vec::with_capacity(env.config.objects.len());
    for obj in env.config.objects.values() {
        if obj.status.ignored() {
            continue;
        }
        let tid = match env.library.find_type(0, &obj.name) {
            Some(x) => x,
            None => continue,
        };
        let deps = supertypes::dependencies(env, tid);
        to_analyze.push((tid, deps));
    }

    let mut analyzed = 1;
    while analyzed > 0 {
        analyzed = 0;
        let mut new_to_analyze: Vec<(TypeId, Vec<TypeId>)> = Vec::with_capacity(to_analyze.len());
        for &(tid, ref deps) in &to_analyze {
            if !is_all_deps_analyzed(env, deps) {
                new_to_analyze.push((tid, deps.clone()));
                continue;
            }
            analyze(env, tid, deps);
            analyzed += 1;
        }

        to_analyze = new_to_analyze;
    }

    if !to_analyze.is_empty() {
        error!(
            "Not analyzed {} objects due unfinished dependencies",
            to_analyze.len()
        );
        return;
    }

    analyze_enums(env);

    analyze_constants(env);

    // Analyze free functions as the last step once all types are analyzed
    analyze_global_functions(env);
}

fn analyze_enums(env: &mut Env) {
    let mut imports = Imports::new(&env.library);
    imports.add("glib::translate::*");

    for obj in env.config.objects.values() {
        if obj.status.ignored() {
            continue;
        }
        let tid = match env.library.find_type(0, &obj.name) {
            Some(x) => x,
            None => continue,
        };

        if let Type::Enumeration(_) = env.library.type_(tid) {
            if let Some(info) = enums::new(env, obj, &mut imports) {
                env.analysis.enumerations.push(info);
            }
        }
    }

    env.analysis.enum_imports = imports;
}

fn analyze_global_functions(env: &mut Env) {
    let ns = env.library.namespace(library::MAIN_NAMESPACE);

    let full_name = format!("{}.*", ns.name);

    let obj = match env.config.objects.get(&*full_name) {
        Some(obj) if obj.status.need_generate() => obj,
        _ => return,
    };

    let functions: Vec<_> = ns
        .functions
        .iter()
        .filter(|f| f.kind == library::FunctionKind::Global)
        .collect();
    if functions.is_empty() {
        return;
    }

    let mut imports = imports::Imports::new(&env.library);
    imports.add("glib::translate::*");

    let functions = functions::analyze(
        env,
        &functions,
        TypeId::tid_none(),
        false,
        false,
        obj,
        &mut imports,
        None,
        None,
    );

    env.analysis.global_functions = Some(info_base::InfoBase {
        full_name,
        type_id: TypeId::tid_none(),
        name: "*".into(),
        functions,
        imports,
        ..Default::default()
    });
}

fn analyze_constants(env: &mut Env) {
    let ns = env.library.namespace(library::MAIN_NAMESPACE);

    let full_name = format!("{}.*", ns.name);

    let obj = match env.config.objects.get(&*full_name) {
        Some(obj) if obj.status.need_generate() => obj,
        _ => return,
    };

    let constants: Vec<_> = ns.constants.iter().collect();
    if constants.is_empty() {
        return;
    }

    env.analysis.constants = constants::analyze(env, &constants, obj);
}

fn analyze(env: &mut Env, tid: TypeId, deps: &[TypeId]) {
    let full_name = tid.full_name(&env.library);
    let obj = match env.config.objects.get(&*full_name) {
        Some(obj) => obj,
        None => return,
    };
    match *env.library.type_(tid) {
        Type::Class(_) => {
            if let Some(info) = object::class(env, obj, deps) {
                env.analysis.objects.insert(full_name, info);
            }
        }
        Type::Interface(_) => {
            if let Some(info) = object::interface(env, obj, deps) {
                env.analysis.objects.insert(full_name, info);
            }
        }
        Type::Record(_) => {
            if let Some(info) = record::new(env, obj) {
                env.analysis.records.insert(full_name, info);
            }
        }
        _ => {}
    }
}

fn is_all_deps_analyzed(env: &mut Env, deps: &[TypeId]) -> bool {
    for tid in deps {
        let full_name = tid.full_name(&env.library);
        if !env.analysis.objects.contains_key(&full_name) {
            return false;
        }
    }
    true
}

pub fn is_gpointer(s: &str) -> bool {
    s == "gpointer" || s == "void*"
}
<|endoftext|>


<commit_before>use flowgger::config::Config;
use flowgger::record::{Record, SDValue};
use serde_json;
use serde_json::builder::ObjectBuilder;
use serde_json::value::Value;
use super::Encoder;

#[derive(Clone)]
pub struct GelfEncoder {
    extra: Vec<(String, String)>,
}

impl GelfEncoder {
    pub fn new(config: &Config) -> GelfEncoder {
        let extra = match config.lookup("output.gelf_extra") {
            None => Vec::new(),
            Some(extra) => {
                extra.as_table()
                    .expect("output.gelf_extra must be a list of key/value pairs")
                    .into_iter()
                    .map(|(k, v)| {
                        (k.to_owned(),
                         v.as_str()
                             .expect("output.gelf_extra values must be strings")
                             .to_owned())
                    })
                    .collect()
            }
        };
        GelfEncoder { extra: extra }
    }
}

impl Encoder for GelfEncoder {
    fn encode(&self, record: Record) -> Result<Vec<u8>, &'static str> {
        let mut map = ObjectBuilder::new()
            .insert("version".to_owned(), Value::String("1.1".to_owned()))
            .insert("host".to_owned(), Value::String(record.hostname))
            .insert("short_message".to_owned(),
                    Value::String(record.msg.unwrap_or("-".to_owned())))
            .insert("timestamp".to_owned(), Value::F64(record.ts));
        if let Some(severity) = record.severity {
            map = map.insert("level".to_owned(), Value::U64(severity as u64));
        }
        if let Some(full_msg) = record.full_msg {
            map = map.insert("full_message".to_owned(), Value::String(full_msg));
        }
        for (name, value) in self.extra.iter().cloned() {
            map = map.insert(name, Value::String(value));
        }
        if let Some(sd) = record.sd {
            if let Some(sd_id) = sd.sd_id {
                map = map.insert("sd_id".to_owned(), Value::String(sd_id));
            }
            for (name, value) in sd.pairs {
                let value = match value {
                    SDValue::String(value) => Value::String(value),
                    SDValue::Bool(value) => Value::Bool(value),
                    SDValue::F64(value) => Value::F64(value),
                    SDValue::I64(value) => Value::I64(value),
                    SDValue::U64(value) => Value::U64(value),
                    SDValue::Null => Value::Null,
                };
                map = map.insert(name, value);
            }
        }
        let json = try!(serde_json::to_vec(&map.build()).or(Err("Unable to serialize to JSON")));
        Ok(json)
    }
}
<commit_msg>Add RFC 5424 additional data Like: https://github.com/Graylog2/graylog2-server/blob/af1a2589dcb85645e197078491fe8b768044f1b8/graylog2-server/src/main/java/org/graylog2/inputs/codecs/SyslogCodec.java#L153<commit_after>use flowgger::config::Config;
use flowgger::record::{Record, SDValue};
use serde_json;
use serde_json::builder::ObjectBuilder;
use serde_json::value::Value;
use super::Encoder;

#[derive(Clone)]
pub struct GelfEncoder {
    extra: Vec<(String, String)>,
}

impl GelfEncoder {
    pub fn new(config: &Config) -> GelfEncoder {
        let extra = match config.lookup("output.gelf_extra") {
            None => Vec::new(),
            Some(extra) => {
                extra.as_table()
                    .expect("output.gelf_extra must be a list of key/value pairs")
                    .into_iter()
                    .map(|(k, v)| {
                        (k.to_owned(),
                         v.as_str()
                             .expect("output.gelf_extra values must be strings")
                             .to_owned())
                    })
                    .collect()
            }
        };
        GelfEncoder { extra: extra }
    }
}

impl Encoder for GelfEncoder {
    fn encode(&self, record: Record) -> Result<Vec<u8>, &'static str> {
        let mut map = ObjectBuilder::new()
            .insert("version".to_owned(), Value::String("1.1".to_owned()))
            .insert("host".to_owned(), Value::String(record.hostname))
            .insert("short_message".to_owned(),
                    Value::String(record.msg.unwrap_or("-".to_owned())))
            .insert("timestamp".to_owned(), Value::F64(record.ts));
        if let Some(severity) = record.severity {
            map = map.insert("level".to_owned(), Value::U64(severity as u64));
        }
        if let Some(full_msg) = record.full_msg {
            map = map.insert("full_message".to_owned(), Value::String(full_msg));
        }
        if let Some(appname) = record.appname {
            map = map.insert("application_name".to_owned(), Value::String(appname));
        }
        if let Some(procid) = record.procid {
            map = map.insert("process_id".to_owned(), Value::String(procid));
        }
        for (name, value) in self.extra.iter().cloned() {
            map = map.insert(name, Value::String(value));
        }
        if let Some(sd) = record.sd {
            if let Some(sd_id) = sd.sd_id {
                map = map.insert("sd_id".to_owned(), Value::String(sd_id));
            }
            for (name, value) in sd.pairs {
                let value = match value {
                    SDValue::String(value) => Value::String(value),
                    SDValue::Bool(value) => Value::Bool(value),
                    SDValue::F64(value) => Value::F64(value),
                    SDValue::I64(value) => Value::I64(value),
                    SDValue::U64(value) => Value::U64(value),
                    SDValue::Null => Value::Null,
                };
                map = map.insert(name, value);
            }
        }
        let json = try!(serde_json::to_vec(&map.build()).or(Err("Unable to serialize to JSON")));
        Ok(json)
    }
}
<|endoftext|>


<commit_before>
use clap::ArgMatches;

use doapi::{DoManager, DoRequest};
use doapi::request::Droplet;

use config::Config;
use message::CliMessage;

fn droplet_from_matches(m: &ArgMatches) -> Droplet {
    Droplet {
        name: m.value_of("name").unwrap().to_owned(),
        region: m.value_of("region").unwrap().to_owned(),
        size: m.value_of("size").unwrap().to_owned(),
        image: m.value_of("image").unwrap().to_owned(),
        ssh_keys: if let Some(v) = m.values_of("keys") {
            Some(v.iter().map(|&k| k.to_owned()).collect::<Vec<_>>())
        } else {
            None
        },
        backups: m.is_present("backups"),
        ipv6: m.is_present("ipv6"),
        private_networking: m.is_present("private-networking"),
        user_data: if let Some(d) = m.value_of("data") {
            Some(d.to_owned())
        } else {
            None
        }
    }
}

pub fn run(m: &ArgMatches, cfg: &mut Config) {
    if m.is_present("verbose") { cfg.verbose = true; }
    if m.is_present("nosend") { cfg.no_send = true; }
    let domgr = DoManager::with_token(&cfg.auth[..]);
    match m.subcommand() {
        ("neighbors", Some(m)) => {
            if cfg.verbose || m.is_present("verbose") {
                CliMessage::Request(
                    &domgr.droplets()
                         .neighbors()
                         .to_string()
                         .replace("\n", "\n\t")[..]).display();
            }
            if cfg.no_send || m.is_present("nosend") { return }
            if cfg.verbose || m.is_present("verbose") {
                CliMessage::JsonResponse.display();
                match domgr.droplets().neighbors().retrieve_json() {
                    Ok(s)  => {
                        CliMessage::Success.display();
                        println!("\n\t{}\n", s);
                    },
                    Err(e) => {
                        CliMessage::Failure.display();
                        println!("\n\t{}\n", e);
                    }
                }
            }
            CliMessage::AllDropletNeighbors.display();
            match domgr.droplets().neighbors().retrieve() {
                Ok(v) => {
                    CliMessage::Success.display();
                    for act in v.iter() {
                        CliMessage::Neighbor.display();
                        println!("\t{}", act);
                    }
                    if v.is_empty() { println!("\tNo neighbors to dipslay"); }
                },
                Err(e) => {
                    CliMessage::Failure.display();
                    println!("{}\n", e);
                }
            }
        },
        ("upgrades", Some(m))  => {
            if cfg.verbose || m.is_present("verbose") {
                CliMessage::Request(
                    &domgr.droplets()
                         .upgrades()
                         .to_string()
                         .replace("\n", "\n\t")[..]).display();
            }
            if cfg.no_send || m.is_present("nosend") { return }
            if cfg.verbose || m.is_present("verbose") {
                CliMessage::JsonResponse.display();
                match domgr.droplets().upgrades().retrieve_json() {
                    Ok(s)  => {
                        CliMessage::Success.display();
                        println!("\n\t{}\n", s);
                    },
                    Err(e) => {
                        CliMessage::Failure.display();
                        println!("\n\t{}\n", e);
                    }
                }
            }
            CliMessage::AllDropletUpgrades.display();
            match domgr.droplets().upgrades().retrieve() {
                Ok(v) => {
                    CliMessage::Success.display();
                    for act in v.iter() {
                        CliMessage::NamelessDroplet.display();
                        println!("\t{}", act);
                    }
                    if v.is_empty() { println!("\tNo upgrades to dipslay"); }
                },
                Err(e) => {
                    CliMessage::Failure.display();
                    println!("{}\n", e);
                }
            }
        },
        ("create", Some(m))         => {
            let droplet_cfg = droplet_from_matches(&m);
            if cfg.verbose || m.is_present("verbose") {
                CliMessage::Request(
                    &domgr.droplets()
                          .create(&droplet_cfg)
                          .to_string()
                          .replace("\n", "\n\t")[..]).display();
            }
            if cfg.no_send || m.is_present("nosend") { return }
            if cfg.verbose || m.is_present("verbose") {
                CliMessage::JsonResponse.display();
                match domgr.droplets().create(&droplet_cfg).retrieve_json() {
                    Ok(s) => {
                        CliMessage::Success.display();
                        println!("\n\t{}\n", s);
                    },
                    Err(e) => {
                        CliMessage::Failure.display();
                        println!("\n\t{}\n", e);
                    }
                }
            }
            CliMessage::CreateDroplet(&droplet_cfg).display();
            match domgr.droplets().create(&droplet_cfg).retrieve() {
                Ok(s) => {
                    CliMessage::Success.display();
                    println!("\n\t{}\n", s);
                },
                Err(e) => {
                    CliMessage::Failure.display();
                    println!("\n\t{}\n", e);
                }
            }
        },
        _                           => {
            if cfg.verbose {
                CliMessage::Request(
                    &domgr.droplets()
                         .to_string()
                         .replace("\n", "\n\t")[..]).display();
            }
            if cfg.no_send { return }
            if cfg.verbose {
                CliMessage::JsonResponse.display();
                match domgr.droplets().retrieve_json() {
                    Ok(s)  => {
                        CliMessage::Success.display();
                        println!("\n\t{}\n", s);
                    },
                    Err(e) => {
                        CliMessage::Failure.display();
                        println!("\n\t{}\n", e);
                    }
                }
            }
            CliMessage::Droplets.display();
            match domgr.droplets().retrieve() {
                Ok(v) => {
                    CliMessage::Success.display();
                    for d in v.iter() {
                        CliMessage::AnonDroplet.display();
                        println!("\t{}", &d.to_string()[..].replace("\n", "\n\t"));
                    }
                    if v.is_empty() { println!("\tNo droplets to dipslay"); }
                },
                Err(e) => {
                    CliMessage::Failure.display();
                    println!("{}\n", e);
                }
            }
        }
    }
}
<commit_msg>imp: fixes output for droplets upgrades commands<commit_after>
use clap::ArgMatches;

use doapi::{DoManager, DoRequest};
use doapi::request::Droplet;

use config::Config;
use message::CliMessage;

fn droplet_from_matches(m: &ArgMatches) -> Droplet {
    Droplet {
        name: m.value_of("name").unwrap().to_owned(),
        region: m.value_of("region").unwrap().to_owned(),
        size: m.value_of("size").unwrap().to_owned(),
        image: m.value_of("image").unwrap().to_owned(),
        ssh_keys: if let Some(v) = m.values_of("keys") {
            Some(v.iter().map(|&k| k.to_owned()).collect::<Vec<_>>())
        } else {
            None
        },
        backups: m.is_present("backups"),
        ipv6: m.is_present("ipv6"),
        private_networking: m.is_present("private-networking"),
        user_data: if let Some(d) = m.value_of("data") {
            Some(d.to_owned())
        } else {
            None
        }
    }
}

pub fn run(m: &ArgMatches, cfg: &mut Config) {
    if m.is_present("verbose") { cfg.verbose = true; }
    if m.is_present("nosend") { cfg.no_send = true; }
    let domgr = DoManager::with_token(&cfg.auth[..]);
    match m.subcommand() {
        ("neighbors", Some(m)) => {
            if cfg.verbose || m.is_present("verbose") {
                CliMessage::Request(
                    &domgr.droplets()
                         .neighbors()
                         .to_string()
                         .replace("\n", "\n\t")[..]).display();
            }
            if cfg.no_send || m.is_present("nosend") { return }
            if cfg.verbose || m.is_present("verbose") {
                CliMessage::JsonResponse.display();
                match domgr.droplets().neighbors().retrieve_json() {
                    Ok(s)  => {
                        CliMessage::Success.display();
                        println!("\n\t{}\n", s);
                    },
                    Err(e) => {
                        CliMessage::Failure.display();
                        println!("\n\t{}\n", e);
                    }
                }
            }
            CliMessage::AllDropletNeighbors.display();
            match domgr.droplets().neighbors().retrieve() {
                Ok(v) => {
                    CliMessage::Success.display();
                    for nv in v.iter() {
                        for dr in nv.iter() {
                            CliMessage::Neighbor.display();
                            println!("\t{}\n", &dr.to_string()[..].replace("\n", "\n\t"));
                        }
                    }
                    if v.is_empty() { println!("\tNo neighbors to dipslay"); }
                },
                Err(e) => {
                    CliMessage::Failure.display();
                    println!("{}\n", e);
                }
            }
        },
        ("upgrades", Some(m))  => {
            if cfg.verbose || m.is_present("verbose") {
                CliMessage::Request(
                    &domgr.droplets()
                         .upgrades()
                         .to_string()
                         .replace("\n", "\n\t")[..]).display();
            }
            if cfg.no_send || m.is_present("nosend") { return }
            if cfg.verbose || m.is_present("verbose") {
                CliMessage::JsonResponse.display();
                match domgr.droplets().upgrades().retrieve_json() {
                    Ok(s)  => {
                        CliMessage::Success.display();
                        println!("\n\t{}\n", s);
                    },
                    Err(e) => {
                        CliMessage::Failure.display();
                        println!("\n\t{}\n", e);
                    }
                }
            }
            CliMessage::AllDropletUpgrades.display();
            match domgr.droplets().upgrades().retrieve() {
                Ok(v) => {
                    CliMessage::Success.display();
                    for act in v.iter() {
                        CliMessage::NamelessDroplet.display();
                        println!("\t{}", act);
                    }
                    if v.is_empty() { println!("\tNo upgrades to dipslay"); }
                },
                Err(e) => {
                    CliMessage::Failure.display();
                    println!("{}\n", e);
                }
            }
        },
        ("create", Some(m))         => {
            let droplet_cfg = droplet_from_matches(&m);
            if cfg.verbose || m.is_present("verbose") {
                CliMessage::Request(
                    &domgr.droplets()
                          .create(&droplet_cfg)
                          .to_string()
                          .replace("\n", "\n\t")[..]).display();
            }
            if cfg.no_send || m.is_present("nosend") { return }
            if cfg.verbose || m.is_present("verbose") {
                CliMessage::JsonResponse.display();
                match domgr.droplets().create(&droplet_cfg).retrieve_json() {
                    Ok(s) => {
                        CliMessage::Success.display();
                        println!("\n\t{}\n", s);
                    },
                    Err(e) => {
                        CliMessage::Failure.display();
                        println!("\n\t{}\n", e);
                    }
                }
            }
            CliMessage::CreateDroplet(&droplet_cfg).display();
            match domgr.droplets().create(&droplet_cfg).retrieve() {
                Ok(s) => {
                    CliMessage::Success.display();
                    println!("\n\t{}\n", s);
                },
                Err(e) => {
                    CliMessage::Failure.display();
                    println!("\n\t{}\n", e);
                }
            }
        },
        _                           => {
            if cfg.verbose {
                CliMessage::Request(
                    &domgr.droplets()
                         .to_string()
                         .replace("\n", "\n\t")[..]).display();
            }
            if cfg.no_send { return }
            if cfg.verbose {
                CliMessage::JsonResponse.display();
                match domgr.droplets().retrieve_json() {
                    Ok(s)  => {
                        CliMessage::Success.display();
                        println!("\n\t{}\n", s);
                    },
                    Err(e) => {
                        CliMessage::Failure.display();
                        println!("\n\t{}\n", e);
                    }
                }
            }
            CliMessage::Droplets.display();
            match domgr.droplets().retrieve() {
                Ok(v) => {
                    CliMessage::Success.display();
                    for d in v.iter() {
                        CliMessage::AnonDroplet.display();
                        println!("\t{}", &d.to_string()[..].replace("\n", "\n\t"));
                    }
                    if v.is_empty() { println!("\tNo droplets to dipslay"); }
                },
                Err(e) => {
                    CliMessage::Failure.display();
                    println!("{}\n", e);
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>use rustc_errors::struct_span_err;
use rustc_hir as hir;
use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
use rustc_hir::itemlikevisit::ItemLikeVisitor;
use rustc_middle::ty::{self, TyCtxt};
use rustc_trait_selection::traits::{self, SkipLeakCheck};
use smallvec::SmallVec;

pub fn crate_inherent_impls_overlap_check(tcx: TyCtxt<'_>, crate_num: CrateNum) {
    assert_eq!(crate_num, LOCAL_CRATE);
    let krate = tcx.hir().krate();
    krate.visit_all_item_likes(&mut InherentOverlapChecker { tcx });
}

struct InherentOverlapChecker<'tcx> {
    tcx: TyCtxt<'tcx>,
}

impl InherentOverlapChecker<'tcx> {
    /// Checks whether any associated items in impls 1 and 2 share the same identifier and
    /// namespace.
    fn impls_have_common_items(
        &self,
        impl_items1: &ty::AssociatedItems<'_>,
        impl_items2: &ty::AssociatedItems<'_>,
    ) -> bool {
        let mut impl_items1 = &impl_items1;
        let mut impl_items2 = &impl_items2;

        // Performance optimization: iterate over the smaller list
        if impl_items1.len() > impl_items2.len() {
            std::mem::swap(&mut impl_items1, &mut impl_items2);
        }

        for item1 in impl_items1.in_definition_order() {
            let collision = impl_items2
                .filter_by_name_unhygienic(item1.ident.name)
                .any(|item2| self.compare_hygienically(item1, item2));

            if collision {
                return true;
            }
        }

        false
    }

    fn compare_hygienically(&self, item1: &'tcx ty::AssocItem, item2: &'tcx ty::AssocItem) -> bool {
        // Symbols and namespace match, compare hygienically.
        item1.kind.namespace() == item2.kind.namespace()
            && item1.ident.normalize_to_macros_2_0() == item2.ident.normalize_to_macros_2_0()
    }

    fn check_for_common_items_in_impls(
        &self,
        impl1: DefId,
        impl2: DefId,
        overlap: traits::OverlapResult<'_>,
    ) {
        let impl_items1 = self.tcx.associated_items(impl1);
        let impl_items2 = self.tcx.associated_items(impl2);

        for item1 in impl_items1.in_definition_order() {
            let collision = impl_items2
                .filter_by_name_unhygienic(item1.ident.name)
                .find(|item2| self.compare_hygienically(item1, item2));

            if let Some(item2) = collision {
                let name = item1.ident.normalize_to_macros_2_0();
                let mut err = struct_span_err!(
                    self.tcx.sess,
                    self.tcx.span_of_impl(item1.def_id).unwrap(),
                    E0592,
                    "duplicate definitions with name `{}`",
                    name
                );
                err.span_label(
                    self.tcx.span_of_impl(item1.def_id).unwrap(),
                    format!("duplicate definitions for `{}`", name),
                );
                err.span_label(
                    self.tcx.span_of_impl(item2.def_id).unwrap(),
                    format!("other definition for `{}`", name),
                );

                for cause in &overlap.intercrate_ambiguity_causes {
                    cause.add_intercrate_ambiguity_hint(&mut err);
                }

                if overlap.involves_placeholder {
                    traits::add_placeholder_note(&mut err);
                }

                err.emit();
            }
        }
    }

    fn check_for_overlapping_inherent_impls(&self, impl1_def_id: DefId, impl2_def_id: DefId) {
        traits::overlapping_impls(
            self.tcx,
            impl1_def_id,
            impl2_def_id,
            // We go ahead and just skip the leak check for
            // inherent impls without warning.
            SkipLeakCheck::Yes,
            |overlap| {
                self.check_for_common_items_in_impls(impl1_def_id, impl2_def_id, overlap);
                false
            },
            || true,
        );
    }
}

impl ItemLikeVisitor<'v> for InherentOverlapChecker<'tcx> {
    fn visit_item(&mut self, item: &'v hir::Item<'v>) {
        match item.kind {
            hir::ItemKind::Enum(..)
            | hir::ItemKind::Struct(..)
            | hir::ItemKind::Trait(..)
            | hir::ItemKind::Union(..) => {
                let ty_def_id = self.tcx.hir().local_def_id(item.hir_id);
                let impls = self.tcx.inherent_impls(ty_def_id);

                // If there is only one inherent impl block,
                // there is nothing to overlap check it with
                if impls.len() <= 1 {
                    return;
                }

                let impls_items = impls
                    .iter()
                    .map(|impl_def_id| (impl_def_id, self.tcx.associated_items(*impl_def_id)))
                    .collect::<SmallVec<[_; 8]>>();

                for (i, &(&impl1_def_id, impl_items1)) in impls_items.iter().enumerate() {
                    for &(&impl2_def_id, impl_items2) in &impls_items[(i + 1)..] {
                        if self.impls_have_common_items(impl_items1, impl_items2) {
                            self.check_for_overlapping_inherent_impls(impl1_def_id, impl2_def_id);
                        }
                    }
                }
            }
            _ => {}
        }
    }

    fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem<'v>) {}

    fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem<'v>) {}

    fn visit_foreign_item(&mut self, _foreign_item: &hir::ForeignItem<'v>) {}
}
<commit_msg>Turn quadratic time on number of impl blocks into linear time<commit_after>use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_errors::struct_span_err;
use rustc_hir as hir;
use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
use rustc_hir::itemlikevisit::ItemLikeVisitor;
use rustc_middle::ty::{self, TyCtxt};
use rustc_span::Symbol;
use rustc_trait_selection::traits::{self, SkipLeakCheck};
use smallvec::SmallVec;
use std::collections::hash_map::Entry;

pub fn crate_inherent_impls_overlap_check(tcx: TyCtxt<'_>, crate_num: CrateNum) {
    assert_eq!(crate_num, LOCAL_CRATE);
    let krate = tcx.hir().krate();
    krate.visit_all_item_likes(&mut InherentOverlapChecker { tcx });
}

struct InherentOverlapChecker<'tcx> {
    tcx: TyCtxt<'tcx>,
}

impl InherentOverlapChecker<'tcx> {
    /// Checks whether any associated items in impls 1 and 2 share the same identifier and
    /// namespace.
    fn impls_have_common_items(
        &self,
        impl_items1: &ty::AssociatedItems<'_>,
        impl_items2: &ty::AssociatedItems<'_>,
    ) -> bool {
        let mut impl_items1 = &impl_items1;
        let mut impl_items2 = &impl_items2;

        // Performance optimization: iterate over the smaller list
        if impl_items1.len() > impl_items2.len() {
            std::mem::swap(&mut impl_items1, &mut impl_items2);
        }

        for item1 in impl_items1.in_definition_order() {
            let collision = impl_items2
                .filter_by_name_unhygienic(item1.ident.name)
                .any(|item2| self.compare_hygienically(item1, item2));

            if collision {
                return true;
            }
        }

        false
    }

    fn compare_hygienically(&self, item1: &ty::AssocItem, item2: &ty::AssocItem) -> bool {
        // Symbols and namespace match, compare hygienically.
        item1.kind.namespace() == item2.kind.namespace()
            && item1.ident.normalize_to_macros_2_0() == item2.ident.normalize_to_macros_2_0()
    }

    fn check_for_common_items_in_impls(
        &self,
        impl1: DefId,
        impl2: DefId,
        overlap: traits::OverlapResult<'_>,
    ) {
        let impl_items1 = self.tcx.associated_items(impl1);
        let impl_items2 = self.tcx.associated_items(impl2);

        for item1 in impl_items1.in_definition_order() {
            let collision = impl_items2
                .filter_by_name_unhygienic(item1.ident.name)
                .find(|item2| self.compare_hygienically(item1, item2));

            if let Some(item2) = collision {
                let name = item1.ident.normalize_to_macros_2_0();
                let mut err = struct_span_err!(
                    self.tcx.sess,
                    self.tcx.span_of_impl(item1.def_id).unwrap(),
                    E0592,
                    "duplicate definitions with name `{}`",
                    name
                );
                err.span_label(
                    self.tcx.span_of_impl(item1.def_id).unwrap(),
                    format!("duplicate definitions for `{}`", name),
                );
                err.span_label(
                    self.tcx.span_of_impl(item2.def_id).unwrap(),
                    format!("other definition for `{}`", name),
                );

                for cause in &overlap.intercrate_ambiguity_causes {
                    cause.add_intercrate_ambiguity_hint(&mut err);
                }

                if overlap.involves_placeholder {
                    traits::add_placeholder_note(&mut err);
                }

                err.emit();
            }
        }
    }

    fn check_for_overlapping_inherent_impls(&self, impl1_def_id: DefId, impl2_def_id: DefId) {
        traits::overlapping_impls(
            self.tcx,
            impl1_def_id,
            impl2_def_id,
            // We go ahead and just skip the leak check for
            // inherent impls without warning.
            SkipLeakCheck::Yes,
            |overlap| {
                self.check_for_common_items_in_impls(impl1_def_id, impl2_def_id, overlap);
                false
            },
            || true,
        );
    }
}

impl ItemLikeVisitor<'v> for InherentOverlapChecker<'tcx> {
    fn visit_item(&mut self, item: &'v hir::Item<'v>) {
        match item.kind {
            hir::ItemKind::Enum(..)
            | hir::ItemKind::Struct(..)
            | hir::ItemKind::Trait(..)
            | hir::ItemKind::Union(..) => {
                let ty_def_id = self.tcx.hir().local_def_id(item.hir_id);
                let impls = self.tcx.inherent_impls(ty_def_id);

                // If there is only one inherent impl block,
                // there is nothing to overlap check it with
                if impls.len() <= 1 {
                    return;
                }

                let impls_items = impls
                    .iter()
                    .map(|impl_def_id| (impl_def_id, self.tcx.associated_items(*impl_def_id)))
                    .collect::<SmallVec<[_; 8]>>();

                // Perform a O(n^2) algorithm for small n,
                // otherwise switch to an allocating algorithm with
                // faster asymptotic runtime.
                if impls.len() < 30 {
                    for (i, &(&impl1_def_id, impl_items1)) in impls_items.iter().enumerate() {
                        for &(&impl2_def_id, impl_items2) in &impls_items[(i + 1)..] {
                            if self.impls_have_common_items(impl_items1, impl_items2) {
                                self.check_for_overlapping_inherent_impls(
                                    impl1_def_id,
                                    impl2_def_id,
                                );
                            }
                        }
                    }
                } else {
                    // Build a set of connected regions of impl blocks.
                    // Two impl blocks are regarded as connected if they share
                    // an item with the same unhygienic identifier.
                    // After we have assembled the connected regions,
                    // run the O(n^2) algorithm on each connected region.
                    // This is advantageous to running the algorithm over the
                    // entire graph when there are many connected regions.

                    struct ConnectedRegion {
                        idents: SmallVec<[Symbol; 8]>,
                        impl_blocks: FxHashSet<usize>,
                    }
                    // Highest connected region id
                    let mut highest_region_id = 0;
                    let mut connected_region_ids = FxHashMap::default();
                    let mut connected_regions = FxHashMap::default();

                    for (i, &(&_impl_def_id, impl_items)) in impls_items.iter().enumerate() {
                        if impl_items.len() == 0 {
                            continue;
                        }
                        // First obtain a list of existing connected region ids
                        let mut idents_to_add = SmallVec::<[Symbol; 8]>::new();
                        let ids = impl_items
                            .in_definition_order()
                            .filter_map(|item| {
                                let entry = connected_region_ids.entry(item.ident.name);
                                if let Entry::Occupied(e) = &entry {
                                    Some(*e.get())
                                } else {
                                    idents_to_add.push(item.ident.name);
                                    None
                                }
                            })
                            .collect::<FxHashSet<usize>>();
                        match ids.len() {
                            0 | 1 => {
                                let id_to_set = if ids.len() == 0 {
                                    // Create a new connected region
                                    let region = ConnectedRegion {
                                        idents: idents_to_add,
                                        impl_blocks: std::iter::once(i).collect(),
                                    };
                                    connected_regions.insert(highest_region_id, region);
                                    (highest_region_id, highest_region_id += 1).0
                                } else {
                                    // Take the only id inside the list
                                    let id_to_set = *ids.iter().next().unwrap();
                                    let region = connected_regions.get_mut(&id_to_set).unwrap();
                                    region.impl_blocks.insert(i);
                                    region.idents.extend_from_slice(&idents_to_add);
                                    id_to_set
                                };
                                let (_id, region) = connected_regions.iter().next().unwrap();
                                // Update the connected region ids
                                for ident in region.idents.iter() {
                                    connected_region_ids.insert(*ident, id_to_set);
                                }
                            }
                            _ => {
                                // We have multiple connected regions to merge.
                                // In the worst case this might add impl blocks
                                // one by one and can thus be O(n^2) in the size
                                // of the resulting final connected region, but
                                // this is no issue as the final step to check
                                // for overlaps runs in O(n^2) as well.

                                // Take the smallest id from the list
                                let id_to_set = *ids.iter().min().unwrap();

                                // Sort the id list so that the algorithm is deterministic
                                let mut ids = ids.into_iter().collect::<SmallVec<[_; 8]>>();
                                ids.sort();

                                let mut region = connected_regions.remove(&id_to_set).unwrap();
                                region.idents.extend_from_slice(&idents_to_add);
                                region.impl_blocks.insert(i);

                                for &id in ids.iter() {
                                    if id == id_to_set {
                                        continue;
                                    }
                                    let r = connected_regions.remove(&id).unwrap();
                                    // Update the connected region ids
                                    for ident in r.idents.iter() {
                                        connected_region_ids.insert(*ident, id_to_set);
                                    }
                                    region.idents.extend_from_slice(&r.idents);
                                    region.impl_blocks.extend(r.impl_blocks);
                                }
                                connected_regions.insert(id_to_set, region);
                            }
                        }
                    }

                    debug!(
                        "churning through {} components (sum={}, avg={}, var={}, max={})",
                        connected_regions.len(),
                        impls.len(),
                        impls.len() / connected_regions.len(),
                        {
                            let avg = impls.len() / connected_regions.len();
                            let s = connected_regions
                                .iter()
                                .map(|r| r.1.impl_blocks.len() as isize - avg as isize)
                                .map(|v| v.abs() as usize)
                                .sum::<usize>();
                            s / connected_regions.len()
                        },
                        connected_regions.iter().map(|r| r.1.impl_blocks.len()).max().unwrap()
                    );
                    // List of connected regions is built. Now, run the overlap check
                    // for each pair of impl blocks in the same connected region.
                    for (_id, region) in connected_regions.into_iter() {
                        let mut impl_blocks =
                            region.impl_blocks.into_iter().collect::<SmallVec<[_; 8]>>();
                        impl_blocks.sort();
                        for (i, &impl1_items_idx) in impl_blocks.iter().enumerate() {
                            let &(&impl1_def_id, impl_items1) = &impls_items[impl1_items_idx];
                            for &impl2_items_idx in impl_blocks[(i + 1)..].iter() {
                                let &(&impl2_def_id, impl_items2) = &impls_items[impl2_items_idx];
                                if self.impls_have_common_items(impl_items1, impl_items2) {
                                    self.check_for_overlapping_inherent_impls(
                                        impl1_def_id,
                                        impl2_def_id,
                                    );
                                }
                            }
                        }
                    }
                }
            }
            _ => {}
        }
    }

    fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem<'v>) {}

    fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem<'v>) {}

    fn visit_foreign_item(&mut self, _foreign_item: &hir::ForeignItem<'v>) {}
}
<|endoftext|>


<commit_before>#![allow(unused_imports)]
#![allow(non_snake_case)]

use procon::*;
use std::cmp::{max, min};
use std::collections::*;
use std::ops::*;
use std::*;

pub fn main() {
    return;
}

pub mod procon {
    use std;
    use std::collections::*;
    use std::io;
    use std::mem;
    use std::str::FromStr;

    pub fn read_line() -> String {
        let mut buf = String::new();
        io::stdin().read_line(&mut buf).unwrap();
        buf.trim_right().to_owned()
    }

    pub fn read_words<T>() -> Vec<T>
    where
        T: std::str::FromStr,
        T::Err: std::fmt::Debug,
    {
        let mut buf = String::new();
        io::stdin().read_line(&mut buf).unwrap();
        buf.split_whitespace()
            .map(|word| T::from_str(word).unwrap())
            .collect()
    }

    pub fn read_vec(len: usize) -> Vec<String> {
        let mut vec = Vec::new();
        while vec.len() < len {
            let line = read_line();
            for word in line.split_whitespace() {
                vec.push(word.to_owned());
            }
        }
        assert!(vec.len() == len);
        vec
    }
}
<commit_msg>Add tests mod<commit_after>#![allow(unused_imports)]
#![allow(non_snake_case)]

use procon::*;
use std::cmp::{max, min};
use std::collections::*;
use std::ops::*;
use std::*;

pub fn main() {
    return;
}

pub mod procon {
    use std;
    use std::collections::*;
    use std::io;
    use std::mem;
    use std::str::FromStr;

    pub fn read_line() -> String {
        let mut buf = String::new();
        io::stdin().read_line(&mut buf).unwrap();
        buf.trim_right().to_owned()
    }

    pub fn read_words<T>() -> Vec<T>
    where
        T: std::str::FromStr,
        T::Err: std::fmt::Debug,
    {
        let mut buf = String::new();
        io::stdin().read_line(&mut buf).unwrap();
        buf.split_whitespace()
            .map(|word| T::from_str(word).unwrap())
            .collect()
    }

    pub fn read_vec(len: usize) -> Vec<String> {
        let mut vec = Vec::new();
        while vec.len() < len {
            let line = read_line();
            for word in line.split_whitespace() {
                vec.push(word.to_owned());
            }
        }
        assert!(vec.len() == len);
        vec
    }
}

#[cfg(test)]
mod tests {
    #[test]
    pub fn test_ok() {
        assert_eq!(7, 1 + 2 * 3);
    }
}
<|endoftext|>


<commit_before>#![allow(unused_imports)]
#![allow(non_snake_case)]

use std::cmp::{max, min, Ordering};
use std::collections::*;
use std::ops::*;
use std::*;

// -----------------------------------------------
// Framework
// -----------------------------------------------

#[allow(unused)]
fn rl() -> String {
    let mut buf = String::new();
    io::stdin().read_line(&mut buf).unwrap();
    buf.trim_right().to_owned()
}

#[allow(unused)]
fn rw<T>() -> Vec<T>
where
    T: std::str::FromStr,
    T::Err: std::fmt::Debug,
{
    let mut buf = String::new();
    io::stdin().read_line(&mut buf).unwrap();
    buf.split_whitespace()
        .map(|word| T::from_str(word).unwrap())
        .collect()
}

// -----------------------------------------------
// Polyfill
// -----------------------------------------------

#[derive(PartialEq, Eq, Clone, Debug)]
pub struct Rev<T>(pub T);

impl<T: PartialOrd> PartialOrd for Rev<T> {
    fn partial_cmp(&self, other: &Rev<T>) -> Option<Ordering> {
        other.0.partial_cmp(&self.0)
    }
}

impl<T: Ord> Ord for Rev<T> {
    fn cmp(&self, other: &Rev<T>) -> Ordering {
        other.0.cmp(&self.0)
    }
}

// -----------------------------------------------
// Solution
// -----------------------------------------------

pub fn main() {
    return;
}

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

    #[test]
    fn test_ok() {
        assert_eq!(7, 1 + 2 * 3);
    }
}
<commit_msg>Add polyfill of eprintln!<commit_after>#![allow(unused_imports)]
#![allow(non_snake_case)]

use std::cmp::{max, min, Ordering};
use std::collections::*;
use std::io::*;
use std::ops::*;
use std::*;

// -----------------------------------------------
// Framework
// -----------------------------------------------

#[allow(unused)]
fn rl() -> String {
    let mut buf = String::new();
    io::stdin().read_line(&mut buf).unwrap();
    buf.trim_right().to_owned()
}

#[allow(unused)]
fn rw<T>() -> Vec<T>
where
    T: std::str::FromStr,
    T::Err: std::fmt::Debug,
{
    let mut buf = String::new();
    io::stdin().read_line(&mut buf).unwrap();
    buf.split_whitespace()
        .map(|word| T::from_str(word).unwrap())
        .collect()
}

// -----------------------------------------------
// Polyfill
// -----------------------------------------------

#[derive(PartialEq, Eq, Clone, Debug)]
pub struct Rev<T>(pub T);

impl<T: PartialOrd> PartialOrd for Rev<T> {
    fn partial_cmp(&self, other: &Rev<T>) -> Option<Ordering> {
        other.0.partial_cmp(&self.0)
    }
}

impl<T: Ord> Ord for Rev<T> {
    fn cmp(&self, other: &Rev<T>) -> Ordering {
        other.0.cmp(&self.0)
    }
}

#[allow(unused)]
macro_rules! eprintln {
    ($($arg:expr),*) => { _eprintln(format_args!($($arg),*)) }
}

fn _eprintln(args: fmt::Arguments) {
    let err = std::io::stderr();
    let mut err = err.lock();
    err.write_fmt(args).unwrap();
    err.write(b"\n").unwrap();
}

// -----------------------------------------------
// Solution
// -----------------------------------------------

pub fn main() {
    return;
}

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

    #[test]
    fn test_ok() {
        assert_eq!(7, 1 + 2 * 3);
    }
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

/// Extract the module name from a path. This is the required prefix for
/// query, fragment, subscription and mutation names.
pub fn extract_module_name(path: &str) -> Option<String> {
    let final_segment = get_final_non_index_js_segment(path)?.to_string();

    let mut iter = final_segment.split('.');
    let mut first_segment = to_camel_case(iter.next()?.to_string());
    let mobile_platform = iter.find_map(|item| {
        if item == "ios" {
            return Some("Ios");
        } else if item == "android" {
            return Some("Android");
        }
        None
    });
    if let Some(mobile_platform) = mobile_platform {
        first_segment.push_str(mobile_platform);
    }
    Some(first_segment)
}

fn get_final_non_index_js_segment(path: &str) -> Option<&str> {
    let mut iter = path.split(std::path::MAIN_SEPARATOR);
    let last_segment = iter.next_back()?;
    if last_segment == "index.js"
        || last_segment == "index.jsx"
        || last_segment == "index.ts"
        || last_segment == "index.tsx"
    {
        return iter.next_back();
    }
    Some(last_segment)
}

/// Converts a `String` to a camel case `String`
fn to_camel_case(non_camelized_string: String) -> String {
    // Emulate the following regex, from the Javascript implementation:
    // moduleName = moduleName.replace(/[^a-zA-Z0-9]+(\w?)/g, (match, next) =>
    //     next.toUpperCase(),
    // );

    let mut camelized_string = String::with_capacity(non_camelized_string.len());
    let mut last_character_was_not_alphanumeric = false;
    for ch in non_camelized_string.chars() {
        if !ch.is_alphanumeric() {
            last_character_was_not_alphanumeric = true;
        } else if last_character_was_not_alphanumeric {
            camelized_string.push(ch.to_ascii_uppercase());
            last_character_was_not_alphanumeric = false;
        } else {
            camelized_string.push(ch);
            last_character_was_not_alphanumeric = false;
        }
    }
    camelized_string
}

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

    #[cfg(not(windows))]
    #[test]
    fn extract_module_names_test() {
        assert_eq!(
            extract_module_name("/path/Button.ios.js"),
            Some("ButtonIos".to_string())
        );
        assert_eq!(
            extract_module_name("/path/Button.android.js"),
            Some("ButtonAndroid".to_string())
        );
        assert_eq!(
            extract_module_name("/path/Button.hooks.android.js"),
            Some("ButtonAndroid".to_string())
        );
        assert_eq!(
            extract_module_name("/path/Button.js"),
            Some("Button".to_string())
        );
        assert_eq!(
            extract_module_name("/path/Button.react.js"),
            Some("Button".to_string())
        );
        assert_eq!(
            extract_module_name("/path/Button.react-test.js"),
            Some("Button".to_string())
        );
        assert_eq!(
            extract_module_name("/path/Button.react-test.jsx"),
            Some("Button".to_string())
        );
        assert_eq!(
            extract_module_name("/path/Button.react.example.jsx"),
            Some("Button".to_string())
        );
        assert_eq!(
            extract_module_name("/path/Button.react-snapshot-test.js"),
            Some("Button".to_string())
        );
        assert_eq!(
            extract_module_name("/path/Button.kit.js"),
            Some("Button".to_string())
        );
        assert_eq!(
            extract_module_name("/path/Button.hooks.js"),
            Some("Button".to_string())
        );
        assert_eq!(
            extract_module_name("/path/Button.brands.react.js"),
            Some("Button".to_string())
        );
        assert_eq!(
            extract_module_name("/path/Button.my.custom.suffix.js"),
            Some("Button".to_string())
        );
        assert_eq!(
            extract_module_name("/path/Slider.ios.js"),
            Some("SliderIos".to_string())
        );
        assert_eq!(
            extract_module_name("/path/TypeScript.ts"),
            Some("TypeScript".to_string())
        );
        assert_eq!(
            extract_module_name("/path/TypeScript.tsx"),
            Some("TypeScript".to_string())
        );
        assert_eq!(
            extract_module_name("/path/TypeScript/index.ts"),
            Some("TypeScript".to_string())
        );
        assert_eq!(
            extract_module_name("/path/TypeScript/index.tsx"),
            Some("TypeScript".to_string())
        );
        assert_eq!(
            extract_module_name("/path/button/index.js"),
            Some("button".to_string())
        );
        assert_eq!(
            extract_module_name("/path/button/index.jsx"),
            Some("button".to_string())
        );
        assert_eq!(
            extract_module_name("/path/foo-bar/index.js"),
            Some("fooBar".to_string())
        );
        assert_eq!(
            extract_module_name("/path/foo-bar-baz.js"),
            Some("fooBarBaz".to_string())
        );
        assert_eq!(
            extract_module_name("/path/non-numeric-end-.js"),
            Some("nonNumericEnd".to_string())
        );
    }

    #[cfg(windows)]
    #[test]
    fn extract_module_names_test() {
        assert_eq!(
            extract_module_name("C:\\path\\Button.ios.js"),
            Some("ButtonIos".to_string())
        );
        assert_eq!(
            extract_module_name("\\path\\Button.android.js"),
            Some("ButtonAndroid".to_string())
        );
    }
}
<commit_msg>Correctly extract module names on windows (#3694)<commit_after>/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

use std::path::{Path, PathBuf};

/// Extract the module name from a path. This is the required prefix for
/// query, fragment, subscription and mutation names.
pub fn extract_module_name(path: &str) -> Option<String> {
    let path = PathBuf::from(path);
    let final_segment = get_final_non_index_js_segment(&path)?;
    let mut iter = final_segment.split('.');
    let mut first_segment = to_camel_case(iter.next()?.to_string());
    let mobile_platform = iter.find_map(|item| {
        if item == "ios" {
            return Some("Ios");
        } else if item == "android" {
            return Some("Android");
        }
        None
    });
    if let Some(mobile_platform) = mobile_platform {
        first_segment.push_str(mobile_platform);
    }
    Some(first_segment)
}

fn get_final_non_index_js_segment(path: &Path) -> Option<&str> {
    let file_stem = path.file_stem()?.to_str();
    if file_stem == Some("index") {
        let mut iter = path.iter();
        iter.next_back()?;
        iter.next_back().and_then(|os_str| os_str.to_str())
    } else {
        file_stem
    }
}

/// Converts a `String` to a camel case `String`
fn to_camel_case(non_camelized_string: String) -> String {
    // Emulate the following regex, from the Javascript implementation:
    // moduleName = moduleName.replace(/[^a-zA-Z0-9]+(\w?)/g, (match, next) =>
    //     next.toUpperCase(),
    // );

    let mut camelized_string = String::with_capacity(non_camelized_string.len());
    let mut last_character_was_not_alphanumeric = false;
    for ch in non_camelized_string.chars() {
        if !ch.is_alphanumeric() {
            last_character_was_not_alphanumeric = true;
        } else if last_character_was_not_alphanumeric {
            camelized_string.push(ch.to_ascii_uppercase());
            last_character_was_not_alphanumeric = false;
        } else {
            camelized_string.push(ch);
            last_character_was_not_alphanumeric = false;
        }
    }
    camelized_string
}

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

    #[cfg(not(windows))]
    #[test]
    fn extract_module_names_test() {
        assert_eq!(
            extract_module_name("/path/Button.ios.js"),
            Some("ButtonIos".to_string())
        );
        assert_eq!(
            extract_module_name("/path/Button.android.js"),
            Some("ButtonAndroid".to_string())
        );
        assert_eq!(
            extract_module_name("/path/Button.hooks.android.js"),
            Some("ButtonAndroid".to_string())
        );
        assert_eq!(
            extract_module_name("/path/Button.js"),
            Some("Button".to_string())
        );
        assert_eq!(
            extract_module_name("/path/Button.react.js"),
            Some("Button".to_string())
        );
        assert_eq!(
            extract_module_name("/path/Button.react-test.js"),
            Some("Button".to_string())
        );
        assert_eq!(
            extract_module_name("/path/Button.react-test.jsx"),
            Some("Button".to_string())
        );
        assert_eq!(
            extract_module_name("/path/Button.react.example.jsx"),
            Some("Button".to_string())
        );
        assert_eq!(
            extract_module_name("/path/Button.react-snapshot-test.js"),
            Some("Button".to_string())
        );
        assert_eq!(
            extract_module_name("/path/Button.kit.js"),
            Some("Button".to_string())
        );
        assert_eq!(
            extract_module_name("/path/Button.hooks.js"),
            Some("Button".to_string())
        );
        assert_eq!(
            extract_module_name("/path/Button.brands.react.js"),
            Some("Button".to_string())
        );
        assert_eq!(
            extract_module_name("/path/Button.my.custom.suffix.js"),
            Some("Button".to_string())
        );
        assert_eq!(
            extract_module_name("/path/Slider.ios.js"),
            Some("SliderIos".to_string())
        );
        assert_eq!(
            extract_module_name("/path/TypeScript.ts"),
            Some("TypeScript".to_string())
        );
        assert_eq!(
            extract_module_name("/path/TypeScript.tsx"),
            Some("TypeScript".to_string())
        );
        assert_eq!(
            extract_module_name("/path/TypeScript/index.ts"),
            Some("TypeScript".to_string())
        );
        assert_eq!(
            extract_module_name("/path/TypeScript/index.tsx"),
            Some("TypeScript".to_string())
        );
        assert_eq!(
            extract_module_name("/path/button/index.js"),
            Some("button".to_string())
        );
        assert_eq!(
            extract_module_name("/path/button/index.jsx"),
            Some("button".to_string())
        );
        assert_eq!(
            extract_module_name("/path/foo-bar/index.js"),
            Some("fooBar".to_string())
        );
        assert_eq!(
            extract_module_name("/path/foo-bar-baz.js"),
            Some("fooBarBaz".to_string())
        );
        assert_eq!(
            extract_module_name("/path/non-numeric-end-.js"),
            Some("nonNumericEnd".to_string())
        );
    }

    #[cfg(windows)]
    #[test]
    fn extract_module_names_test() {
        assert_eq!(
            extract_module_name("C:\\path\\Button.ios.js"),
            Some("ButtonIos".to_string())
        );
        assert_eq!(
            extract_module_name("\\path\\Button.android.js"),
            Some("ButtonAndroid".to_string())
        );
    }
}
<|endoftext|>


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

use dom::bindings::codegen::Bindings::MouseEventBinding;
use dom::bindings::codegen::Bindings::MouseEventBinding::MouseEventMethods;
use dom::bindings::codegen::Bindings::UIEventBinding::UIEventMethods;
use dom::bindings::codegen::InheritTypes::{UIEventCast, MouseEventDerived};
use dom::bindings::error::Fallible;
use dom::bindings::global::GlobalRef;
use dom::bindings::global;
use dom::bindings::js::{MutNullableJS, JSRef, RootedReference, Temporary, OptionalSettable};
use dom::bindings::trace::Traceable;
use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object};
use dom::event::{Event, MouseEventTypeId};
use dom::eventtarget::EventTarget;
use dom::uievent::UIEvent;
use dom::window::Window;
use servo_util::str::DOMString;
use std::cell::Cell;
use std::default::Default;

#[jstraceable]
#[must_root]
pub struct MouseEvent {
    pub mouseevent: UIEvent,
    pub screen_x: Traceable<Cell<i32>>,
    pub screen_y: Traceable<Cell<i32>>,
    pub client_x: Traceable<Cell<i32>>,
    pub client_y: Traceable<Cell<i32>>,
    pub ctrl_key: Traceable<Cell<bool>>,
    pub shift_key: Traceable<Cell<bool>>,
    pub alt_key: Traceable<Cell<bool>>,
    pub meta_key: Traceable<Cell<bool>>,
    pub button: Traceable<Cell<i16>>,
    pub related_target: MutNullableJS<EventTarget>
}

impl MouseEventDerived for Event {
    fn is_mouseevent(&self) -> bool {
        self.type_id == MouseEventTypeId
    }
}

impl MouseEvent {
    fn new_inherited() -> MouseEvent {
        MouseEvent {
            mouseevent: UIEvent::new_inherited(MouseEventTypeId),
            screen_x: Traceable::new(Cell::new(0)),
            screen_y: Traceable::new(Cell::new(0)),
            client_x: Traceable::new(Cell::new(0)),
            client_y: Traceable::new(Cell::new(0)),
            ctrl_key: Traceable::new(Cell::new(false)),
            shift_key: Traceable::new(Cell::new(false)),
            alt_key: Traceable::new(Cell::new(false)),
            meta_key: Traceable::new(Cell::new(false)),
            button: Traceable::new(Cell::new(0)),
            related_target: Default::default(),
        }
    }

    pub fn new_uninitialized(window: JSRef<Window>) -> Temporary<MouseEvent> {
        reflect_dom_object(box MouseEvent::new_inherited(),
                           &global::Window(window),
                           MouseEventBinding::Wrap)
    }

    pub fn new(window: JSRef<Window>,
               type_: DOMString,
               canBubble: bool,
               cancelable: bool,
               view: Option<JSRef<Window>>,
               detail: i32,
               screenX: i32,
               screenY: i32,
               clientX: i32,
               clientY: i32,
               ctrlKey: bool,
               altKey: bool,
               shiftKey: bool,
               metaKey: bool,
               button: i16,
               relatedTarget: Option<JSRef<EventTarget>>) -> Temporary<MouseEvent> {
        let ev = MouseEvent::new_uninitialized(window).root();
        ev.deref().InitMouseEvent(type_, canBubble, cancelable, view, detail,
                                  screenX, screenY, clientX, clientY,
                                  ctrlKey, altKey, shiftKey, metaKey,
                                  button, relatedTarget);
        Temporary::from_rooted(*ev)
    }

    pub fn Constructor(global: &GlobalRef,
                       type_: DOMString,
                       init: &MouseEventBinding::MouseEventInit) -> Fallible<Temporary<MouseEvent>> {
        let event = MouseEvent::new(global.as_window(), type_,
                                    init.parent.parent.bubbles,
                                    init.parent.parent.cancelable,
                                    init.parent.view.root_ref(),
                                    init.parent.detail,
                                    init.screenX, init.screenY,
                                    init.clientX, init.clientY, init.ctrlKey,
                                    init.altKey, init.shiftKey, init.metaKey,
                                    init.button, init.relatedTarget.root_ref());
        Ok(event)
    }
}

impl<'a> MouseEventMethods for JSRef<'a, MouseEvent> {
    fn ScreenX(self) -> i32 {
        self.screen_x.deref().get()
    }

    fn ScreenY(self) -> i32 {
        self.screen_y.deref().get()
    }

    fn ClientX(self) -> i32 {
        self.client_x.deref().get()
    }

    fn ClientY(self) -> i32 {
        self.client_y.deref().get()
    }

    fn CtrlKey(self) -> bool {
        self.ctrl_key.deref().get()
    }

    fn ShiftKey(self) -> bool {
        self.shift_key.deref().get()
    }

    fn AltKey(self) -> bool {
        self.alt_key.deref().get()
    }

    fn MetaKey(self) -> bool {
        self.meta_key.deref().get()
    }

    fn Button(self) -> i16 {
        self.button.deref().get()
    }

    fn GetRelatedTarget(self) -> Option<Temporary<EventTarget>> {
        self.related_target.get()
    }

    fn InitMouseEvent(self,
                      typeArg: DOMString,
                      canBubbleArg: bool,
                      cancelableArg: bool,
                      viewArg: Option<JSRef<Window>>,
                      detailArg: i32,
                      screenXArg: i32,
                      screenYArg: i32,
                      clientXArg: i32,
                      clientYArg: i32,
                      ctrlKeyArg: bool,
                      altKeyArg: bool,
                      shiftKeyArg: bool,
                      metaKeyArg: bool,
                      buttonArg: i16,
                      relatedTargetArg: Option<JSRef<EventTarget>>) {
        let uievent: JSRef<UIEvent> = UIEventCast::from_ref(self);
        uievent.InitUIEvent(typeArg, canBubbleArg, cancelableArg, viewArg, detailArg);
        self.screen_x.deref().set(screenXArg);
        self.screen_y.deref().set(screenYArg);
        self.client_x.deref().set(clientXArg);
        self.client_y.deref().set(clientYArg);
        self.ctrl_key.deref().set(ctrlKeyArg);
        self.alt_key.deref().set(altKeyArg);
        self.shift_key.deref().set(shiftKeyArg);
        self.meta_key.deref().set(metaKeyArg);
        self.button.deref().set(buttonArg);
        self.related_target.assign(relatedTargetArg);
    }
}

impl Reflectable for MouseEvent {
    fn reflector<'a>(&'a self) -> &'a Reflector {
        self.mouseevent.reflector()
    }
}
<commit_msg>Remove Traceable from mouseevent.rs<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use dom::bindings::codegen::Bindings::MouseEventBinding;
use dom::bindings::codegen::Bindings::MouseEventBinding::MouseEventMethods;
use dom::bindings::codegen::Bindings::UIEventBinding::UIEventMethods;
use dom::bindings::codegen::InheritTypes::{UIEventCast, MouseEventDerived};
use dom::bindings::error::Fallible;
use dom::bindings::global::GlobalRef;
use dom::bindings::global;
use dom::bindings::js::{MutNullableJS, JSRef, RootedReference, Temporary, OptionalSettable};
use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object};
use dom::event::{Event, MouseEventTypeId};
use dom::eventtarget::EventTarget;
use dom::uievent::UIEvent;
use dom::window::Window;
use servo_util::str::DOMString;
use std::cell::Cell;
use std::default::Default;

#[jstraceable]
#[must_root]
pub struct MouseEvent {
    pub mouseevent: UIEvent,
    pub screen_x: Cell<i32>,
    pub screen_y: Cell<i32>,
    pub client_x: Cell<i32>,
    pub client_y: Cell<i32>,
    pub ctrl_key: Cell<bool>,
    pub shift_key: Cell<bool>,
    pub alt_key: Cell<bool>,
    pub meta_key: Cell<bool>,
    pub button: Cell<i16>,
    pub related_target: MutNullableJS<EventTarget>
}

impl MouseEventDerived for Event {
    fn is_mouseevent(&self) -> bool {
        self.type_id == MouseEventTypeId
    }
}

impl MouseEvent {
    fn new_inherited() -> MouseEvent {
        MouseEvent {
            mouseevent: UIEvent::new_inherited(MouseEventTypeId),
            screen_x: Cell::new(0),
            screen_y: Cell::new(0),
            client_x: Cell::new(0),
            client_y: Cell::new(0),
            ctrl_key: Cell::new(false),
            shift_key: Cell::new(false),
            alt_key: Cell::new(false),
            meta_key: Cell::new(false),
            button: Cell::new(0),
            related_target: Default::default(),
        }
    }

    pub fn new_uninitialized(window: JSRef<Window>) -> Temporary<MouseEvent> {
        reflect_dom_object(box MouseEvent::new_inherited(),
                           &global::Window(window),
                           MouseEventBinding::Wrap)
    }

    pub fn new(window: JSRef<Window>,
               type_: DOMString,
               canBubble: bool,
               cancelable: bool,
               view: Option<JSRef<Window>>,
               detail: i32,
               screenX: i32,
               screenY: i32,
               clientX: i32,
               clientY: i32,
               ctrlKey: bool,
               altKey: bool,
               shiftKey: bool,
               metaKey: bool,
               button: i16,
               relatedTarget: Option<JSRef<EventTarget>>) -> Temporary<MouseEvent> {
        let ev = MouseEvent::new_uninitialized(window).root();
        ev.InitMouseEvent(type_, canBubble, cancelable, view, detail,
                                  screenX, screenY, clientX, clientY,
                                  ctrlKey, altKey, shiftKey, metaKey,
                                  button, relatedTarget);
        Temporary::from_rooted(*ev)
    }

    pub fn Constructor(global: &GlobalRef,
                       type_: DOMString,
                       init: &MouseEventBinding::MouseEventInit) -> Fallible<Temporary<MouseEvent>> {
        let event = MouseEvent::new(global.as_window(), type_,
                                    init.parent.parent.bubbles,
                                    init.parent.parent.cancelable,
                                    init.parent.view.root_ref(),
                                    init.parent.detail,
                                    init.screenX, init.screenY,
                                    init.clientX, init.clientY, init.ctrlKey,
                                    init.altKey, init.shiftKey, init.metaKey,
                                    init.button, init.relatedTarget.root_ref());
        Ok(event)
    }
}

impl<'a> MouseEventMethods for JSRef<'a, MouseEvent> {
    fn ScreenX(self) -> i32 {
        self.screen_x.get()
    }

    fn ScreenY(self) -> i32 {
        self.screen_y.get()
    }

    fn ClientX(self) -> i32 {
        self.client_x.get()
    }

    fn ClientY(self) -> i32 {
        self.client_y.get()
    }

    fn CtrlKey(self) -> bool {
        self.ctrl_key.get()
    }

    fn ShiftKey(self) -> bool {
        self.shift_key.get()
    }

    fn AltKey(self) -> bool {
        self.alt_key.get()
    }

    fn MetaKey(self) -> bool {
        self.meta_key.get()
    }

    fn Button(self) -> i16 {
        self.button.get()
    }

    fn GetRelatedTarget(self) -> Option<Temporary<EventTarget>> {
        self.related_target.get()
    }

    fn InitMouseEvent(self,
                      typeArg: DOMString,
                      canBubbleArg: bool,
                      cancelableArg: bool,
                      viewArg: Option<JSRef<Window>>,
                      detailArg: i32,
                      screenXArg: i32,
                      screenYArg: i32,
                      clientXArg: i32,
                      clientYArg: i32,
                      ctrlKeyArg: bool,
                      altKeyArg: bool,
                      shiftKeyArg: bool,
                      metaKeyArg: bool,
                      buttonArg: i16,
                      relatedTargetArg: Option<JSRef<EventTarget>>) {
        let uievent: JSRef<UIEvent> = UIEventCast::from_ref(self);
        uievent.InitUIEvent(typeArg, canBubbleArg, cancelableArg, viewArg, detailArg);
        self.screen_x.set(screenXArg);
        self.screen_y.set(screenYArg);
        self.client_x.set(clientXArg);
        self.client_y.set(clientYArg);
        self.ctrl_key.set(ctrlKeyArg);
        self.alt_key.set(altKeyArg);
        self.shift_key.set(shiftKeyArg);
        self.meta_key.set(metaKeyArg);
        self.button.set(buttonArg);
        self.related_target.assign(relatedTargetArg);
    }
}

impl Reflectable for MouseEvent {
    fn reflector<'a>(&'a self) -> &'a Reflector {
        self.mouseevent.reflector()
    }
}
<|endoftext|>