<commit_before>// Copyright (c) Aptos
// SPDX-License-Identifier: Apache-2.0

use crate::common::utils::prompt_yes;
use crate::common::{
    types::{
        CliCommand, CliConfig, CliError, CliTypedResult, ConfigSearchMode, EncodingOptions,
        EncodingType, ExtractPublicKey, ParsePrivateKey, ProfileConfig, ProfileOptions,
        PublicKeyInputOptions, RestOptions, RotationProofChallenge, TransactionOptions,
        TransactionSummary,
    },
    utils::{prompt_yes_with_override, read_line},
};
use aptos_crypto::{
    ed25519::{Ed25519PrivateKey, Ed25519PublicKey},
    PrivateKey, SigningKey,
};
use aptos_rest_client::aptos_api_types::{AptosError, AptosErrorCode};
use aptos_rest_client::error::{AptosErrorResponse, RestError};
use aptos_rest_client::Client;
use aptos_types::{
    account_address::AccountAddress, account_config::CORE_CODE_ADDRESS,
    transaction::authenticator::AuthenticationKey,
};
use async_trait::async_trait;
use cached_packages::aptos_stdlib;
use clap::Parser;
use serde::{Deserialize, Serialize};
use std::{collections::BTreeMap, path::PathBuf};

/// Command to rotate an account's authentication key
///
#[derive(Debug, Parser)]
pub struct RotateKey {
    #[clap(flatten)]
    pub(crate) txn_options: TransactionOptions,

    /// File name that contains the new private key
    #[clap(long, group = "new_private_key", parse(from_os_str))]
    pub(crate) new_private_key_file: Option<PathBuf>,
    /// New private key encoded in a type as shown in `encoding`
    #[clap(long, group = "new_private_key")]
    pub(crate) new_private_key: Option<String>,

    /// Name of the profile to save the new private key
    #[clap(long)]
    pub(crate) save_to_profile: Option<String>,

    /// Skip saving profile
    #[clap(long)]
    pub(crate) skip_saving_profile: bool,
}

impl ParsePrivateKey for RotateKey {}

impl RotateKey {
    /// Extract private key from CLI args
    pub fn extract_private_key(
        &self,
        encoding: EncodingType,
    ) -> CliTypedResult<Option<Ed25519PrivateKey>> {
        self.parse_private_key(
            encoding,
            self.new_private_key_file.clone(),
            self.new_private_key.clone(),
        )
    }
}

#[derive(Debug, Deserialize, Serialize)]
pub struct RotateSummary {
    message: Option<String>,
    transaction: TransactionSummary,
}

#[async_trait]
impl CliCommand<RotateSummary> for RotateKey {
    fn command_name(&self) -> &'static str {
        "RotateKey"
    }

    async fn execute(self) -> CliTypedResult<RotateSummary> {
        let new_private_key = self
            .extract_private_key(self.txn_options.encoding_options.encoding)?
            .ok_or_else(|| {
                CliError::CommandArgumentError(
                    "One of ['--new-private-key', '--new-private-key-file'] must be used"
                        .to_string(),
                )
            })?;

        let (current_private_key, sender_address) = self.txn_options.get_key_and_address()?;

        // Get sequence number for account
        let sequence_number = self.txn_options.sequence_number(sender_address).await?;
        let auth_key = self.txn_options.auth_key(sender_address).await?;

        let rotation_proof = RotationProofChallenge {
            account_address: CORE_CODE_ADDRESS,
            module_name: "account".to_string(),
            struct_name: "RotationProofChallenge".to_string(),
            sequence_number,
            originator: sender_address,
            current_auth_key: AccountAddress::from_bytes(&auth_key)
                .map_err(|err| CliError::UnableToParse("auth_key", err.to_string()))?,
            new_public_key: new_private_key.public_key().to_bytes().to_vec(),
        };

        let rotation_msg =
            bcs::to_bytes(&rotation_proof).map_err(|err| CliError::BCS("rotation_proof", err))?;

        // Signs the struct using both the current private key and the next private key
        let rotation_proof_signed_by_current_private_key =
            current_private_key.sign_arbitrary_message(&rotation_msg.clone());
        let rotation_proof_signed_by_new_private_key =
            new_private_key.sign_arbitrary_message(&rotation_msg);

        let txn_summary = self
            .txn_options
            .submit_transaction(aptos_stdlib::account_rotate_authentication_key(
                0,
                // Existing public key
                current_private_key.public_key().to_bytes().to_vec(),
                0,
                // New public key
                new_private_key.public_key().to_bytes().to_vec(),
                rotation_proof_signed_by_current_private_key
                    .to_bytes()
                    .to_vec(),
                rotation_proof_signed_by_new_private_key.to_bytes().to_vec(),
            ))
            .await
            .map(TransactionSummary::from)?;

        let string = serde_json::to_string_pretty(&txn_summary)
            .map_err(|err| CliError::UnableToParse("transaction summary", err.to_string()))?;

        eprintln!("{}", string);

        if let Some(txn_success) = txn_summary.success {
            if !txn_success {
                return Err(CliError::ApiError(
                    "Transaction was not executed successfully".to_string(),
                ));
            }
        } else {
            return Err(CliError::UnexpectedError(
                "Malformed transaction response".to_string(),
            ));
        }

        let mut profile_name: String;

        if self.save_to_profile.is_none() {
            if self.skip_saving_profile
                || !prompt_yes("Do you want to create a profile for the new key?")
            {
                return Ok(RotateSummary {
                    transaction: txn_summary,
                    message: None,
                });
            }

            eprintln!("Enter the name for the profile");
            profile_name = read_line("Profile name")?.trim().to_string();
        } else {
            // We can safely unwrap here
            profile_name = self.save_to_profile.unwrap();
        }

        // Check if profile name exists
        let mut config = CliConfig::load(ConfigSearchMode::CurrentDirAndParents)?;

        if let Some(ref profiles) = config.profiles {
            if profiles.contains_key(&profile_name) {
                if let Err(cli_err) = prompt_yes_with_override(
                    format!(
                        "Profile {} exits. Do you want to provide a new profile name?",
                        profile_name
                    )
                    .as_str(),
                    self.txn_options.prompt_options,
                ) {
                    match cli_err {
                        CliError::AbortedError => {
                            return Ok(RotateSummary {
                                transaction: txn_summary,
                                message: None,
                            });
                        }
                        _ => {
                            return Err(cli_err);
                        }
                    }
                }

                eprintln!("Enter the name for the profile");
                profile_name = read_line("Profile name")?.trim().to_string();
            }
        }

        if profile_name.is_empty() {
            return Err(CliError::AbortedError);
        }

        let mut profile_config = ProfileConfig {
            private_key: Some(new_private_key.clone()),
            public_key: Some(new_private_key.public_key()),
            account: Some(sender_address),
            ..self.txn_options.profile_options.profile()?
        };

        if let Some(url) = self.txn_options.rest_options.url {
            profile_config.rest_url = Some(url.into());
        }

        if config.profiles.is_none() {
            config.profiles = Some(BTreeMap::new());
        }

        config
            .profiles
            .as_mut()
            .unwrap()
            .insert(profile_name.clone(), profile_config);
        config.save()?;

        eprintln!("Profile {} is saved.", profile_name);

        Ok(RotateSummary {
            transaction: txn_summary,
            message: Some(format!("Profile {} is saved.", profile_name)),
        })
    }
}

/// Command to lookup the account adress through on-chain lookup table
///
#[derive(Debug, Parser)]
pub struct LookupAddress {
    #[clap(flatten)]
    pub(crate) encoding_options: EncodingOptions,

    #[clap(flatten)]
    pub(crate) public_key_options: PublicKeyInputOptions,

    #[clap(flatten)]
    pub(crate) profile_options: ProfileOptions,

    #[clap(flatten)]
    pub(crate) rest_options: RestOptions,
}

impl LookupAddress {
    pub(crate) fn public_key(&self) -> CliTypedResult<Ed25519PublicKey> {
        self.public_key_options.extract_public_key(
            self.encoding_options.encoding,
            &self.profile_options.profile,
        )
    }

    /// Builds a rest client
    fn rest_client(&self) -> CliTypedResult<Client> {
        self.rest_options.client(&self.profile_options.profile)
    }
}

#[async_trait]
impl CliCommand<AccountAddress> for LookupAddress {
    fn command_name(&self) -> &'static str {
        "LookupAddress"
    }

    async fn execute(self) -> CliTypedResult<AccountAddress> {
        let rest_client = self.rest_client()?;

        let originating_resource: OriginatingResource = rest_client
            .get_account_resource_bcs(CORE_CODE_ADDRESS, "0x1::account::OriginatingAddress")
            .await?
            .into_inner();

        let table_handle = originating_resource.address_map.handle;

        // The derived address that can be used to look up the original address
        // TODO: This command needs to support multi-ed25519
        let address_key = AuthenticationKey::ed25519(&self.public_key()?).derived_address();
        match rest_client
            .get_table_item_bcs(
                table_handle,
                "address",
                "address",
                address_key.to_hex_literal(),
            )
            .await
        {
            Ok(inner) => Ok(inner.into_inner()),
            Err(RestError::Api(AptosErrorResponse {
                error:
                    AptosError {
                        error_code: AptosErrorCode::TableItemNotFound,
                        ..
                    },
                ..
            })) => {
                // If the table item wasn't found, let's at least check if the account exists
                // It won't be in the table if it wasn't rotated, then return the derived account address
                rest_client.get_account_bcs(address_key).await?;
                Ok(address_key)
            }
            Err(err) => Err(err)?,
        }
    }
}

#[derive(Deserialize)]
pub struct OriginatingResource {
    pub address_map: Table,
}

#[derive(Deserialize)]
pub struct Table {
    pub handle: AccountAddress,
}
<commit_msg>Fix spelling error<commit_after>// Copyright (c) Aptos
// SPDX-License-Identifier: Apache-2.0

use crate::common::utils::prompt_yes;
use crate::common::{
    types::{
        CliCommand, CliConfig, CliError, CliTypedResult, ConfigSearchMode, EncodingOptions,
        EncodingType, ExtractPublicKey, ParsePrivateKey, ProfileConfig, ProfileOptions,
        PublicKeyInputOptions, RestOptions, RotationProofChallenge, TransactionOptions,
        TransactionSummary,
    },
    utils::{prompt_yes_with_override, read_line},
};
use aptos_crypto::{
    ed25519::{Ed25519PrivateKey, Ed25519PublicKey},
    PrivateKey, SigningKey,
};
use aptos_rest_client::aptos_api_types::{AptosError, AptosErrorCode};
use aptos_rest_client::error::{AptosErrorResponse, RestError};
use aptos_rest_client::Client;
use aptos_types::{
    account_address::AccountAddress, account_config::CORE_CODE_ADDRESS,
    transaction::authenticator::AuthenticationKey,
};
use async_trait::async_trait;
use cached_packages::aptos_stdlib;
use clap::Parser;
use serde::{Deserialize, Serialize};
use std::{collections::BTreeMap, path::PathBuf};

/// Command to rotate an account's authentication key
///
#[derive(Debug, Parser)]
pub struct RotateKey {
    #[clap(flatten)]
    pub(crate) txn_options: TransactionOptions,

    /// File name that contains the new private key
    #[clap(long, group = "new_private_key", parse(from_os_str))]
    pub(crate) new_private_key_file: Option<PathBuf>,
    /// New private key encoded in a type as shown in `encoding`
    #[clap(long, group = "new_private_key")]
    pub(crate) new_private_key: Option<String>,

    /// Name of the profile to save the new private key
    #[clap(long)]
    pub(crate) save_to_profile: Option<String>,

    /// Skip saving profile
    #[clap(long)]
    pub(crate) skip_saving_profile: bool,
}

impl ParsePrivateKey for RotateKey {}

impl RotateKey {
    /// Extract private key from CLI args
    pub fn extract_private_key(
        &self,
        encoding: EncodingType,
    ) -> CliTypedResult<Option<Ed25519PrivateKey>> {
        self.parse_private_key(
            encoding,
            self.new_private_key_file.clone(),
            self.new_private_key.clone(),
        )
    }
}

#[derive(Debug, Deserialize, Serialize)]
pub struct RotateSummary {
    message: Option<String>,
    transaction: TransactionSummary,
}

#[async_trait]
impl CliCommand<RotateSummary> for RotateKey {
    fn command_name(&self) -> &'static str {
        "RotateKey"
    }

    async fn execute(self) -> CliTypedResult<RotateSummary> {
        let new_private_key = self
            .extract_private_key(self.txn_options.encoding_options.encoding)?
            .ok_or_else(|| {
                CliError::CommandArgumentError(
                    "One of ['--new-private-key', '--new-private-key-file'] must be used"
                        .to_string(),
                )
            })?;

        let (current_private_key, sender_address) = self.txn_options.get_key_and_address()?;

        // Get sequence number for account
        let sequence_number = self.txn_options.sequence_number(sender_address).await?;
        let auth_key = self.txn_options.auth_key(sender_address).await?;

        let rotation_proof = RotationProofChallenge {
            account_address: CORE_CODE_ADDRESS,
            module_name: "account".to_string(),
            struct_name: "RotationProofChallenge".to_string(),
            sequence_number,
            originator: sender_address,
            current_auth_key: AccountAddress::from_bytes(&auth_key)
                .map_err(|err| CliError::UnableToParse("auth_key", err.to_string()))?,
            new_public_key: new_private_key.public_key().to_bytes().to_vec(),
        };

        let rotation_msg =
            bcs::to_bytes(&rotation_proof).map_err(|err| CliError::BCS("rotation_proof", err))?;

        // Signs the struct using both the current private key and the next private key
        let rotation_proof_signed_by_current_private_key =
            current_private_key.sign_arbitrary_message(&rotation_msg.clone());
        let rotation_proof_signed_by_new_private_key =
            new_private_key.sign_arbitrary_message(&rotation_msg);

        let txn_summary = self
            .txn_options
            .submit_transaction(aptos_stdlib::account_rotate_authentication_key(
                0,
                // Existing public key
                current_private_key.public_key().to_bytes().to_vec(),
                0,
                // New public key
                new_private_key.public_key().to_bytes().to_vec(),
                rotation_proof_signed_by_current_private_key
                    .to_bytes()
                    .to_vec(),
                rotation_proof_signed_by_new_private_key.to_bytes().to_vec(),
            ))
            .await
            .map(TransactionSummary::from)?;

        let string = serde_json::to_string_pretty(&txn_summary)
            .map_err(|err| CliError::UnableToParse("transaction summary", err.to_string()))?;

        eprintln!("{}", string);

        if let Some(txn_success) = txn_summary.success {
            if !txn_success {
                return Err(CliError::ApiError(
                    "Transaction was not executed successfully".to_string(),
                ));
            }
        } else {
            return Err(CliError::UnexpectedError(
                "Malformed transaction response".to_string(),
            ));
        }

        let mut profile_name: String;

        if self.save_to_profile.is_none() {
            if self.skip_saving_profile
                || !prompt_yes("Do you want to create a profile for the new key?")
            {
                return Ok(RotateSummary {
                    transaction: txn_summary,
                    message: None,
                });
            }

            eprintln!("Enter the name for the profile");
            profile_name = read_line("Profile name")?.trim().to_string();
        } else {
            // We can safely unwrap here
            profile_name = self.save_to_profile.unwrap();
        }

        // Check if profile name exists
        let mut config = CliConfig::load(ConfigSearchMode::CurrentDirAndParents)?;

        if let Some(ref profiles) = config.profiles {
            if profiles.contains_key(&profile_name) {
                if let Err(cli_err) = prompt_yes_with_override(
                    format!(
                        "Profile {} exits. Do you want to provide a new profile name?",
                        profile_name
                    )
                    .as_str(),
                    self.txn_options.prompt_options,
                ) {
                    match cli_err {
                        CliError::AbortedError => {
                            return Ok(RotateSummary {
                                transaction: txn_summary,
                                message: None,
                            });
                        }
                        _ => {
                            return Err(cli_err);
                        }
                    }
                }

                eprintln!("Enter the name for the profile");
                profile_name = read_line("Profile name")?.trim().to_string();
            }
        }

        if profile_name.is_empty() {
            return Err(CliError::AbortedError);
        }

        let mut profile_config = ProfileConfig {
            private_key: Some(new_private_key.clone()),
            public_key: Some(new_private_key.public_key()),
            account: Some(sender_address),
            ..self.txn_options.profile_options.profile()?
        };

        if let Some(url) = self.txn_options.rest_options.url {
            profile_config.rest_url = Some(url.into());
        }

        if config.profiles.is_none() {
            config.profiles = Some(BTreeMap::new());
        }

        config
            .profiles
            .as_mut()
            .unwrap()
            .insert(profile_name.clone(), profile_config);
        config.save()?;

        eprintln!("Profile {} is saved.", profile_name);

        Ok(RotateSummary {
            transaction: txn_summary,
            message: Some(format!("Profile {} is saved.", profile_name)),
        })
    }
}

/// Command to lookup the account address through on-chain lookup table
///
#[derive(Debug, Parser)]
pub struct LookupAddress {
    #[clap(flatten)]
    pub(crate) encoding_options: EncodingOptions,

    #[clap(flatten)]
    pub(crate) public_key_options: PublicKeyInputOptions,

    #[clap(flatten)]
    pub(crate) profile_options: ProfileOptions,

    #[clap(flatten)]
    pub(crate) rest_options: RestOptions,
}

impl LookupAddress {
    pub(crate) fn public_key(&self) -> CliTypedResult<Ed25519PublicKey> {
        self.public_key_options.extract_public_key(
            self.encoding_options.encoding,
            &self.profile_options.profile,
        )
    }

    /// Builds a rest client
    fn rest_client(&self) -> CliTypedResult<Client> {
        self.rest_options.client(&self.profile_options.profile)
    }
}

#[async_trait]
impl CliCommand<AccountAddress> for LookupAddress {
    fn command_name(&self) -> &'static str {
        "LookupAddress"
    }

    async fn execute(self) -> CliTypedResult<AccountAddress> {
        let rest_client = self.rest_client()?;

        let originating_resource: OriginatingResource = rest_client
            .get_account_resource_bcs(CORE_CODE_ADDRESS, "0x1::account::OriginatingAddress")
            .await?
            .into_inner();

        let table_handle = originating_resource.address_map.handle;

        // The derived address that can be used to look up the original address
        // TODO: This command needs to support multi-ed25519
        let address_key = AuthenticationKey::ed25519(&self.public_key()?).derived_address();
        match rest_client
            .get_table_item_bcs(
                table_handle,
                "address",
                "address",
                address_key.to_hex_literal(),
            )
            .await
        {
            Ok(inner) => Ok(inner.into_inner()),
            Err(RestError::Api(AptosErrorResponse {
                error:
                    AptosError {
                        error_code: AptosErrorCode::TableItemNotFound,
                        ..
                    },
                ..
            })) => {
                // If the table item wasn't found, let's at least check if the account exists
                // It won't be in the table if it wasn't rotated, then return the derived account address
                rest_client.get_account_bcs(address_key).await?;
                Ok(address_key)
            }
            Err(err) => Err(err)?,
        }
    }
}

#[derive(Deserialize)]
pub struct OriginatingResource {
    pub address_map: Table,
}

#[derive(Deserialize)]
pub struct Table {
    pub handle: AccountAddress,
}
<|endoftext|>


<commit_before>pub(super) mod imp;
pub(super) mod nameres;

use std::sync::Arc;

use ra_editor::find_node_at_offset;

use ra_syntax::{
    algo::generate,
    ast::{self, AstNode, NameOwner},
    SmolStr, SyntaxNode,
};
use relative_path::RelativePathBuf;

use crate::{
    db::SyntaxDatabase, syntax_ptr::SyntaxPtr, FileId, FilePosition, Cancelable,
    hir::{Path, PathKind, HirDatabase},
    input::SourceRootId,
    arena::{Arena, Id},
    loc2id::{DefLoc, DefId},
};

pub(crate) use self::nameres::ModuleScope;

/// `Module` is API entry point to get all the information
/// about a particular module.
#[derive(Debug, Clone)]
pub(crate) struct Module {
    tree: Arc<ModuleTree>,
    source_root_id: SourceRootId,
    module_id: ModuleId,
}

impl Module {
    /// Lookup `Module` by `FileId`. Note that this is inherently
    /// lossy transformation: in general, a single source might correspond to
    /// several modules.
    pub fn guess_from_file_id(
        db: &impl HirDatabase,
        file_id: FileId,
    ) -> Cancelable<Option<Module>> {
        Module::guess_from_source(db, file_id, ModuleSource::SourceFile(file_id))
    }

    /// Lookup `Module` by position in the source code. Note that this
    /// is inherently lossy transformation: in general, a single source might
    /// correspond to several modules.
    pub fn guess_from_position(
        db: &impl HirDatabase,
        position: FilePosition,
    ) -> Cancelable<Option<Module>> {
        let file = db.file_syntax(position.file_id);
        let module_source = match find_node_at_offset::<ast::Module>(file.syntax(), position.offset)
        {
            Some(m) if !m.has_semi() => ModuleSource::new_inline(position.file_id, m),
            _ => ModuleSource::SourceFile(position.file_id),
        };
        Module::guess_from_source(db, position.file_id, module_source)
    }

    fn guess_from_source(
        db: &impl HirDatabase,
        file_id: FileId,
        module_source: ModuleSource,
    ) -> Cancelable<Option<Module>> {
        let source_root_id = db.file_source_root(file_id);
        let module_tree = db.module_tree(source_root_id)?;

        let res = match module_tree.any_module_for_source(module_source) {
            None => None,
            Some(module_id) => Some(Module {
                tree: module_tree,
                source_root_id,
                module_id,
            }),
        };
        Ok(res)
    }

    pub(super) fn new(
        db: &impl HirDatabase,
        source_root_id: SourceRootId,
        module_id: ModuleId,
    ) -> Cancelable<Module> {
        let module_tree = db.module_tree(source_root_id)?;
        let res = Module {
            tree: module_tree,
            source_root_id,
            module_id,
        };
        Ok(res)
    }

    /// Returns `mod foo;` or `mod foo {}` node whihc declared this module.
    /// Returns `None` for the root module
    pub fn parent_link_source(&self, db: &impl HirDatabase) -> Option<(FileId, ast::ModuleNode)> {
        let link = self.module_id.parent_link(&self.tree)?;
        let file_id = link.owner(&self.tree).source(&self.tree).file_id();
        let src = link.bind_source(&self.tree, db);
        Some((file_id, src))
    }

    pub fn source(&self) -> ModuleSource {
        self.module_id.source(&self.tree)
    }

    /// Parent module. Returns `None` if this is a root module.
    pub fn parent(&self) -> Option<Module> {
        let parent_id = self.module_id.parent(&self.tree)?;
        Some(Module {
            module_id: parent_id,
            ..self.clone()
        })
    }

    /// The root of the tree this module is part of
    pub fn crate_root(&self) -> Module {
        let root_id = self.module_id.crate_root(&self.tree);
        Module {
            module_id: root_id,
            ..self.clone()
        }
    }

    /// `name` is `None` for the crate's root module
    #[allow(unused)]
    pub fn name(&self) -> Option<SmolStr> {
        let link = self.module_id.parent_link(&self.tree)?;
        Some(link.name(&self.tree))
    }

    pub fn def_id(&self, db: &impl HirDatabase) -> DefId {
        let def_loc = DefLoc::Module {
            id: self.module_id,
            source_root: self.source_root_id,
        };
        db.id_maps().def_id(def_loc)
    }

    /// Finds a child module with the specified name.
    pub fn child(&self, name: &str) -> Option<Module> {
        let child_id = self.module_id.child(&self.tree, name)?;
        Some(Module {
            module_id: child_id,
            ..self.clone()
        })
    }

    /// Returns a `ModuleScope`: a set of items, visible in this module.
    pub(crate) fn scope(&self, db: &impl HirDatabase) -> Cancelable<ModuleScope> {
        let item_map = db.item_map(self.source_root_id)?;
        let res = item_map.per_module[&self.module_id].clone();
        Ok(res)
    }

    pub(crate) fn resolve_path(
        &self,
        db: &impl HirDatabase,
        path: Path,
    ) -> Cancelable<Option<DefId>> {
        let mut curr = match path.kind {
            PathKind::Crate => self.crate_root(),
            PathKind::Self_ | PathKind::Plain => self.clone(),
            PathKind::Super => ctry!(self.parent()),
        }
        .def_id(db);

        let segments = path.segments;
        for name in segments.iter() {
            let module = match db.id_maps().def_loc(curr) {
                DefLoc::Module { id, source_root } => Module::new(db, source_root, id)?,
                _ => return Ok(None),
            };
            let scope = module.scope(db)?;
            curr = ctry!(ctry!(scope.get(&name)).def_id);
        }
        Ok(Some(curr))
    }

    pub fn problems(&self, db: &impl HirDatabase) -> Vec<(SyntaxNode, Problem)> {
        self.module_id.problems(&self.tree, db)
    }
}

/// Phisically, rust source is organized as a set of files, but logically it is
/// organized as a tree of modules. Usually, a single file corresponds to a
/// single module, but it is not nessary the case.
///
/// Module encapsulate the logic of transitioning from the fuzzy world of files
/// (which can have multiple parents) to the precise world of modules (which
/// always have one parent).
#[derive(Default, Debug, PartialEq, Eq)]
pub(crate) struct ModuleTree {
    mods: Arena<ModuleData>,
    links: Arena<LinkData>,
}

impl ModuleTree {
    pub(in crate::hir) fn modules<'a>(&'a self) -> impl Iterator<Item = ModuleId> + 'a {
        self.mods.iter().map(|(id, _)| id)
    }

    fn modules_for_source(&self, source: ModuleSource) -> Vec<ModuleId> {
        self.mods
            .iter()
            .filter(|(_idx, it)| it.source == source)
            .map(|(idx, _)| idx)
            .collect()
    }

    fn any_module_for_source(&self, source: ModuleSource) -> Option<ModuleId> {
        self.modules_for_source(source).pop()
    }
}

/// `ModuleSource` is the syntax tree element that produced this module:
/// either a file, or an inlinde module.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub(crate) enum ModuleSource {
    SourceFile(FileId),
    #[allow(dead_code)]
    Module(SyntaxPtr),
}

/// An owned syntax node for a module. Unlike `ModuleSource`,
/// this holds onto the AST for the whole file.
pub(crate) enum ModuleSourceNode {
    SourceFile(ast::SourceFileNode),
    Module(ast::ModuleNode),
}

pub(crate) type ModuleId = Id<ModuleData>;
type LinkId = Id<LinkData>;

#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub enum Problem {
    UnresolvedModule {
        candidate: RelativePathBuf,
    },
    NotDirOwner {
        move_to: RelativePathBuf,
        candidate: RelativePathBuf,
    },
}

impl ModuleId {
    pub(in crate::hir) fn source(self, tree: &ModuleTree) -> ModuleSource {
        tree.mods[self].source
    }
    fn parent_link(self, tree: &ModuleTree) -> Option<LinkId> {
        tree.mods[self].parent
    }
    fn parent(self, tree: &ModuleTree) -> Option<ModuleId> {
        let link = self.parent_link(tree)?;
        Some(tree.links[link].owner)
    }
    fn crate_root(self, tree: &ModuleTree) -> ModuleId {
        generate(Some(self), move |it| it.parent(tree))
            .last()
            .unwrap()
    }
    fn child(self, tree: &ModuleTree, name: &str) -> Option<ModuleId> {
        let link = tree.mods[self]
            .children
            .iter()
            .map(|&it| &tree.links[it])
            .find(|it| it.name == name)?;
        Some(*link.points_to.first()?)
    }
    fn children<'a>(self, tree: &'a ModuleTree) -> impl Iterator<Item = (SmolStr, ModuleId)> + 'a {
        tree.mods[self].children.iter().filter_map(move |&it| {
            let link = &tree.links[it];
            let module = *link.points_to.first()?;
            Some((link.name.clone(), module))
        })
    }
    fn problems(self, tree: &ModuleTree, db: &impl SyntaxDatabase) -> Vec<(SyntaxNode, Problem)> {
        tree.mods[self]
            .children
            .iter()
            .filter_map(|&it| {
                let p = tree.links[it].problem.clone()?;
                let s = it.bind_source(tree, db);
                let s = s.borrowed().name().unwrap().syntax().owned();
                Some((s, p))
            })
            .collect()
    }
}

impl LinkId {
    fn owner(self, tree: &ModuleTree) -> ModuleId {
        tree.links[self].owner
    }
    fn name(self, tree: &ModuleTree) -> SmolStr {
        tree.links[self].name.clone()
    }
    fn bind_source<'a>(self, tree: &ModuleTree, db: &impl SyntaxDatabase) -> ast::ModuleNode {
        let owner = self.owner(tree);
        match owner.source(tree).resolve(db) {
            ModuleSourceNode::SourceFile(root) => {
                let ast = imp::modules(root.borrowed())
                    .find(|(name, _)| name == &tree.links[self].name)
                    .unwrap()
                    .1;
                ast.owned()
            }
            ModuleSourceNode::Module(it) => it,
        }
    }
}

#[derive(Debug, PartialEq, Eq, Hash)]
pub(crate) struct ModuleData {
    source: ModuleSource,
    parent: Option<LinkId>,
    children: Vec<LinkId>,
}

impl ModuleSource {
    pub(crate) fn new_inline(file_id: FileId, module: ast::Module) -> ModuleSource {
        assert!(!module.has_semi());
        let ptr = SyntaxPtr::new(file_id, module.syntax());
        ModuleSource::Module(ptr)
    }

    pub(crate) fn as_file(self) -> Option<FileId> {
        match self {
            ModuleSource::SourceFile(f) => Some(f),
            ModuleSource::Module(..) => None,
        }
    }

    pub(crate) fn file_id(self) -> FileId {
        match self {
            ModuleSource::SourceFile(f) => f,
            ModuleSource::Module(ptr) => ptr.file_id(),
        }
    }

    pub(crate) fn resolve(self, db: &impl SyntaxDatabase) -> ModuleSourceNode {
        match self {
            ModuleSource::SourceFile(file_id) => {
                let syntax = db.file_syntax(file_id);
                ModuleSourceNode::SourceFile(syntax.ast().owned())
            }
            ModuleSource::Module(ptr) => {
                let syntax = db.resolve_syntax_ptr(ptr);
                let syntax = syntax.borrowed();
                let module = ast::Module::cast(syntax).unwrap();
                ModuleSourceNode::Module(module.owned())
            }
        }
    }
}

#[derive(Hash, Debug, PartialEq, Eq)]
struct LinkData {
    owner: ModuleId,
    name: SmolStr,
    points_to: Vec<ModuleId>,
    problem: Option<Problem>,
}

impl ModuleTree {
    fn push_mod(&mut self, data: ModuleData) -> ModuleId {
        self.mods.alloc(data)
    }
    fn push_link(&mut self, data: LinkData) -> LinkId {
        let owner = data.owner;
        let id = self.links.alloc(data);
        self.mods[owner].children.push(id);
        id
    }
}
<commit_msg>Remove unused dead code<commit_after>pub(super) mod imp;
pub(super) mod nameres;

use std::sync::Arc;

use ra_editor::find_node_at_offset;

use ra_syntax::{
    algo::generate,
    ast::{self, AstNode, NameOwner},
    SmolStr, SyntaxNode,
};
use relative_path::RelativePathBuf;

use crate::{
    db::SyntaxDatabase, syntax_ptr::SyntaxPtr, FileId, FilePosition, Cancelable,
    hir::{Path, PathKind, HirDatabase},
    input::SourceRootId,
    arena::{Arena, Id},
    loc2id::{DefLoc, DefId},
};

pub(crate) use self::nameres::ModuleScope;

/// `Module` is API entry point to get all the information
/// about a particular module.
#[derive(Debug, Clone)]
pub(crate) struct Module {
    tree: Arc<ModuleTree>,
    source_root_id: SourceRootId,
    module_id: ModuleId,
}

impl Module {
    /// Lookup `Module` by `FileId`. Note that this is inherently
    /// lossy transformation: in general, a single source might correspond to
    /// several modules.
    pub fn guess_from_file_id(
        db: &impl HirDatabase,
        file_id: FileId,
    ) -> Cancelable<Option<Module>> {
        Module::guess_from_source(db, file_id, ModuleSource::SourceFile(file_id))
    }

    /// Lookup `Module` by position in the source code. Note that this
    /// is inherently lossy transformation: in general, a single source might
    /// correspond to several modules.
    pub fn guess_from_position(
        db: &impl HirDatabase,
        position: FilePosition,
    ) -> Cancelable<Option<Module>> {
        let file = db.file_syntax(position.file_id);
        let module_source = match find_node_at_offset::<ast::Module>(file.syntax(), position.offset)
        {
            Some(m) if !m.has_semi() => ModuleSource::new_inline(position.file_id, m),
            _ => ModuleSource::SourceFile(position.file_id),
        };
        Module::guess_from_source(db, position.file_id, module_source)
    }

    fn guess_from_source(
        db: &impl HirDatabase,
        file_id: FileId,
        module_source: ModuleSource,
    ) -> Cancelable<Option<Module>> {
        let source_root_id = db.file_source_root(file_id);
        let module_tree = db.module_tree(source_root_id)?;

        let res = match module_tree.any_module_for_source(module_source) {
            None => None,
            Some(module_id) => Some(Module {
                tree: module_tree,
                source_root_id,
                module_id,
            }),
        };
        Ok(res)
    }

    pub(super) fn new(
        db: &impl HirDatabase,
        source_root_id: SourceRootId,
        module_id: ModuleId,
    ) -> Cancelable<Module> {
        let module_tree = db.module_tree(source_root_id)?;
        let res = Module {
            tree: module_tree,
            source_root_id,
            module_id,
        };
        Ok(res)
    }

    /// Returns `mod foo;` or `mod foo {}` node whihc declared this module.
    /// Returns `None` for the root module
    pub fn parent_link_source(&self, db: &impl HirDatabase) -> Option<(FileId, ast::ModuleNode)> {
        let link = self.module_id.parent_link(&self.tree)?;
        let file_id = link.owner(&self.tree).source(&self.tree).file_id();
        let src = link.bind_source(&self.tree, db);
        Some((file_id, src))
    }

    pub fn source(&self) -> ModuleSource {
        self.module_id.source(&self.tree)
    }

    /// Parent module. Returns `None` if this is a root module.
    pub fn parent(&self) -> Option<Module> {
        let parent_id = self.module_id.parent(&self.tree)?;
        Some(Module {
            module_id: parent_id,
            ..self.clone()
        })
    }

    /// The root of the tree this module is part of
    pub fn crate_root(&self) -> Module {
        let root_id = self.module_id.crate_root(&self.tree);
        Module {
            module_id: root_id,
            ..self.clone()
        }
    }

    /// `name` is `None` for the crate's root module
    #[allow(unused)]
    pub fn name(&self) -> Option<SmolStr> {
        let link = self.module_id.parent_link(&self.tree)?;
        Some(link.name(&self.tree))
    }

    pub fn def_id(&self, db: &impl HirDatabase) -> DefId {
        let def_loc = DefLoc::Module {
            id: self.module_id,
            source_root: self.source_root_id,
        };
        db.id_maps().def_id(def_loc)
    }

    /// Finds a child module with the specified name.
    pub fn child(&self, name: &str) -> Option<Module> {
        let child_id = self.module_id.child(&self.tree, name)?;
        Some(Module {
            module_id: child_id,
            ..self.clone()
        })
    }

    /// Returns a `ModuleScope`: a set of items, visible in this module.
    pub(crate) fn scope(&self, db: &impl HirDatabase) -> Cancelable<ModuleScope> {
        let item_map = db.item_map(self.source_root_id)?;
        let res = item_map.per_module[&self.module_id].clone();
        Ok(res)
    }

    pub(crate) fn resolve_path(
        &self,
        db: &impl HirDatabase,
        path: Path,
    ) -> Cancelable<Option<DefId>> {
        let mut curr = match path.kind {
            PathKind::Crate => self.crate_root(),
            PathKind::Self_ | PathKind::Plain => self.clone(),
            PathKind::Super => ctry!(self.parent()),
        }
        .def_id(db);

        let segments = path.segments;
        for name in segments.iter() {
            let module = match db.id_maps().def_loc(curr) {
                DefLoc::Module { id, source_root } => Module::new(db, source_root, id)?,
                _ => return Ok(None),
            };
            let scope = module.scope(db)?;
            curr = ctry!(ctry!(scope.get(&name)).def_id);
        }
        Ok(Some(curr))
    }

    pub fn problems(&self, db: &impl HirDatabase) -> Vec<(SyntaxNode, Problem)> {
        self.module_id.problems(&self.tree, db)
    }
}

/// Phisically, rust source is organized as a set of files, but logically it is
/// organized as a tree of modules. Usually, a single file corresponds to a
/// single module, but it is not nessary the case.
///
/// Module encapsulate the logic of transitioning from the fuzzy world of files
/// (which can have multiple parents) to the precise world of modules (which
/// always have one parent).
#[derive(Default, Debug, PartialEq, Eq)]
pub(crate) struct ModuleTree {
    mods: Arena<ModuleData>,
    links: Arena<LinkData>,
}

impl ModuleTree {
    pub(in crate::hir) fn modules<'a>(&'a self) -> impl Iterator<Item = ModuleId> + 'a {
        self.mods.iter().map(|(id, _)| id)
    }

    fn modules_for_source(&self, source: ModuleSource) -> Vec<ModuleId> {
        self.mods
            .iter()
            .filter(|(_idx, it)| it.source == source)
            .map(|(idx, _)| idx)
            .collect()
    }

    fn any_module_for_source(&self, source: ModuleSource) -> Option<ModuleId> {
        self.modules_for_source(source).pop()
    }
}

/// `ModuleSource` is the syntax tree element that produced this module:
/// either a file, or an inlinde module.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub(crate) enum ModuleSource {
    SourceFile(FileId),
    Module(SyntaxPtr),
}

/// An owned syntax node for a module. Unlike `ModuleSource`,
/// this holds onto the AST for the whole file.
pub(crate) enum ModuleSourceNode {
    SourceFile(ast::SourceFileNode),
    Module(ast::ModuleNode),
}

pub(crate) type ModuleId = Id<ModuleData>;
type LinkId = Id<LinkData>;

#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub enum Problem {
    UnresolvedModule {
        candidate: RelativePathBuf,
    },
    NotDirOwner {
        move_to: RelativePathBuf,
        candidate: RelativePathBuf,
    },
}

impl ModuleId {
    pub(in crate::hir) fn source(self, tree: &ModuleTree) -> ModuleSource {
        tree.mods[self].source
    }
    fn parent_link(self, tree: &ModuleTree) -> Option<LinkId> {
        tree.mods[self].parent
    }
    fn parent(self, tree: &ModuleTree) -> Option<ModuleId> {
        let link = self.parent_link(tree)?;
        Some(tree.links[link].owner)
    }
    fn crate_root(self, tree: &ModuleTree) -> ModuleId {
        generate(Some(self), move |it| it.parent(tree))
            .last()
            .unwrap()
    }
    fn child(self, tree: &ModuleTree, name: &str) -> Option<ModuleId> {
        let link = tree.mods[self]
            .children
            .iter()
            .map(|&it| &tree.links[it])
            .find(|it| it.name == name)?;
        Some(*link.points_to.first()?)
    }
    fn children<'a>(self, tree: &'a ModuleTree) -> impl Iterator<Item = (SmolStr, ModuleId)> + 'a {
        tree.mods[self].children.iter().filter_map(move |&it| {
            let link = &tree.links[it];
            let module = *link.points_to.first()?;
            Some((link.name.clone(), module))
        })
    }
    fn problems(self, tree: &ModuleTree, db: &impl SyntaxDatabase) -> Vec<(SyntaxNode, Problem)> {
        tree.mods[self]
            .children
            .iter()
            .filter_map(|&it| {
                let p = tree.links[it].problem.clone()?;
                let s = it.bind_source(tree, db);
                let s = s.borrowed().name().unwrap().syntax().owned();
                Some((s, p))
            })
            .collect()
    }
}

impl LinkId {
    fn owner(self, tree: &ModuleTree) -> ModuleId {
        tree.links[self].owner
    }
    fn name(self, tree: &ModuleTree) -> SmolStr {
        tree.links[self].name.clone()
    }
    fn bind_source<'a>(self, tree: &ModuleTree, db: &impl SyntaxDatabase) -> ast::ModuleNode {
        let owner = self.owner(tree);
        match owner.source(tree).resolve(db) {
            ModuleSourceNode::SourceFile(root) => {
                let ast = imp::modules(root.borrowed())
                    .find(|(name, _)| name == &tree.links[self].name)
                    .unwrap()
                    .1;
                ast.owned()
            }
            ModuleSourceNode::Module(it) => it,
        }
    }
}

#[derive(Debug, PartialEq, Eq, Hash)]
pub(crate) struct ModuleData {
    source: ModuleSource,
    parent: Option<LinkId>,
    children: Vec<LinkId>,
}

impl ModuleSource {
    pub(crate) fn new_inline(file_id: FileId, module: ast::Module) -> ModuleSource {
        assert!(!module.has_semi());
        let ptr = SyntaxPtr::new(file_id, module.syntax());
        ModuleSource::Module(ptr)
    }

    pub(crate) fn as_file(self) -> Option<FileId> {
        match self {
            ModuleSource::SourceFile(f) => Some(f),
            ModuleSource::Module(..) => None,
        }
    }

    pub(crate) fn file_id(self) -> FileId {
        match self {
            ModuleSource::SourceFile(f) => f,
            ModuleSource::Module(ptr) => ptr.file_id(),
        }
    }

    pub(crate) fn resolve(self, db: &impl SyntaxDatabase) -> ModuleSourceNode {
        match self {
            ModuleSource::SourceFile(file_id) => {
                let syntax = db.file_syntax(file_id);
                ModuleSourceNode::SourceFile(syntax.ast().owned())
            }
            ModuleSource::Module(ptr) => {
                let syntax = db.resolve_syntax_ptr(ptr);
                let syntax = syntax.borrowed();
                let module = ast::Module::cast(syntax).unwrap();
                ModuleSourceNode::Module(module.owned())
            }
        }
    }
}

#[derive(Hash, Debug, PartialEq, Eq)]
struct LinkData {
    owner: ModuleId,
    name: SmolStr,
    points_to: Vec<ModuleId>,
    problem: Option<Problem>,
}

impl ModuleTree {
    fn push_mod(&mut self, data: ModuleData) -> ModuleId {
        self.mods.alloc(data)
    }
    fn push_link(&mut self, data: LinkData) -> LinkId {
        let owner = data.owner;
        let id = self.links.alloc(data);
        self.mods[owner].children.push(id);
        id
    }
}
<|endoftext|>


<commit_before>use {success,expect,Matcher,MatchResult,SelfDescribing};

pub enum PathType {
  AnyType,
  File,
  Dir
}

pub struct ExistingPath {
  path_type: PathType
}

impl ExistingPath {
  fn match_path_type(&self, actual: &Path) -> MatchResult {
    match self.path_type {
      File => expect(actual.is_file(), format!("`{}` was not a file", actual.display())),
      Dir => expect(actual.is_dir(), format!("`{}` was not a dir", actual.display())),
      _ => success()
    }
  }
}

impl SelfDescribing for ExistingPath {
  fn describe(&self) -> String {
    "an existing file".to_string()
  }
}

impl<'a> Matcher<&'a Path> for ExistingPath {
  fn matches(&self, actual: &Path) -> MatchResult {
    expect(actual.exists(), format!("{} was missing", actual.display()))
      .and(self.match_path_type(actual))
  }
}

pub fn existing_path() -> ExistingPath {
  ExistingPath { path_type: AnyType }
}

pub fn existing_file() -> ExistingPath {
  ExistingPath { path_type: File }
}

pub fn existing_dir() -> ExistingPath {
  ExistingPath { path_type: Dir }
}

#[cfg(test)]
mod test {
  use std::os;
  use {assert_that,is,is_not,existing_file,existing_dir,existing_path};

  #[test]
  fn test_with_existing_file() {
    let path = path(os::getenv("TEST_EXISTS_FILE"), "./README.md");

    assert_that(&path, is(existing_path()));
    assert_that(&path, is(existing_file()));
    assert_that(&path, is_not(existing_dir()));
  }

  #[test]
  fn test_with_existing_dir() {
    let path = path(os::getenv("TEST_EXISTS_DIR"), "./target");

    assert_that(&path, is(existing_path()));
    assert_that(&path, is(existing_dir()));
    assert_that(&path, is_not(existing_file()));
  }

  #[test]
  fn test_with_nonexisting_path() {
    let path = path(os::getenv("TEST_EXISTS_NONE"), "./zomg.txt");

    assert_that(&path, is_not(existing_path()));
    assert_that(&path, is_not(existing_file()));
    assert_that(&path, is_not(existing_dir()));
  }

  fn path(path: Option<String>, default: &str) -> Path {
    Path::new(path.unwrap_or(default.to_string()))
  }
}
<commit_msg>Update to master<commit_after>use {success,expect,Matcher,MatchResult,SelfDescribing};
use std::io::fs::PathExtensions;

pub enum PathType {
  AnyType,
  File,
  Dir
}

pub struct ExistingPath {
  path_type: PathType
}

impl ExistingPath {
  fn match_path_type(&self, actual: &Path) -> MatchResult {
    match self.path_type {
      File => expect(actual.is_file(), format!("`{}` was not a file", actual.display())),
      Dir => expect(actual.is_dir(), format!("`{}` was not a dir", actual.display())),
      _ => success()
    }
  }
}

impl SelfDescribing for ExistingPath {
  fn describe(&self) -> String {
    "an existing file".to_string()
  }
}

impl<'a> Matcher<&'a Path> for ExistingPath {
  fn matches(&self, actual: &Path) -> MatchResult {
    expect(actual.exists(), format!("{} was missing", actual.display()))
      .and(self.match_path_type(actual))
  }
}

pub fn existing_path() -> ExistingPath {
  ExistingPath { path_type: AnyType }
}

pub fn existing_file() -> ExistingPath {
  ExistingPath { path_type: File }
}

pub fn existing_dir() -> ExistingPath {
  ExistingPath { path_type: Dir }
}

#[cfg(test)]
mod test {
  use std::os;
  use {assert_that,is,is_not,existing_file,existing_dir,existing_path};

  #[test]
  fn test_with_existing_file() {
    let path = path(os::getenv("TEST_EXISTS_FILE"), "./README.md");

    assert_that(&path, is(existing_path()));
    assert_that(&path, is(existing_file()));
    assert_that(&path, is_not(existing_dir()));
  }

  #[test]
  fn test_with_existing_dir() {
    let path = path(os::getenv("TEST_EXISTS_DIR"), "./target");

    assert_that(&path, is(existing_path()));
    assert_that(&path, is(existing_dir()));
    assert_that(&path, is_not(existing_file()));
  }

  #[test]
  fn test_with_nonexisting_path() {
    let path = path(os::getenv("TEST_EXISTS_NONE"), "./zomg.txt");

    assert_that(&path, is_not(existing_path()));
    assert_that(&path, is_not(existing_file()));
    assert_that(&path, is_not(existing_dir()));
  }

  fn path(path: Option<String>, default: &str) -> Path {
    Path::new(path.unwrap_or(default.to_string()))
  }
}
<|endoftext|>


<commit_before>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// Test how resolving a projection interacts with inference.  In this
// case, we were eagerly unifying the type variable for the iterator
// type with `I` from the where clause, ignoring the in-scope `impl`
// for `ByRef`. The right answer was to consider the result ambiguous
// until more type information was available.

#![feature(associated_types, lang_items, unboxed_closures)]
#![no_implicit_prelude]

use std::option::Option::{None, Some, mod};

trait Iterator {
    type Item;

    fn next(&mut self) -> Option<Self::Item>;
}

trait IteratorExt: Iterator {
    fn by_ref(&mut self) -> ByRef<Self> {
        ByRef(self)
    }
}

impl<I> IteratorExt for I where I: Iterator {}

struct ByRef<'a, I: 'a + Iterator>(&'a mut I);

impl<'a, A, I> Iterator for ByRef<'a, I> where I: Iterator<Item=A> {
    type Item = A;

    fn next(&mut self) -> Option< <I as Iterator>::Item > {
        self.0.next()
    }
}

fn is_iterator_of<A, I: Iterator<Item=A>>(_: &I) {}

fn test<A, I: Iterator<Item=A>>(mut it: I) {
    is_iterator_of::<A, _>(&it.by_ref());
}

fn main() { }
<commit_msg>Add ignore pretty.<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// Test how resolving a projection interacts with inference.  In this
// case, we were eagerly unifying the type variable for the iterator
// type with `I` from the where clause, ignoring the in-scope `impl`
// for `ByRef`. The right answer was to consider the result ambiguous
// until more type information was available.

// ignore-pretty -- FIXME(#17362) pretty prints with `<<` which lexes wrong

#![feature(associated_types, lang_items, unboxed_closures)]
#![no_implicit_prelude]

use std::option::Option::{None, Some, mod};

trait Iterator {
    type Item;

    fn next(&mut self) -> Option<Self::Item>;
}

trait IteratorExt: Iterator {
    fn by_ref(&mut self) -> ByRef<Self> {
        ByRef(self)
    }
}

impl<I> IteratorExt for I where I: Iterator {}

struct ByRef<'a, I: 'a + Iterator>(&'a mut I);

impl<'a, A, I> Iterator for ByRef<'a, I> where I: Iterator<Item=A> {
    type Item = A;

    fn next(&mut self) -> Option< <I as Iterator>::Item > {
        self.0.next()
    }
}

fn is_iterator_of<A, I: Iterator<Item=A>>(_: &I) {}

fn test<A, I: Iterator<Item=A>>(mut it: I) {
    is_iterator_of::<A, _>(&it.by_ref());
}

fn main() { }
<|endoftext|>


<commit_before>// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#[cfg(not(windows))]
pub fn cmd(name: &str) -> String {
    name.to_string()
}

#[cfg(windows)]
pub fn cmd(name: &str) -> String {
    [name, ".bat"].concat()
}
<commit_msg>Use cfg!() to get type checking everywhere.<commit_after>// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

pub fn cmd(name: &str) -> String {
    if cfg!(windows) {
        format!("{}.bat", name)
    } else {
        name.to_string()
    }
}
<|endoftext|>


<commit_before>use fallible_iterator::FallibleIterator;
use geo_types_04::{Coordinate, LineString, Point, Rect};
use postgres_protocol::types;
use std::error::Error;

use crate::types::{FromSql, IsNull, ToSql, Type};

impl<'a> FromSql<'a> for Point<f64> {
    fn from_sql(_: &Type, raw: &[u8]) -> Result<Self, Box<dyn Error + Sync + Send>> {
        let point = types::point_from_sql(raw)?;
        Ok(Point::new(point.x(), point.y()))
    }

    accepts!(POINT);
}

impl ToSql for Point<f64> {
    fn to_sql(&self, _: &Type, out: &mut Vec<u8>) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
        types::point_to_sql(self.x(), self.y(), out);
        Ok(IsNull::No)
    }

    accepts!(POINT);
    to_sql_checked!();
}

impl<'a> FromSql<'a> for Rect<f64> {
    fn from_sql(_: &Type, raw: &[u8]) -> Result<Self, Box<dyn Error + Sync + Send>> {
        let rect = types::box_from_sql(raw)?;
        Ok(Rect {
            min: Coordinate {
                x: rect.lower_left().x(),
                y: rect.lower_left().y(),
            },
            max: Coordinate {
                x: rect.upper_right().x(),
                y: rect.upper_right().y(),
            },
        })
    }

    accepts!(BOX);
}

impl ToSql for Rect<f64> {
    fn to_sql(&self, _: &Type, out: &mut Vec<u8>) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
        types::box_to_sql(self.min.x, self.min.y, self.max.x, self.max.y, out);
        Ok(IsNull::No)
    }

    accepts!(BOX);
    to_sql_checked!();
}

impl<'a> FromSql<'a> for LineString<f64> {
    fn from_sql(_: &Type, raw: &[u8]) -> Result<Self, Box<dyn Error + Sync + Send>> {
        let path = types::path_from_sql(raw)?;
        let points = path
            .points()
            .map(|p| Coordinate { x: p.x(), y: p.y() })
            .collect()?;
        Ok(LineString(points))
    }

    accepts!(PATH);
}

impl ToSql for LineString<f64> {
    fn to_sql(&self, _: &Type, out: &mut Vec<u8>) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
        let closed = false; // always encode an open path from LineString
        types::path_to_sql(closed, self.0.iter().map(|p| (p.x, p.y)), out)?;
        Ok(IsNull::No)
    }

    accepts!(PATH);
    to_sql_checked!();
}
<commit_msg>Fix build<commit_after>use fallible_iterator::FallibleIterator;
use geo_types_04::{Coordinate, LineString, Point, Rect};
use postgres_protocol::types;
use std::error::Error;

use crate::types::{FromSql, IsNull, ToSql, Type};

impl<'a> FromSql<'a> for Point<f64> {
    fn from_sql(_: &Type, raw: &[u8]) -> Result<Self, Box<dyn Error + Sync + Send>> {
        let point = types::point_from_sql(raw)?;
        Ok(Point::new(point.x(), point.y()))
    }

    accepts!(POINT);
}

impl ToSql for Point<f64> {
    fn to_sql(&self, _: &Type, out: &mut Vec<u8>) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
        types::point_to_sql(self.x(), self.y(), out);
        Ok(IsNull::No)
    }

    accepts!(POINT);
    to_sql_checked!();
}

impl<'a> FromSql<'a> for Rect<f64> {
    fn from_sql(_: &Type, raw: &[u8]) -> Result<Self, Box<dyn Error + Sync + Send>> {
        let rect = types::box_from_sql(raw)?;
        Ok(Rect {
            min: Coordinate {
                x: rect.lower_left().x(),
                y: rect.lower_left().y(),
            },
            max: Coordinate {
                x: rect.upper_right().x(),
                y: rect.upper_right().y(),
            },
        })
    }

    accepts!(BOX);
}

impl ToSql for Rect<f64> {
    fn to_sql(&self, _: &Type, out: &mut Vec<u8>) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
        types::box_to_sql(self.min.x, self.min.y, self.max.x, self.max.y, out);
        Ok(IsNull::No)
    }

    accepts!(BOX);
    to_sql_checked!();
}

impl<'a> FromSql<'a> for LineString<f64> {
    fn from_sql(_: &Type, raw: &[u8]) -> Result<Self, Box<dyn Error + Sync + Send>> {
        let path = types::path_from_sql(raw)?;
        let points = path
            .points()
            .map(|p| Ok(Coordinate { x: p.x(), y: p.y() }))
            .collect()?;
        Ok(LineString(points))
    }

    accepts!(PATH);
}

impl ToSql for LineString<f64> {
    fn to_sql(&self, _: &Type, out: &mut Vec<u8>) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
        let closed = false; // always encode an open path from LineString
        types::path_to_sql(closed, self.0.iter().map(|p| (p.x, p.y)), out)?;
        Ok(IsNull::No)
    }

    accepts!(PATH);
    to_sql_checked!();
}
<|endoftext|>


<commit_before>#![cfg(not(feature = "preserve_order"))]

use serde_json::{json, Deserializer, Value};

// Rustfmt issue https://github.com/rust-lang-nursery/rustfmt/issues/2740
#[cfg_attr(rustfmt, rustfmt_skip)]
macro_rules! test_stream {
    ($data:expr, $ty:ty, |$stream:ident| $test:block) => {
        {
            let de = Deserializer::from_str($data);
            let mut $stream = de.into_iter::<$ty>();
            assert_eq!($stream.byte_offset(), 0);
            $test
        }
        {
            let de = Deserializer::from_slice($data.as_bytes());
            let mut $stream = de.into_iter::<$ty>();
            assert_eq!($stream.byte_offset(), 0);
            $test
        }
        {
            let mut bytes = $data.as_bytes();
            let de = Deserializer::from_reader(&mut bytes);
            let mut $stream = de.into_iter::<$ty>();
            assert_eq!($stream.byte_offset(), 0);
            $test
        }
    };
}

#[test]
fn test_json_stream_newlines() {
    let data = "{\"x\":39} {\"x\":40}{\"x\":41}\n{\"x\":42}";

    test_stream!(data, Value, |stream| {
        assert_eq!(stream.next().unwrap().unwrap()["x"], 39);
        assert_eq!(stream.byte_offset(), 8);

        assert_eq!(stream.next().unwrap().unwrap()["x"], 40);
        assert_eq!(stream.byte_offset(), 17);

        assert_eq!(stream.next().unwrap().unwrap()["x"], 41);
        assert_eq!(stream.byte_offset(), 25);

        assert_eq!(stream.next().unwrap().unwrap()["x"], 42);
        assert_eq!(stream.byte_offset(), 34);

        assert!(stream.next().is_none());
        assert_eq!(stream.byte_offset(), 34);
    });
}

#[test]
fn test_json_stream_trailing_whitespaces() {
    let data = "{\"x\":42} \t\n";

    test_stream!(data, Value, |stream| {
        assert_eq!(stream.next().unwrap().unwrap()["x"], 42);
        assert_eq!(stream.byte_offset(), 8);

        assert!(stream.next().is_none());
        assert_eq!(stream.byte_offset(), 11);
    });
}

#[test]
fn test_json_stream_truncated() {
    let data = "{\"x\":40}\n{\"x\":";

    test_stream!(data, Value, |stream| {
        assert_eq!(stream.next().unwrap().unwrap()["x"], 40);
        assert_eq!(stream.byte_offset(), 8);

        assert!(stream.next().unwrap().unwrap_err().is_eof());
        assert_eq!(stream.byte_offset(), 9);
    });
}

#[test]
fn test_json_stream_truncated_decimal() {
    let data = "{\"x\":4.";

    test_stream!(data, Value, |stream| {
        assert!(stream.next().unwrap().unwrap_err().is_eof());
        assert_eq!(stream.byte_offset(), 0);
    });
}

#[test]
fn test_json_stream_truncated_negative() {
    let data = "{\"x\":-";

    test_stream!(data, Value, |stream| {
        assert!(stream.next().unwrap().unwrap_err().is_eof());
        assert_eq!(stream.byte_offset(), 0);
    });
}

#[test]
fn test_json_stream_truncated_exponent() {
    let data = "{\"x\":4e";

    test_stream!(data, Value, |stream| {
        assert!(stream.next().unwrap().unwrap_err().is_eof());
        assert_eq!(stream.byte_offset(), 0);
    });
}

#[test]
fn test_json_stream_empty() {
    let data = "";

    test_stream!(data, Value, |stream| {
        assert!(stream.next().is_none());
        assert_eq!(stream.byte_offset(), 0);
    });
}

#[test]
fn test_json_stream_primitive() {
    let data = "{} true{}1[]\nfalse\"hey\"2 ";

    test_stream!(data, Value, |stream| {
        assert_eq!(stream.next().unwrap().unwrap(), json!({}));
        assert_eq!(stream.byte_offset(), 2);

        assert_eq!(stream.next().unwrap().unwrap(), true);
        assert_eq!(stream.byte_offset(), 7);

        assert_eq!(stream.next().unwrap().unwrap(), json!({}));
        assert_eq!(stream.byte_offset(), 9);

        assert_eq!(stream.next().unwrap().unwrap(), 1);
        assert_eq!(stream.byte_offset(), 10);

        assert_eq!(stream.next().unwrap().unwrap(), json!([]));
        assert_eq!(stream.byte_offset(), 12);

        assert_eq!(stream.next().unwrap().unwrap(), false);
        assert_eq!(stream.byte_offset(), 18);

        assert_eq!(stream.next().unwrap().unwrap(), "hey");
        assert_eq!(stream.byte_offset(), 23);

        assert_eq!(stream.next().unwrap().unwrap(), 2);
        assert_eq!(stream.byte_offset(), 24);

        assert!(stream.next().is_none());
        assert_eq!(stream.byte_offset(), 25);
    });
}

#[test]
fn test_json_stream_invalid_literal() {
    let data = "truefalse";

    test_stream!(data, Value, |stream| {
        let second = stream.next().unwrap().unwrap_err();
        assert_eq!(second.to_string(), "trailing characters at line 1 column 5");
    });
}

#[test]
fn test_json_stream_invalid_number() {
    let data = "1true";

    test_stream!(data, Value, |stream| {
        let second = stream.next().unwrap().unwrap_err();
        assert_eq!(second.to_string(), "trailing characters at line 1 column 2");
    });
}
<commit_msg>Switch rustfmt skip to tool attribute<commit_after>#![cfg(not(feature = "preserve_order"))]

use serde_json::{json, Deserializer, Value};

// Rustfmt issue https://github.com/rust-lang-nursery/rustfmt/issues/2740
#[rustfmt::skip]
macro_rules! test_stream {
    ($data:expr, $ty:ty, |$stream:ident| $test:block) => {
        {
            let de = Deserializer::from_str($data);
            let mut $stream = de.into_iter::<$ty>();
            assert_eq!($stream.byte_offset(), 0);
            $test
        }
        {
            let de = Deserializer::from_slice($data.as_bytes());
            let mut $stream = de.into_iter::<$ty>();
            assert_eq!($stream.byte_offset(), 0);
            $test
        }
        {
            let mut bytes = $data.as_bytes();
            let de = Deserializer::from_reader(&mut bytes);
            let mut $stream = de.into_iter::<$ty>();
            assert_eq!($stream.byte_offset(), 0);
            $test
        }
    };
}

#[test]
fn test_json_stream_newlines() {
    let data = "{\"x\":39} {\"x\":40}{\"x\":41}\n{\"x\":42}";

    test_stream!(data, Value, |stream| {
        assert_eq!(stream.next().unwrap().unwrap()["x"], 39);
        assert_eq!(stream.byte_offset(), 8);

        assert_eq!(stream.next().unwrap().unwrap()["x"], 40);
        assert_eq!(stream.byte_offset(), 17);

        assert_eq!(stream.next().unwrap().unwrap()["x"], 41);
        assert_eq!(stream.byte_offset(), 25);

        assert_eq!(stream.next().unwrap().unwrap()["x"], 42);
        assert_eq!(stream.byte_offset(), 34);

        assert!(stream.next().is_none());
        assert_eq!(stream.byte_offset(), 34);
    });
}

#[test]
fn test_json_stream_trailing_whitespaces() {
    let data = "{\"x\":42} \t\n";

    test_stream!(data, Value, |stream| {
        assert_eq!(stream.next().unwrap().unwrap()["x"], 42);
        assert_eq!(stream.byte_offset(), 8);

        assert!(stream.next().is_none());
        assert_eq!(stream.byte_offset(), 11);
    });
}

#[test]
fn test_json_stream_truncated() {
    let data = "{\"x\":40}\n{\"x\":";

    test_stream!(data, Value, |stream| {
        assert_eq!(stream.next().unwrap().unwrap()["x"], 40);
        assert_eq!(stream.byte_offset(), 8);

        assert!(stream.next().unwrap().unwrap_err().is_eof());
        assert_eq!(stream.byte_offset(), 9);
    });
}

#[test]
fn test_json_stream_truncated_decimal() {
    let data = "{\"x\":4.";

    test_stream!(data, Value, |stream| {
        assert!(stream.next().unwrap().unwrap_err().is_eof());
        assert_eq!(stream.byte_offset(), 0);
    });
}

#[test]
fn test_json_stream_truncated_negative() {
    let data = "{\"x\":-";

    test_stream!(data, Value, |stream| {
        assert!(stream.next().unwrap().unwrap_err().is_eof());
        assert_eq!(stream.byte_offset(), 0);
    });
}

#[test]
fn test_json_stream_truncated_exponent() {
    let data = "{\"x\":4e";

    test_stream!(data, Value, |stream| {
        assert!(stream.next().unwrap().unwrap_err().is_eof());
        assert_eq!(stream.byte_offset(), 0);
    });
}

#[test]
fn test_json_stream_empty() {
    let data = "";

    test_stream!(data, Value, |stream| {
        assert!(stream.next().is_none());
        assert_eq!(stream.byte_offset(), 0);
    });
}

#[test]
fn test_json_stream_primitive() {
    let data = "{} true{}1[]\nfalse\"hey\"2 ";

    test_stream!(data, Value, |stream| {
        assert_eq!(stream.next().unwrap().unwrap(), json!({}));
        assert_eq!(stream.byte_offset(), 2);

        assert_eq!(stream.next().unwrap().unwrap(), true);
        assert_eq!(stream.byte_offset(), 7);

        assert_eq!(stream.next().unwrap().unwrap(), json!({}));
        assert_eq!(stream.byte_offset(), 9);

        assert_eq!(stream.next().unwrap().unwrap(), 1);
        assert_eq!(stream.byte_offset(), 10);

        assert_eq!(stream.next().unwrap().unwrap(), json!([]));
        assert_eq!(stream.byte_offset(), 12);

        assert_eq!(stream.next().unwrap().unwrap(), false);
        assert_eq!(stream.byte_offset(), 18);

        assert_eq!(stream.next().unwrap().unwrap(), "hey");
        assert_eq!(stream.byte_offset(), 23);

        assert_eq!(stream.next().unwrap().unwrap(), 2);
        assert_eq!(stream.byte_offset(), 24);

        assert!(stream.next().is_none());
        assert_eq!(stream.byte_offset(), 25);
    });
}

#[test]
fn test_json_stream_invalid_literal() {
    let data = "truefalse";

    test_stream!(data, Value, |stream| {
        let second = stream.next().unwrap().unwrap_err();
        assert_eq!(second.to_string(), "trailing characters at line 1 column 5");
    });
}

#[test]
fn test_json_stream_invalid_number() {
    let data = "1true";

    test_stream!(data, Value, |stream| {
        let second = stream.next().unwrap().unwrap_err();
        assert_eq!(second.to_string(), "trailing characters at line 1 column 2");
    });
}
<|endoftext|>


<commit_before>export method;
export request;

enum method {
    HEAD,
    GET,
    POST,
    PUT,
    DELETE,
    TRACE,
    OPTIONS,
    CONNECT,
    PATCH
}

type request<T> = {
    req: @mongrel2::request,
    method: method,
    cookies: hashmap<str, cookie::cookie>,
    mut data: T,
};

fn request<T: copy>(req: @mongrel2::request, rep: @response, data: T)
  -> option<@request<T>> {
    let method = alt req.headers.find("METHOD") {
      none {
        rep.http_400("");
        ret none
      }
      some(methods) {
        alt methods[0] {
          "HEAD" { HEAD }
          "GET" { GET }
          "POST" { POST }
          "PUT" { PUT }
          "DELETE" { DELETE }
          "TRACE" { TRACE }
          "OPTIONS" { OPTIONS }
          "CONNECT" { CONNECT }
          "PATCH" { PATCH }
          _ {
            rep.http_501("");
            ret none
          }
        }
      }
    };

    let cookies = alt req.headers.find("cookie") {
      none { str_hash() }
      some(cookies) {
        alt cookie::parse_headers(cookies) {
          ok(cookies) { cookies }
          err(e) {
            rep.http_400(e);
            ret none
          }
        }
      }
    };

    some(@{
        req: req,
        method: method,
        cookies: cookies,
        mut data: data,
    })
}

impl request<T: copy> for @request<T> {
    fn body() -> [u8] {
        self.req.body
    }

    fn path() -> str {
        self.req.path
    }

    fn is_disconnect() -> bool {
        import mongrel2::request;
        self.req.is_disconnect()
    }

    fn find_headers(key: str) -> option<[str]> {
        self.req.headers.find(key)
    }

    fn find_header(key: str) -> option<str> {
        self.find_headers(key).chain { |values|
            if values.len() == 0u {
                none
            } else {
                some(values[0])
            }
        }
    }
}
<commit_msg>Add a Accept request header parser.<commit_after>import std::sort;

export method;
export accept;
export request;

enum method {
    HEAD,
    GET,
    POST,
    PUT,
    DELETE,
    TRACE,
    OPTIONS,
    CONNECT,
    PATCH
}

type accept = {
    mime_type: (str, str),
    quality: float,
    options: [str],
};

type request<T> = {
    req: @mongrel2::request,
    method: method,
    cookies: hashmap<str, cookie::cookie>,
    mut data: T,
    mut _accepts: option<[accept]>,
};

fn request<T: copy>(req: @mongrel2::request, rep: @response, data: T)
  -> option<@request<T>> {
    let method = alt req.headers.find("METHOD") {
      none {
        rep.http_400("");
        ret none
      }
      some(methods) {
        alt methods[0] {
          "HEAD" { HEAD }
          "GET" { GET }
          "POST" { POST }
          "PUT" { PUT }
          "DELETE" { DELETE }
          "TRACE" { TRACE }
          "OPTIONS" { OPTIONS }
          "CONNECT" { CONNECT }
          "PATCH" { PATCH }
          _ {
            rep.http_501("");
            ret none
          }
        }
      }
    };

    let cookies = alt req.headers.find("cookie") {
      none { str_hash() }
      some(cookies) {
        alt cookie::parse_headers(cookies) {
          ok(cookies) { cookies }
          err(e) {
            rep.http_400(e);
            ret none
          }
        }
      }
    };

    some(@{
        req: req,
        method: method,
        cookies: cookies,
        mut data: data,
        mut _accepts: none,
    })
}

#[doc = "Split a mime string into the mime type and subtype."]
fn parse_mime_type(mime_type: str) -> (str, str) {
    let parts = str::splitn_char(mime_type, '/', 1u);
    let typ = parts[0];
    let subtyp = if parts.len() == 2u { parts[1] } else { "*" };

    (typ, subtyp)
}

#[doc = ""]
fn parse_accept_header(header: str) -> [accept] {
    let accepts = header.split_char(',').map { |e|
        let parts = str::replace(e, " ", "").split_char(';');

        let mime_type = parse_mime_type(parts[0]);
        let mut quality = 1.0;
        let mut options = [];

        if parts.len() > 1u {
            vec::iter_between(parts, 1u, parts.len()) { |option|
                if option.starts_with("q=") {
                    let q = option.substr(2u, option.len() - 2u);
                    alt float::from_str(q) {
                      none { /* Ignore invalid quality values. */ }
                      some(q) { quality = q; }
                    }
                } else {
                    vec::push(options, option);
                }
            }
        }

        { mime_type: mime_type, quality: quality, options: options }
    };

    // Sort by quality, with highest quality first.
    sort::merge_sort({ |e1, e2| e1.quality >= e2.quality }, accepts)
}

impl request<T: copy> for @request<T> {
    fn body() -> [u8] {
        self.req.body
    }

    fn path() -> str {
        self.req.path
    }

    fn is_disconnect() -> bool {
        import mongrel2::request;
        self.req.is_disconnect()
    }

    fn find_headers(key: str) -> option<[str]> {
        self.req.headers.find(key)
    }

    fn find_header(key: str) -> option<str> {
        self.find_headers(key).chain { |values|
            if values.len() == 0u {
                none
            } else {
                some(values[0])
            }
        }
    }

    fn content_type() -> option<str> {
        self.find_header("content-type")
    }

    fn accepts() -> [accept] {
        // Lazily parse the accept header.
        alt self._accepts {
          none {
            let accepts = alt self.find_header("accept") {
              none {
                // If we don't have the header, assume we accept everything.
                [{ mime_type: ("*", "*"), quality: 1.0, options: [] }]
              }
              some(accept) { parse_accept_header(accept) }
            };

            self._accepts = some(accepts);

            accepts
          }
          some(accepts) { accepts }
        }
    }

    fn accept(mime_type: str) -> bool {
        let mime_type = parse_mime_type(mime_type);

        for self.accepts().each { |accept|
            if accept.mime_type == ("*", "*") { ret true; }
            if accept.mime_type == mime_type { ret true; }
        }

        false
    }

    fn negotiate_media_types<U: copy>(mime_types: [(str, U)]) -> option<U> {
        let mime_types = mime_types.map { |t_v|
            let (t, v) = t_v;
            let (t, s) = parse_mime_type(t);
            (t, s, v)
        };

        // Walk over the accepts in order and return the first item that
        // matches.
        for self.accepts().each { |accept|
            let (typ, subtyp) = accept.mime_type;

            for mime_types.each { |t_s_v|
                let (t, s, v) = t_s_v;

                #error("%? %? -> %? %?", typ, subtyp, t, s);

                if typ == "*" || typ == t {
                    if subtyp == "*" || subtyp == s {
                        ret some(v)
                    }
                }
            }
        }

        none
    }
}

#[cfg(test)]
mod tests {
    #[test]
    fn test_parse_accept_header_firefox() {
        let firefox = "text/html," +
                      "application/xhtml+xml," +
                      "application/xml;q=0.9," +
                      "*/*;q=0.8";

        assert parse_accept_header(firefox) == [
            {
                mime_type: ("text", "html"),
                quality: 1.0,
                options: []
            },
            {
                mime_type: ("application", "xhtml+xml"),
                quality: 1.0,
                options: []
            },
            {
                mime_type: ("application", "xml"),
                quality: 0.9,
                options: []
            },
            {
                mime_type: ("*", "*"),
                quality: 0.8,
                options: []
            }
        ];
    }

    #[test]
    fn test_parse_accept_header_webkit() {
        let webkit = "application/xml," +
                     "application/xhtml+xml," +
                     "text/html;q=0.9," +
                     "text/plain;q=0.8," +
                     "image/png," +
                     "*/*;q=0.5";

        assert parse_accept_header(webkit) == [
            {
                mime_type: ("application", "xml"),
                quality: 1.0,
                options: []
            },
            {
                mime_type: ("application", "xhtml+xml"),
                quality: 1.0,
                options: []
            },
            {
                mime_type: ("image", "png"),
                quality: 1.0,
                options: []
            },
            {
                mime_type: ("text", "html"),
                quality: 0.9,
                options: []
            },
            {
                mime_type: ("text", "plain"),
                quality: 0.8,
                options: []
            },
            {
                mime_type: ("*", "*"),
                quality: 0.5,
                options: []
            }
        ];
    }
}
<|endoftext|>


<commit_before>extern crate futures_await as futures;
extern crate tokio;

#[macro_use]
extern crate reql;
extern crate reql_types;

#[macro_use]
extern crate serde_derive;
extern crate serde;
extern crate serde_json;

use futures::stream::Stream;
use reql::{Client, Document, Run};
use reql_types::Change;

/**
 * rethinkdb changelog example
 * After running, access your admin panel at localhost:8080
 *
 * setup a "test" database, with a "test" table, and run:
 *
 * // Insert an item
 * r.db('test').table('test').insert({ test: 1 });
 *
 * // Give the first item a random number
 * r.db('test').table('test').nth(0).update({ test: r.random(0, 100) }, { nonAtomic: true });
 *
 * // Remove the first item
 * r.db('test').table('test').nth(0).delete();
 */
/**
 * Or, in another rust context, you could run the following:
 *
 * // Insert an item
 * r.db("test").table("test").insert(json!({ "test": 1 })) // => run & unwrap
 *
 * // Give the first item a random number
 * r.db("test").table("test").nth(0).update(args!(
 *     json!({ "test": r.random(0, 100) }),
 *     { non_atomic: true }
 * ))  // => run & unwrap
 *
 * // Remove the first item
 * r.db("test").table("test").nth(0).delete() // => run & unwrap
 *
 */
#[derive(Debug, Serialize, Deserialize)]
struct TestItem {
    test: i32,
    id: String,
}

fn main() {
    // Create a new ReQL client
    let r = Client::new();

    // Create a connection pool
    let conn = r.connect(args!()).unwrap();

    // Run the query
    let query = r.db("test")
        .table("test")
        .filter(args!(|doc| {

            // Filter only documents which match our current TestItem trait
            doc.has_fields("test").and(doc.get_field("test").type_of().eq("NUMBER"))
        }))
        .changes()

        // We want rethinkdb to inform us of the change type
        .with_args(args!({
            include_types: true
        }))
        .run::<Change<TestItem, TestItem>>(conn)
        .unwrap();

    // Process the results
    let stati = query.and_then(|change| {
        match change {
            // The server returned the response we were expecting,
            // and deserialized the data into our Change structure
            Some(Document::Expected(change)) => {
                // Valid String change type
                match change.result_type {
                    Some(action) => {
                        // Extract the change type
                        print!("{:?} action received\n\t=> ", action);

                        // Match the change type
                        match action.as_str() {
                            "add" => println!("{:?}", change.new_val),
                            "remove" => println!("{:?}", change.old_val),
                            "change" => println!("from {:?} to {:?}", change.old_val, change.new_val),
                            _ => println!("Unsupported change type: {:?}", action)
                        }
                    }
                    None => println!("No change type"),
                }
            }

            // We got a response alright, but it wasn't the one we were
            // expecting plus it's not an error either, otherwise it would
            // have been returned as such (This simply means that the response
            // we got couldn't be serialised into the type we were expecting)
            Some(Document::Unexpected(change)) => {
                println!("Got unexpected change: {}",change)
            }
            // This is impossible in this particular example since there
            // needs to be at least one server available to give this
            // response otherwise we would have run into an error for
            // failing to connect
            None => {
                println!("got no documents in the database");
            }
        }
        Ok(())
    })
    // Our query ran into an error
    .or_else(|error| {
        println!("{:?}", error);
        Err(())
    });

    // Wait for all the results to be processed
    for _ in stati.wait() {}
}
<commit_msg>Update changelog example<commit_after>extern crate futures_await as futures;

#[macro_use]
extern crate reql;
extern crate reql_types;

#[macro_use]
extern crate serde_derive;
extern crate serde;
extern crate serde_json;

use futures::StreamExt;
use futures::executor::block_on;
use reql::{Client, Document, Run};
use reql_types::Change;

/**
 * rethinkdb changelog example
 * After running, access your admin panel at localhost:8080
 *
 * setup a "test" database, with a "test" table, and run:
 *
 * // Insert an item
 * r.db('test').table('test').insert({ test: 1 });
 *
 * // Give the first item a random number
 * r.db('test').table('test').nth(0).update({ test: r.random(0, 100) }, { nonAtomic: true });
 *
 * // Remove the first item
 * r.db('test').table('test').nth(0).delete();
 */
/**
 * Or, in another rust context, you could run the following:
 *
 * // Insert an item
 * r.db("test").table("test").insert(json!({ "test": 1 })) // => run & unwrap
 *
 * // Give the first item a random number
 * r.db("test").table("test").nth(0).update(args!(
 *     json!({ "test": r.random(0, 100) }),
 *     { non_atomic: true }
 * ))  // => run & unwrap
 *
 * // Remove the first item
 * r.db("test").table("test").nth(0).delete() // => run & unwrap
 *
 */
#[derive(Debug, Serialize, Deserialize)]
struct TestItem {
    test: i32,
    id: String,
}

fn main() {
    // Create a new ReQL client
    let r = Client::new();

    // Create a connection pool
    let conn = r.connect(args!()).unwrap();

    // Run the query
    let query = r.db("test")
        .table("test")
        .filter(args!(|doc| {

            // Filter only documents which match our current TestItem trait
            doc.has_fields("test").and(doc.get_field("test").type_of().eq("NUMBER"))
        }))
        .changes()

        // We want rethinkdb to inform us of the change type
        .with_args(args!({
            include_types: true
        }))
        .run::<Change<TestItem, TestItem>>(conn)
        .unwrap();

    // Process the results
    let stati = query.for_each(|change| {
        match change {
            // The server returned the response we were expecting,
            // and deserialized the data into our Change structure
            Some(Document::Expected(change)) => {
                // Valid String change type
                match change.result_type {
                    Some(action) => {
                        // Extract the change type
                        print!("{:?} action received\n\t=> ", action);

                        // Match the change type
                        match action.as_str() {
                            "add" => println!("{:?}", change.new_val),
                            "remove" => println!("{:?}", change.old_val),
                            "change" => println!("from {:?} to {:?}", change.old_val, change.new_val),
                            _ => println!("Unsupported change type: {:?}", action)
                        }
                    }
                    None => println!("No change type"),
                }
            }

            // We got a response alright, but it wasn't the one we were
            // expecting plus it's not an error either, otherwise it would
            // have been returned as such (This simply means that the response
            // we got couldn't be serialised into the type we were expecting)
            Some(Document::Unexpected(change)) => {
                println!("Got unexpected change: {}",change)
            }
            // This is impossible in this particular example since there
            // needs to be at least one server available to give this
            // response otherwise we would have run into an error for
            // failing to connect
            None => {
                println!("got no documents in the database");
            }
        }
        Ok(())
    });

    // Wait for all the results to be processed
    let _ = block_on(stati);
}
<|endoftext|>


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

#![feature(proc_macro)]

extern crate gtk;
#[macro_use]
extern crate relm;
extern crate relm_attributes;
#[macro_use]
extern crate relm_derive;

use gtk::{
    ButtonExt,
    Inhibit,
    LabelExt,
    OrientableExt,
    WidgetExt,
};
use gtk::Orientation::Vertical;
use relm::Widget;
use relm_attributes::widget;

use self::Msg::*;

// Define the structure of the model.
pub struct Model {
    counter: i32,
}

// The messages that can be sent to the update function.
#[derive(Msg)]
pub enum Msg {
    #[cfg(test)] Test,
    Decrement,
    Increment,
    Quit,
}

#[widget]
impl Widget for Win {
    // The initial model.
    fn model() -> Model {
        Model {
            counter: 0,
        }
    }

    // Update the model according to the message received.
    fn update(&mut self, event: Msg) {
        match event {
            Decrement => self.model.counter -= 1,
            Increment => self.model.counter += 1,
            Quit => gtk::main_quit(),
        }
    }

    view! {
        gtk::Window {
            gtk::Box {
                // Set the orientation property of the Box.
                orientation: Vertical,
                // Create a Button inside the Box.
                gtk::Button {
                    // Send the message Increment when the button is clicked.
                    clicked => Increment,
                    // TODO: check if using two events of the same name work.
                    label: "+",
                },
                gtk::Label {
                    // Bind the text property of the label to the counter attribute of the model.
                    text: &self.model.counter.to_string(),
                },
                gtk::Button {
                    clicked => Decrement,
                    label: "-",
                },
            },
            delete_event(_, _) => (Quit, Inhibit(false)),
        }
    }
}

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

#![feature(proc_macro)]

extern crate gtk;
#[macro_use]
extern crate relm;
extern crate relm_attributes;
#[macro_use]
extern crate relm_derive;
#[macro_use]
extern crate relm_test;

use gtk::{
    ButtonExt,
    Inhibit,
    LabelExt,
    OrientableExt,
    WidgetExt,
};
use gtk::Orientation::Vertical;
use relm::Widget;
use relm_attributes::widget;

use self::Msg::*;

// Define the structure of the model.
pub struct Model {
    counter: i32,
}

// The messages that can be sent to the update function.
#[derive(Msg)]
pub enum Msg {
    #[cfg(test)] Test,
    Decrement,
    Increment,
    Quit,
}

#[widget]
impl Widget for Win {
    // The initial model.
    fn model() -> Model {
        Model {
            counter: 0,
        }
    }

    // Update the model according to the message received.
    fn update(&mut self, event: Msg) {
        match event {
            #[cfg(test)] Test => (),
            Decrement => self.model.counter -= 1,
            Increment => self.model.counter += 1,
            Quit => gtk::main_quit(),
        }
    }

    view! {
        gtk::Window {
            gtk::Box {
                // Set the orientation property of the Box.
                orientation: Vertical,
                // Create a Button inside the Box.
                #[name="inc_button"]
                gtk::Button {
                    // Send the message Increment when the button is clicked.
                    clicked => Increment,
                    // TODO: check if using two events of the same name work.
                    label: "+",
                },
                #[name="label"]
                gtk::Label {
                    // Bind the text property of the label to the counter attribute of the model.
                    text: &self.model.counter.to_string(),
                },
                #[name="dec_button"]
                gtk::Button {
                    clicked => Decrement,
                    label: "-",
                },
            },
            delete_event(_, _) => (Quit, Inhibit(false)),
        }
    }
}

fn main() {
    Win::run(()).unwrap();
}

#[cfg(test)]
mod tests {
    use gtk::LabelExt;

    use relm;
    use relm_test::click;

    use Win;

    #[test]
    fn label_change() {
        let (_component, widgets) = relm::init_test::<Win>(()).unwrap();
        let inc_button = &widgets.inc_button;
        let dec_button = &widgets.dec_button;
        let label = &widgets.label;

        assert_text!(label, 0);
        click(inc_button);
        assert_text!(label, 1);
        click(inc_button);
        assert_text!(label, 2);
        click(inc_button);
        assert_text!(label, 3);
        click(inc_button);
        assert_text!(label, 4);

        click(dec_button);
        assert_text!(label, 3);
        click(dec_button);
        assert_text!(label, 2);
        click(dec_button);
        assert_text!(label, 1);
        click(dec_button);
        assert_text!(label, 0);
        click(dec_button);
        assert_text!(label, 0);
    }
}
<|endoftext|>