<commit_before>use crate::errors::*;
use crate::providers::aws;
use mockito;

#[test]
fn test_aws_basic() {
    let ep = "/meta-data/public-keys";
    let client = crate::retry::Client::try_new()
        .chain_err(|| "failed to create http client")
        .unwrap()
        .max_attempts(1)
        .return_on_404(true);
    let provider = aws::AwsProvider { client };

    provider.fetch_ssh_keys().unwrap_err();

    let _m = mockito::mock("GET", ep).with_status(503).create();
    provider.fetch_ssh_keys().unwrap_err();

    let _m = mockito::mock("GET", ep).with_status(200).create();
    let v = provider.fetch_ssh_keys().unwrap();
    assert_eq!(v.len(), 0);

    let _m = mockito::mock("GET", ep).with_status(404).create();
    let v = provider.fetch_ssh_keys().unwrap();
    assert_eq!(v.len(), 0);
}
<commit_msg>providers/aws: Add mock-test for attributes fetching<commit_after>use crate::errors::*;
use crate::providers::aws;
use mockito;
use std::collections::HashMap;
use crate::providers::MetadataProvider;

#[cfg(not(feature = "cl-legacy"))]
static ENV_PREFIX: &str = "AWS";
#[cfg(feature = "cl-legacy")]
static ENV_PREFIX: &str = "EC2";

#[test]
fn test_aws_basic() {
    let ep = "/meta-data/public-keys";
    let client = crate::retry::Client::try_new()
        .chain_err(|| "failed to create http client")
        .unwrap()
        .max_attempts(1)
        .return_on_404(true);
    let provider = aws::AwsProvider { client };

    provider.fetch_ssh_keys().unwrap_err();

    let _m = mockito::mock("GET", ep).with_status(503).create();
    provider.fetch_ssh_keys().unwrap_err();

    let _m = mockito::mock("GET", ep).with_status(200).create();
    let v = provider.fetch_ssh_keys().unwrap();
    assert_eq!(v.len(), 0);

    let _m = mockito::mock("GET", ep).with_status(404).create();
    let v = provider.fetch_ssh_keys().unwrap();
    assert_eq!(v.len(), 0);
}

#[test]
fn test_attributes_fetching() {
    let ep_instance_id = "/meta-data/instance-id";
    let instance_id = "test-instance-id";

    let ep_instance_type = "/meta-data/instance-type";
    let instance_type = "test-instance-type";

    let ep_ipv4_local = "/meta-data/local-ipv4";
    let ipv4_local = "test-ipv4-local";

    let ep_ipv4_public = "/meta-data/public-ipv4";
    let ipv4_public = "test-ipv4-public";

    let ep_availability_zone = "/meta-data/placement/availability-zone";
    let availability_zone = "test-availability-zone";

    let ep_hostname = "/meta-data/hostname";
    let hostname = "test-hostname";

    let ep_public_hostname = "/meta-data/public-hostname";
    let public_hostname = "test-public-hostname";

    let ep_region = "/dynamic/instance-identity/document";
    let instance_id_doc = "{\"region\": \"test-region\"}";
    let region = "test-region";

    let mut attributes:HashMap<String, String> = HashMap::new();
    attributes.insert(format!("{}_INSTANCE_ID", ENV_PREFIX), String::from(instance_id));
    attributes.insert(format!("{}_INSTANCE_TYPE", ENV_PREFIX), String::from(instance_type));
    attributes.insert(format!("{}_IPV4_LOCAL", ENV_PREFIX), String::from(ipv4_local));
    attributes.insert(format!("{}_IPV4_PUBLIC", ENV_PREFIX), String::from(ipv4_public));
    attributes.insert(format!("{}_AVAILABILITY_ZONE", ENV_PREFIX), String::from(availability_zone));
    attributes.insert(format!("{}_HOSTNAME", ENV_PREFIX), String::from(hostname));
    attributes.insert(format!("{}_PUBLIC_HOSTNAME", ENV_PREFIX), String::from(public_hostname));
    attributes.insert(format!("{}_REGION", ENV_PREFIX), String::from(region));

    let client = crate::retry::Client::try_new()
        .chain_err(|| "failed to create http client")
        .unwrap()
        .max_attempts(1)
        .return_on_404(true);
    let provider = aws::AwsProvider { client };

    let _m = mockito::mock("GET", ep_instance_id)
        .with_status(200)
        .with_body(instance_id)
        .create();
    let _m = mockito::mock("GET", ep_instance_type)
        .with_status(200)
        .with_body(instance_type)
        .create();
    let _m = mockito::mock("GET", ep_ipv4_local)
        .with_status(200)
        .with_body(ipv4_local)
        .create();
    let _m = mockito::mock("GET", ep_ipv4_public)
        .with_status(200)
        .with_body(ipv4_public)
        .create();
    let _m = mockito::mock("GET", ep_availability_zone)
        .with_status(200)
        .with_body(availability_zone)
        .create();
    let _m = mockito::mock("GET", ep_hostname)
        .with_status(200)
        .with_body(hostname)
        .create();
    let _m = mockito::mock("GET", ep_public_hostname)
        .with_status(200)
        .with_body(public_hostname)
        .create();
    let _m = mockito::mock("GET", ep_region)
        .with_status(200)
        .with_body(instance_id_doc)
        .create();

    let v = provider.attributes().unwrap();

    assert_eq!(v, attributes);
}<|endoftext|>


<commit_before>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

#![forbid(unsafe_code)]

use chrono::{
    prelude::{SecondsFormat, Utc},
    DateTime,
};
use cli::{
    client_proxy::ClientProxy,
    commands::{get_commands, parse_cmd, report_error, Command},
};
use libra_types::{chain_id::ChainId, waypoint::Waypoint};
use rustyline::{config::CompletionType, error::ReadlineError, Config, Editor};
use std::{
    str::FromStr,
    time::{Duration, UNIX_EPOCH},
};
use structopt::StructOpt;

#[derive(Debug, StructOpt)]
#[structopt(
    name = "Libra Client",
    author = "The Libra Association",
    about = "Libra client to connect to a specific validator"
)]
struct Args {
    /// Chain ID of the network this client is connecting to
    #[structopt(
        short = "c",
        long,
        help = "\
            Explicitly specify the chain ID of the network the CLI is connecting to: e.g.,
            for mainnet: \"MAINNET\" or 1, testnet: \"TESTNET\" or 2, devnet: \"DEVNET\" or 3, \
            local swarm: \"TESTING\" or 4
            Note: Chain ID of 0 is not allowed
        "
    )]
    pub chain_id: ChainId,
    /// Full URL address to connect to - should include port number, if applicable
    #[structopt(short = "u", long)]
    pub url: String,
    /// Path to the generated keypair for the faucet account. The faucet account can be used to
    /// mint coins. If not passed, a new keypair will be generated for
    /// you and placed in a temporary directory.
    /// To manually generate a keypair, use generate-key:
    /// `cargo run -p generate-keypair -- -o <output_file_path>`
    #[structopt(short = "m", long = "faucet-key-file-path")]
    pub faucet_account_file: Option<String>,
    /// Host that operates a faucet service
    /// If not passed, will be derived from host parameter
    #[structopt(short = "f", long)]
    pub faucet_url: Option<String>,
    /// File location from which to load mnemonic word for user account address/key generation.
    /// If not passed, a new mnemonic file will be generated by libra-wallet in the current
    /// directory.
    #[structopt(short = "n", long)]
    pub mnemonic_file: Option<String>,
    /// If set, client will sync with validator during wallet recovery.
    #[structopt(short = "r", long = "sync")]
    pub sync: bool,
    /// If set, a client uses the waypoint parameter for its initial LedgerInfo verification.
    #[structopt(
        name = "waypoint",
        long,
        help = "Explicitly specify the waypoint to use"
    )]
    pub waypoint: Option<Waypoint>,
    #[structopt(
        name = "waypoint_url",
        long,
        help = "URL for a file with the waypoint to use"
    )]
    pub waypoint_url: Option<String>,
    /// Verbose output.
    #[structopt(short = "v", long = "verbose")]
    pub verbose: bool,
}

fn main() {
    ::libra_logger::Logger::new().init();
    crash_handler::setup_panic_handler();
    let args = Args::from_args();

    if !args.verbose {
        ::libra_logger::Logger::new()
            .level(::libra_logger::Level::Warn)
            .init();
    }

    let (commands, alias_to_cmd) = get_commands(args.faucet_account_file.is_some());

    let faucet_account_file = args
        .faucet_account_file
        .clone()
        .unwrap_or_else(|| "".to_string());
    // Faucet, TreasuryCompliance and DD use the same keypair for now
    let treasury_compliance_account_file = faucet_account_file.clone();
    let dd_account_file = faucet_account_file.clone();
    let mnemonic_file = args.mnemonic_file.clone();

    // If waypoint is given explicitly, use its value,
    // otherwise waypoint_url is required, try to retrieve the waypoint from the URL.
    let waypoint = args.waypoint.unwrap_or_else(|| {
        args.waypoint_url
            .as_ref()
            .map(|url_str| {
                retrieve_waypoint(url_str.as_str()).unwrap_or_else(|e| {
                    panic!("Failure to retrieve a waypoint from {}: {}", url_str, e)
                })
            })
            .unwrap()
    });
    let mut client_proxy = ClientProxy::new(
        args.chain_id,
        &args.url,
        &faucet_account_file,
        &treasury_compliance_account_file,
        &dd_account_file,
        args.sync,
        args.faucet_url.clone(),
        mnemonic_file,
        waypoint,
    )
    .expect("Failed to construct client.");

    // Test connection to validator
    let block_metadata = client_proxy
        .test_validator_connection()
        .unwrap_or_else(|e| {
            panic!(
                "Not able to connect to validator at {}. Error: {}",
                args.url, e,
            )
        });
    let ledger_info_str = format!(
        "latest version = {}, timestamp = {}",
        block_metadata.version,
        DateTime::<Utc>::from(UNIX_EPOCH + Duration::from_micros(block_metadata.timestamp))
    );
    let cli_info = format!(
        "Connected to validator at: {}, {}",
        args.url, ledger_info_str
    );
    if args.mnemonic_file.is_some() {
        match client_proxy.recover_accounts_in_wallet() {
            Ok(account_data) => {
                println!(
                    "Wallet recovered and the first {} child accounts were derived",
                    account_data.len()
                );
                for data in account_data {
                    println!("#{} address {}", data.index, hex::encode(data.address));
                }
            }
            Err(e) => report_error("Error recovering Libra wallet", e),
        }
    }
    print_help(&cli_info, &commands);
    println!("Please, input commands: \n");

    let config = Config::builder()
        .history_ignore_space(true)
        .completion_type(CompletionType::List)
        .auto_add_history(true)
        .build();
    let mut rl = Editor::<()>::with_config(config);
    loop {
        let readline = rl.readline("libra% ");
        match readline {
            Ok(line) => {
                let params = parse_cmd(&line);
                if params.is_empty() {
                    continue;
                }
                match alias_to_cmd.get(&params[0]) {
                    Some(cmd) => {
                        if args.verbose {
                            println!("{}", Utc::now().to_rfc3339_opts(SecondsFormat::Secs, true));
                        }
                        cmd.execute(&mut client_proxy, &params);
                    }
                    None => match params[0] {
                        "quit" | "q!" => break,
                        "help" | "h" => print_help(&cli_info, &commands),
                        "" => continue,
                        x => println!("Unknown command: {:?}", x),
                    },
                }
            }
            Err(ReadlineError::Interrupted) => {
                println!("CTRL-C");
                break;
            }
            Err(ReadlineError::Eof) => {
                println!("CTRL-D");
                break;
            }
            Err(err) => {
                println!("Error: {:?}", err);
                break;
            }
        }
    }
}

/// Print the help message for the client and underlying command.
fn print_help(client_info: &str, commands: &[std::sync::Arc<dyn Command>]) {
    println!("{}", client_info);
    println!("usage: <command> <args>\n\nUse the following commands:\n");
    for cmd in commands {
        println!(
            "{} {}\n\t{}",
            cmd.get_aliases().join(" | "),
            cmd.get_params_help(),
            cmd.get_description()
        );
    }

    println!("help | h \n\tPrints this help");
    println!("quit | q! \n\tExit this client");
    println!("\n");
}

/// Retrieve a waypoint given the URL.
fn retrieve_waypoint(url_str: &str) -> anyhow::Result<Waypoint> {
    let client = reqwest::blocking::ClientBuilder::new().build()?;
    let response = client.get(url_str).send()?;

    Ok(response
        .error_for_status()
        .map_err(|_| anyhow::format_err!("Failed to retrieve waypoint from URL {}", url_str))?
        .text()
        .map(|r| Waypoint::from_str(r.trim()))??)
}
<commit_msg>cli: don't init the logger twice<commit_after>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

#![forbid(unsafe_code)]

use chrono::{
    prelude::{SecondsFormat, Utc},
    DateTime,
};
use cli::{
    client_proxy::ClientProxy,
    commands::{get_commands, parse_cmd, report_error, Command},
};
use libra_types::{chain_id::ChainId, waypoint::Waypoint};
use rustyline::{config::CompletionType, error::ReadlineError, Config, Editor};
use std::{
    str::FromStr,
    time::{Duration, UNIX_EPOCH},
};
use structopt::StructOpt;

#[derive(Debug, StructOpt)]
#[structopt(
    name = "Libra Client",
    author = "The Libra Association",
    about = "Libra client to connect to a specific validator"
)]
struct Args {
    /// Chain ID of the network this client is connecting to
    #[structopt(
        short = "c",
        long,
        help = "\
            Explicitly specify the chain ID of the network the CLI is connecting to: e.g.,
            for mainnet: \"MAINNET\" or 1, testnet: \"TESTNET\" or 2, devnet: \"DEVNET\" or 3, \
            local swarm: \"TESTING\" or 4
            Note: Chain ID of 0 is not allowed
        "
    )]
    pub chain_id: ChainId,
    /// Full URL address to connect to - should include port number, if applicable
    #[structopt(short = "u", long)]
    pub url: String,
    /// Path to the generated keypair for the faucet account. The faucet account can be used to
    /// mint coins. If not passed, a new keypair will be generated for
    /// you and placed in a temporary directory.
    /// To manually generate a keypair, use generate-key:
    /// `cargo run -p generate-keypair -- -o <output_file_path>`
    #[structopt(short = "m", long = "faucet-key-file-path")]
    pub faucet_account_file: Option<String>,
    /// Host that operates a faucet service
    /// If not passed, will be derived from host parameter
    #[structopt(short = "f", long)]
    pub faucet_url: Option<String>,
    /// File location from which to load mnemonic word for user account address/key generation.
    /// If not passed, a new mnemonic file will be generated by libra-wallet in the current
    /// directory.
    #[structopt(short = "n", long)]
    pub mnemonic_file: Option<String>,
    /// If set, client will sync with validator during wallet recovery.
    #[structopt(short = "r", long = "sync")]
    pub sync: bool,
    /// If set, a client uses the waypoint parameter for its initial LedgerInfo verification.
    #[structopt(
        name = "waypoint",
        long,
        help = "Explicitly specify the waypoint to use"
    )]
    pub waypoint: Option<Waypoint>,
    #[structopt(
        name = "waypoint_url",
        long,
        help = "URL for a file with the waypoint to use"
    )]
    pub waypoint_url: Option<String>,
    /// Verbose output.
    #[structopt(short = "v", long = "verbose")]
    pub verbose: bool,
}

fn main() {
    ::libra_logger::Logger::new().init();
    crash_handler::setup_panic_handler();
    let args = Args::from_args();

    let mut logger = ::libra_logger::Logger::new();

    if !args.verbose {
        logger.level(::libra_logger::Level::Warn);
    }
    logger.init();

    let (commands, alias_to_cmd) = get_commands(args.faucet_account_file.is_some());

    let faucet_account_file = args
        .faucet_account_file
        .clone()
        .unwrap_or_else(|| "".to_string());
    // Faucet, TreasuryCompliance and DD use the same keypair for now
    let treasury_compliance_account_file = faucet_account_file.clone();
    let dd_account_file = faucet_account_file.clone();
    let mnemonic_file = args.mnemonic_file.clone();

    // If waypoint is given explicitly, use its value,
    // otherwise waypoint_url is required, try to retrieve the waypoint from the URL.
    let waypoint = args.waypoint.unwrap_or_else(|| {
        args.waypoint_url
            .as_ref()
            .map(|url_str| {
                retrieve_waypoint(url_str.as_str()).unwrap_or_else(|e| {
                    panic!("Failure to retrieve a waypoint from {}: {}", url_str, e)
                })
            })
            .unwrap()
    });
    let mut client_proxy = ClientProxy::new(
        args.chain_id,
        &args.url,
        &faucet_account_file,
        &treasury_compliance_account_file,
        &dd_account_file,
        args.sync,
        args.faucet_url.clone(),
        mnemonic_file,
        waypoint,
    )
    .expect("Failed to construct client.");

    // Test connection to validator
    let block_metadata = client_proxy
        .test_validator_connection()
        .unwrap_or_else(|e| {
            panic!(
                "Not able to connect to validator at {}. Error: {}",
                args.url, e,
            )
        });
    let ledger_info_str = format!(
        "latest version = {}, timestamp = {}",
        block_metadata.version,
        DateTime::<Utc>::from(UNIX_EPOCH + Duration::from_micros(block_metadata.timestamp))
    );
    let cli_info = format!(
        "Connected to validator at: {}, {}",
        args.url, ledger_info_str
    );
    if args.mnemonic_file.is_some() {
        match client_proxy.recover_accounts_in_wallet() {
            Ok(account_data) => {
                println!(
                    "Wallet recovered and the first {} child accounts were derived",
                    account_data.len()
                );
                for data in account_data {
                    println!("#{} address {}", data.index, hex::encode(data.address));
                }
            }
            Err(e) => report_error("Error recovering Libra wallet", e),
        }
    }
    print_help(&cli_info, &commands);
    println!("Please, input commands: \n");

    let config = Config::builder()
        .history_ignore_space(true)
        .completion_type(CompletionType::List)
        .auto_add_history(true)
        .build();
    let mut rl = Editor::<()>::with_config(config);
    loop {
        let readline = rl.readline("libra% ");
        match readline {
            Ok(line) => {
                let params = parse_cmd(&line);
                if params.is_empty() {
                    continue;
                }
                match alias_to_cmd.get(&params[0]) {
                    Some(cmd) => {
                        if args.verbose {
                            println!("{}", Utc::now().to_rfc3339_opts(SecondsFormat::Secs, true));
                        }
                        cmd.execute(&mut client_proxy, &params);
                    }
                    None => match params[0] {
                        "quit" | "q!" => break,
                        "help" | "h" => print_help(&cli_info, &commands),
                        "" => continue,
                        x => println!("Unknown command: {:?}", x),
                    },
                }
            }
            Err(ReadlineError::Interrupted) => {
                println!("CTRL-C");
                break;
            }
            Err(ReadlineError::Eof) => {
                println!("CTRL-D");
                break;
            }
            Err(err) => {
                println!("Error: {:?}", err);
                break;
            }
        }
    }
}

/// Print the help message for the client and underlying command.
fn print_help(client_info: &str, commands: &[std::sync::Arc<dyn Command>]) {
    println!("{}", client_info);
    println!("usage: <command> <args>\n\nUse the following commands:\n");
    for cmd in commands {
        println!(
            "{} {}\n\t{}",
            cmd.get_aliases().join(" | "),
            cmd.get_params_help(),
            cmd.get_description()
        );
    }

    println!("help | h \n\tPrints this help");
    println!("quit | q! \n\tExit this client");
    println!("\n");
}

/// Retrieve a waypoint given the URL.
fn retrieve_waypoint(url_str: &str) -> anyhow::Result<Waypoint> {
    let client = reqwest::blocking::ClientBuilder::new().build()?;
    let response = client.get(url_str).send()?;

    Ok(response
        .error_for_status()
        .map_err(|_| anyhow::format_err!("Failed to retrieve waypoint from URL {}", url_str))?
        .text()
        .map(|r| Waypoint::from_str(r.trim()))??)
}
<|endoftext|>


<commit_before>//! Extension traits for `Stream` implementing various operators.
//!
//! A collection of functions taking typed `Stream` objects as input and producing new `Stream`
//! objects as output. Many of the operators provide simple, composable functionality. Some of the
//! operators are more complicated, for use with advanced timely dataflow features.
//!
//! The [`Unary`](./unary/index.html) and [`Binary`](./binary/index.html) operators provide general
//! operators whose behavior can be supplied using closures accepting input and output handles.
//! Most of the operators in this module are defined using these two general operators.

pub use self::enterleave::{Enter, EnterAt, Leave};
pub use self::unary::Unary;
// pub use self::queue::*;
pub use self::input::Input;
pub use self::feedback::{LoopVariable, ConnectLoop};
pub use self::concat::{Concat, Concatenate};
pub use self::partition::Partition;
pub use self::map::Map;
pub use self::inspect::Inspect;
pub use self::filter::Filter;
pub use self::binary::Binary;
pub use self::delay::Delay;
pub use self::exchange::Exchange as ExchangeExtension;
pub use self::broadcast::Broadcast;
pub use self::probe::Probe;
pub use self::to_stream::ToStream;
pub use self::capture::Capture;

pub use self::reclock::Reclock;

pub mod enterleave;
pub mod unary;
// pub mod queue;
pub mod input;
pub mod feedback;
pub mod concat;
pub mod partition;
pub mod map;
pub mod inspect;
pub mod filter;
pub mod binary;
pub mod delay;
pub mod exchange;
pub mod broadcast;
pub mod probe;
pub mod to_stream;
pub mod capture;

pub mod aggregation;

pub mod reclock;

// keep the handle constructors private
mod handles;
pub use self::handles::{InputHandle, OutputHandle};

mod notificator;
pub use self::notificator::Notificator;

// keep "mint" module-private
mod capability;
pub use self::capability::Capability;
<commit_msg>added count operator for diagnostics<commit_after>//! Extension traits for `Stream` implementing various operators.
//!
//! A collection of functions taking typed `Stream` objects as input and producing new `Stream`
//! objects as output. Many of the operators provide simple, composable functionality. Some of the
//! operators are more complicated, for use with advanced timely dataflow features.
//!
//! The [`Unary`](./unary/index.html) and [`Binary`](./binary/index.html) operators provide general
//! operators whose behavior can be supplied using closures accepting input and output handles.
//! Most of the operators in this module are defined using these two general operators.

pub use self::enterleave::{Enter, EnterAt, Leave};
pub use self::unary::Unary;
// pub use self::queue::*;
pub use self::input::Input;
pub use self::feedback::{LoopVariable, ConnectLoop};
pub use self::concat::{Concat, Concatenate};
pub use self::partition::Partition;
pub use self::map::Map;
pub use self::inspect::Inspect;
pub use self::filter::Filter;
pub use self::binary::Binary;
pub use self::delay::Delay;
pub use self::exchange::Exchange as ExchangeExtension;
pub use self::broadcast::Broadcast;
pub use self::probe::Probe;
pub use self::to_stream::ToStream;
pub use self::capture::Capture;

pub use self::reclock::Reclock;
pub use self::count::Count;

pub mod enterleave;
pub mod unary;
// pub mod queue;
pub mod input;
pub mod feedback;
pub mod concat;
pub mod partition;
pub mod map;
pub mod inspect;
pub mod filter;
pub mod binary;
pub mod delay;
pub mod exchange;
pub mod broadcast;
pub mod probe;
pub mod to_stream;
pub mod capture;

pub mod aggregation;

pub mod reclock;
pub mod count;

// keep the handle constructors private
mod handles;
pub use self::handles::{InputHandle, OutputHandle};

mod notificator;
pub use self::notificator::Notificator;

// keep "mint" module-private
mod capability;
pub use self::capability::Capability;
<|endoftext|>


<commit_before>use std::fs::File;
use std::env;
use std::io::BufReader;
use std::io::BufRead;
use std::io::Write;
use std::collections::HashMap;
use std::collections::BTreeMap;
use std::collections::BTreeSet;

extern crate tools;
use tools::find_source_file;
use tools::file_format::analysis::{read_analysis, read_target, AnalysisKind};
use tools::config;

extern crate rustc_serialize;
use rustc_serialize::json::{Json, ToJson};

#[derive(Debug, RustcEncodable, RustcDecodable)]
struct SearchResult {
    lineno: u32,
    bounds: (u32, u32),
    line: String,
    context: String,
    contextsym: String,
}

impl ToJson for SearchResult {
    fn to_json(&self) -> Json {
        let (st, en) = self.bounds;
        let bounds = vec![st, en];

        let mut obj = BTreeMap::new();
        obj.insert("lno".to_string(), self.lineno.to_json());
        obj.insert("bounds".to_string(), bounds.to_json());
        obj.insert("line".to_string(), self.line.to_json());
        obj.insert("context".to_string(), self.context.to_json());
        obj.insert("contextsym".to_string(), self.contextsym.to_json());
        Json::Object(obj)
    }
}

fn split_scopes(id: &str) -> Vec<String> {
    let mut result = Vec::new();
    let mut start = 0;
    let mut argument_nesting = 0;
    for (index, m) in id.match_indices(|c| c == ':' || c == '<' || c == '>') {
        if m == ":" && argument_nesting == 0 {
            if start != index {
                result.push(id[start .. index].to_owned());
                start = index + 1;
            } else {
                start = index + 1;
            }
        } else if m == "<" {
            argument_nesting += 1;
        } else if m == ">" {
            argument_nesting -= 1;
        }
    }
    result.push(id[start ..].to_owned());
    return result;
}

fn main() {
    let args: Vec<_> = env::args().collect();

    let cfg = config::load(&args[1], false);

    let tree_name = &args[2];
    let tree_config = cfg.trees.get(tree_name).unwrap();

    let filenames_file = &args[3];

    let output_file = format!("{}/crossref", tree_config.paths.index_path);
    let jump_file = format!("{}/jumps", tree_config.paths.index_path);
    let id_file = format!("{}/identifiers", tree_config.paths.index_path);

    let mut table = HashMap::new();
    let mut pretty_table = HashMap::new();
    let mut id_table = HashMap::new();
    let mut jumps = Vec::new();

    {
        let mut process_file = |path: &str| {
            print!("File {}\n", path);

            let analysis_fname = format!("{}/analysis/{}", tree_config.paths.index_path, path);
            let analysis = read_analysis(&analysis_fname, &read_target);

            let source_fname = find_source_file(path, &tree_config.paths.files_path, &tree_config.paths.objdir_path);
            let source_file = match File::open(source_fname) {
                Ok(f) => f,
                Err(_) => {
                    println!("Unable to open source file");
                    return;
                },
            };
            let reader = BufReader::new(&source_file);
            let mut lines = Vec::new();
            for line in reader.lines() {
                match line {
                    Ok(l) => lines.push(l),
                    Err(_) => lines.push("".to_string()),
                }
            }

            for datum in analysis {
                for piece in datum.data {
                    let t1 = table.entry(piece.sym.to_owned()).or_insert(BTreeMap::new());
                    let t2 = t1.entry(piece.kind).or_insert(BTreeMap::new());
                    let t3 = t2.entry(path.to_owned()).or_insert(Vec::new());
                    let lineno = (datum.loc.lineno - 1) as usize;
                    if lineno >= lines.len() {
                        print!("Bad line number in file {} (line {})\n", path, lineno);
                        return;
                    }
                    let line = lines[lineno].clone();
                    let line_cut = line.trim_right();
                    let len = line_cut.len();
                    let line_cut = line_cut.trim_left();
                    let offset = (len - line_cut.len()) as u32;
                    let mut buf = String::new();
                    let mut i = 0;
                    for c in line_cut.chars() {
                        buf.push(c);
                        i += 1;
                        if i > 100 {
                            break;
                        }
                    }
                    t3.push(SearchResult {
                        lineno: datum.loc.lineno,
                        bounds: (datum.loc.col_start - offset, datum.loc.col_end - offset),
                        line: buf,
                        context: piece.context,
                        contextsym: piece.contextsym,
                    });

                    pretty_table.insert(piece.sym.to_owned(), piece.pretty.to_owned());

                    let ch = piece.sym.chars().nth(0).unwrap();
                    if !(ch >= '0' && ch <= '9') && !piece.sym.contains(' ') {
                        let t1 = id_table.entry(piece.pretty.to_owned()).or_insert(BTreeSet::new());
                        t1.insert(piece.sym.to_owned());
                    }
                }
            }
        };

        let f = File::open(filenames_file).unwrap();
        let file = BufReader::new(&f);
        for line in file.lines() {
            process_file(&line.unwrap());
        }
    }

    let mut outputf = File::create(output_file).unwrap();

    for (id, id_data) in table {
        let mut kindmap = BTreeMap::new();
        for (kind, kind_data) in &id_data {
            let mut result = Vec::new();
            for (path, results) in kind_data {
                let mut obj = BTreeMap::new();
                obj.insert("path".to_string(), path.to_json());
                obj.insert("lines".to_string(), results.to_json());
                result.push(Json::Object(obj));
            }
            let kindstr = match *kind {
                AnalysisKind::Use => "Uses",
                AnalysisKind::Def => "Definitions",
                AnalysisKind::Assign => "Assignments",
                AnalysisKind::Decl => "Declarations",
                AnalysisKind::Idl => "IDL",
            };
            kindmap.insert(kindstr.to_string(), Json::Array(result));
        }
        let kindmap = Json::Object(kindmap);

        let _ = outputf.write_all(format!("{}\n{}\n", id, kindmap.to_string()).as_bytes());

        if id_data.contains_key(&AnalysisKind::Def) {
            let defs = id_data.get(&AnalysisKind::Def).unwrap();
            if defs.len() == 1 {
                for (path, results) in defs {
                    if results.len() == 1 {
                        let mut v = Vec::new();
                        v.push(id.to_json());
                        v.push(path.to_json());
                        v.push(results[0].lineno.to_json());
                        let pretty = pretty_table.get(&id).unwrap();
                        v.push(pretty.to_json());
                        jumps.push(Json::Array(v));
                    }
                }
            }
        }
    }

    let mut jumpf = File::create(jump_file).unwrap();
    for jump in jumps {
        let _ = jumpf.write_all((jump.to_string() + "\n").as_bytes());
    }

    let mut idf = File::create(id_file).unwrap();
    for (id, syms) in id_table {
        for sym in syms {
            let components = split_scopes(&id);
            for i in 0..components.len() {
                let sub = &components[i..components.len()];
                let sub = sub.join("::");

                if !sub.is_empty() {
                    let line = format!("{} {}\n", sub, sym);
                    let _ = idf.write_all(line.as_bytes());
                }
            }
        }
    }
}
<commit_msg>Bug 1416485 - Remove unused derive in crossref.rs.<commit_after>use std::fs::File;
use std::env;
use std::io::BufReader;
use std::io::BufRead;
use std::io::Write;
use std::collections::HashMap;
use std::collections::BTreeMap;
use std::collections::BTreeSet;

extern crate tools;
use tools::find_source_file;
use tools::file_format::analysis::{read_analysis, read_target, AnalysisKind};
use tools::config;

extern crate rustc_serialize;
use rustc_serialize::json::{Json, ToJson};

#[derive(Debug)]
struct SearchResult {
    lineno: u32,
    bounds: (u32, u32),
    line: String,
    context: String,
    contextsym: String,
}

impl ToJson for SearchResult {
    fn to_json(&self) -> Json {
        let (st, en) = self.bounds;
        let bounds = vec![st, en];

        let mut obj = BTreeMap::new();
        obj.insert("lno".to_string(), self.lineno.to_json());
        obj.insert("bounds".to_string(), bounds.to_json());
        obj.insert("line".to_string(), self.line.to_json());
        obj.insert("context".to_string(), self.context.to_json());
        obj.insert("contextsym".to_string(), self.contextsym.to_json());
        Json::Object(obj)
    }
}

fn split_scopes(id: &str) -> Vec<String> {
    let mut result = Vec::new();
    let mut start = 0;
    let mut argument_nesting = 0;
    for (index, m) in id.match_indices(|c| c == ':' || c == '<' || c == '>') {
        if m == ":" && argument_nesting == 0 {
            if start != index {
                result.push(id[start .. index].to_owned());
                start = index + 1;
            } else {
                start = index + 1;
            }
        } else if m == "<" {
            argument_nesting += 1;
        } else if m == ">" {
            argument_nesting -= 1;
        }
    }
    result.push(id[start ..].to_owned());
    return result;
}

fn main() {
    let args: Vec<_> = env::args().collect();

    let cfg = config::load(&args[1], false);

    let tree_name = &args[2];
    let tree_config = cfg.trees.get(tree_name).unwrap();

    let filenames_file = &args[3];

    let output_file = format!("{}/crossref", tree_config.paths.index_path);
    let jump_file = format!("{}/jumps", tree_config.paths.index_path);
    let id_file = format!("{}/identifiers", tree_config.paths.index_path);

    let mut table = HashMap::new();
    let mut pretty_table = HashMap::new();
    let mut id_table = HashMap::new();
    let mut jumps = Vec::new();

    {
        let mut process_file = |path: &str| {
            print!("File {}\n", path);

            let analysis_fname = format!("{}/analysis/{}", tree_config.paths.index_path, path);
            let analysis = read_analysis(&analysis_fname, &read_target);

            let source_fname = find_source_file(path, &tree_config.paths.files_path, &tree_config.paths.objdir_path);
            let source_file = match File::open(source_fname) {
                Ok(f) => f,
                Err(_) => {
                    println!("Unable to open source file");
                    return;
                },
            };
            let reader = BufReader::new(&source_file);
            let mut lines = Vec::new();
            for line in reader.lines() {
                match line {
                    Ok(l) => lines.push(l),
                    Err(_) => lines.push("".to_string()),
                }
            }

            for datum in analysis {
                for piece in datum.data {
                    let t1 = table.entry(piece.sym.to_owned()).or_insert(BTreeMap::new());
                    let t2 = t1.entry(piece.kind).or_insert(BTreeMap::new());
                    let t3 = t2.entry(path.to_owned()).or_insert(Vec::new());
                    let lineno = (datum.loc.lineno - 1) as usize;
                    if lineno >= lines.len() {
                        print!("Bad line number in file {} (line {})\n", path, lineno);
                        return;
                    }
                    let line = lines[lineno].clone();
                    let line_cut = line.trim_right();
                    let len = line_cut.len();
                    let line_cut = line_cut.trim_left();
                    let offset = (len - line_cut.len()) as u32;
                    let mut buf = String::new();
                    let mut i = 0;
                    for c in line_cut.chars() {
                        buf.push(c);
                        i += 1;
                        if i > 100 {
                            break;
                        }
                    }
                    t3.push(SearchResult {
                        lineno: datum.loc.lineno,
                        bounds: (datum.loc.col_start - offset, datum.loc.col_end - offset),
                        line: buf,
                        context: piece.context,
                        contextsym: piece.contextsym,
                    });

                    pretty_table.insert(piece.sym.to_owned(), piece.pretty.to_owned());

                    let ch = piece.sym.chars().nth(0).unwrap();
                    if !(ch >= '0' && ch <= '9') && !piece.sym.contains(' ') {
                        let t1 = id_table.entry(piece.pretty.to_owned()).or_insert(BTreeSet::new());
                        t1.insert(piece.sym.to_owned());
                    }
                }
            }
        };

        let f = File::open(filenames_file).unwrap();
        let file = BufReader::new(&f);
        for line in file.lines() {
            process_file(&line.unwrap());
        }
    }

    let mut outputf = File::create(output_file).unwrap();

    for (id, id_data) in table {
        let mut kindmap = BTreeMap::new();
        for (kind, kind_data) in &id_data {
            let mut result = Vec::new();
            for (path, results) in kind_data {
                let mut obj = BTreeMap::new();
                obj.insert("path".to_string(), path.to_json());
                obj.insert("lines".to_string(), results.to_json());
                result.push(Json::Object(obj));
            }
            let kindstr = match *kind {
                AnalysisKind::Use => "Uses",
                AnalysisKind::Def => "Definitions",
                AnalysisKind::Assign => "Assignments",
                AnalysisKind::Decl => "Declarations",
                AnalysisKind::Idl => "IDL",
            };
            kindmap.insert(kindstr.to_string(), Json::Array(result));
        }
        let kindmap = Json::Object(kindmap);

        let _ = outputf.write_all(format!("{}\n{}\n", id, kindmap.to_string()).as_bytes());

        if id_data.contains_key(&AnalysisKind::Def) {
            let defs = id_data.get(&AnalysisKind::Def).unwrap();
            if defs.len() == 1 {
                for (path, results) in defs {
                    if results.len() == 1 {
                        let mut v = Vec::new();
                        v.push(id.to_json());
                        v.push(path.to_json());
                        v.push(results[0].lineno.to_json());
                        let pretty = pretty_table.get(&id).unwrap();
                        v.push(pretty.to_json());
                        jumps.push(Json::Array(v));
                    }
                }
            }
        }
    }

    let mut jumpf = File::create(jump_file).unwrap();
    for jump in jumps {
        let _ = jumpf.write_all((jump.to_string() + "\n").as_bytes());
    }

    let mut idf = File::create(id_file).unwrap();
    for (id, syms) in id_table {
        for sym in syms {
            let components = split_scopes(&id);
            for i in 0..components.len() {
                let sub = &components[i..components.len()];
                let sub = sub.join("::");

                if !sub.is_empty() {
                    let line = format!("{} {}\n", sub, sym);
                    let _ = idf.write_all(line.as_bytes());
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>//! Wrappers around a xdg_surface and xdg_shell setup code.

use std::os::unix::io::AsRawFd;
use std::cell::RefCell;
use std::fmt;

use wayland_client::{Proxy, NewProxy};
use wayland_client::protocol::wl_surface::{WlSurface,
                                           RequestsTrait as WlSurfaceTrait};
use wayland_protocols::xdg_shell::{xdg_wm_base::{XdgWmBase,
                                                 RequestsTrait as XdgWmBaseTrait},
                                   xdg_toplevel::{self,
                                                  RequestsTrait as XdgToplevelTrait},
                                   xdg_surface::{self,
                                                 XdgSurface,
                                                 RequestsTrait as XdgSurfaceTrait}};
use wayland_client::protocol::wl_buffer::WlBuffer;
use wlroots::{Area, Origin, Size};

use wayland_obj;

/// The minimum version of the xdg_wm_base global to bind to.
pub const XDG_WM_BASE_VERSION: u32 = 2;

thread_local! {
    /// The XDG surface creator.
    ///
    /// This should remain local to just this module.
    static XDG_SHELL_CREATOR: RefCell<Option<Proxy<XdgWmBase>>> = RefCell::new(None);
}

/// A wrapper around `xdg_toplevel::Xdgtoplevel` that keeps track of the changes to the
/// internal state of the `xdg_toplevel`, `xdg_surface, and `wl_surface`.
///
/// This should be used instead of using a xdg_toplevel directly as
/// otherwise you need to roll your own caching scheme.
#[derive(Clone, Eq, PartialEq)]
pub struct XdgToplevel {
    proxy: Proxy<xdg_toplevel::XdgToplevel>
}

/// The cached state for the 'XdgToplevel. Cached state about the `xdg_surface`
/// and the `wl_surface` is also stored in here.
///
/// This needs to be stored as the user data in the `XdgToplevel` so that it
/// can be accessed anywhere.
#[derive(Clone, Eq, PartialEq)]
struct XdgToplevelState {
    // TODO These should have wrappers around the proxies as well,
    // so that their cached state is transparent to this cached state.
    wl_surface: Proxy<WlSurface>,
    xdg_surface: Proxy<XdgSurface>,
    buffer: Option<Proxy<WlBuffer>>,
    size: Size
}

impl XdgToplevel {
    fn new(wl_surface: Proxy<WlSurface>,
           xdg_surface: Proxy<XdgSurface>,
           xdg_proxy: NewProxy<xdg_toplevel::XdgToplevel>) -> Self {
        let proxy = xdg_proxy.implement(|event, proxy: Proxy<xdg_toplevel::XdgToplevel>| {
            use self::xdg_toplevel::Event;
            match event {
                Event::Configure { .. } => {
                    // TODO Fill in
                    let state = unwrap_state(&proxy);
                    state.xdg_surface.set_window_geometry(0, 0, state.size.width, state.size.height);
                },
                Event::Close => {
                    // TODO We should probably do what the compositor wants here.
                }
            }
        });
        wl_surface.commit();
        let cached_state = Box::new(XdgToplevelState { wl_surface,
                                                       xdg_surface,
                                                       buffer: None,
                                                       size: Size::default() });
        proxy.set_user_data(Box::into_raw(cached_state) as _);
        XdgToplevel { proxy }
    }

    pub fn set_size(&self, size: Size) {
        let Size { width, height } = size;
        // TODO Is there ever a need for us to set the x and y?
        unwrap_state(&self.proxy).xdg_surface.set_window_geometry(0, 0, width, height);
    }

    // TODO Better interface than RawFd. T: AsRawFd?
    /// Set the backing storage of the xdg shell surface.
    ///
    /// The contents will not be sent until a wl_surface commit, due to
    /// Wayland surfaces being double buffered.
    pub fn set_surface<FD>(&mut self, fd: &FD, size: Size) -> Result<(), ()>
    where FD: AsRawFd {
        let buffer = wayland_obj::create_buffer(fd.as_raw_fd(), size)?;
        let state = unwrap_state_mut(&mut self.proxy);
        state.wl_surface.attach(Some(&buffer), 0, 0);
        state.size = size;
        state.buffer = Some(buffer);
        Ok(())
    }

    #[allow(dead_code)]
    pub fn commit(&self) {
        unwrap_state(&self.proxy).wl_surface.commit();
    }
}

impl Drop for XdgToplevel {
    fn drop(&mut self) {
        self.proxy.destroy();
        unsafe {
            let user_data = self.proxy.get_user_data() as *mut XdgToplevelState;
            if !user_data.is_null() {
                Box::from_raw(user_data);
            }
        }
    }
}

pub fn xdg_shell_init(new_proxy: Result<NewProxy<XdgWmBase>, u32>, _: ()) {
    let new_proxy = new_proxy.expect("Could not create Xdgsurface");
    let proxy = new_proxy.implement(move |event, proxy: Proxy<XdgWmBase>| {
        use xdg_wm_base::Event;
        match event {
            Event::Ping { serial } => proxy.pong(serial)
        }
    });
    XDG_SHELL_CREATOR.with(|shell_creator| {
        *shell_creator.borrow_mut() = Some(proxy);
    });
}

pub fn create_xdg_toplevel<G>(geometry: G)
                              -> Result<XdgToplevel, ()>
where G: Into<Option<Area>> {
    let surface = wayland_obj::create_surface()?;
    let xdg_surface = create_xdg_surface(&surface)?;
    if let Some(geometry) = geometry.into() {
        let Origin { x, y } = geometry.origin;
        let Size { width, height } = geometry.size;
        xdg_surface.set_window_geometry(x, y, width, height);
    }
    xdg_surface.get_toplevel()
        .map(|toplevel| XdgToplevel::new(surface, xdg_surface, toplevel))
}

fn create_xdg_surface(surface: &Proxy<WlSurface>)
                      -> Result<Proxy<XdgSurface>, ()> {
    XDG_SHELL_CREATOR.with(|shell_creator| {
        let shell_creator = shell_creator.borrow();
        let shell_creator = shell_creator.as_ref()
            .expect("XDG Shell creator not initilized");
        let surface_ = surface.clone();
        shell_creator.get_xdg_surface(surface)
            .map(|new_proxy| new_proxy.implement(move |event, proxy: Proxy<XdgSurface>| {
                use self::xdg_surface::Event;
                match event {
                    Event::Configure { serial } => {
                        proxy.ack_configure(serial);
                        surface_.commit();
                    }
                }
            }))
    })
}

impl fmt::Debug for XdgToplevel {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:?}", self.proxy.c_ptr())
    }
}

fn unwrap_state_mut<'this>(proxy: &'this mut Proxy<xdg_toplevel::XdgToplevel>)
                           -> &'this mut XdgToplevelState {
    unsafe {
        let user_data = proxy.get_user_data() as *mut XdgToplevelState;
        if user_data.is_null() {
            panic!("User data has not been set yet");
        }
        &mut *user_data
    }
}

fn unwrap_state<'this>(proxy: &'this Proxy<xdg_toplevel::XdgToplevel>)
                           -> &'this XdgToplevelState {
    unsafe {
        let user_data = proxy.get_user_data() as *const XdgToplevelState;
        if user_data.is_null() {
            panic!("User data has not been set yet");
        }
        &*user_data
    }
}
<commit_msg>Removed todo<commit_after>//! Wrappers around a xdg_surface and xdg_shell setup code.

use std::os::unix::io::AsRawFd;
use std::cell::RefCell;
use std::fmt;

use wayland_client::{Proxy, NewProxy};
use wayland_client::protocol::wl_surface::{WlSurface,
                                           RequestsTrait as WlSurfaceTrait};
use wayland_protocols::xdg_shell::{xdg_wm_base::{XdgWmBase,
                                                 RequestsTrait as XdgWmBaseTrait},
                                   xdg_toplevel::{self,
                                                  RequestsTrait as XdgToplevelTrait},
                                   xdg_surface::{self,
                                                 XdgSurface,
                                                 RequestsTrait as XdgSurfaceTrait}};
use wayland_client::protocol::wl_buffer::WlBuffer;
use wlroots::{Area, Origin, Size};

use wayland_obj;

/// The minimum version of the xdg_wm_base global to bind to.
pub const XDG_WM_BASE_VERSION: u32 = 2;

thread_local! {
    /// The XDG surface creator.
    ///
    /// This should remain local to just this module.
    static XDG_SHELL_CREATOR: RefCell<Option<Proxy<XdgWmBase>>> = RefCell::new(None);
}

/// A wrapper around `xdg_toplevel::Xdgtoplevel` that keeps track of the changes to the
/// internal state of the `xdg_toplevel`, `xdg_surface, and `wl_surface`.
///
/// This should be used instead of using a xdg_toplevel directly as
/// otherwise you need to roll your own caching scheme.
#[derive(Clone, Eq, PartialEq)]
pub struct XdgToplevel {
    proxy: Proxy<xdg_toplevel::XdgToplevel>
}

/// The cached state for the 'XdgToplevel. Cached state about the `xdg_surface`
/// and the `wl_surface` is also stored in here.
///
/// This needs to be stored as the user data in the `XdgToplevel` so that it
/// can be accessed anywhere.
#[derive(Clone, Eq, PartialEq)]
struct XdgToplevelState {
    // TODO These should have wrappers around the proxies as well,
    // so that their cached state is transparent to this cached state.
    wl_surface: Proxy<WlSurface>,
    xdg_surface: Proxy<XdgSurface>,
    buffer: Option<Proxy<WlBuffer>>,
    size: Size
}

impl XdgToplevel {
    fn new(wl_surface: Proxy<WlSurface>,
           xdg_surface: Proxy<XdgSurface>,
           xdg_proxy: NewProxy<xdg_toplevel::XdgToplevel>) -> Self {
        let proxy = xdg_proxy.implement(|event, proxy: Proxy<xdg_toplevel::XdgToplevel>| {
            use self::xdg_toplevel::Event;
            match event {
                Event::Configure { .. } => {
                    // TODO Fill in
                    let state = unwrap_state(&proxy);
                    state.xdg_surface.set_window_geometry(0, 0, state.size.width, state.size.height);
                },
                Event::Close => {
                    // TODO We should probably do what the compositor wants here.
                }
            }
        });
        wl_surface.commit();
        let cached_state = Box::new(XdgToplevelState { wl_surface,
                                                       xdg_surface,
                                                       buffer: None,
                                                       size: Size::default() });
        proxy.set_user_data(Box::into_raw(cached_state) as _);
        XdgToplevel { proxy }
    }

    pub fn set_size(&self, size: Size) {
        let Size { width, height } = size;
        // TODO Is there ever a need for us to set the x and y?
        unwrap_state(&self.proxy).xdg_surface.set_window_geometry(0, 0, width, height);
    }

    /// Set the backing storage of the xdg shell surface.
    ///
    /// The contents will not be sent until a wl_surface commit, due to
    /// Wayland surfaces being double buffered.
    pub fn set_surface<FD>(&mut self, fd: &FD, size: Size) -> Result<(), ()>
    where FD: AsRawFd {
        let buffer = wayland_obj::create_buffer(fd.as_raw_fd(), size)?;
        let state = unwrap_state_mut(&mut self.proxy);
        state.wl_surface.attach(Some(&buffer), 0, 0);
        state.size = size;
        state.buffer = Some(buffer);
        Ok(())
    }

    #[allow(dead_code)]
    pub fn commit(&self) {
        unwrap_state(&self.proxy).wl_surface.commit();
    }
}

impl Drop for XdgToplevel {
    fn drop(&mut self) {
        self.proxy.destroy();
        unsafe {
            let user_data = self.proxy.get_user_data() as *mut XdgToplevelState;
            if !user_data.is_null() {
                Box::from_raw(user_data);
            }
        }
    }
}

pub fn xdg_shell_init(new_proxy: Result<NewProxy<XdgWmBase>, u32>, _: ()) {
    let new_proxy = new_proxy.expect("Could not create Xdgsurface");
    let proxy = new_proxy.implement(move |event, proxy: Proxy<XdgWmBase>| {
        use xdg_wm_base::Event;
        match event {
            Event::Ping { serial } => proxy.pong(serial)
        }
    });
    XDG_SHELL_CREATOR.with(|shell_creator| {
        *shell_creator.borrow_mut() = Some(proxy);
    });
}

pub fn create_xdg_toplevel<G>(geometry: G)
                              -> Result<XdgToplevel, ()>
where G: Into<Option<Area>> {
    let surface = wayland_obj::create_surface()?;
    let xdg_surface = create_xdg_surface(&surface)?;
    if let Some(geometry) = geometry.into() {
        let Origin { x, y } = geometry.origin;
        let Size { width, height } = geometry.size;
        xdg_surface.set_window_geometry(x, y, width, height);
    }
    xdg_surface.get_toplevel()
        .map(|toplevel| XdgToplevel::new(surface, xdg_surface, toplevel))
}

fn create_xdg_surface(surface: &Proxy<WlSurface>)
                      -> Result<Proxy<XdgSurface>, ()> {
    XDG_SHELL_CREATOR.with(|shell_creator| {
        let shell_creator = shell_creator.borrow();
        let shell_creator = shell_creator.as_ref()
            .expect("XDG Shell creator not initilized");
        let surface_ = surface.clone();
        shell_creator.get_xdg_surface(surface)
            .map(|new_proxy| new_proxy.implement(move |event, proxy: Proxy<XdgSurface>| {
                use self::xdg_surface::Event;
                match event {
                    Event::Configure { serial } => {
                        proxy.ack_configure(serial);
                        surface_.commit();
                    }
                }
            }))
    })
}

impl fmt::Debug for XdgToplevel {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:?}", self.proxy.c_ptr())
    }
}

fn unwrap_state_mut<'this>(proxy: &'this mut Proxy<xdg_toplevel::XdgToplevel>)
                           -> &'this mut XdgToplevelState {
    unsafe {
        let user_data = proxy.get_user_data() as *mut XdgToplevelState;
        if user_data.is_null() {
            panic!("User data has not been set yet");
        }
        &mut *user_data
    }
}

fn unwrap_state<'this>(proxy: &'this Proxy<xdg_toplevel::XdgToplevel>)
                           -> &'this XdgToplevelState {
    unsafe {
        let user_data = proxy.get_user_data() as *const XdgToplevelState;
        if user_data.is_null() {
            panic!("User data has not been set yet");
        }
        &*user_data
    }
}
<|endoftext|>


<commit_before>extern mod http;
use http::client::RequestWriter;
use http::method::Get;
use std::str;
use std::rt::io::Reader;
use std::rt::io::net::ip::{SocketAddr, Ipv4Addr};

fn main() {
    let mut request = ~RequestWriter::new(Get, FromStr::from_str("http://localhost/example")
                                                .expect("Uh oh, that's *really* badly broken!"));
    // Temporary measure, as hostname lookup is not yet supported in std::rt::io.
    request.remote_addr = Some(SocketAddr { ip: Ipv4Addr(127, 0, 0, 1), port: 8001 });
    let mut response = match request.read_response() {
        Ok(response) => response,
        Err(_request) => fail!("This example can progress no further with no response :-("),
    };
    println("Yay! Started to get the response.");
    printfln!("Status: %s", response.status.to_str());
    println("Headers: [extension headers only; TODO HeaderCollection.iter()]");
    for (name, value) in response.headers.extensions.iter() {
        printfln!(" - %s: %s", *name, *value);
    }
    print("\n");
    println("First 1024 bytes of response:");
    let mut buf = [0, ..1024];
    match response.read(buf) {
        Some(len) => printfln!("%?", str::from_bytes(buf.slice_to(len))),
        None => println("uh oh, got None :-("),
    }
    // TODO: read it *all*, correctly
}
<commit_msg>Make client example show all headers.<commit_after>extern mod http;
use http::client::RequestWriter;
use http::method::Get;
use http::headers::HeaderEnum;
use std::str;
use std::rt::io::Reader;
use std::rt::io::net::ip::{SocketAddr, Ipv4Addr};

fn main() {
    let mut request = ~RequestWriter::new(Get, FromStr::from_str("http://localhost/example")
                                                .expect("Uh oh, that's *really* badly broken!"));
    // Temporary measure, as hostname lookup is not yet supported in std::rt::io.
    request.remote_addr = Some(SocketAddr { ip: Ipv4Addr(127, 0, 0, 1), port: 8001 });
    let mut response = match request.read_response() {
        Ok(response) => response,
        Err(_request) => fail!("This example can progress no further with no response :-("),
    };
    println("Yay! Started to get the response.");
    printfln!("Status: %s", response.status.to_str());
    println("Headers:");
    for header in response.headers.iter() {
        printfln!(" - %s: %s", header.header_name(), header.header_value());
    }
    print("\n");
    println("First 1024 bytes of response:");
    let mut buf = [0, ..1024];
    match response.read(buf) {
        Some(len) => printfln!("%?", str::from_bytes(buf.slice_to(len))),
        None => println("uh oh, got None :-("),
    }
    // TODO: read it *all*, correctly
}
<|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.
 */

use common::{Named, NamedItem};
use graphql_syntax::*;
use interner::StringKey;
use std::collections::HashMap;
use std::fmt;
use std::hash::Hash;
use std::slice::Iter;

pub(crate) type TypeMap = HashMap<StringKey, Type>;

macro_rules! type_id {
    ($name:ident, $type:ident) => {
        #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
        pub struct $name(pub $type);
        impl $name {
            pub(crate) fn as_usize(&self) -> usize {
                self.0 as usize
            }
        }
    };
}

type_id!(EnumID, u32);
type_id!(InputObjectID, u32);
type_id!(InterfaceID, u32);
type_id!(ObjectID, u32);
type_id!(ScalarID, u32);
type_id!(UnionID, u32);
type_id!(FieldID, u32);

#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub enum Type {
    Enum(EnumID),
    InputObject(InputObjectID),
    Interface(InterfaceID),
    Object(ObjectID),
    Scalar(ScalarID),
    Union(UnionID),
}

impl Type {
    pub fn is_scalar(self) -> bool {
        matches!(self, Type::Scalar(_))
    }

    pub fn is_enum(self) -> bool {
        matches!(self, Type::Enum(_))
    }

    pub fn is_input_type(self) -> bool {
        matches!(self, Type::Scalar(_) | Type::Enum(_) | Type::InputObject(_))
    }

    pub fn is_abstract_type(self) -> bool {
        matches!(self, Type::Union(_) | Type::Interface(_))
    }

    pub fn is_object(self) -> bool {
        matches!(self, Type::Object(_))
    }

    pub fn is_interface(self) -> bool {
        matches!(self, Type::Interface(_))
    }

    pub fn is_object_or_interface(self) -> bool {
        matches!(self, Type::Object(_) | Type::Interface(_))
    }

    pub fn is_union(self) -> bool {
        matches!(self, Type::Union(_))
    }

    pub fn get_enum_id(self) -> Option<EnumID> {
        match self {
            Type::Enum(id) => Some(id),
            _ => None,
        }
    }

    pub fn get_input_object_id(self) -> Option<InputObjectID> {
        match self {
            Type::InputObject(id) => Some(id),
            _ => None,
        }
    }

    pub fn get_interface_id(self) -> Option<InterfaceID> {
        match self {
            Type::Interface(id) => Some(id),
            _ => None,
        }
    }

    pub fn get_object_id(self) -> Option<ObjectID> {
        match self {
            Type::Object(id) => Some(id),
            _ => None,
        }
    }

    pub fn get_scalar_id(self) -> Option<ScalarID> {
        match self {
            Type::Scalar(id) => Some(id),
            _ => None,
        }
    }

    pub fn get_union_id(self) -> Option<UnionID> {
        match self {
            Type::Union(id) => Some(id),
            _ => None,
        }
    }
}

impl fmt::Debug for Type {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Type::Enum(id) => f.write_fmt(format_args!("Enum({:?})", id.0)),
            Type::InputObject(id) => f.write_fmt(format_args!("InputObject({:?})", id.0)),
            Type::Interface(id) => f.write_fmt(format_args!("Interface({:?})", id.0)),
            Type::Object(id) => f.write_fmt(format_args!("Object({:?})", id.0)),
            Type::Scalar(id) => f.write_fmt(format_args!("Scalar({:?})", id.0)),
            Type::Union(id) => f.write_fmt(format_args!("Union({:?})", id.0)),
        }
    }
}

#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub enum TypeReference {
    Named(Type),
    NonNull(Box<TypeReference>),
    List(Box<TypeReference>),
}

impl TypeReference {
    pub fn inner(&self) -> Type {
        match self {
            TypeReference::Named(type_) => *type_,
            TypeReference::List(of) => of.inner(),
            TypeReference::NonNull(of) => of.inner(),
        }
    }

    pub fn non_null(&self) -> TypeReference {
        match self {
            TypeReference::Named(_) => TypeReference::NonNull(Box::new(self.clone())),
            TypeReference::List(_) => TypeReference::NonNull(Box::new(self.clone())),
            TypeReference::NonNull(_) => self.clone(),
        }
    }

    pub fn nullable_type(&self) -> &TypeReference {
        match self {
            TypeReference::Named(_) => self,
            TypeReference::List(_) => self,
            TypeReference::NonNull(of) => of,
        }
    }

    pub fn is_non_null(&self) -> bool {
        matches!(self, TypeReference::NonNull(_))
    }

    pub fn is_list(&self) -> bool {
        matches!(self.nullable_type(), TypeReference::List(_))
    }

    // If the type is Named or NonNull<Named> return the inner named.
    // If the type is a List or NonNull<List> returns a matching list with nullable items.
    pub fn with_nullable_item_type(&self) -> TypeReference {
        match self {
            TypeReference::Named(_) => self.clone(),
            TypeReference::List(of) => TypeReference::List(Box::new(of.nullable_type().clone())),
            TypeReference::NonNull(of) => {
                let inner: &TypeReference = of;
                match inner {
                    TypeReference::List(_) => {
                        TypeReference::NonNull(Box::new(of.with_nullable_item_type()))
                    }
                    TypeReference::Named(_) => inner.clone(),
                    TypeReference::NonNull(_) => {
                        unreachable!("Invalid nested TypeReference::NonNull")
                    }
                }
            }
        }
    }

    pub fn list_item_type(&self) -> Option<&TypeReference> {
        match self.nullable_type() {
            TypeReference::List(of) => Some(of),
            _ => None,
        }
    }

    // Return None if the type is a List, otherwise return the inner type
    pub fn non_list_type(&self) -> Option<Type> {
        match self {
            TypeReference::List(_) => None,
            TypeReference::Named(type_) => Some(*type_),
            TypeReference::NonNull(of) => of.non_list_type(),
        }
    }
}

#[derive(Clone, Debug)]
pub struct Directive {
    pub name: StringKey,
    pub arguments: ArgumentDefinitions,
    pub locations: Vec<DirectiveLocation>,
    pub repeatable: bool,
    pub is_extension: bool,
}

impl Named for Directive {
    fn name(&self) -> StringKey {
        self.name
    }
}

#[derive(Clone, Debug)]
pub struct Scalar {
    pub name: StringKey,
    pub is_extension: bool,
    pub directives: Vec<DirectiveValue>,
}

#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub struct Object {
    pub name: StringKey,
    pub is_extension: bool,
    pub fields: Vec<FieldID>,
    pub interfaces: Vec<InterfaceID>,
    pub directives: Vec<DirectiveValue>,
}

#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub struct InputObject {
    pub name: StringKey,
    pub fields: ArgumentDefinitions,
    pub directives: Vec<DirectiveValue>,
}

#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub struct Enum {
    pub name: StringKey,
    pub is_extension: bool,
    pub values: Vec<EnumValue>,
    pub directives: Vec<DirectiveValue>,
}

#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub struct Union {
    pub name: StringKey,
    pub is_extension: bool,
    pub members: Vec<ObjectID>,
    pub directives: Vec<DirectiveValue>,
}

#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub struct Interface {
    pub name: StringKey,
    pub is_extension: bool,
    pub implementing_objects: Vec<ObjectID>,
    pub fields: Vec<FieldID>,
    pub directives: Vec<DirectiveValue>,
    pub interfaces: Vec<InterfaceID>,
}

#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub struct Field {
    pub name: StringKey,
    pub is_extension: bool,
    pub arguments: ArgumentDefinitions,
    pub type_: TypeReference,
    pub directives: Vec<DirectiveValue>,
    /// The type on which this field was defined. This field is (should)
    /// always be set, except for special fields such as __typename and
    /// __id, which are queryable on all types and therefore don't have
    /// a single parent type.
    pub parent_type: Option<Type>,
}

#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct Argument {
    pub name: StringKey,
    pub type_: TypeReference,
    pub default_value: Option<ConstantValue>,
}

impl Named for Argument {
    fn name(&self) -> StringKey {
        self.name
    }
}

#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub struct ArgumentValue {
    pub name: StringKey,
    pub value: ConstantValue,
}

impl Named for ArgumentValue {
    fn name(&self) -> StringKey {
        self.name
    }
}

#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub struct DirectiveValue {
    pub name: StringKey,
    pub arguments: Vec<ArgumentValue>,
}

impl Named for DirectiveValue {
    fn name(&self) -> StringKey {
        self.name
    }
}

#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub struct EnumValue {
    pub value: StringKey,
    pub directives: Vec<DirectiveValue>,
}

#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct ArgumentDefinitions(pub(crate) Vec<Argument>);

impl ArgumentDefinitions {
    pub fn new(arguments: Vec<Argument>) -> Self {
        Self(arguments)
    }

    pub fn named(&self, name: StringKey) -> Option<&Argument> {
        self.0.named(name)
    }

    pub fn contains(&self, name: StringKey) -> bool {
        self.0.iter().any(|x| x.name == name)
    }

    pub fn iter(&self) -> Iter<'_, Argument> {
        self.0.iter()
    }

    pub fn is_empty(&self) -> bool {
        self.0.is_empty()
    }
}

impl fmt::Debug for ArgumentDefinitions {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_fmt(format_args!("{:#?}", self.0))
    }
}

impl IntoIterator for ArgumentDefinitions {
    type Item = Argument;
    type IntoIter = std::vec::IntoIter<Self::Item>;

    fn into_iter(self) -> Self::IntoIter {
        self.0.into_iter()
    }
}

pub trait TypeWithFields {
    fn name(&self) -> StringKey;
    fn fields(&self) -> &Vec<FieldID>;
    fn interfaces(&self) -> &Vec<InterfaceID>;
}

impl TypeWithFields for Interface {
    fn name(&self) -> StringKey {
        self.name
    }

    fn fields(&self) -> &Vec<FieldID> {
        &self.fields
    }

    fn interfaces(&self) -> &Vec<InterfaceID> {
        &self.interfaces
    }
}

impl TypeWithFields for Object {
    fn name(&self) -> StringKey {
        self.name
    }

    fn fields(&self) -> &Vec<FieldID> {
        &self.fields
    }

    fn interfaces(&self) -> &Vec<InterfaceID> {
        &self.interfaces
    }
}
<commit_msg>add is_input_object() to schema::Type<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 common::{Named, NamedItem};
use graphql_syntax::*;
use interner::StringKey;
use std::collections::HashMap;
use std::fmt;
use std::hash::Hash;
use std::slice::Iter;

pub(crate) type TypeMap = HashMap<StringKey, Type>;

macro_rules! type_id {
    ($name:ident, $type:ident) => {
        #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
        pub struct $name(pub $type);
        impl $name {
            pub(crate) fn as_usize(&self) -> usize {
                self.0 as usize
            }
        }
    };
}

type_id!(EnumID, u32);
type_id!(InputObjectID, u32);
type_id!(InterfaceID, u32);
type_id!(ObjectID, u32);
type_id!(ScalarID, u32);
type_id!(UnionID, u32);
type_id!(FieldID, u32);

#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub enum Type {
    Enum(EnumID),
    InputObject(InputObjectID),
    Interface(InterfaceID),
    Object(ObjectID),
    Scalar(ScalarID),
    Union(UnionID),
}

impl Type {
    pub fn is_scalar(self) -> bool {
        matches!(self, Type::Scalar(_))
    }

    pub fn is_enum(self) -> bool {
        matches!(self, Type::Enum(_))
    }

    pub fn is_input_type(self) -> bool {
        matches!(self, Type::Scalar(_) | Type::Enum(_) | Type::InputObject(_))
    }

    pub fn is_abstract_type(self) -> bool {
        matches!(self, Type::Union(_) | Type::Interface(_))
    }

    pub fn is_object(self) -> bool {
        matches!(self, Type::Object(_))
    }

    pub fn is_input_object(self) -> bool {
        matches!(self, Type::InputObject(_))
    }

    pub fn is_interface(self) -> bool {
        matches!(self, Type::Interface(_))
    }

    pub fn is_object_or_interface(self) -> bool {
        matches!(self, Type::Object(_) | Type::Interface(_))
    }

    pub fn is_union(self) -> bool {
        matches!(self, Type::Union(_))
    }

    pub fn get_enum_id(self) -> Option<EnumID> {
        match self {
            Type::Enum(id) => Some(id),
            _ => None,
        }
    }

    pub fn get_input_object_id(self) -> Option<InputObjectID> {
        match self {
            Type::InputObject(id) => Some(id),
            _ => None,
        }
    }

    pub fn get_interface_id(self) -> Option<InterfaceID> {
        match self {
            Type::Interface(id) => Some(id),
            _ => None,
        }
    }

    pub fn get_object_id(self) -> Option<ObjectID> {
        match self {
            Type::Object(id) => Some(id),
            _ => None,
        }
    }

    pub fn get_scalar_id(self) -> Option<ScalarID> {
        match self {
            Type::Scalar(id) => Some(id),
            _ => None,
        }
    }

    pub fn get_union_id(self) -> Option<UnionID> {
        match self {
            Type::Union(id) => Some(id),
            _ => None,
        }
    }
}

impl fmt::Debug for Type {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Type::Enum(id) => f.write_fmt(format_args!("Enum({:?})", id.0)),
            Type::InputObject(id) => f.write_fmt(format_args!("InputObject({:?})", id.0)),
            Type::Interface(id) => f.write_fmt(format_args!("Interface({:?})", id.0)),
            Type::Object(id) => f.write_fmt(format_args!("Object({:?})", id.0)),
            Type::Scalar(id) => f.write_fmt(format_args!("Scalar({:?})", id.0)),
            Type::Union(id) => f.write_fmt(format_args!("Union({:?})", id.0)),
        }
    }
}

#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub enum TypeReference {
    Named(Type),
    NonNull(Box<TypeReference>),
    List(Box<TypeReference>),
}

impl TypeReference {
    pub fn inner(&self) -> Type {
        match self {
            TypeReference::Named(type_) => *type_,
            TypeReference::List(of) => of.inner(),
            TypeReference::NonNull(of) => of.inner(),
        }
    }

    pub fn non_null(&self) -> TypeReference {
        match self {
            TypeReference::Named(_) => TypeReference::NonNull(Box::new(self.clone())),
            TypeReference::List(_) => TypeReference::NonNull(Box::new(self.clone())),
            TypeReference::NonNull(_) => self.clone(),
        }
    }

    pub fn nullable_type(&self) -> &TypeReference {
        match self {
            TypeReference::Named(_) => self,
            TypeReference::List(_) => self,
            TypeReference::NonNull(of) => of,
        }
    }

    pub fn is_non_null(&self) -> bool {
        matches!(self, TypeReference::NonNull(_))
    }

    pub fn is_list(&self) -> bool {
        matches!(self.nullable_type(), TypeReference::List(_))
    }

    // If the type is Named or NonNull<Named> return the inner named.
    // If the type is a List or NonNull<List> returns a matching list with nullable items.
    pub fn with_nullable_item_type(&self) -> TypeReference {
        match self {
            TypeReference::Named(_) => self.clone(),
            TypeReference::List(of) => TypeReference::List(Box::new(of.nullable_type().clone())),
            TypeReference::NonNull(of) => {
                let inner: &TypeReference = of;
                match inner {
                    TypeReference::List(_) => {
                        TypeReference::NonNull(Box::new(of.with_nullable_item_type()))
                    }
                    TypeReference::Named(_) => inner.clone(),
                    TypeReference::NonNull(_) => {
                        unreachable!("Invalid nested TypeReference::NonNull")
                    }
                }
            }
        }
    }

    pub fn list_item_type(&self) -> Option<&TypeReference> {
        match self.nullable_type() {
            TypeReference::List(of) => Some(of),
            _ => None,
        }
    }

    // Return None if the type is a List, otherwise return the inner type
    pub fn non_list_type(&self) -> Option<Type> {
        match self {
            TypeReference::List(_) => None,
            TypeReference::Named(type_) => Some(*type_),
            TypeReference::NonNull(of) => of.non_list_type(),
        }
    }
}

#[derive(Clone, Debug)]
pub struct Directive {
    pub name: StringKey,
    pub arguments: ArgumentDefinitions,
    pub locations: Vec<DirectiveLocation>,
    pub repeatable: bool,
    pub is_extension: bool,
}

impl Named for Directive {
    fn name(&self) -> StringKey {
        self.name
    }
}

#[derive(Clone, Debug)]
pub struct Scalar {
    pub name: StringKey,
    pub is_extension: bool,
    pub directives: Vec<DirectiveValue>,
}

#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub struct Object {
    pub name: StringKey,
    pub is_extension: bool,
    pub fields: Vec<FieldID>,
    pub interfaces: Vec<InterfaceID>,
    pub directives: Vec<DirectiveValue>,
}

#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub struct InputObject {
    pub name: StringKey,
    pub fields: ArgumentDefinitions,
    pub directives: Vec<DirectiveValue>,
}

#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub struct Enum {
    pub name: StringKey,
    pub is_extension: bool,
    pub values: Vec<EnumValue>,
    pub directives: Vec<DirectiveValue>,
}

#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub struct Union {
    pub name: StringKey,
    pub is_extension: bool,
    pub members: Vec<ObjectID>,
    pub directives: Vec<DirectiveValue>,
}

#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub struct Interface {
    pub name: StringKey,
    pub is_extension: bool,
    pub implementing_objects: Vec<ObjectID>,
    pub fields: Vec<FieldID>,
    pub directives: Vec<DirectiveValue>,
    pub interfaces: Vec<InterfaceID>,
}

#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub struct Field {
    pub name: StringKey,
    pub is_extension: bool,
    pub arguments: ArgumentDefinitions,
    pub type_: TypeReference,
    pub directives: Vec<DirectiveValue>,
    /// The type on which this field was defined. This field is (should)
    /// always be set, except for special fields such as __typename and
    /// __id, which are queryable on all types and therefore don't have
    /// a single parent type.
    pub parent_type: Option<Type>,
}

#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct Argument {
    pub name: StringKey,
    pub type_: TypeReference,
    pub default_value: Option<ConstantValue>,
}

impl Named for Argument {
    fn name(&self) -> StringKey {
        self.name
    }
}

#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub struct ArgumentValue {
    pub name: StringKey,
    pub value: ConstantValue,
}

impl Named for ArgumentValue {
    fn name(&self) -> StringKey {
        self.name
    }
}

#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub struct DirectiveValue {
    pub name: StringKey,
    pub arguments: Vec<ArgumentValue>,
}

impl Named for DirectiveValue {
    fn name(&self) -> StringKey {
        self.name
    }
}

#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub struct EnumValue {
    pub value: StringKey,
    pub directives: Vec<DirectiveValue>,
}

#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct ArgumentDefinitions(pub(crate) Vec<Argument>);

impl ArgumentDefinitions {
    pub fn new(arguments: Vec<Argument>) -> Self {
        Self(arguments)
    }

    pub fn named(&self, name: StringKey) -> Option<&Argument> {
        self.0.named(name)
    }

    pub fn contains(&self, name: StringKey) -> bool {
        self.0.iter().any(|x| x.name == name)
    }

    pub fn iter(&self) -> Iter<'_, Argument> {
        self.0.iter()
    }

    pub fn is_empty(&self) -> bool {
        self.0.is_empty()
    }
}

impl fmt::Debug for ArgumentDefinitions {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_fmt(format_args!("{:#?}", self.0))
    }
}

impl IntoIterator for ArgumentDefinitions {
    type Item = Argument;
    type IntoIter = std::vec::IntoIter<Self::Item>;

    fn into_iter(self) -> Self::IntoIter {
        self.0.into_iter()
    }
}

pub trait TypeWithFields {
    fn name(&self) -> StringKey;
    fn fields(&self) -> &Vec<FieldID>;
    fn interfaces(&self) -> &Vec<InterfaceID>;
}

impl TypeWithFields for Interface {
    fn name(&self) -> StringKey {
        self.name
    }

    fn fields(&self) -> &Vec<FieldID> {
        &self.fields
    }

    fn interfaces(&self) -> &Vec<InterfaceID> {
        &self.interfaces
    }
}

impl TypeWithFields for Object {
    fn name(&self) -> StringKey {
        self.name
    }

    fn fields(&self) -> &Vec<FieldID> {
        &self.fields
    }

    fn interfaces(&self) -> &Vec<InterfaceID> {
        &self.interfaces
    }
}
<|endoftext|>