<commit_before>extern crate gcc;

use std::path::Path;
use std::process::Command;

struct Perl {
    bin: String,
}

impl Perl {
    fn new() -> Perl {
        Perl {
            bin: std::env::var("PERL").unwrap(),
        }
    }

    fn cfg(&self, key: &str) -> String {
        let out = Command::new(&self.bin)
            .arg("-MConfig")
            .arg("-e")
            .arg(format!("print $Config::Config{{{}}}", key))
            .output()
            .unwrap();

        String::from_utf8(out.stdout).unwrap()
    }

    fn run(&self, script: &str) {
        let status = Command::new(&self.bin)
            .arg(script)
            .status()
            .unwrap();
        assert!(status.success());
    }
}

fn build_ouro(perl: &Perl) {
    let mut gcc = gcc::Config::new();

    let ccflags = perl.cfg("ccflags");
    for flag in ccflags.split_whitespace() {
        gcc.flag(flag);
    }

    let archlib = perl.cfg("archlibexp");
    let coreinc = Path::new(&archlib).join("CORE");
    gcc.include(&coreinc);

    gcc.file("ouroboros/libouroboros.c");
    gcc.compile("libouroboros.a");
}

fn main() {
    let perl = Perl::new();

    build_ouro(&perl);

    perl.run("build/regen.pl");
}
<commit_msg>Use default perl if env variable is not set.<commit_after>extern crate gcc;

use std::path::Path;
use std::process::Command;

struct Perl {
    bin: String,
}

impl Perl {
    fn new() -> Perl {
        Perl {
            bin: std::env::var("PERL").unwrap_or("perl".to_owned()),
        }
    }

    fn cfg(&self, key: &str) -> String {
        let out = Command::new(&self.bin)
            .arg("-MConfig")
            .arg("-e")
            .arg(format!("print $Config::Config{{{}}}", key))
            .output()
            .unwrap();

        String::from_utf8(out.stdout).unwrap()
    }

    fn run(&self, script: &str) {
        let status = Command::new(&self.bin)
            .arg(script)
            .status()
            .unwrap();
        assert!(status.success());
    }
}

fn build_ouro(perl: &Perl) {
    let mut gcc = gcc::Config::new();

    let ccflags = perl.cfg("ccflags");
    for flag in ccflags.split_whitespace() {
        gcc.flag(flag);
    }

    let archlib = perl.cfg("archlibexp");
    let coreinc = Path::new(&archlib).join("CORE");
    gcc.include(&coreinc);

    gcc.file("ouroboros/libouroboros.c");
    gcc.compile("libouroboros.a");
}

fn main() {
    let perl = Perl::new();

    build_ouro(&perl);

    perl.run("build/regen.pl");
}
<|endoftext|>


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

use std::{collections::HashMap, path::PathBuf};

use crate::type_path::{TypePath, TypePathItem};
use common::{SourceLocationKey, Span};
use graphql_syntax::{
    parse_executable, ExecutableDefinition, ExecutableDocument, FragmentSpread, GraphQLSource,
    InlineFragment, LinkedField, List, OperationDefinition, ScalarField, Selection,
};
use interner::StringKey;
use log::info;
use lsp_types::{Position, TextDocumentPositionParams, Url};
use relay_compiler::{compiler_state::SourceSet, FileCategorizer, FileGroup};
#[derive(Debug, Clone, Copy)]
pub enum NodeKind {
    FieldName,
    FragmentSpread(StringKey),
}

#[derive(Debug)]
pub struct NodeResolutionInfo {
    /// The type of the leaf node on which the information request was made
    pub kind: NodeKind,
    /// A list of type metadata that we can use to resolve the leaf
    /// type the request is being made against
    pub type_path: TypePath,
    /// The project the request belongs to
    pub project_name: StringKey,
}

impl NodeResolutionInfo {
    fn new(project_name: StringKey) -> Self {
        Self {
            kind: NodeKind::FieldName,
            type_path: Default::default(),
            project_name,
        }
    }
}

/// Return a `GraphQLSource` for a given position, if the position
/// falls within a graphql literal.
fn get_graphql_source<'a>(
    text_document_position: &'a TextDocumentPositionParams,
    graphql_source_cache: &'a HashMap<Url, Vec<GraphQLSource>>,
) -> Option<&'a GraphQLSource> {
    let TextDocumentPositionParams {
        text_document,
        position,
    } = text_document_position;
    let url = &text_document.uri;

    let graphql_sources = graphql_source_cache.get(url)?;

    info!("Current sources: {:#?}", *graphql_sources);
    info!("position: {:?}", position);

    // We have GraphQL documents, now check if the position
    // falls within the range of one of these documents.
    let graphql_source = graphql_sources.iter().find(|graphql_source| {
        let range = graphql_source.to_range();
        position >= &range.start && position <= &range.end
    })?;

    Some(graphql_source)
}

/// Return a parsed executable document for this LSP request, only if the request occurs
/// within a GraphQL document. Otherwise return `None`
pub fn extract_executable_document_from_text(
    text_document_position: TextDocumentPositionParams,
    graphql_source_cache: &HashMap<Url, Vec<GraphQLSource>>,
    file_categorizer: &FileCategorizer,
    root_dir: &PathBuf,
) -> Option<(ExecutableDocument, Span, StringKey)> {
    let graphql_source = get_graphql_source(&text_document_position, graphql_source_cache)?;
    let url = &text_document_position.text_document.uri;
    let position = text_document_position.position;
    let absolute_file_path = PathBuf::from(url.path());
    let file_path = if let Ok(file_path) = absolute_file_path.strip_prefix(root_dir) {
        file_path
    } else {
        info!("Failed to parse file path: {:#?}", &absolute_file_path);
        return None;
    };
    let project_name =
        if let FileGroup::Source { source_set } = file_categorizer.categorize(&file_path.into()) {
            match source_set {
                SourceSet::SourceSetName(source) => source,
                SourceSet::SourceSetNames(sources) => sources[0],
            }
        } else {
            return None;
        };

    match parse_executable(
        &graphql_source.text,
        SourceLocationKey::standalone(&url.to_string()),
    ) {
        Ok(document) => {
            // Now we need to take the `Position` and map that to an offset relative
            // to this GraphQL document, as the `Span`s in the document are relative.
            info!("Successfully parsed the definitions for a target GraphQL source");
            // Map the position to a zero-length span, relative to this GraphQL source.
            let position_span = match position_to_span(position, &graphql_source) {
                Some(span) => span,
                // Exit early if we can't map the position for some reason
                None => return None,
            };
            // Now we need to walk the Document, tracking our path along the way, until
            // we find the position within the document. Note that the GraphQLSource will
            // already be updated *with the characters that triggered the completion request*
            // since the change event fires before completion.
            info!("position_span: {:?}", position_span);

            Some((document, position_span, project_name))
        }
        Err(err) => {
            info!("Failed to parse this target!");
            info!("{:?}", err);
            None
        }
    }
}

/// Maps the LSP `Position` type back to a relative span, so we can find out which syntax node(s)
/// this completion request came from
fn position_to_span(position: Position, source: &GraphQLSource) -> Option<Span> {
    let mut index_of_last_line = 0;
    let mut line_index = source.line_index as u64;

    let mut chars = source.text.chars().enumerate().peekable();

    while let Some((index, chr)) = chars.next() {
        let is_newline = match chr {
            // Line terminators: https://www.ecma-international.org/ecma-262/#sec-line-terminators
            '\u{000A}' | '\u{000D}' | '\u{2028}' | '\u{2029}' => {
                !matches!((chr, chars.peek()), ('\u{000D}', Some((_, '\u{000D}'))))
            }
            _ => false,
        };

        if is_newline {
            line_index += 1;
            index_of_last_line = index as u64;
        }

        if line_index == position.line {
            let start_offset = (index_of_last_line + position.character) as u32;
            return Some(Span::new(start_offset, start_offset));
        }
    }
    None
}

fn create_node_resolution_info(
    document: ExecutableDocument,
    position_span: Span,
    project_name: StringKey,
) -> Option<NodeResolutionInfo> {
    info!("Building node resolution info for {:#?}", document);
    let mut node_resolution_info = NodeResolutionInfo::new(project_name);

    for definition in document.definitions {
        match &definition {
            ExecutableDefinition::Operation(operation) => {
                if operation.location.contains(position_span) {
                    let (_, kind) = operation.operation.clone()?;
                    node_resolution_info
                        .type_path
                        .add_type(TypePathItem::Operation(kind));

                    info!("Node is within operation: {:?}", operation.name);
                    let OperationDefinition { selections, .. } = operation;

                    build_node_resolution_info_from_selections(
                        selections,
                        position_span,
                        &mut node_resolution_info,
                    );
                }
            }
            ExecutableDefinition::Fragment(fragment) => {
                if fragment.location.contains(position_span) {
                    let type_name = fragment.type_condition.type_.value;
                    node_resolution_info
                        .type_path
                        .add_type(TypePathItem::FragmentDefinition { type_name });
                    build_node_resolution_info_from_selections(
                        &fragment.selections,
                        position_span,
                        &mut node_resolution_info,
                    );
                }
            }
        }
    }
    Some(node_resolution_info)
}

fn build_node_resolution_info_from_selections(
    selections: &List<Selection>,
    position_span: Span,
    node_resolution_info: &mut NodeResolutionInfo,
) {
    if let Some(item) = selections
        .items
        .iter()
        .find(|item| item.span().contains(position_span))
    {
        match item {
            Selection::LinkedField(node) => {
                node_resolution_info.kind = NodeKind::FieldName;
                let LinkedField {
                    name, selections, ..
                } = node;
                node_resolution_info
                    .type_path
                    .add_type(TypePathItem::LinkedField { name: name.value });
                build_node_resolution_info_from_selections(
                    selections,
                    position_span,
                    node_resolution_info,
                );
            }
            Selection::FragmentSpread(spread) => {
                let FragmentSpread { name, .. } = spread;
                if name.span.contains(position_span) {
                    node_resolution_info.kind = NodeKind::FragmentSpread(name.value);
                }
            }
            Selection::InlineFragment(node) => {
                let InlineFragment {
                    selections,
                    type_condition,
                    ..
                } = node;
                if let Some(type_condition) = type_condition {
                    let type_name = type_condition.type_.value;
                    node_resolution_info
                        .type_path
                        .add_type(TypePathItem::InlineFragment { type_name });
                    build_node_resolution_info_from_selections(
                        selections,
                        position_span,
                        node_resolution_info,
                    )
                }
            }
            Selection::ScalarField(node) => {
                let ScalarField { name, .. } = node;
                node_resolution_info.kind = NodeKind::FieldName;
                node_resolution_info
                    .type_path
                    .add_type(TypePathItem::ScalarField { name: name.value });
            }
        }
    }
}

/// Return a `NodeResolutionInfo` for this request if the request occured
/// within a GraphQL document.
pub fn get_node_resolution_info(
    text_document_position: TextDocumentPositionParams,
    graphql_source_cache: &HashMap<Url, Vec<GraphQLSource>>,
    file_categorizer: &FileCategorizer,
    root_dir: &PathBuf,
) -> Option<NodeResolutionInfo> {
    let (document, position_span, project_name) = extract_executable_document_from_text(
        text_document_position,
        graphql_source_cache,
        file_categorizer,
        root_dir,
    )?;

    create_node_resolution_info(document, position_span, project_name)
}
<commit_msg>remove some info! logs that were making it difficult to debug<commit_after>/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

use std::{collections::HashMap, path::PathBuf};

use crate::type_path::{TypePath, TypePathItem};
use common::{SourceLocationKey, Span};
use graphql_syntax::{
    parse_executable, ExecutableDefinition, ExecutableDocument, FragmentSpread, GraphQLSource,
    InlineFragment, LinkedField, List, OperationDefinition, ScalarField, Selection,
};
use interner::StringKey;
use log::info;
use lsp_types::{Position, TextDocumentPositionParams, Url};
use relay_compiler::{compiler_state::SourceSet, FileCategorizer, FileGroup};
#[derive(Debug, Clone, Copy)]
pub enum NodeKind {
    FieldName,
    FragmentSpread(StringKey),
}

#[derive(Debug)]
pub struct NodeResolutionInfo {
    /// The type of the leaf node on which the information request was made
    pub kind: NodeKind,
    /// A list of type metadata that we can use to resolve the leaf
    /// type the request is being made against
    pub type_path: TypePath,
    /// The project the request belongs to
    pub project_name: StringKey,
}

impl NodeResolutionInfo {
    fn new(project_name: StringKey) -> Self {
        Self {
            kind: NodeKind::FieldName,
            type_path: Default::default(),
            project_name,
        }
    }
}

/// Return a `GraphQLSource` for a given position, if the position
/// falls within a graphql literal.
fn get_graphql_source<'a>(
    text_document_position: &'a TextDocumentPositionParams,
    graphql_source_cache: &'a HashMap<Url, Vec<GraphQLSource>>,
) -> Option<&'a GraphQLSource> {
    let TextDocumentPositionParams {
        text_document,
        position,
    } = text_document_position;
    let url = &text_document.uri;

    let graphql_sources = graphql_source_cache.get(url)?;

    // We have GraphQL documents, now check if the position
    // falls within the range of one of these documents.
    let graphql_source = graphql_sources.iter().find(|graphql_source| {
        let range = graphql_source.to_range();
        position >= &range.start && position <= &range.end
    })?;

    Some(graphql_source)
}

/// Return a parsed executable document for this LSP request, only if the request occurs
/// within a GraphQL document. Otherwise return `None`
pub fn extract_executable_document_from_text(
    text_document_position: TextDocumentPositionParams,
    graphql_source_cache: &HashMap<Url, Vec<GraphQLSource>>,
    file_categorizer: &FileCategorizer,
    root_dir: &PathBuf,
) -> Option<(ExecutableDocument, Span, StringKey)> {
    let graphql_source = get_graphql_source(&text_document_position, graphql_source_cache)?;
    let url = &text_document_position.text_document.uri;
    let position = text_document_position.position;
    let absolute_file_path = PathBuf::from(url.path());
    let file_path = if let Ok(file_path) = absolute_file_path.strip_prefix(root_dir) {
        file_path
    } else {
        info!("Failed to parse file path: {:#?}", &absolute_file_path);
        return None;
    };
    let project_name =
        if let FileGroup::Source { source_set } = file_categorizer.categorize(&file_path.into()) {
            match source_set {
                SourceSet::SourceSetName(source) => source,
                SourceSet::SourceSetNames(sources) => sources[0],
            }
        } else {
            return None;
        };

    match parse_executable(
        &graphql_source.text,
        SourceLocationKey::standalone(&url.to_string()),
    ) {
        Ok(document) => {
            // Now we need to take the `Position` and map that to an offset relative
            // to this GraphQL document, as the `Span`s in the document are relative.
            info!("Successfully parsed the definitions for a target GraphQL source");
            // Map the position to a zero-length span, relative to this GraphQL source.
            let position_span = match position_to_span(position, &graphql_source) {
                Some(span) => span,
                // Exit early if we can't map the position for some reason
                None => return None,
            };
            // Now we need to walk the Document, tracking our path along the way, until
            // we find the position within the document. Note that the GraphQLSource will
            // already be updated *with the characters that triggered the completion request*
            // since the change event fires before completion.
            info!("position_span: {:?}", position_span);

            Some((document, position_span, project_name))
        }
        Err(err) => {
            info!("Failed to parse this target!");
            info!("{:?}", err);
            None
        }
    }
}

/// Maps the LSP `Position` type back to a relative span, so we can find out which syntax node(s)
/// this completion request came from
fn position_to_span(position: Position, source: &GraphQLSource) -> Option<Span> {
    let mut index_of_last_line = 0;
    let mut line_index = source.line_index as u64;

    let mut chars = source.text.chars().enumerate().peekable();

    while let Some((index, chr)) = chars.next() {
        let is_newline = match chr {
            // Line terminators: https://www.ecma-international.org/ecma-262/#sec-line-terminators
            '\u{000A}' | '\u{000D}' | '\u{2028}' | '\u{2029}' => {
                !matches!((chr, chars.peek()), ('\u{000D}', Some((_, '\u{000D}'))))
            }
            _ => false,
        };

        if is_newline {
            line_index += 1;
            index_of_last_line = index as u64;
        }

        if line_index == position.line {
            let start_offset = (index_of_last_line + position.character) as u32;
            return Some(Span::new(start_offset, start_offset));
        }
    }
    None
}

fn create_node_resolution_info(
    document: ExecutableDocument,
    position_span: Span,
    project_name: StringKey,
) -> Option<NodeResolutionInfo> {
    info!("Building node resolution info");
    let mut node_resolution_info = NodeResolutionInfo::new(project_name);

    for definition in document.definitions {
        match &definition {
            ExecutableDefinition::Operation(operation) => {
                if operation.location.contains(position_span) {
                    let (_, kind) = operation.operation.clone()?;
                    node_resolution_info
                        .type_path
                        .add_type(TypePathItem::Operation(kind));

                    info!("Node is within operation: {:?}", operation.name);
                    let OperationDefinition { selections, .. } = operation;

                    build_node_resolution_info_from_selections(
                        selections,
                        position_span,
                        &mut node_resolution_info,
                    );
                }
            }
            ExecutableDefinition::Fragment(fragment) => {
                if fragment.location.contains(position_span) {
                    let type_name = fragment.type_condition.type_.value;
                    node_resolution_info
                        .type_path
                        .add_type(TypePathItem::FragmentDefinition { type_name });
                    build_node_resolution_info_from_selections(
                        &fragment.selections,
                        position_span,
                        &mut node_resolution_info,
                    );
                }
            }
        }
    }
    Some(node_resolution_info)
}

fn build_node_resolution_info_from_selections(
    selections: &List<Selection>,
    position_span: Span,
    node_resolution_info: &mut NodeResolutionInfo,
) {
    if let Some(item) = selections
        .items
        .iter()
        .find(|item| item.span().contains(position_span))
    {
        match item {
            Selection::LinkedField(node) => {
                node_resolution_info.kind = NodeKind::FieldName;
                let LinkedField {
                    name, selections, ..
                } = node;
                node_resolution_info
                    .type_path
                    .add_type(TypePathItem::LinkedField { name: name.value });
                build_node_resolution_info_from_selections(
                    selections,
                    position_span,
                    node_resolution_info,
                );
            }
            Selection::FragmentSpread(spread) => {
                let FragmentSpread { name, .. } = spread;
                if name.span.contains(position_span) {
                    node_resolution_info.kind = NodeKind::FragmentSpread(name.value);
                }
            }
            Selection::InlineFragment(node) => {
                let InlineFragment {
                    selections,
                    type_condition,
                    ..
                } = node;
                if let Some(type_condition) = type_condition {
                    let type_name = type_condition.type_.value;
                    node_resolution_info
                        .type_path
                        .add_type(TypePathItem::InlineFragment { type_name });
                    build_node_resolution_info_from_selections(
                        selections,
                        position_span,
                        node_resolution_info,
                    )
                }
            }
            Selection::ScalarField(node) => {
                let ScalarField { name, .. } = node;
                node_resolution_info.kind = NodeKind::FieldName;
                node_resolution_info
                    .type_path
                    .add_type(TypePathItem::ScalarField { name: name.value });
            }
        }
    }
}

/// Return a `NodeResolutionInfo` for this request if the request occured
/// within a GraphQL document.
pub fn get_node_resolution_info(
    text_document_position: TextDocumentPositionParams,
    graphql_source_cache: &HashMap<Url, Vec<GraphQLSource>>,
    file_categorizer: &FileCategorizer,
    root_dir: &PathBuf,
) -> Option<NodeResolutionInfo> {
    let (document, position_span, project_name) = extract_executable_document_from_text(
        text_document_position,
        graphql_source_cache,
        file_categorizer,
        root_dir,
    )?;

    create_node_resolution_info(document, position_span, project_name)
}
<|endoftext|>


<commit_before>// Copyright:: Copyright (c) 2015-2016 The Habitat Maintainers
//
// The terms of the Evaluation Agreement (Habitat) between Chef Software Inc.
// and the party accessing this file ("Licensee") apply to Licensee's use of
// the Software until such time that the Software is made available under an
// open source license such as the Apache 2.0 License.

//! A module containing the HTTP server and handlers for servicing client requests

pub mod handlers;

use std::sync::{mpsc, Arc};
use std::thread::{self, JoinHandle};

use depot;
use hab_net::oauth::github::GitHubClient;
use hab_net::routing::BrokerContext;
use iron::prelude::*;
use iron::AfterMiddleware;
use iron::headers;
use iron::method::Method;
use mount::Mount;
use staticfile::Static;
use unicase::UniCase;

use config::Config;
use error::Result;
use self::handlers::*;

/// Create a new `iron::Chain` containing a Router and it's required middleware
pub fn router(config: Arc<Config>, context: Arc<BrokerContext>) -> Result<Chain> {
    let github = GitHubClient::new(&*config);
    let ctx1 = context.clone();
    let ctx2 = context.clone();
    let ctx3 = context.clone();
    let ctx4 = context.clone();
    let ctx5 = context.clone();
    let ctx6 = context.clone();

    let router = router!(
        get "/status" => move |r: &mut Request| status(r),
        get "/authenticate/:code" => move |r: &mut Request| session_create(r, &github, &ctx1),

        post "/jobs" => move |r: &mut Request| job_create(r, &ctx2),
        get "/jobs/:id" => move |r: &mut Request| job_show(r, &ctx3),

        get "/user/invitations" => move |r: &mut Request| list_account_invitations(r, &ctx4),
        put "/user/invitations/:invitation_id" => move |r: &mut Request| accept_invitation(r, &ctx5),
        get "/user/origins" => move |r: &mut Request| list_user_origins(r, &ctx6),

    );
    let mut chain = Chain::new(router);
    chain.link_after(Cors);
    Ok(chain)
}

/// Create a new HTTP listener and run it in a separate thread. This function will block the calling
/// thread until the new listener has successfully started.
///
/// # Errors
///
/// * Depot could not be started
/// * Couldn't create Router or it's middleware
///
/// # Panics
///
/// * Listener crashed during startup
pub fn run(config: Arc<Config>, context: Arc<BrokerContext>) -> Result<JoinHandle<()>> {
    let (tx, rx) = mpsc::sync_channel(1);

    let addr = config.http_addr.clone();
    let ctx = context.clone();
    let depot = try!(depot::Depot::new(config.depot.clone(), ctx));
    let depot_chain = try!(depot::server::router(depot));

    let mut mount = Mount::new();
    if let Some(ref path) = config.ui_root {
        debug!("Mounting UI at filepath {}", path);
        mount.mount("/", Static::new(path));
    }
    let chain = try!(router(config, context));
    mount.mount("/v1", chain).mount("/v1/depot", depot_chain);

    let handle = thread::Builder::new()
        .name("http-srv".to_string())
        .spawn(move || {
            let _server = Iron::new(mount).http(addr).unwrap();
            tx.send(()).unwrap();
        })
        .unwrap();
    match rx.recv() {
        Ok(()) => Ok(handle),
        Err(e) => panic!("http-srv thread startup error, err={}", e),
    }
}

struct Cors;

impl AfterMiddleware for Cors {
    fn after(&self, _req: &mut Request, mut res: Response) -> IronResult<Response> {
        res.headers.set(headers::AccessControlAllowOrigin::Any);
        res.headers
            .set(headers::AccessControlAllowHeaders(vec![UniCase("authorization".to_owned())]));
        res.headers
                .set(headers::AccessControlAllowMethods(vec![Method::Put]));
        Ok(res)
    }
}
<commit_msg>[builder-api] Increase default number of threads for HTTP server.<commit_after>// Copyright:: Copyright (c) 2015-2016 The Habitat Maintainers
//
// The terms of the Evaluation Agreement (Habitat) between Chef Software Inc.
// and the party accessing this file ("Licensee") apply to Licensee's use of
// the Software until such time that the Software is made available under an
// open source license such as the Apache 2.0 License.

//! A module containing the HTTP server and handlers for servicing client requests

pub mod handlers;

use std::sync::{mpsc, Arc};
use std::thread::{self, JoinHandle};

use depot;
use hab_net::oauth::github::GitHubClient;
use hab_net::routing::BrokerContext;
use iron::prelude::*;
use iron::AfterMiddleware;
use iron::headers;
use iron::method::Method;
use iron::Protocol;
use mount::Mount;
use staticfile::Static;
use unicase::UniCase;

use config::Config;
use error::Result;
use self::handlers::*;

// Iron defaults to a threadpool of size `8 * num_cpus`.
// See: http://172.16.2.131:9633/iron/prelude/struct.Iron.html#method.http
const HTTP_THREAD_COUNT: usize = 128;

/// Create a new `iron::Chain` containing a Router and it's required middleware
pub fn router(config: Arc<Config>, context: Arc<BrokerContext>) -> Result<Chain> {
    let github = GitHubClient::new(&*config);
    let ctx1 = context.clone();
    let ctx2 = context.clone();
    let ctx3 = context.clone();
    let ctx4 = context.clone();
    let ctx5 = context.clone();
    let ctx6 = context.clone();

    let router = router!(
        get "/status" => move |r: &mut Request| status(r),
        get "/authenticate/:code" => move |r: &mut Request| session_create(r, &github, &ctx1),

        post "/jobs" => move |r: &mut Request| job_create(r, &ctx2),
        get "/jobs/:id" => move |r: &mut Request| job_show(r, &ctx3),

        get "/user/invitations" => move |r: &mut Request| list_account_invitations(r, &ctx4),
        put "/user/invitations/:invitation_id" => move |r: &mut Request| accept_invitation(r, &ctx5),
        get "/user/origins" => move |r: &mut Request| list_user_origins(r, &ctx6),

    );
    let mut chain = Chain::new(router);
    chain.link_after(Cors);
    Ok(chain)
}

/// Create a new HTTP listener and run it in a separate thread. This function will block the calling
/// thread until the new listener has successfully started.
///
/// # Errors
///
/// * Depot could not be started
/// * Couldn't create Router or it's middleware
///
/// # Panics
///
/// * Listener crashed during startup
pub fn run(config: Arc<Config>, context: Arc<BrokerContext>) -> Result<JoinHandle<()>> {
    let (tx, rx) = mpsc::sync_channel(1);

    let addr = config.http_addr.clone();
    let ctx = context.clone();
    let depot = try!(depot::Depot::new(config.depot.clone(), ctx));
    let depot_chain = try!(depot::server::router(depot));

    let mut mount = Mount::new();
    if let Some(ref path) = config.ui_root {
        debug!("Mounting UI at filepath {}", path);
        mount.mount("/", Static::new(path));
    }
    let chain = try!(router(config, context));
    mount.mount("/v1", chain).mount("/v1/depot", depot_chain);

    let handle = thread::Builder::new()
        .name("http-srv".to_string())
        .spawn(move || {
            let _server = Iron::new(mount)
                .listen_with(addr, HTTP_THREAD_COUNT, Protocol::Http, None)
                .unwrap();
            tx.send(()).unwrap();
        })
        .unwrap();
    match rx.recv() {
        Ok(()) => Ok(handle),
        Err(e) => panic!("http-srv thread startup error, err={}", e),
    }
}

struct Cors;

impl AfterMiddleware for Cors {
    fn after(&self, _req: &mut Request, mut res: Response) -> IronResult<Response> {
        res.headers.set(headers::AccessControlAllowOrigin::Any);
        res.headers
            .set(headers::AccessControlAllowHeaders(vec![UniCase("authorization".to_owned())]));
        res.headers
            .set(headers::AccessControlAllowMethods(vec![Method::Put]));
        Ok(res)
    }
}
<|endoftext|>


<commit_before>// Copyright 2014 Johannes Köster.
// Licensed under the MIT license (http://opensource.org/licenses/MIT)
// This file may not be copied, modified, or distributed
// except according to those terms.

/// A classical, flexible, q-gram index implementation.
///
/// # Example
///
/// ```
/// use bio::data_structures::qgram_index;
/// use bio::alphabets;
///
/// let text = b"ACGGCTGAGATGAT";
/// let alphabet = alphabets::dna::alphabet();
/// let q = 3;
/// let qgram_index = qgram_index::QGramIndex::new(q, text, &alphabet);
///
/// let pattern = b"GCTG";
/// let matches = qgram_index.matches(pattern, 1);
/// assert_eq!(matches, [
///     qgram_index::Match {
///         pattern: qgram_index::Interval { start: 0, stop: 4 },
///         text: qgram_index::Interval { start: 3, stop: 7 },
///         count: 2
///     }
/// ]);
/// ```

use std::collections;
use std;

use alphabets::{Alphabet, RankTransform};
use utils;

/// A classical, flexible, q-gram index implementation.
pub struct QGramIndex {
    q: u32,
    address: Vec<usize>,
    pos: Vec<usize>,
    ranks: RankTransform,
}

impl QGramIndex {
    /// Create a new q-gram index.
    /// The q has to be smaller than b / log2(|A|) with |A| being the alphabet size and b the number
    /// bits with the `usize` data type.
    pub fn new(q: u32, text: &[u8], alphabet: &Alphabet) -> Self {
        QGramIndex::with_max_count(q, text, alphabet, std::usize::MAX)
    }

    /// Create a new q-gram index, only considering q-grams that occur at most `max_count` times.
    /// The q has to be smaller than b / log2(|A|) with |A| being the alphabet size and b the number
    /// bits with the `usize` data type.
    pub fn with_max_count(q: u32, text: &[u8], alphabet: &Alphabet, max_count: usize) -> Self {
        let ranks = RankTransform::new(alphabet);

        let qgram_count = alphabet.len().pow(q as u32);
        let mut address = vec![0; qgram_count + 1];
        let mut pos = vec![0; text.len()];

        for qgram in ranks.qgrams(q, text) {
            address[qgram] += 1;
        }

        for g in 1..address.len() {
            if address[g] > max_count {
                // mask qgram
                address[g] = 0;
            }
        }

        utils::prescan(&mut address, 0, |a, b| a + b);

        {
            let mut offset = vec![0; qgram_count];
            for (i, qgram) in ranks.qgrams(q, text).enumerate() {
                let a = address[qgram as usize];
                if address[qgram as usize + 1] - a != 0 {
                    // if not masked, insert positions
                    pos[a + offset[qgram as usize]] = i;
                    offset[qgram as usize] += 1;
                }
            }
        }

        QGramIndex { q: q, address: address, pos: pos, ranks: ranks }
    }

    /// Return text positions with matching q-gram.
    pub fn qgram_matches(&self, qgram: usize) -> &[usize] {
        &self.pos[self.address[qgram]..self.address[qgram + 1]]
    }

    /// Return matches of the given pattern.
    pub fn matches(&self, pattern: &[u8], min_count: usize) -> Vec<Match> {
        let q = self.q as usize;
        let mut diagonals = collections::HashMap::new();
        for (i, qgram) in self.ranks.qgrams(self.q, pattern).enumerate() {
            for &p in self.qgram_matches(qgram) {
                let diagonal = p - i;
                if !diagonals.contains_key(&diagonal) {
                    diagonals.insert(diagonal, Match {
                        pattern: Interval { start: i, stop: i + q },
                        text: Interval { start: p, stop: p + q },
                        count: 1,
                    });
                }
                else {
                    let m = diagonals.get_mut(&diagonal).unwrap();
                    m.pattern.stop = i + q;
                    m.text.stop = p + q;
                    m.count += 1;
                }
            }
        }
        diagonals.into_iter().filter_map(
            |(_, m)| if m.count >= min_count { Some(m) } else { None }
        ).collect()
    }

    /// Return exact matches of the given pattern.
    pub fn exact_matches(&self, pattern: &[u8]) -> Vec<ExactMatch> {
        let q = self.q as usize;
        let mut diagonals = collections::HashMap::new();
        let mut matches = Vec::new();

        for (i, qgram) in self.ranks.qgrams(self.q, pattern).enumerate() {
            for &p in self.qgram_matches(qgram) {
                let diagonal = p - i;
                if !diagonals.contains_key(&diagonal) {
                    diagonals.insert(diagonal, ExactMatch {
                        pattern: Interval { start: i, stop: i + q },
                        text: Interval { start: p, stop: p + q },
                    });
                }
                else {
                    let m = diagonals.get_mut(&diagonal).unwrap();
                    if m.pattern.stop - q + 1 != i {
                        // discontinue match
                        matches.push(*m);
                        // start new match
                        m.pattern.start = i;
                        m.pattern.stop = i + q;
                        m.text.start = p;
                        m.text.stop = p + q;
                    }
                    else {
                        m.pattern.stop = i + q;
                        m.text.stop = p + q;
                    }
                }
            }
        }
        for (_, m) in diagonals.into_iter() {
            matches.push(m);
        }

        matches
    }
}

/// An interval, consisting of start and stop position (the latter exclusive).
#[derive(PartialEq, Debug, Copy, Clone)]
pub struct Interval {
    pub start: usize,
    pub stop: usize
}

impl Interval {
    pub fn get<'a>(&self, text: &'a [u8]) -> &'a [u8] {
        &text[self.start..self.stop]
    }
}

#[derive(PartialEq, Debug, Copy, Clone)]
pub struct Match {
    pub pattern: Interval,
    pub text: Interval,
    pub count: usize,
}

#[derive(PartialEq, Debug, Copy, Clone)]
pub struct ExactMatch {
    pub pattern: Interval,
    pub text: Interval,
}

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

    fn setup() -> (&'static [u8], alphabets::Alphabet) {
        let text = b"ACGGCTGAGATGAT";
        let alphabet = alphabets::dna::alphabet();

        (text, alphabet)
    }

    #[test]
    fn test_qgram_matches() {
        let (text, alphabet) = setup();
        let q = 3;
        let qgram_index = QGramIndex::new(q, text, &alphabet);

        let ranks = alphabets::RankTransform::new(&alphabet);

        let qgram = ranks.qgrams(q, b"TGA").next().unwrap();

        let matches = qgram_index.qgram_matches(qgram);
        assert_eq!(matches, [5, 10]);
    }

    #[test]
    fn test_matches() {
        let (text, alphabet) = setup();
        let q = 3;
        let qgram_index = QGramIndex::new(q, text, &alphabet);

        let pattern = b"GCTG";
        let matches = qgram_index.matches(pattern, 1);
        assert_eq!(matches, [
            Match {
                pattern: Interval { start: 0, stop: 4 },
                text: Interval { start: 3, stop: 7 },
                count: 2
            }
        ]);
    }

    #[test]
    fn test_exact_matches() {
        let (text, alphabet) = setup();
        let q = 3;
        let qgram_index = QGramIndex::new(q, text, &alphabet);

        let pattern = b"GCTGA";
        let exact_matches = qgram_index.exact_matches(pattern);
        assert!(exact_matches.len() == 2);
        for m in exact_matches {
            assert_eq!(m.pattern.get(pattern), m.text.get(text));
        }
    }
}
<commit_msg>Implement Ord for Match.<commit_after>// Copyright 2014 Johannes Köster.
// Licensed under the MIT license (http://opensource.org/licenses/MIT)
// This file may not be copied, modified, or distributed
// except according to those terms.

/// A classical, flexible, q-gram index implementation.
///
/// # Example
///
/// ```
/// use bio::data_structures::qgram_index;
/// use bio::alphabets;
///
/// let text = b"ACGGCTGAGATGAT";
/// let alphabet = alphabets::dna::alphabet();
/// let q = 3;
/// let qgram_index = qgram_index::QGramIndex::new(q, text, &alphabet);
///
/// let pattern = b"GCTG";
/// let matches = qgram_index.matches(pattern, 1);
/// assert_eq!(matches, [
///     qgram_index::Match {
///         pattern: qgram_index::Interval { start: 0, stop: 4 },
///         text: qgram_index::Interval { start: 3, stop: 7 },
///         count: 2
///     }
/// ]);
/// ```

use std::collections;
use std;
use std::cmp;

use alphabets::{Alphabet, RankTransform};
use utils;

/// A classical, flexible, q-gram index implementation.
pub struct QGramIndex {
    q: u32,
    address: Vec<usize>,
    pos: Vec<usize>,
    ranks: RankTransform,
}

impl QGramIndex {
    /// Create a new q-gram index.
    /// The q has to be smaller than b / log2(|A|) with |A| being the alphabet size and b the number
    /// bits with the `usize` data type.
    pub fn new(q: u32, text: &[u8], alphabet: &Alphabet) -> Self {
        QGramIndex::with_max_count(q, text, alphabet, std::usize::MAX)
    }

    /// Create a new q-gram index, only considering q-grams that occur at most `max_count` times.
    /// The q has to be smaller than b / log2(|A|) with |A| being the alphabet size and b the number
    /// bits with the `usize` data type.
    pub fn with_max_count(q: u32, text: &[u8], alphabet: &Alphabet, max_count: usize) -> Self {
        let ranks = RankTransform::new(alphabet);

        let qgram_count = alphabet.len().pow(q as u32);
        let mut address = vec![0; qgram_count + 1];
        let mut pos = vec![0; text.len()];

        for qgram in ranks.qgrams(q, text) {
            address[qgram] += 1;
        }

        for g in 1..address.len() {
            if address[g] > max_count {
                // mask qgram
                address[g] = 0;
            }
        }

        utils::prescan(&mut address, 0, |a, b| a + b);

        {
            let mut offset = vec![0; qgram_count];
            for (i, qgram) in ranks.qgrams(q, text).enumerate() {
                let a = address[qgram as usize];
                if address[qgram as usize + 1] - a != 0 {
                    // if not masked, insert positions
                    pos[a + offset[qgram as usize]] = i;
                    offset[qgram as usize] += 1;
                }
            }
        }

        QGramIndex { q: q, address: address, pos: pos, ranks: ranks }
    }

    pub fn q(&self) -> u32 {
        self.q
    }

    /// Return text positions with matching q-gram.
    pub fn qgram_matches(&self, qgram: usize) -> &[usize] {
        &self.pos[self.address[qgram]..self.address[qgram + 1]]
    }

    /// Return matches of the given pattern.
    pub fn matches(&self, pattern: &[u8], min_count: usize) -> Vec<Match> {
        let q = self.q as usize;
        let mut diagonals = collections::HashMap::new();
        for (i, qgram) in self.ranks.qgrams(self.q, pattern).enumerate() {
            for &p in self.qgram_matches(qgram) {
                let diagonal = p - i;
                if !diagonals.contains_key(&diagonal) {
                    diagonals.insert(diagonal, Match {
                        pattern: Interval { start: i, stop: i + q },
                        text: Interval { start: p, stop: p + q },
                        count: 1,
                    });
                }
                else {
                    let m = diagonals.get_mut(&diagonal).unwrap();
                    m.pattern.stop = i + q;
                    m.text.stop = p + q;
                    m.count += 1;
                }
            }
        }
        diagonals.into_iter().filter_map(
            |(_, m)| if m.count >= min_count { Some(m) } else { None }
        ).collect()
    }

    /// Return exact matches of the given pattern.
    pub fn exact_matches(&self, pattern: &[u8]) -> Vec<ExactMatch> {
        let q = self.q as usize;
        let mut diagonals = collections::HashMap::new();
        let mut matches = Vec::new();

        for (i, qgram) in self.ranks.qgrams(self.q, pattern).enumerate() {
            for &p in self.qgram_matches(qgram) {
                let diagonal = p - i;
                if !diagonals.contains_key(&diagonal) {
                    diagonals.insert(diagonal, ExactMatch {
                        pattern: Interval { start: i, stop: i + q },
                        text: Interval { start: p, stop: p + q },
                    });
                }
                else {
                    let m = diagonals.get_mut(&diagonal).unwrap();
                    if m.pattern.stop - q + 1 != i {
                        // discontinue match
                        matches.push(*m);
                        // start new match
                        m.pattern.start = i;
                        m.pattern.stop = i + q;
                        m.text.start = p;
                        m.text.stop = p + q;
                    }
                    else {
                        m.pattern.stop = i + q;
                        m.text.stop = p + q;
                    }
                }
            }
        }
        for (_, m) in diagonals.into_iter() {
            matches.push(m);
        }

        matches
    }
}

/// An interval, consisting of start and stop position (the latter exclusive).
#[derive(PartialEq, Eq, Debug, Copy, Clone)]
pub struct Interval {
    pub start: usize,
    pub stop: usize
}

impl Interval {
    pub fn get<'a>(&self, text: &'a [u8]) -> &'a [u8] {
        &text[self.start..self.stop]
    }
}

#[derive(PartialEq, Eq, Debug, Copy, Clone)]
pub struct Match {
    pub pattern: Interval,
    pub text: Interval,
    pub count: usize,
}

impl cmp::Ord for Match {
    fn cmp(&self, other: &Self) -> cmp::Ordering {
        self.count.cmp(&other.count)
    }
}

impl cmp::PartialOrd for Match {
    fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
        Some(self.cmp(other))
    }
}

#[derive(PartialEq, Debug, Copy, Clone)]
pub struct ExactMatch {
    pub pattern: Interval,
    pub text: Interval,
}

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

    fn setup() -> (&'static [u8], alphabets::Alphabet) {
        let text = b"ACGGCTGAGATGAT";
        let alphabet = alphabets::dna::alphabet();

        (text, alphabet)
    }

    #[test]
    fn test_qgram_matches() {
        let (text, alphabet) = setup();
        let q = 3;
        let qgram_index = QGramIndex::new(q, text, &alphabet);

        let ranks = alphabets::RankTransform::new(&alphabet);

        let qgram = ranks.qgrams(q, b"TGA").next().unwrap();

        let matches = qgram_index.qgram_matches(qgram);
        assert_eq!(matches, [5, 10]);
    }

    #[test]
    fn test_matches() {
        let (text, alphabet) = setup();
        let q = 3;
        let qgram_index = QGramIndex::new(q, text, &alphabet);

        let pattern = b"GCTG";
        let matches = qgram_index.matches(pattern, 1);
        assert_eq!(matches, [
            Match {
                pattern: Interval { start: 0, stop: 4 },
                text: Interval { start: 3, stop: 7 },
                count: 2
            }
        ]);
    }

    #[test]
    fn test_exact_matches() {
        let (text, alphabet) = setup();
        let q = 3;
        let qgram_index = QGramIndex::new(q, text, &alphabet);

        let pattern = b"GCTGA";
        let exact_matches = qgram_index.exact_matches(pattern);
        assert!(exact_matches.len() == 2);
        for m in exact_matches {
            assert_eq!(m.pattern.get(pattern), m.text.get(text));
        }
    }
}
<|endoftext|>


<commit_before>//! darwin-rs: evolutionary algorithms with Rust
//!
//! Written by Willi Kappler, Version 0.2 (2016.07.xx)
//!
//! Repository: https://github.com/willi-kappler/darwin-rs
//!
//! License: MIT
//!
//! This library allows you to write evolutionary algorithms (EA) in Rust.
//! Examples provided: TSP, Sudoku, Queens Problem
//!
//!

// external modules
use std::cmp::Ordering;

/// A wrapper helper struct for the individuals.
/// It does the book keeping of the fitness and the number of mutations this individual
/// has to run in one iteration.
#[derive(Debug,Clone)]
pub struct IndividualWrapper<T: Individual> {
    /// The actual individual, user defined struct.
    pub individual: T,
    /// the current calculated fitness for this individual.
    pub fitness: f64,
    /// The number of mutation this individual is doing in one iteration.
    pub num_of_mutations: u32,
}

/// Implement this for sorting
impl<T: Individual> PartialEq for IndividualWrapper<T> {
    fn eq(&self, other: &IndividualWrapper<T>) -> bool {
        self.fitness == other.fitness
    }
}

/// Implement this for sorting
impl<T: Individual> Eq for IndividualWrapper<T> {}

/// Implement this for sorting
impl<T: Individual> Ord for IndividualWrapper<T> {
    fn cmp(&self, other: &IndividualWrapper<T>) -> Ordering {
        self.partial_cmp(other).expect("Fitness of Individual is NaN")
    }
}

/// Implement this for sorting
impl<T: Individual> PartialOrd for IndividualWrapper<T> {
    fn partial_cmp(&self, other: &IndividualWrapper<T>) -> Option<Ordering> {
        self.fitness.partial_cmp(&other.fitness)
    }
}

/// This trait has to be implemented for the user defined struct.
pub trait Individual {
    /// This method creates a new individual.
    fn new() -> Self;
    /// This method mutates the individual. Usually this is a cheap and easy to implement
    /// function. In order to improve the simulation, the user can make this function a bit
    /// "smarter". This is nicely shown in the tsp and tsp2 example. The tsp2 example contains
    /// two types of mutation, tsp just one:
    ///
    /// examples/tsp: 1. swap position
    ///
    /// examples/tsp2: 1. swap position, 2. rotate (shift) positions
    ///
    /// By just adding this one additional mutation type the simulation converges much faster
    /// to the optimum. Of course rotation can be "simulated" by a number of swaps, but re-doing
    /// all these steps takes time and the chances that these steps are taken in the correct
    /// order by just randomly swaping positions are very slim. So just start with one simple
    /// mutation function (one operation) and add more and more "smarter" mutation types to the
    /// mutate function.
    fn mutate(&mut self);
    /// This method calculates the fitness for the individual. Usually this is an expensive
    /// operation and a bit more difficult to implement, compared to the mutation method above.
    /// The lower the fitness value, the better (healthier) the individual is and the closer
    /// the individual is to the perfect solution. This can also correspont to the number of
    /// errors like for example in the sudoku or queens problem case.
    fn calculate_fitness(&self) -> f64;
}
<commit_msg>add test case for comparing IndividualWrapper<commit_after>//! darwin-rs: evolutionary algorithms with Rust
//!
//! Written by Willi Kappler, Version 0.2 (2016.07.xx)
//!
//! Repository: https://github.com/willi-kappler/darwin-rs
//!
//! License: MIT
//!
//! This library allows you to write evolutionary algorithms (EA) in Rust.
//! Examples provided: TSP, Sudoku, Queens Problem
//!
//!

// external modules
use std::cmp::Ordering;

/// A wrapper helper struct for the individuals.
/// It does the book keeping of the fitness and the number of mutations this individual
/// has to run in one iteration.
#[derive(Debug,Clone)]
pub struct IndividualWrapper<T: Individual> {
    /// The actual individual, user defined struct.
    pub individual: T,
    /// the current calculated fitness for this individual.
    pub fitness: f64,
    /// The number of mutation this individual is doing in one iteration.
    pub num_of_mutations: u32,
}

/// Implement this for sorting
impl<T: Individual> PartialEq for IndividualWrapper<T> {
    fn eq(&self, other: &IndividualWrapper<T>) -> bool {
        self.fitness == other.fitness
    }
}

/// Implement this for sorting
impl<T: Individual> Eq for IndividualWrapper<T> {}

/// Implement this for sorting
impl<T: Individual> Ord for IndividualWrapper<T> {
    fn cmp(&self, other: &IndividualWrapper<T>) -> Ordering {
        self.partial_cmp(other).expect("Fitness of Individual is NaN")
    }
}

/// Implement this for sorting
impl<T: Individual> PartialOrd for IndividualWrapper<T> {
    fn partial_cmp(&self, other: &IndividualWrapper<T>) -> Option<Ordering> {
        self.fitness.partial_cmp(&other.fitness)
    }
}

/// This trait has to be implemented for the user defined struct.
pub trait Individual {
    /// This method creates a new individual.
    fn new() -> Self;
    /// This method mutates the individual. Usually this is a cheap and easy to implement
    /// function. In order to improve the simulation, the user can make this function a bit
    /// "smarter". This is nicely shown in the tsp and tsp2 example. The tsp2 example contains
    /// two types of mutation, tsp just one:
    ///
    /// examples/tsp: 1. swap position
    ///
    /// examples/tsp2: 1. swap position, 2. rotate (shift) positions
    ///
    /// By just adding this one additional mutation type the simulation converges much faster
    /// to the optimum. Of course rotation can be "simulated" by a number of swaps, but re-doing
    /// all these steps takes time and the chances that these steps are taken in the correct
    /// order by just randomly swaping positions are very slim. So just start with one simple
    /// mutation function (one operation) and add more and more "smarter" mutation types to the
    /// mutate function.
    fn mutate(&mut self);
    /// This method calculates the fitness for the individual. Usually this is an expensive
    /// operation and a bit more difficult to implement, compared to the mutation method above.
    /// The lower the fitness value, the better (healthier) the individual is and the closer
    /// the individual is to the perfect solution. This can also correspont to the number of
    /// errors like for example in the sudoku or queens problem case.
    fn calculate_fitness(&self) -> f64;
}

#[cfg(test)]
mod test {

    use super::{IndividualWrapper, Individual};

    struct IndividualTest1;

    impl Individual for IndividualTest1 {
        fn new() -> IndividualTest1 {
            IndividualTest1
        }

        fn mutate(&mut self) {
        }

        fn calculate_fitness(&self) -> f64 {
            0.0
        }
    }

    #[test]
    fn compare1() {
        let individual1 = IndividualWrapper{individual: IndividualTest1::new(), fitness: 1.2, num_of_mutations: 1};
        let individual2 = IndividualWrapper{individual: IndividualTest1::new(), fitness: 5.93, num_of_mutations: 1};

        assert!(individual2 > individual1);
    }

    #[test]
    fn compare2() {
        let individual1 = IndividualWrapper{individual: IndividualTest1::new(), fitness: 21.996, num_of_mutations: 1};
        let individual2 = IndividualWrapper{individual: IndividualTest1::new(), fitness: 21.996, num_of_mutations: 1};

        assert!(individual1 == individual2);
    }

}
<|endoftext|>


<commit_before>// Copyright 2019 TiKV Project Authors. Licensed under Apache-2.0.

mod backward;
mod forward;
mod txn_entry;

use engine::{CfName, CF_DEFAULT, CF_LOCK, CF_WRITE};
use kvproto::kvrpcpb::IsolationLevel;

use crate::storage::mvcc::Result;
use crate::storage::txn::Result as TxnResult;
use crate::storage::{
    Cursor, CursorBuilder, Key, ScanMode, Scanner as StoreScanner, Snapshot, Statistics, Value,
};

use self::backward::BackwardScanner;
use self::forward::ForwardScanner;
pub use self::txn_entry::Scanner as EntryScanner;

/// `Scanner` factory.
pub struct ScannerBuilder<S: Snapshot>(ScannerConfig<S>);

impl<S: Snapshot> std::ops::Deref for ScannerBuilder<S> {
    type Target = ScannerConfig<S>;
    fn deref(&self) -> &ScannerConfig<S> {
        &self.0
    }
}

impl<S: Snapshot> std::ops::DerefMut for ScannerBuilder<S> {
    fn deref_mut(&mut self) -> &mut ScannerConfig<S> {
        &mut self.0
    }
}

impl<S: Snapshot> ScannerBuilder<S> {
    /// Initialize a new `ScannerBuilder`
    pub fn new(snapshot: S, ts: u64, desc: bool) -> Self {
        Self(ScannerConfig::new(snapshot, ts, desc))
    }

    /// Set whether or not read operations should fill the cache.
    ///
    /// Defaults to `true`.
    #[inline]
    pub fn fill_cache(mut self, fill_cache: bool) -> Self {
        self.fill_cache = fill_cache;
        self
    }

    /// Set whether values of the user key should be omitted. When `omit_value` is `true`, the
    /// length of returned value will be 0.
    ///
    /// Previously this option is called `key_only`.
    ///
    /// Defaults to `false`.
    #[inline]
    pub fn omit_value(mut self, omit_value: bool) -> Self {
        self.omit_value = omit_value;
        self
    }

    /// Set the isolation level.
    ///
    /// Defaults to `IsolationLevel::Si`.
    #[inline]
    pub fn isolation_level(mut self, isolation_level: IsolationLevel) -> Self {
        self.isolation_level = isolation_level;
        self
    }

    /// Limit the range to `[lower_bound, upper_bound)` in which the `ForwardScanner` should scan.
    /// `None` means unbounded.
    ///
    /// Default is `(None, None)`.
    #[inline]
    pub fn range(mut self, lower_bound: Option<Key>, upper_bound: Option<Key>) -> Self {
        self.lower_bound = lower_bound;
        self.upper_bound = upper_bound;
        self
    }

    /// Build `Scanner` from the current configuration.
    pub fn build(mut self) -> Result<Scanner<S>> {
        let lock_cursor = self.create_cf_cursor(CF_LOCK)?;
        let write_cursor = self.create_cf_cursor(CF_WRITE)?;
        if self.desc {
            Ok(Scanner::Backward(BackwardScanner::new(
                self.0,
                lock_cursor,
                write_cursor,
            )))
        } else {
            Ok(Scanner::Forward(ForwardScanner::new(
                self.0,
                lock_cursor,
                write_cursor,
            )))
        }
    }

    pub fn build_entry_scanner(mut self) -> Result<EntryScanner<S>> {
        let lower_bound = self.lower_bound.clone();
        let lock_cursor = self.create_cf_cursor(CF_LOCK)?;
        let write_cursor = self.create_cf_cursor(CF_WRITE)?;
        // Note: Create a default cf cursor will take key range, so we need to
        //       ensure the default cursor is created after lock and write.
        let default_cursor = self.create_cf_cursor(CF_DEFAULT)?;
        Ok(EntryScanner::new(
            self.0,
            lock_cursor,
            write_cursor,
            default_cursor,
            lower_bound,
        )?)
    }
}

pub enum Scanner<S: Snapshot> {
    Forward(ForwardScanner<S>),
    Backward(BackwardScanner<S>),
}

impl<S: Snapshot> StoreScanner for Scanner<S> {
    fn next(&mut self) -> TxnResult<Option<(Key, Value)>> {
        match self {
            Scanner::Forward(scanner) => Ok(scanner.read_next()?),
            Scanner::Backward(scanner) => Ok(scanner.read_next()?),
        }
    }
    /// Take out and reset the statistics collected so far.
    fn take_statistics(&mut self) -> Statistics {
        match self {
            Scanner::Forward(scanner) => scanner.take_statistics(),
            Scanner::Backward(scanner) => scanner.take_statistics(),
        }
    }
}

pub struct ScannerConfig<S: Snapshot> {
    snapshot: S,
    fill_cache: bool,
    omit_value: bool,
    isolation_level: IsolationLevel,

    /// `lower_bound` and `upper_bound` is used to create `default_cursor`. `upper_bound`
    /// is used in initial seek(or `lower_bound` in initial backward seek) as well. They will be consumed after `default_cursor` is being
    /// created.
    lower_bound: Option<Key>,
    upper_bound: Option<Key>,

    ts: u64,
    desc: bool,
}

impl<S: Snapshot> ScannerConfig<S> {
    fn new(snapshot: S, ts: u64, desc: bool) -> Self {
        Self {
            snapshot,
            fill_cache: true,
            omit_value: false,
            isolation_level: IsolationLevel::Si,
            lower_bound: None,
            upper_bound: None,
            ts,
            desc,
        }
    }

    #[inline]
    fn scan_mode(&self) -> ScanMode {
        if self.desc {
            ScanMode::Backward
        } else {
            ScanMode::Forward
        }
    }

    /// Create the cursor.
    #[inline]
    fn create_cf_cursor(&mut self, cf: CfName) -> Result<Cursor<S::Iter>> {
        let (lower, upper) = if cf == CF_DEFAULT {
            (self.lower_bound.take(), self.upper_bound.take())
        } else {
            (self.lower_bound.clone(), self.upper_bound.clone())
        };
        let cursor = CursorBuilder::new(&self.snapshot, cf)
            .range(lower, upper)
            .fill_cache(self.fill_cache)
            .scan_mode(self.scan_mode())
            .build()?;
        Ok(cursor)
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::storage::kv::Engine;
    use crate::storage::mvcc::tests::*;
    use crate::storage::mvcc::Error as MvccError;
    use crate::storage::txn::Error as TxnError;
    use crate::storage::TestEngineBuilder;
    use kvproto::kvrpcpb::Context;

    // Collect data from the scanner and assert it equals to `expected`, which is a collection of
    // (raw_key, value).
    // `None` value in `expected` means the key is locked.
    fn check_scan_result<S: Snapshot>(
        mut scanner: Scanner<S>,
        expected: &[(Vec<u8>, Option<Vec<u8>>)],
    ) {
        let mut scan_result = Vec::new();
        loop {
            match scanner.next() {
                Ok(None) => break,
                Ok(Some((key, value))) => scan_result.push((key.to_raw().unwrap(), Some(value))),
                Err(TxnError::Mvcc(MvccError::KeyIsLocked(mut info))) => {
                    scan_result.push((info.take_key(), None))
                }
                e => panic!("got error while scanning: {:?}", e),
            }
        }

        assert_eq!(scan_result, expected);
    }

    fn test_scan_with_lock_impl(desc: bool) {
        let engine = TestEngineBuilder::new().build().unwrap();

        for i in 0..5 {
            must_prewrite_put(&engine, &[i], &[b'v', i], &[i], 1);
            must_commit(&engine, &[i], 1, 2);
            must_prewrite_put(&engine, &[i], &[b'v', i], &[i], 10);
            must_commit(&engine, &[i], 10, 100);
        }

        must_acquire_pessimistic_lock(&engine, &[1], &[1], 20, 110);
        must_acquire_pessimistic_lock(&engine, &[2], &[2], 50, 110);
        must_acquire_pessimistic_lock(&engine, &[3], &[3], 105, 110);
        must_prewrite_put(&engine, &[4], b"a", &[4], 105);

        let snapshot = engine.snapshot(&Context::default()).unwrap();

        let mut expected_result = vec![
            (vec![0], Some(vec![b'v', 0])),
            (vec![1], Some(vec![b'v', 1])),
            (vec![2], Some(vec![b'v', 2])),
            (vec![3], Some(vec![b'v', 3])),
            (vec![4], Some(vec![b'v', 4])),
        ];

        if desc {
            expected_result = expected_result.into_iter().rev().collect();
        }

        let scanner = ScannerBuilder::new(snapshot.clone(), 30, desc)
            .build()
            .unwrap();
        check_scan_result(scanner, &expected_result);

        let scanner = ScannerBuilder::new(snapshot.clone(), 70, desc)
            .build()
            .unwrap();
        check_scan_result(scanner, &expected_result);

        let scanner = ScannerBuilder::new(snapshot.clone(), 103, desc)
            .build()
            .unwrap();
        check_scan_result(scanner, &expected_result);

        // The value of key 4 is locked at 105 so that it can't be read at 106
        if desc {
            expected_result[0].1 = None;
        } else {
            expected_result[4].1 = None;
        }
        let scanner = ScannerBuilder::new(snapshot, 106, desc).build().unwrap();
        check_scan_result(scanner, &expected_result);
    }

    #[test]
    fn test_scan_with_lock() {
        test_scan_with_lock_impl(false);
        test_scan_with_lock_impl(true);
    }
}
<commit_msg>MVCC Scanner unit tests: Add test for scanner under lock (#5474)<commit_after>// Copyright 2019 TiKV Project Authors. Licensed under Apache-2.0.

mod backward;
mod forward;
mod txn_entry;

use engine::{CfName, CF_DEFAULT, CF_LOCK, CF_WRITE};
use kvproto::kvrpcpb::IsolationLevel;

use crate::storage::mvcc::Result;
use crate::storage::txn::Result as TxnResult;
use crate::storage::{
    Cursor, CursorBuilder, Key, ScanMode, Scanner as StoreScanner, Snapshot, Statistics, Value,
};

use self::backward::BackwardScanner;
use self::forward::ForwardScanner;
pub use self::txn_entry::Scanner as EntryScanner;

/// `Scanner` factory.
pub struct ScannerBuilder<S: Snapshot>(ScannerConfig<S>);

impl<S: Snapshot> std::ops::Deref for ScannerBuilder<S> {
    type Target = ScannerConfig<S>;
    fn deref(&self) -> &ScannerConfig<S> {
        &self.0
    }
}

impl<S: Snapshot> std::ops::DerefMut for ScannerBuilder<S> {
    fn deref_mut(&mut self) -> &mut ScannerConfig<S> {
        &mut self.0
    }
}

impl<S: Snapshot> ScannerBuilder<S> {
    /// Initialize a new `ScannerBuilder`
    pub fn new(snapshot: S, ts: u64, desc: bool) -> Self {
        Self(ScannerConfig::new(snapshot, ts, desc))
    }

    /// Set whether or not read operations should fill the cache.
    ///
    /// Defaults to `true`.
    #[inline]
    pub fn fill_cache(mut self, fill_cache: bool) -> Self {
        self.fill_cache = fill_cache;
        self
    }

    /// Set whether values of the user key should be omitted. When `omit_value` is `true`, the
    /// length of returned value will be 0.
    ///
    /// Previously this option is called `key_only`.
    ///
    /// Defaults to `false`.
    #[inline]
    pub fn omit_value(mut self, omit_value: bool) -> Self {
        self.omit_value = omit_value;
        self
    }

    /// Set the isolation level.
    ///
    /// Defaults to `IsolationLevel::Si`.
    #[inline]
    pub fn isolation_level(mut self, isolation_level: IsolationLevel) -> Self {
        self.isolation_level = isolation_level;
        self
    }

    /// Limit the range to `[lower_bound, upper_bound)` in which the `ForwardScanner` should scan.
    /// `None` means unbounded.
    ///
    /// Default is `(None, None)`.
    #[inline]
    pub fn range(mut self, lower_bound: Option<Key>, upper_bound: Option<Key>) -> Self {
        self.lower_bound = lower_bound;
        self.upper_bound = upper_bound;
        self
    }

    /// Build `Scanner` from the current configuration.
    pub fn build(mut self) -> Result<Scanner<S>> {
        let lock_cursor = self.create_cf_cursor(CF_LOCK)?;
        let write_cursor = self.create_cf_cursor(CF_WRITE)?;
        if self.desc {
            Ok(Scanner::Backward(BackwardScanner::new(
                self.0,
                lock_cursor,
                write_cursor,
            )))
        } else {
            Ok(Scanner::Forward(ForwardScanner::new(
                self.0,
                lock_cursor,
                write_cursor,
            )))
        }
    }

    pub fn build_entry_scanner(mut self) -> Result<EntryScanner<S>> {
        let lower_bound = self.lower_bound.clone();
        let lock_cursor = self.create_cf_cursor(CF_LOCK)?;
        let write_cursor = self.create_cf_cursor(CF_WRITE)?;
        // Note: Create a default cf cursor will take key range, so we need to
        //       ensure the default cursor is created after lock and write.
        let default_cursor = self.create_cf_cursor(CF_DEFAULT)?;
        Ok(EntryScanner::new(
            self.0,
            lock_cursor,
            write_cursor,
            default_cursor,
            lower_bound,
        )?)
    }
}

pub enum Scanner<S: Snapshot> {
    Forward(ForwardScanner<S>),
    Backward(BackwardScanner<S>),
}

impl<S: Snapshot> StoreScanner for Scanner<S> {
    fn next(&mut self) -> TxnResult<Option<(Key, Value)>> {
        match self {
            Scanner::Forward(scanner) => Ok(scanner.read_next()?),
            Scanner::Backward(scanner) => Ok(scanner.read_next()?),
        }
    }
    /// Take out and reset the statistics collected so far.
    fn take_statistics(&mut self) -> Statistics {
        match self {
            Scanner::Forward(scanner) => scanner.take_statistics(),
            Scanner::Backward(scanner) => scanner.take_statistics(),
        }
    }
}

pub struct ScannerConfig<S: Snapshot> {
    snapshot: S,
    fill_cache: bool,
    omit_value: bool,
    isolation_level: IsolationLevel,

    /// `lower_bound` and `upper_bound` is used to create `default_cursor`. `upper_bound`
    /// is used in initial seek(or `lower_bound` in initial backward seek) as well. They will be consumed after `default_cursor` is being
    /// created.
    lower_bound: Option<Key>,
    upper_bound: Option<Key>,

    ts: u64,
    desc: bool,
}

impl<S: Snapshot> ScannerConfig<S> {
    fn new(snapshot: S, ts: u64, desc: bool) -> Self {
        Self {
            snapshot,
            fill_cache: true,
            omit_value: false,
            isolation_level: IsolationLevel::Si,
            lower_bound: None,
            upper_bound: None,
            ts,
            desc,
        }
    }

    #[inline]
    fn scan_mode(&self) -> ScanMode {
        if self.desc {
            ScanMode::Backward
        } else {
            ScanMode::Forward
        }
    }

    /// Create the cursor.
    #[inline]
    fn create_cf_cursor(&mut self, cf: CfName) -> Result<Cursor<S::Iter>> {
        let (lower, upper) = if cf == CF_DEFAULT {
            (self.lower_bound.take(), self.upper_bound.take())
        } else {
            (self.lower_bound.clone(), self.upper_bound.clone())
        };
        let cursor = CursorBuilder::new(&self.snapshot, cf)
            .range(lower, upper)
            .fill_cache(self.fill_cache)
            .scan_mode(self.scan_mode())
            .build()?;
        Ok(cursor)
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::storage::kv::Engine;
    use crate::storage::mvcc::tests::*;
    use crate::storage::mvcc::Error as MvccError;
    use crate::storage::txn::Error as TxnError;
    use crate::storage::RocksEngine;
    use crate::storage::TestEngineBuilder;
    use kvproto::kvrpcpb::Context;

    // Collect data from the scanner and assert it equals to `expected`, which is a collection of
    // (raw_key, value).
    // `None` value in `expected` means the key is locked.
    fn check_scan_result<S: Snapshot>(
        mut scanner: Scanner<S>,
        expected: &[(Vec<u8>, Option<Vec<u8>>)],
    ) {
        let mut scan_result = Vec::new();
        loop {
            match scanner.next() {
                Ok(None) => break,
                Ok(Some((key, value))) => scan_result.push((key.to_raw().unwrap(), Some(value))),
                Err(TxnError::Mvcc(MvccError::KeyIsLocked(mut info))) => {
                    scan_result.push((info.take_key(), None))
                }
                e => panic!("got error while scanning: {:?}", e),
            }
        }

        assert_eq!(scan_result, expected);
    }

    fn test_scan_with_lock_and_write_impl(desc: bool) {
        const SCAN_TS: u64 = 10;
        const PREV_TS: u64 = 4;
        const POST_TS: u64 = 5;

        let new_engine = || TestEngineBuilder::new().build().unwrap();
        let add_write_at_ts = |commit_ts, engine, key, value| {
            must_prewrite_put(engine, key, value, key, commit_ts);
            must_commit(engine, key, commit_ts, commit_ts);
        };

        let add_lock_at_ts = |lock_ts, engine, key| {
            must_prewrite_put(engine, key, b"lock", key, lock_ts);
            must_locked(engine, key, lock_ts);
        };

        let test_scanner_result =
            move |engine: &RocksEngine, expected_result: Vec<(Vec<u8>, Option<Vec<u8>>)>| {
                let snapshot = engine.snapshot(&Context::default()).unwrap();

                let scanner = ScannerBuilder::new(snapshot.clone(), SCAN_TS, desc)
                    .build()
                    .unwrap();
                check_scan_result(scanner, &expected_result);
            };

        let desc_map = move |result: Vec<(Vec<u8>, Option<Vec<u8>>)>| {
            if desc {
                result.into_iter().rev().collect()
            } else {
                result
            }
        };

        // Lock after write
        let engine = new_engine();

        add_write_at_ts(POST_TS, &engine, b"a", b"a_value");
        add_lock_at_ts(PREV_TS, &engine, b"b");

        let expected_result = desc_map(vec![
            (b"a".to_vec(), Some(b"a_value".to_vec())),
            (b"b".to_vec(), None),
        ]);

        test_scanner_result(&engine, expected_result);

        // Lock before write for same key
        let engine = new_engine();
        add_write_at_ts(PREV_TS, &engine, b"a", b"a_value");
        add_lock_at_ts(POST_TS, &engine, b"a");

        let expected_result = vec![(b"a".to_vec(), None)];

        test_scanner_result(&engine, expected_result);

        // Lock before write in different keys
        let engine = new_engine();
        add_lock_at_ts(POST_TS, &engine, b"a");
        add_write_at_ts(PREV_TS, &engine, b"b", b"b_value");

        let expected_result = desc_map(vec![
            (b"a".to_vec(), None),
            (b"b".to_vec(), Some(b"b_value".to_vec())),
        ]);
        test_scanner_result(&engine, expected_result);

        // Only a lock here
        let engine = new_engine();
        add_lock_at_ts(PREV_TS, &engine, b"a");

        let expected_result = desc_map(vec![(b"a".to_vec(), None)]);

        test_scanner_result(&engine, expected_result);

        // Write Only
        let engine = new_engine();
        add_write_at_ts(PREV_TS, &engine, b"a", b"a_value");

        let expected_result = desc_map(vec![(b"a".to_vec(), Some(b"a_value".to_vec()))]);
        test_scanner_result(&engine, expected_result);
    }

    fn test_scan_with_lock_impl(desc: bool) {
        let engine = TestEngineBuilder::new().build().unwrap();

        for i in 0..5 {
            must_prewrite_put(&engine, &[i], &[b'v', i], &[i], 1);
            must_commit(&engine, &[i], 1, 2);
            must_prewrite_put(&engine, &[i], &[b'v', i], &[i], 10);
            must_commit(&engine, &[i], 10, 100);
        }

        must_acquire_pessimistic_lock(&engine, &[1], &[1], 20, 110);
        must_acquire_pessimistic_lock(&engine, &[2], &[2], 50, 110);
        must_acquire_pessimistic_lock(&engine, &[3], &[3], 105, 110);
        must_prewrite_put(&engine, &[4], b"a", &[4], 105);

        let snapshot = engine.snapshot(&Context::default()).unwrap();

        let mut expected_result = vec![
            (vec![0], Some(vec![b'v', 0])),
            (vec![1], Some(vec![b'v', 1])),
            (vec![2], Some(vec![b'v', 2])),
            (vec![3], Some(vec![b'v', 3])),
            (vec![4], Some(vec![b'v', 4])),
        ];

        if desc {
            expected_result = expected_result.into_iter().rev().collect();
        }

        let scanner = ScannerBuilder::new(snapshot.clone(), 30, desc)
            .build()
            .unwrap();
        check_scan_result(scanner, &expected_result);

        let scanner = ScannerBuilder::new(snapshot.clone(), 70, desc)
            .build()
            .unwrap();
        check_scan_result(scanner, &expected_result);

        let scanner = ScannerBuilder::new(snapshot.clone(), 103, desc)
            .build()
            .unwrap();
        check_scan_result(scanner, &expected_result);

        // The value of key 4 is locked at 105 so that it can't be read at 106
        if desc {
            expected_result[0].1 = None;
        } else {
            expected_result[4].1 = None;
        }
        let scanner = ScannerBuilder::new(snapshot, 106, desc).build().unwrap();
        check_scan_result(scanner, &expected_result);
    }

    #[test]
    fn test_scan_with_lock_and_write() {
        test_scan_with_lock_and_write_impl(true);
        test_scan_with_lock_and_write_impl(false);
    }

    #[test]
    fn test_scan_with_lock() {
        test_scan_with_lock_impl(false);
        test_scan_with_lock_impl(true);
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// 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.

//! Dynamically typed value.

use alloc::boxed::Box;
use alloc::vec::Vec;

use crate::capability::FromClientHook;
use crate::private::capability::{ClientHook, PipelineHook, PipelineOp};
use crate::private::layout::{PointerReader, PointerBuilder};
use crate::traits::{FromPointerReader, FromPointerBuilder, SetPointerBuilder};
use crate::Result;

#[derive(Copy, Clone)]
pub struct Owned(());

impl <'a> crate::traits::Owned<'a> for Owned {
    type Reader = Reader<'a>;
    type Builder = Builder<'a>;
}

impl crate::traits::Pipelined for Owned {
    type Pipeline = Pipeline;
}

#[derive(Copy, Clone)]
pub struct Reader<'a> {
    reader: PointerReader<'a>
}

impl <'a> Reader<'a> {
    #[inline]
    pub fn new<'b>(reader: PointerReader<'b>) -> Reader<'b> {
        Reader { reader: reader }
    }

    #[inline]
    pub fn is_null(&self) -> bool {
        self.reader.is_null()
    }

    /// Gets the total size of the target and all of its children. Does not count far pointer overhead.
    pub fn target_size(&self) -> Result<crate::MessageSize> {
        self.reader.total_size()
    }

    #[inline]
    pub fn get_as<T: FromPointerReader<'a>>(&self) -> Result<T> {
        FromPointerReader::get_from_pointer(&self.reader, None)
    }

    pub fn get_as_capability<T: FromClientHook>(&self) -> Result<T> {
        Ok(FromClientHook::new(self.reader.get_capability()?))
    }

    //# Used by RPC system to implement pipelining. Applications
    //# generally shouldn't use this directly.
    pub fn get_pipelined_cap(&self, ops: &[PipelineOp]) -> Result<Box<dyn ClientHook>> {
        let mut pointer = self.reader;

        for op in ops {
            match *op {
                PipelineOp::Noop =>  { }
                PipelineOp::GetPointerField(idx) => {
                    pointer = pointer.get_struct(None)?.get_pointer_field(idx as usize);
                }
            }
        }

        pointer.get_capability()
    }
}

impl <'a> FromPointerReader<'a> for Reader<'a> {
    fn get_from_pointer(reader: &PointerReader<'a>, default: Option<&'a [crate::Word]>) -> Result<Reader<'a>> {
        if default.is_some() {
            panic!("Unsupported: any_pointer with a default value.");
        }
        Ok(Reader { reader: *reader })
    }
}

impl <'a> crate::traits::SetPointerBuilder<Builder<'a>> for Reader<'a> {
    fn set_pointer_builder<'b>(mut pointer: crate::private::layout::PointerBuilder<'b>,
                               value: Reader<'a>,
                               canonicalize: bool) -> Result<()> {
        pointer.copy_from(value.reader, canonicalize)
    }
}

impl <'a> crate::traits::Imbue<'a> for Reader<'a> {
    fn imbue(&mut self, cap_table: &'a crate::private::layout::CapTable) {
        self.reader.imbue(crate::private::layout::CapTableReader::Plain(cap_table));
    }
}

pub struct Builder<'a> {
    builder: PointerBuilder<'a>
}

impl <'a> Builder<'a> {
    #[inline]
    pub fn new<'b>(builder: PointerBuilder<'a>) -> Builder<'a> {
        Builder { builder: builder }
    }

    pub fn reborrow<'b>(&'b mut self) -> Builder<'b> {
        Builder { builder: self.builder.borrow() }
    }

    pub fn is_null(&self) -> bool {
        self.builder.is_null()
    }

    /// Gets the total size of the target and all of its children. Does not count far pointer overhead.
    pub fn target_size(&self) -> Result<crate::MessageSize> {
        self.builder.into_reader().total_size()
    }

    pub fn get_as<T : FromPointerBuilder<'a>>(self) -> Result<T> {
        FromPointerBuilder::get_from_pointer(self.builder, None)
    }

    pub fn init_as<T : FromPointerBuilder<'a>>(self) -> T {
        FromPointerBuilder::init_pointer(self.builder, 0)
    }

    pub fn initn_as<T: FromPointerBuilder<'a>>(self, size: u32) -> T {
        FromPointerBuilder::init_pointer(self.builder, size)
    }

    pub fn set_as<To, From : SetPointerBuilder<To>>(self, value: From) -> Result<()> {
        SetPointerBuilder::<To>::set_pointer_builder(self.builder, value, false)
    }

    // XXX value should be a user client.
    pub fn set_as_capability(&mut self, value: Box<dyn ClientHook>) {
        self.builder.set_capability(value);
    }

    #[inline]
    pub fn clear(&mut self) {
        self.builder.clear()
    }

    pub fn into_reader(self) -> Reader<'a> {
        Reader { reader: self.builder.into_reader() }
    }
}

impl <'a> FromPointerBuilder<'a> for Builder<'a> {
    fn init_pointer(mut builder: PointerBuilder<'a>, _len: u32) -> Builder<'a> {
        if !builder.is_null() {
            builder.clear();
        }
        Builder { builder: builder }
    }
    fn get_from_pointer(builder: PointerBuilder<'a>, default: Option<&'a [crate::Word]>) -> Result<Builder<'a>> {
        if default.is_some() {
            panic!("AnyPointer defaults are unsupported")
        }
        Ok(Builder { builder: builder })
    }
}

impl <'a> crate::traits::ImbueMut<'a> for Builder<'a> {
    fn imbue_mut(&mut self, cap_table: &'a mut crate::private::layout::CapTable) {
        self.builder.imbue(crate::private::layout::CapTableBuilder::Plain(cap_table));
    }
}

pub struct Pipeline {
    // XXX this should not be public
    pub hook: Box<dyn PipelineHook>,

    ops: Vec<PipelineOp>,
}

impl Pipeline {
    pub fn new(hook: Box<dyn PipelineHook>) -> Pipeline {
        Pipeline { hook: hook, ops: Vec::new() }
    }

    pub fn noop(&self) -> Pipeline {
        Pipeline { hook: self.hook.add_ref(), ops: self.ops.clone() }
    }

    pub fn get_pointer_field(&self, pointer_index: u16) -> Pipeline {
        let mut new_ops = Vec::with_capacity(self.ops.len() + 1);
        for op in &self.ops {
            new_ops.push(*op)
        }
        new_ops.push(PipelineOp::GetPointerField(pointer_index));
        Pipeline { hook : self.hook.add_ref(), ops: new_ops }
    }

    pub fn as_cap(&self) -> Box<dyn ClientHook> {
        self.hook.get_pipelined_cap(&self.ops)
    }
}

impl crate::capability::FromTypelessPipeline for Pipeline {
    fn new(typeless: Pipeline) -> Pipeline {
        typeless
    }
}

#[test]
fn init_clears_value() {
    let mut message = crate::message::Builder::new_default();
    {
        let root: crate::any_pointer::Builder = message.init_root();
        let mut list: crate::primitive_list::Builder<u16> = root.initn_as(10);
        for idx in 0..10 {
            list.set(idx, idx as u16);
        }
    }

    {
        let root: crate::any_pointer::Builder = message.init_root();
        assert!(root.is_null());
    }

    let mut output: Vec<u8> = Vec::new();
    crate::serialize::write_message(&mut output, &mut message).unwrap();
    assert_eq!(output.len(), 40);
    for byte in &output[8..] {
        // Everything not in the message header is zero.
        assert_eq!(*byte, 0u8);
    }
}
<commit_msg>remove unneeded lifetime parameter<commit_after>// Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// 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.

//! Dynamically typed value.

use alloc::boxed::Box;
use alloc::vec::Vec;

use crate::capability::FromClientHook;
use crate::private::capability::{ClientHook, PipelineHook, PipelineOp};
use crate::private::layout::{PointerReader, PointerBuilder};
use crate::traits::{FromPointerReader, FromPointerBuilder, SetPointerBuilder};
use crate::Result;

#[derive(Copy, Clone)]
pub struct Owned(());

impl <'a> crate::traits::Owned<'a> for Owned {
    type Reader = Reader<'a>;
    type Builder = Builder<'a>;
}

impl crate::traits::Pipelined for Owned {
    type Pipeline = Pipeline;
}

#[derive(Copy, Clone)]
pub struct Reader<'a> {
    reader: PointerReader<'a>
}

impl <'a> Reader<'a> {
    #[inline]
    pub fn new<'b>(reader: PointerReader<'b>) -> Reader<'b> {
        Reader { reader: reader }
    }

    #[inline]
    pub fn is_null(&self) -> bool {
        self.reader.is_null()
    }

    /// Gets the total size of the target and all of its children. Does not count far pointer overhead.
    pub fn target_size(&self) -> Result<crate::MessageSize> {
        self.reader.total_size()
    }

    #[inline]
    pub fn get_as<T: FromPointerReader<'a>>(&self) -> Result<T> {
        FromPointerReader::get_from_pointer(&self.reader, None)
    }

    pub fn get_as_capability<T: FromClientHook>(&self) -> Result<T> {
        Ok(FromClientHook::new(self.reader.get_capability()?))
    }

    //# Used by RPC system to implement pipelining. Applications
    //# generally shouldn't use this directly.
    pub fn get_pipelined_cap(&self, ops: &[PipelineOp]) -> Result<Box<dyn ClientHook>> {
        let mut pointer = self.reader;

        for op in ops {
            match *op {
                PipelineOp::Noop =>  { }
                PipelineOp::GetPointerField(idx) => {
                    pointer = pointer.get_struct(None)?.get_pointer_field(idx as usize);
                }
            }
        }

        pointer.get_capability()
    }
}

impl <'a> FromPointerReader<'a> for Reader<'a> {
    fn get_from_pointer(reader: &PointerReader<'a>, default: Option<&'a [crate::Word]>) -> Result<Reader<'a>> {
        if default.is_some() {
            panic!("Unsupported: any_pointer with a default value.");
        }
        Ok(Reader { reader: *reader })
    }
}

impl <'a> crate::traits::SetPointerBuilder<Builder<'a>> for Reader<'a> {
    fn set_pointer_builder<'b>(mut pointer: crate::private::layout::PointerBuilder<'b>,
                               value: Reader<'a>,
                               canonicalize: bool) -> Result<()> {
        pointer.copy_from(value.reader, canonicalize)
    }
}

impl <'a> crate::traits::Imbue<'a> for Reader<'a> {
    fn imbue(&mut self, cap_table: &'a crate::private::layout::CapTable) {
        self.reader.imbue(crate::private::layout::CapTableReader::Plain(cap_table));
    }
}

pub struct Builder<'a> {
    builder: PointerBuilder<'a>
}

impl <'a> Builder<'a> {
    #[inline]
    pub fn new(builder: PointerBuilder<'a>) -> Builder<'a> {
        Builder { builder: builder }
    }

    pub fn reborrow<'b>(&'b mut self) -> Builder<'b> {
        Builder { builder: self.builder.borrow() }
    }

    pub fn is_null(&self) -> bool {
        self.builder.is_null()
    }

    /// Gets the total size of the target and all of its children. Does not count far pointer overhead.
    pub fn target_size(&self) -> Result<crate::MessageSize> {
        self.builder.into_reader().total_size()
    }

    pub fn get_as<T : FromPointerBuilder<'a>>(self) -> Result<T> {
        FromPointerBuilder::get_from_pointer(self.builder, None)
    }

    pub fn init_as<T : FromPointerBuilder<'a>>(self) -> T {
        FromPointerBuilder::init_pointer(self.builder, 0)
    }

    pub fn initn_as<T: FromPointerBuilder<'a>>(self, size: u32) -> T {
        FromPointerBuilder::init_pointer(self.builder, size)
    }

    pub fn set_as<To, From : SetPointerBuilder<To>>(self, value: From) -> Result<()> {
        SetPointerBuilder::<To>::set_pointer_builder(self.builder, value, false)
    }

    // XXX value should be a user client.
    pub fn set_as_capability(&mut self, value: Box<dyn ClientHook>) {
        self.builder.set_capability(value);
    }

    #[inline]
    pub fn clear(&mut self) {
        self.builder.clear()
    }

    pub fn into_reader(self) -> Reader<'a> {
        Reader { reader: self.builder.into_reader() }
    }
}

impl <'a> FromPointerBuilder<'a> for Builder<'a> {
    fn init_pointer(mut builder: PointerBuilder<'a>, _len: u32) -> Builder<'a> {
        if !builder.is_null() {
            builder.clear();
        }
        Builder { builder: builder }
    }
    fn get_from_pointer(builder: PointerBuilder<'a>, default: Option<&'a [crate::Word]>) -> Result<Builder<'a>> {
        if default.is_some() {
            panic!("AnyPointer defaults are unsupported")
        }
        Ok(Builder { builder: builder })
    }
}

impl <'a> crate::traits::ImbueMut<'a> for Builder<'a> {
    fn imbue_mut(&mut self, cap_table: &'a mut crate::private::layout::CapTable) {
        self.builder.imbue(crate::private::layout::CapTableBuilder::Plain(cap_table));
    }
}

pub struct Pipeline {
    // XXX this should not be public
    pub hook: Box<dyn PipelineHook>,

    ops: Vec<PipelineOp>,
}

impl Pipeline {
    pub fn new(hook: Box<dyn PipelineHook>) -> Pipeline {
        Pipeline { hook: hook, ops: Vec::new() }
    }

    pub fn noop(&self) -> Pipeline {
        Pipeline { hook: self.hook.add_ref(), ops: self.ops.clone() }
    }

    pub fn get_pointer_field(&self, pointer_index: u16) -> Pipeline {
        let mut new_ops = Vec::with_capacity(self.ops.len() + 1);
        for op in &self.ops {
            new_ops.push(*op)
        }
        new_ops.push(PipelineOp::GetPointerField(pointer_index));
        Pipeline { hook : self.hook.add_ref(), ops: new_ops }
    }

    pub fn as_cap(&self) -> Box<dyn ClientHook> {
        self.hook.get_pipelined_cap(&self.ops)
    }
}

impl crate::capability::FromTypelessPipeline for Pipeline {
    fn new(typeless: Pipeline) -> Pipeline {
        typeless
    }
}

#[test]
fn init_clears_value() {
    let mut message = crate::message::Builder::new_default();
    {
        let root: crate::any_pointer::Builder = message.init_root();
        let mut list: crate::primitive_list::Builder<u16> = root.initn_as(10);
        for idx in 0..10 {
            list.set(idx, idx as u16);
        }
    }

    {
        let root: crate::any_pointer::Builder = message.init_root();
        assert!(root.is_null());
    }

    let mut output: Vec<u8> = Vec::new();
    crate::serialize::write_message(&mut output, &mut message).unwrap();
    assert_eq!(output.len(), 40);
    for byte in &output[8..] {
        // Everything not in the message header is zero.
        assert_eq!(*byte, 0u8);
    }
}
<|endoftext|>