<commit_before>//! FIXME: write short doc here

use hir::db::HirDatabase;
use ra_db::FileRange;
use ra_fmt::{leading_indent, reindent};
use ra_syntax::{
    algo::{self, find_covering_element, find_node_at_offset},
    AstNode, SourceFile, SyntaxElement, SyntaxKind, SyntaxNode, SyntaxToken, TextRange, TextUnit,
    TokenAtOffset,
};
use ra_text_edit::TextEditBuilder;

use crate::{AssistAction, AssistId, AssistLabel};

#[derive(Clone, Debug)]
pub(crate) enum Assist {
    Unresolved(Vec<AssistLabel>),
    Resolved(Vec<(AssistLabel, AssistAction)>),
}

/// `AssistCtx` allows to apply an assist or check if it could be applied.
///
/// Assists use a somewhat over-engineered approach, given the current needs. The
/// assists workflow consists of two phases. In the first phase, a user asks for
/// the list of available assists. In the second phase, the user picks a
/// particular assist and it gets applied.
///
/// There are two peculiarities here:
///
/// * first, we ideally avoid computing more things then necessary to answer
///   "is assist applicable" in the first phase.
/// * second, when we are applying assist, we don't have a guarantee that there
///   weren't any changes between the point when user asked for assists and when
///   they applied a particular assist. So, when applying assist, we need to do
///   all the checks from scratch.
///
/// To avoid repeating the same code twice for both "check" and "apply"
/// functions, we use an approach reminiscent of that of Django's function based
/// views dealing with forms. Each assist receives a runtime parameter,
/// `should_compute_edit`. It first check if an edit is applicable (potentially
/// computing info required to compute the actual edit). If it is applicable,
/// and `should_compute_edit` is `true`, it then computes the actual edit.
///
/// So, to implement the original assists workflow, we can first apply each edit
/// with `should_compute_edit = false`, and then applying the selected edit
/// again, with `should_compute_edit = true` this time.
///
/// Note, however, that we don't actually use such two-phase logic at the
/// moment, because the LSP API is pretty awkward in this place, and it's much
/// easier to just compute the edit eagerly :-)#[derive(Debug, Clone)]
#[derive(Debug)]
pub(crate) struct AssistCtx<'a, DB> {
    pub(crate) db: &'a DB,
    pub(crate) frange: FileRange,
    source_file: SourceFile,
    should_compute_edit: bool,
    assist: Assist,
}

impl<'a, DB> Clone for AssistCtx<'a, DB> {
    fn clone(&self) -> Self {
        AssistCtx {
            db: self.db,
            frange: self.frange,
            source_file: self.source_file.clone(),
            should_compute_edit: self.should_compute_edit,
            assist: self.assist.clone(),
        }
    }
}

impl<'a, DB: HirDatabase> AssistCtx<'a, DB> {
    pub(crate) fn with_ctx<F, T>(db: &DB, frange: FileRange, should_compute_edit: bool, f: F) -> T
    where
        F: FnOnce(AssistCtx<DB>) -> T,
    {
        let parse = db.parse(frange.file_id);
        let assist =
            if should_compute_edit { Assist::Resolved(vec![]) } else { Assist::Unresolved(vec![]) };

        let ctx = AssistCtx { db, frange, source_file: parse.tree(), should_compute_edit, assist };
        f(ctx)
    }

    pub(crate) fn add_action(
        &mut self,
        id: AssistId,
        label: impl Into<String>,
        f: impl FnOnce(&mut AssistBuilder),
    ) -> &mut Self {
        let label = AssistLabel { label: label.into(), id };
        match &mut self.assist {
            Assist::Unresolved(labels) => labels.push(label),
            Assist::Resolved(labels_actions) => {
                let action = {
                    let mut edit = AssistBuilder::default();
                    f(&mut edit);
                    edit.build()
                };
                labels_actions.push((label, action));
            }
        }
        self
    }

    pub(crate) fn build(self) -> Option<Assist> {
        Some(self.assist)
    }

    pub(crate) fn token_at_offset(&self) -> TokenAtOffset<SyntaxToken> {
        self.source_file.syntax().token_at_offset(self.frange.range.start())
    }

    pub(crate) fn find_token_at_offset(&self, kind: SyntaxKind) -> Option<SyntaxToken> {
        self.token_at_offset().find(|it| it.kind() == kind)
    }

    pub(crate) fn find_node_at_offset<N: AstNode>(&self) -> Option<N> {
        find_node_at_offset(self.source_file.syntax(), self.frange.range.start())
    }
    pub(crate) fn covering_element(&self) -> SyntaxElement {
        find_covering_element(self.source_file.syntax(), self.frange.range)
    }

    pub(crate) fn covering_node_for_range(&self, range: TextRange) -> SyntaxElement {
        find_covering_element(self.source_file.syntax(), range)
    }
}

#[derive(Default)]
pub(crate) struct AssistBuilder {
    edit: TextEditBuilder,
    cursor_position: Option<TextUnit>,
    target: Option<TextRange>,
}

impl AssistBuilder {
    /// Replaces specified `range` of text with a given string.
    pub(crate) fn replace(&mut self, range: TextRange, replace_with: impl Into<String>) {
        self.edit.replace(range, replace_with.into())
    }

    /// Replaces specified `node` of text with a given string, reindenting the
    /// string to maintain `node`'s existing indent.
    // FIXME: remove in favor of ra_syntax::edit::IndentLevel::increase_indent
    pub(crate) fn replace_node_and_indent(
        &mut self,
        node: &SyntaxNode,
        replace_with: impl Into<String>,
    ) {
        let mut replace_with = replace_with.into();
        if let Some(indent) = leading_indent(node) {
            replace_with = reindent(&replace_with, &indent)
        }
        self.replace(node.text_range(), replace_with)
    }

    /// Remove specified `range` of text.
    #[allow(unused)]
    pub(crate) fn delete(&mut self, range: TextRange) {
        self.edit.delete(range)
    }

    /// Append specified `text` at the given `offset`
    pub(crate) fn insert(&mut self, offset: TextUnit, text: impl Into<String>) {
        self.edit.insert(offset, text.into())
    }

    /// Specify desired position of the cursor after the assist is applied.
    pub(crate) fn set_cursor(&mut self, offset: TextUnit) {
        self.cursor_position = Some(offset)
    }

    /// Specify that the assist should be active withing the `target` range.
    ///
    /// Target ranges are used to sort assists: the smaller the target range,
    /// the more specific assist is, and so it should be sorted first.
    pub(crate) fn target(&mut self, target: TextRange) {
        self.target = Some(target)
    }

    /// Get access to the raw `TextEditBuilder`.
    pub(crate) fn text_edit_builder(&mut self) -> &mut TextEditBuilder {
        &mut self.edit
    }

    pub(crate) fn replace_ast<N: AstNode>(&mut self, old: N, new: N) {
        algo::diff(old.syntax(), new.syntax()).into_text_edit(&mut self.edit)
    }

    fn build(self) -> AssistAction {
        AssistAction {
            edit: self.edit.finish(),
            cursor_position: self.cursor_position,
            target: self.target,
        }
    }
}
<commit_msg>lightly document assist_ctx module<commit_after>//! This module defines `AssistCtx` -- the API surface that is exposed to assists.

use hir::db::HirDatabase;
use ra_db::FileRange;
use ra_fmt::{leading_indent, reindent};
use ra_syntax::{
    algo::{self, find_covering_element, find_node_at_offset},
    AstNode, SourceFile, SyntaxElement, SyntaxKind, SyntaxNode, SyntaxToken, TextRange, TextUnit,
    TokenAtOffset,
};
use ra_text_edit::TextEditBuilder;

use crate::{AssistAction, AssistId, AssistLabel};

#[derive(Clone, Debug)]
pub(crate) enum Assist {
    Unresolved(Vec<AssistLabel>),
    Resolved(Vec<(AssistLabel, AssistAction)>),
}

/// `AssistCtx` allows to apply an assist or check if it could be applied.
///
/// Assists use a somewhat over-engineered approach, given the current needs. The
/// assists workflow consists of two phases. In the first phase, a user asks for
/// the list of available assists. In the second phase, the user picks a
/// particular assist and it gets applied.
///
/// There are two peculiarities here:
///
/// * first, we ideally avoid computing more things then necessary to answer
///   "is assist applicable" in the first phase.
/// * second, when we are applying assist, we don't have a guarantee that there
///   weren't any changes between the point when user asked for assists and when
///   they applied a particular assist. So, when applying assist, we need to do
///   all the checks from scratch.
///
/// To avoid repeating the same code twice for both "check" and "apply"
/// functions, we use an approach reminiscent of that of Django's function based
/// views dealing with forms. Each assist receives a runtime parameter,
/// `should_compute_edit`. It first check if an edit is applicable (potentially
/// computing info required to compute the actual edit). If it is applicable,
/// and `should_compute_edit` is `true`, it then computes the actual edit.
///
/// So, to implement the original assists workflow, we can first apply each edit
/// with `should_compute_edit = false`, and then applying the selected edit
/// again, with `should_compute_edit = true` this time.
///
/// Note, however, that we don't actually use such two-phase logic at the
/// moment, because the LSP API is pretty awkward in this place, and it's much
/// easier to just compute the edit eagerly :-)#[derive(Debug, Clone)]
#[derive(Debug)]
pub(crate) struct AssistCtx<'a, DB> {
    pub(crate) db: &'a DB,
    pub(crate) frange: FileRange,
    source_file: SourceFile,
    should_compute_edit: bool,
    assist: Assist,
}

impl<'a, DB> Clone for AssistCtx<'a, DB> {
    fn clone(&self) -> Self {
        AssistCtx {
            db: self.db,
            frange: self.frange,
            source_file: self.source_file.clone(),
            should_compute_edit: self.should_compute_edit,
            assist: self.assist.clone(),
        }
    }
}

impl<'a, DB: HirDatabase> AssistCtx<'a, DB> {
    pub(crate) fn with_ctx<F, T>(db: &DB, frange: FileRange, should_compute_edit: bool, f: F) -> T
    where
        F: FnOnce(AssistCtx<DB>) -> T,
    {
        let parse = db.parse(frange.file_id);
        let assist =
            if should_compute_edit { Assist::Resolved(vec![]) } else { Assist::Unresolved(vec![]) };

        let ctx = AssistCtx { db, frange, source_file: parse.tree(), should_compute_edit, assist };
        f(ctx)
    }

    pub(crate) fn add_action(
        &mut self,
        id: AssistId,
        label: impl Into<String>,
        f: impl FnOnce(&mut AssistBuilder),
    ) -> &mut Self {
        let label = AssistLabel { label: label.into(), id };
        match &mut self.assist {
            Assist::Unresolved(labels) => labels.push(label),
            Assist::Resolved(labels_actions) => {
                let action = {
                    let mut edit = AssistBuilder::default();
                    f(&mut edit);
                    edit.build()
                };
                labels_actions.push((label, action));
            }
        }
        self
    }

    pub(crate) fn build(self) -> Option<Assist> {
        Some(self.assist)
    }

    pub(crate) fn token_at_offset(&self) -> TokenAtOffset<SyntaxToken> {
        self.source_file.syntax().token_at_offset(self.frange.range.start())
    }

    pub(crate) fn find_token_at_offset(&self, kind: SyntaxKind) -> Option<SyntaxToken> {
        self.token_at_offset().find(|it| it.kind() == kind)
    }

    pub(crate) fn find_node_at_offset<N: AstNode>(&self) -> Option<N> {
        find_node_at_offset(self.source_file.syntax(), self.frange.range.start())
    }
    pub(crate) fn covering_element(&self) -> SyntaxElement {
        find_covering_element(self.source_file.syntax(), self.frange.range)
    }

    pub(crate) fn covering_node_for_range(&self, range: TextRange) -> SyntaxElement {
        find_covering_element(self.source_file.syntax(), range)
    }
}

#[derive(Default)]
pub(crate) struct AssistBuilder {
    edit: TextEditBuilder,
    cursor_position: Option<TextUnit>,
    target: Option<TextRange>,
}

impl AssistBuilder {
    /// Replaces specified `range` of text with a given string.
    pub(crate) fn replace(&mut self, range: TextRange, replace_with: impl Into<String>) {
        self.edit.replace(range, replace_with.into())
    }

    /// Replaces specified `node` of text with a given string, reindenting the
    /// string to maintain `node`'s existing indent.
    // FIXME: remove in favor of ra_syntax::edit::IndentLevel::increase_indent
    pub(crate) fn replace_node_and_indent(
        &mut self,
        node: &SyntaxNode,
        replace_with: impl Into<String>,
    ) {
        let mut replace_with = replace_with.into();
        if let Some(indent) = leading_indent(node) {
            replace_with = reindent(&replace_with, &indent)
        }
        self.replace(node.text_range(), replace_with)
    }

    /// Remove specified `range` of text.
    #[allow(unused)]
    pub(crate) fn delete(&mut self, range: TextRange) {
        self.edit.delete(range)
    }

    /// Append specified `text` at the given `offset`
    pub(crate) fn insert(&mut self, offset: TextUnit, text: impl Into<String>) {
        self.edit.insert(offset, text.into())
    }

    /// Specify desired position of the cursor after the assist is applied.
    pub(crate) fn set_cursor(&mut self, offset: TextUnit) {
        self.cursor_position = Some(offset)
    }

    /// Specify that the assist should be active withing the `target` range.
    ///
    /// Target ranges are used to sort assists: the smaller the target range,
    /// the more specific assist is, and so it should be sorted first.
    pub(crate) fn target(&mut self, target: TextRange) {
        self.target = Some(target)
    }

    /// Get access to the raw `TextEditBuilder`.
    pub(crate) fn text_edit_builder(&mut self) -> &mut TextEditBuilder {
        &mut self.edit
    }

    pub(crate) fn replace_ast<N: AstNode>(&mut self, old: N, new: N) {
        algo::diff(old.syntax(), new.syntax()).into_text_edit(&mut self.edit)
    }

    fn build(self) -> AssistAction {
        AssistAction {
            edit: self.edit.finish(),
            cursor_position: self.cursor_position,
            target: self.target,
        }
    }
}
<|endoftext|>


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

use x_lint::prelude::*;

static LICENSE_HEADER: &str = "Copyright (c) The Diem Core Contributors\n\
                               SPDX-License-Identifier: Apache-2.0\n\
                               ";

#[derive(Copy, Clone, Debug)]
pub(super) struct LicenseHeader;

impl Linter for LicenseHeader {
    fn name(&self) -> &'static str {
        "license-header"
    }
}

impl ContentLinter for LicenseHeader {
    fn pre_run<'l>(&self, file_ctx: &FilePathContext<'l>) -> Result<RunStatus<'l>> {
        // TODO: Add a way to pass around state between pre_run and run, so that this computation
        // only needs to be done once.
        match FileType::new(file_ctx) {
            Some(_) => Ok(RunStatus::Executed),
            None => Ok(RunStatus::Skipped(SkipReason::UnsupportedExtension(
                file_ctx.extension(),
            ))),
        }
    }

    fn run<'l>(
        &self,
        ctx: &ContentContext<'l>,
        out: &mut LintFormatter<'l, '_>,
    ) -> Result<RunStatus<'l>> {
        let content = match ctx.content() {
            Some(content) => content,
            None => {
                // This is not a UTF-8 file -- don't analyze it.
                return Ok(RunStatus::Skipped(SkipReason::NonUtf8Content));
            }
        };

        let file_type = FileType::new(ctx.file_ctx()).expect("None filtered out in pre_run");
        // Determine if the file is missing the license header
        let missing_header = match file_type {
            FileType::Rust | FileType::Proto => {
                let maybe_license = content
                    .lines()
                    .skip_while(|line| line.is_empty())
                    .take(2)
                    .map(|s| s.trim_start_matches("// "));
                !LICENSE_HEADER.lines().eq(maybe_license)
            }
            FileType::Shell => {
                let maybe_license = content
                    .lines()
                    .skip_while(|line| line.starts_with("#!"))
                    .skip_while(|line| line.is_empty())
                    .take(2)
                    .map(|s| s.trim_start_matches("# "));
                !LICENSE_HEADER.lines().eq(maybe_license)
            }
        };

        if missing_header {
            out.write(LintLevel::Error, "missing license header");
        }

        Ok(RunStatus::Executed)
    }
}

enum FileType {
    Rust,
    Shell,
    Proto,
}

impl FileType {
    fn new(ctx: &FilePathContext<'_>) -> Option<Self> {
        match ctx.extension() {
            Some("rs") => Some(FileType::Rust),
            Some("sh") => Some(FileType::Shell),
            Some("proto") => Some(FileType::Proto),
            _ => None,
        }
    }
}
<commit_msg>trivial: linter doesn't require copyright banner<commit_after>// Copyright (c) The Diem Core Contributors
// SPDX-License-Identifier: Apache-2.0

use std::collections::HashSet;
use x_lint::prelude::*;

static LICENSE_HEADER: &str = "\
                               SPDX-License-Identifier: Apache-2.0\n\
                               ";

#[derive(Copy, Clone, Debug)]
pub(super) struct LicenseHeader;

impl Linter for LicenseHeader {
    fn name(&self) -> &'static str {
        "license-header"
    }
}

impl ContentLinter for LicenseHeader {
    fn pre_run<'l>(&self, file_ctx: &FilePathContext<'l>) -> Result<RunStatus<'l>> {
        // TODO: Add a way to pass around state between pre_run and run, so that this computation
        // only needs to be done once.
        match FileType::new(file_ctx) {
            Some(_) => Ok(RunStatus::Executed),
            None => Ok(RunStatus::Skipped(SkipReason::UnsupportedExtension(
                file_ctx.extension(),
            ))),
        }
    }

    fn run<'l>(
        &self,
        ctx: &ContentContext<'l>,
        out: &mut LintFormatter<'l, '_>,
    ) -> Result<RunStatus<'l>> {
        let content = match ctx.content() {
            Some(content) => content,
            None => {
                // This is not a UTF-8 file -- don't analyze it.
                return Ok(RunStatus::Skipped(SkipReason::NonUtf8Content));
            }
        };

        let file_type = FileType::new(ctx.file_ctx()).expect("None filtered out in pre_run");
        // Determine if the file is missing the license header
        let missing_header = match file_type {
            FileType::Rust | FileType::Proto => {
                let maybe_license: HashSet<_> = content
                    .lines()
                    .skip_while(|line| line.is_empty())
                    .take(2)
                    .map(|s| s.trim_start_matches("// "))
                    .collect();
                !LICENSE_HEADER
                    .lines()
                    .collect::<HashSet<_>>()
                    .is_subset(&maybe_license)
            }
            FileType::Shell => {
                let maybe_license = content
                    .lines()
                    .skip_while(|line| line.starts_with("#!"))
                    .skip_while(|line| line.is_empty())
                    .take(2)
                    .map(|s| s.trim_start_matches("# "))
                    .collect();
                !LICENSE_HEADER
                    .lines()
                    .collect::<HashSet<_>>()
                    .is_subset(&maybe_license)
            }
        };

        if missing_header {
            out.write(LintLevel::Error, "missing license header");
        }

        Ok(RunStatus::Executed)
    }
}

enum FileType {
    Rust,
    Shell,
    Proto,
}

impl FileType {
    fn new(ctx: &FilePathContext<'_>) -> Option<Self> {
        match ctx.extension() {
            Some("rs") => Some(FileType::Rust),
            Some("sh") => Some(FileType::Shell),
            Some("proto") => Some(FileType::Proto),
            _ => None,
        }
    }
}
<|endoftext|>


<commit_before>extern crate futures;
extern crate openssl;
extern crate rustls;
extern crate trust_dns;
extern crate trust_dns_integration;
extern crate trust_dns_openssl;
extern crate trust_dns_rustls;
extern crate trust_dns_server;

use std::env;
use std::fs::File;
use std::io;
use std::io::Read;
use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4, UdpSocket, TcpListener};
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};
use std::thread;
use std::time::Duration;

use futures::Stream;
use openssl::pkcs12::Pkcs12;
use rustls::Certificate;

use trust_dns::client::*;
use trust_dns::op::*;
use trust_dns::rr::*;
use trust_dns::udp::UdpClientConnection;
use trust_dns::tcp::TcpClientConnection;
use trust_dns_rustls::TlsClientConnection;

use trust_dns_server::ServerFuture;
use trust_dns_server::authority::*;

use trust_dns_integration::authority::create_example;

#[test]
fn test_server_www_udp() {
    let addr = SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 0));
    let udp_socket = UdpSocket::bind(&addr).unwrap();

    let ipaddr = udp_socket.local_addr().unwrap();
    println!("udp_socket on port: {}", ipaddr);
    let server_continue = Arc::new(AtomicBool::new(true));
    let server_continue2 = server_continue.clone();

    let server_thread = thread::Builder::new()
        .name("test_server:udp:server".to_string())
        .spawn(move || server_thread_udp(udp_socket, server_continue2))
        .unwrap();

    let client_thread = thread::Builder::new()
        .name("test_server:udp:client".to_string())
        .spawn(move || client_thread_www(lazy_udp_client(ipaddr)))
        .unwrap();

    let client_result = client_thread.join();

    assert!(client_result.is_ok(), "client failed: {:?}", client_result);
    server_continue.store(false, Ordering::Relaxed);
    server_thread.join().unwrap();;
}

#[test]
fn test_server_www_tcp() {
    let addr = SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 0));
    let tcp_listener = TcpListener::bind(&addr).unwrap();

    let ipaddr = tcp_listener.local_addr().unwrap();
    println!("tcp_listner on port: {}", ipaddr);
    let server_continue = Arc::new(AtomicBool::new(true));
    let server_continue2 = server_continue.clone();

    let server_thread = thread::Builder::new()
        .name("test_server:tcp:server".to_string())
        .spawn(move || server_thread_tcp(tcp_listener, server_continue2))
        .unwrap();

    let client_thread = thread::Builder::new()
        .name("test_server:tcp:client".to_string())
        .spawn(move || client_thread_www(lazy_tcp_client(ipaddr)))
        .unwrap();

    let client_result = client_thread.join();

    assert!(client_result.is_ok(), "client failed: {:?}", client_result);
    server_continue.store(false, Ordering::Relaxed);
    server_thread.join().unwrap();;
}

fn read_file(path: &str) -> Vec<u8> {
    let mut bytes = vec![];

    let mut file = File::open(path).expect(&format!("failed to open file: {}", path));
    file.read_to_end(&mut bytes).expect(&format!(
        "failed to read file: {}",
        path
    ));
    bytes
}

#[test]
fn test_server_www_tls() {
    let dns_name = "ns.example.com";

    let server_path = env::var("TDNS_SERVER_SRC_ROOT").unwrap_or("../server".to_owned());
    println!("using server src path: {}", server_path);

    let cert_der = read_file(&format!("{}/../tests/ca.der", server_path));

    let pkcs12_der = read_file(&format!("{}/../tests/cert.p12", server_path));

    // Server address
    let addr = SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 0));
    let tcp_listener = TcpListener::bind(&addr).unwrap();

    let ipaddr = tcp_listener.local_addr().unwrap();
    println!("tcp_listner on port: {}", ipaddr);
    let server_continue = Arc::new(AtomicBool::new(true));
    let server_continue2 = server_continue.clone();

    let server_thread = thread::Builder::new()
        .name("test_server:tls:server".to_string())
        .spawn(move || {
            server_thread_tls(tcp_listener, server_continue2, pkcs12_der)
        })
        .unwrap();

    let client_thread = thread::Builder::new()
        .name("test_server:tcp:client".to_string())
        .spawn(move || {
            client_thread_www(lazy_tls_client(ipaddr, dns_name.to_string(), cert_der))
        })
        .unwrap();

    let client_result = client_thread.join();

    assert!(client_result.is_ok(), "client failed: {:?}", client_result);
    server_continue.store(false, Ordering::Relaxed);
    server_thread.join().unwrap();
}

fn lazy_udp_client(ipaddr: SocketAddr) -> UdpClientConnection {
    UdpClientConnection::new(ipaddr).unwrap()
}

fn lazy_tcp_client(ipaddr: SocketAddr) -> TcpClientConnection {
    TcpClientConnection::new(ipaddr).unwrap()
}

fn lazy_tls_client(ipaddr: SocketAddr, dns_name: String, cert_der: Vec<u8>) -> TlsClientConnection {
    let mut builder = TlsClientConnection::builder();

    let trust_chain = Certificate(cert_der);

    builder.add_ca(trust_chain);
    builder.build(ipaddr, dns_name).unwrap()
}

fn client_thread_www<C: ClientConnection>(conn: C)
where
    C::MessageStream: Stream<Item = Vec<u8>, Error = io::Error> + 'static,
{
    let name = Name::from_labels(vec!["www", "example", "com"]);
    let client = SyncClient::new(conn);

    let response = client.query(&name, DNSClass::IN, RecordType::A).expect(
        "error querying",
    );

    assert!(
        response.response_code() == ResponseCode::NoError,
        "got an error: {:?}",
        response.response_code()
    );

    let record = &response.answers()[0];
    assert_eq!(record.name(), &name);
    assert_eq!(record.rr_type(), RecordType::A);
    assert_eq!(record.dns_class(), DNSClass::IN);

    if let &RData::A(ref address) = record.rdata() {
        assert_eq!(address, &Ipv4Addr::new(93, 184, 216, 34))
    } else {
        assert!(false);
    }

    let mut ns: Vec<_> = response.name_servers().to_vec();
    ns.sort();

    assert_eq!(ns.len(), 2);
    assert_eq!(ns.first().unwrap().rr_type(), RecordType::NS);
    assert_eq!(
        ns.first().unwrap().rdata(),
        &RData::NS(Name::parse("a.iana-servers.net.", None).unwrap())
    );
    assert_eq!(ns.last().unwrap().rr_type(), RecordType::NS);
    assert_eq!(
        ns.last().unwrap().rdata(),
        &RData::NS(Name::parse("b.iana-servers.net.", None).unwrap())
    );
}

fn new_catalog() -> Catalog {
    let example = create_example();
    let origin = example.origin().clone();

    let mut catalog: Catalog = Catalog::new();
    catalog.upsert(origin.clone(), example);
    catalog
}

fn server_thread_udp(udp_socket: UdpSocket, server_continue: Arc<AtomicBool>) {
    let catalog = new_catalog();

    let mut server = ServerFuture::new(catalog).expect("new udp server failed");
    server.register_socket(udp_socket);

    while server_continue.load(Ordering::Relaxed) {
        server.tokio_core().turn(Some(Duration::from_millis(10)));
    }
}

fn server_thread_tcp(tcp_listener: TcpListener, server_continue: Arc<AtomicBool>) {
    let catalog = new_catalog();
    let mut server = ServerFuture::new(catalog).expect("new tcp server failed");
    server
        .register_listener(tcp_listener, Duration::from_secs(30))
        .expect("tcp registration failed");

    while server_continue.load(Ordering::Relaxed) {
        server.tokio_core().turn(Some(Duration::from_millis(10)));
    }
}

fn server_thread_tls(
    tls_listener: TcpListener,
    server_continue: Arc<AtomicBool>,
    pkcs12_der: Vec<u8>,
) {
    let catalog = new_catalog();
    let mut server = ServerFuture::new(catalog).expect("new tcp server failed");
    let pkcs12 = Pkcs12::from_der(&pkcs12_der)
        .expect("bad pkcs12 der")
        .parse("mypass")
        .expect("Pkcs12::from_der");
    server
        .register_tls_listener(tls_listener, Duration::from_secs(30), pkcs12)
        .expect("tcp registration failed");

    while server_continue.load(Ordering::Relaxed) {
        server.tokio_core().turn(Some(Duration::from_millis(10)));
    }
}
<commit_msg>add test for Unknown record type request<commit_after>extern crate futures;
extern crate openssl;
extern crate rustls;
extern crate trust_dns;
extern crate trust_dns_integration;
extern crate trust_dns_openssl;
extern crate trust_dns_rustls;
extern crate trust_dns_server;

use std::env;
use std::fs::File;
use std::io;
use std::io::Read;
use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4, UdpSocket, TcpListener};
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};
use std::str::FromStr;
use std::thread;
use std::time::Duration;

use futures::Stream;
use openssl::pkcs12::Pkcs12;
use rustls::Certificate;

use trust_dns::client::*;
use trust_dns::op::*;
use trust_dns::rr::*;
use trust_dns::udp::UdpClientConnection;
use trust_dns::tcp::TcpClientConnection;
use trust_dns_rustls::TlsClientConnection;

use trust_dns_server::ServerFuture;
use trust_dns_server::authority::*;

use trust_dns_integration::authority::create_example;

#[test]
fn test_server_www_udp() {
    let addr = SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 0));
    let udp_socket = UdpSocket::bind(&addr).unwrap();

    let ipaddr = udp_socket.local_addr().unwrap();
    println!("udp_socket on port: {}", ipaddr);
    let server_continue = Arc::new(AtomicBool::new(true));
    let server_continue2 = server_continue.clone();

    let server_thread = thread::Builder::new()
        .name("test_server:udp:server".to_string())
        .spawn(move || server_thread_udp(udp_socket, server_continue2))
        .unwrap();

    let client_thread = thread::Builder::new()
        .name("test_server:udp:client".to_string())
        .spawn(move || client_thread_www(lazy_udp_client(ipaddr)))
        .unwrap();

    let client_result = client_thread.join();

    assert!(client_result.is_ok(), "client failed: {:?}", client_result);
    server_continue.store(false, Ordering::Relaxed);
    server_thread.join().unwrap();;
}

#[test]
fn test_server_www_tcp() {
    let addr = SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 0));
    let tcp_listener = TcpListener::bind(&addr).unwrap();

    let ipaddr = tcp_listener.local_addr().unwrap();
    println!("tcp_listner on port: {}", ipaddr);
    let server_continue = Arc::new(AtomicBool::new(true));
    let server_continue2 = server_continue.clone();

    let server_thread = thread::Builder::new()
        .name("test_server:tcp:server".to_string())
        .spawn(move || server_thread_tcp(tcp_listener, server_continue2))
        .unwrap();

    let client_thread = thread::Builder::new()
        .name("test_server:tcp:client".to_string())
        .spawn(move || client_thread_www(lazy_tcp_client(ipaddr)))
        .unwrap();

    let client_result = client_thread.join();

    assert!(client_result.is_ok(), "client failed: {:?}", client_result);
    server_continue.store(false, Ordering::Relaxed);
    server_thread.join().unwrap();;
}

#[test]
fn test_server_unknown_type() {
    let addr = SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 0));
    let udp_socket = UdpSocket::bind(&addr).unwrap();

    let ipaddr = udp_socket.local_addr().unwrap();
    println!("udp_socket on port: {}", ipaddr);
    let server_continue = Arc::new(AtomicBool::new(true));
    let server_continue2 = server_continue.clone();

    let server_thread = thread::Builder::new()
        .name("test_server:udp:server".to_string())
        .spawn(move || server_thread_udp(udp_socket, server_continue2))
        .unwrap();

    let conn = UdpClientConnection::new(ipaddr).unwrap();
    let client = SyncClient::new(conn);
    let client_result = client.query(
        &Name::from_str("www.example.com.").unwrap(),
        DNSClass::IN,
        RecordType::Unknown(65535),
    ).expect("query failed for unknown");

    assert_eq!(client_result.response_code(), ResponseCode::NoError);
    assert_eq!(client_result.queries().first().unwrap().query_type(), RecordType::Unknown(65535));
    assert!(client_result.answers().is_empty());

    server_continue.store(false, Ordering::Relaxed);
    server_thread.join().unwrap();;
}

fn read_file(path: &str) -> Vec<u8> {
    let mut bytes = vec![];

    let mut file = File::open(path).expect(&format!("failed to open file: {}", path));
    file.read_to_end(&mut bytes).expect(&format!(
        "failed to read file: {}",
        path
    ));
    bytes
}

#[test]
fn test_server_www_tls() {
    let dns_name = "ns.example.com";

    let server_path = env::var("TDNS_SERVER_SRC_ROOT").unwrap_or("../server".to_owned());
    println!("using server src path: {}", server_path);

    let cert_der = read_file(&format!("{}/../tests/ca.der", server_path));

    let pkcs12_der = read_file(&format!("{}/../tests/cert.p12", server_path));

    // Server address
    let addr = SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 0));
    let tcp_listener = TcpListener::bind(&addr).unwrap();

    let ipaddr = tcp_listener.local_addr().unwrap();
    println!("tcp_listner on port: {}", ipaddr);
    let server_continue = Arc::new(AtomicBool::new(true));
    let server_continue2 = server_continue.clone();

    let server_thread = thread::Builder::new()
        .name("test_server:tls:server".to_string())
        .spawn(move || {
            server_thread_tls(tcp_listener, server_continue2, pkcs12_der)
        })
        .unwrap();

    let client_thread = thread::Builder::new()
        .name("test_server:tcp:client".to_string())
        .spawn(move || {
            client_thread_www(lazy_tls_client(ipaddr, dns_name.to_string(), cert_der))
        })
        .unwrap();

    let client_result = client_thread.join();

    assert!(client_result.is_ok(), "client failed: {:?}", client_result);
    server_continue.store(false, Ordering::Relaxed);
    server_thread.join().unwrap();
}

fn lazy_udp_client(ipaddr: SocketAddr) -> UdpClientConnection {
    UdpClientConnection::new(ipaddr).unwrap()
}

fn lazy_tcp_client(ipaddr: SocketAddr) -> TcpClientConnection {
    TcpClientConnection::new(ipaddr).unwrap()
}

fn lazy_tls_client(ipaddr: SocketAddr, dns_name: String, cert_der: Vec<u8>) -> TlsClientConnection {
    let mut builder = TlsClientConnection::builder();

    let trust_chain = Certificate(cert_der);

    builder.add_ca(trust_chain);
    builder.build(ipaddr, dns_name).unwrap()
}

fn client_thread_www<C: ClientConnection>(conn: C)
where
    C::MessageStream: Stream<Item = Vec<u8>, Error = io::Error> + 'static,
{
    let name = Name::from_labels(vec!["www", "example", "com"]);
    let client = SyncClient::new(conn);

    let response = client.query(&name, DNSClass::IN, RecordType::A).expect(
        "error querying",
    );

    assert!(
        response.response_code() == ResponseCode::NoError,
        "got an error: {:?}",
        response.response_code()
    );

    let record = &response.answers()[0];
    assert_eq!(record.name(), &name);
    assert_eq!(record.rr_type(), RecordType::A);
    assert_eq!(record.dns_class(), DNSClass::IN);

    if let &RData::A(ref address) = record.rdata() {
        assert_eq!(address, &Ipv4Addr::new(93, 184, 216, 34))
    } else {
        assert!(false);
    }

    let mut ns: Vec<_> = response.name_servers().to_vec();
    ns.sort();

    assert_eq!(ns.len(), 2);
    assert_eq!(ns.first().unwrap().rr_type(), RecordType::NS);
    assert_eq!(
        ns.first().unwrap().rdata(),
        &RData::NS(Name::parse("a.iana-servers.net.", None).unwrap())
    );
    assert_eq!(ns.last().unwrap().rr_type(), RecordType::NS);
    assert_eq!(
        ns.last().unwrap().rdata(),
        &RData::NS(Name::parse("b.iana-servers.net.", None).unwrap())
    );
}

fn new_catalog() -> Catalog {
    let example = create_example();
    let origin = example.origin().clone();

    let mut catalog: Catalog = Catalog::new();
    catalog.upsert(origin.clone(), example);
    catalog
}

fn server_thread_udp(udp_socket: UdpSocket, server_continue: Arc<AtomicBool>) {
    let catalog = new_catalog();

    let mut server = ServerFuture::new(catalog).expect("new udp server failed");
    server.register_socket(udp_socket);

    while server_continue.load(Ordering::Relaxed) {
        server.tokio_core().turn(Some(Duration::from_millis(10)));
    }
}

fn server_thread_tcp(tcp_listener: TcpListener, server_continue: Arc<AtomicBool>) {
    let catalog = new_catalog();
    let mut server = ServerFuture::new(catalog).expect("new tcp server failed");
    server
        .register_listener(tcp_listener, Duration::from_secs(30))
        .expect("tcp registration failed");

    while server_continue.load(Ordering::Relaxed) {
        server.tokio_core().turn(Some(Duration::from_millis(10)));
    }
}

fn server_thread_tls(
    tls_listener: TcpListener,
    server_continue: Arc<AtomicBool>,
    pkcs12_der: Vec<u8>,
) {
    let catalog = new_catalog();
    let mut server = ServerFuture::new(catalog).expect("new tcp server failed");
    let pkcs12 = Pkcs12::from_der(&pkcs12_der)
        .expect("bad pkcs12 der")
        .parse("mypass")
        .expect("Pkcs12::from_der");
    server
        .register_tls_listener(tls_listener, Duration::from_secs(30), pkcs12)
        .expect("tcp registration failed");

    while server_continue.load(Ordering::Relaxed) {
        server.tokio_core().turn(Some(Duration::from_millis(10)));
    }
}
<|endoftext|>


<commit_before>use crate::{
    beacon_state::CommitteesError, AttestationData, BeaconState, Bitfield, ChainSpec,
    PendingAttestation,
};
use log::debug;

#[derive(Debug, PartialEq)]
pub enum Error {
    NoCommitteeForShard,
    NoCommittees,
    BadBitfieldLength,
    CommitteesError(CommitteesError),
}

impl BeaconState {
    pub fn get_attestation_participants_union(
        &self,
        attestations: &[&PendingAttestation],
        spec: &ChainSpec,
    ) -> Result<Vec<usize>, Error> {
        attestations.iter().try_fold(vec![], |mut acc, a| {
            acc.append(&mut self.get_attestation_participants(
                &a.data,
                &a.aggregation_bitfield,
                spec,
            )?);
            Ok(acc)
        })
    }

    // TODO: analyse for efficiency improvments. This implementation is naive.
    pub fn get_attestation_participants(
        &self,
        attestation_data: &AttestationData,
        aggregation_bitfield: &Bitfield,
        spec: &ChainSpec,
    ) -> Result<Vec<usize>, Error> {
        let crosslink_committees =
            self.get_crosslink_committees_at_slot(attestation_data.slot, spec)?;

        /*
        let mut shard_present = false;
        for (_committee, shard) in &crosslink_committees {
            println!("want shard: {}, got shard: {}", shard, attestation_data.shard);
            if *shard == attestation_data.shard {
                shard_present = true;
            }
        }
        if !shard_present {
            return Err(Error::NoCommitteeForShard);
        }
        */

        let crosslink_committee: Vec<usize> = crosslink_committees
            .iter()
            .filter_map(|(committee, shard)| {
                if *shard == attestation_data.shard {
                    Some(committee.clone())
                } else {
                    None
                }
            })
            .collect::<Vec<Vec<usize>>>()
            .first()
            .ok_or_else(|| Error::NoCommitteeForShard)?
            .clone();

        /*
         * TODO: check for this condition.
         *
        if aggregation_bitfield.len() != (crosslink_committee.len() + 7) / 8 {
            return Err(Error::BadBitfieldLength);
        }
        */

        let mut participants = vec![];
        for (i, validator_index) in crosslink_committee.iter().enumerate() {
            if aggregation_bitfield.get(i).unwrap() {
                debug!(
                    "committee index {} found in attestation on slot {}",
                    i, attestation_data.slot
                );
                participants.push(*validator_index);
            } else {
                debug!(
                    "committee index {} not found in attestation on slot {}",
                    i, attestation_data.slot
                );
            }
        }
        Ok(participants)
    }
}

impl From<CommitteesError> for Error {
    fn from(e: CommitteesError) -> Error {
        Error::CommitteesError(e)
    }
}
<commit_msg>Tidy attestation_participants function.<commit_after>use crate::{
    beacon_state::CommitteesError, AttestationData, BeaconState, Bitfield, ChainSpec,
    PendingAttestation,
};
use log::debug;

#[derive(Debug, PartialEq)]
pub enum Error {
    NoCommitteeForShard,
    NoCommittees,
    BadBitfieldLength,
    CommitteesError(CommitteesError),
}

impl BeaconState {
    pub fn get_attestation_participants_union(
        &self,
        attestations: &[&PendingAttestation],
        spec: &ChainSpec,
    ) -> Result<Vec<usize>, Error> {
        attestations.iter().try_fold(vec![], |mut acc, a| {
            acc.append(&mut self.get_attestation_participants(
                &a.data,
                &a.aggregation_bitfield,
                spec,
            )?);
            Ok(acc)
        })
    }

    // TODO: analyse for efficiency improvments. This implementation is naive.
    pub fn get_attestation_participants(
        &self,
        attestation_data: &AttestationData,
        aggregation_bitfield: &Bitfield,
        spec: &ChainSpec,
    ) -> Result<Vec<usize>, Error> {
        let crosslink_committees =
            self.get_crosslink_committees_at_slot(attestation_data.slot, spec)?;

        let committee_index: usize = crosslink_committees
            .iter()
            .position(|(_committee, shard)| *shard == attestation_data.shard)
            .ok_or_else(|| Error::NoCommitteeForShard)?;
        let (crosslink_committee, _shard) = &crosslink_committees[committee_index];

        /*
         * TODO: that bitfield length is valid.
         *
         */

        let mut participants = vec![];
        for (i, validator_index) in crosslink_committee.iter().enumerate() {
            if aggregation_bitfield.get(i).unwrap() {
                participants.push(*validator_index);
            }
        }
        Ok(participants)
    }
}

impl From<CommitteesError> for Error {
    fn from(e: CommitteesError) -> Error {
        Error::CommitteesError(e)
    }
}
<|endoftext|>


<commit_before>use std::io::Write;
use std::io;
use common::serialize::BinarySerializable;
use std::mem;
use std::ops::Deref;

/// Computes the number of bits that will be used for bitpacking.
///
/// In general the target is the minimum number of bits
/// required to express the amplitude given in argument.
///
/// e.g. If the amplitude is 10, we can store all ints on simply 4bits.
///
/// The logic is slightly more convoluted here as for optimization
/// reasons, we want to ensure that a value spawns over at most 8 bytes
/// of aligns bytes.
///
/// Spanning over 9 bytes is possible for instance, if we do
/// bitpacking with an amplitude of 63 bits.
/// In this case, the second int will start on bit
/// 63 (which belongs to byte 7) and ends at byte 15;
/// Hence 9 bytes (from byte 7 to byte 15 included).
///
/// To avoid this, we force the number of bits to 64bits
/// when the result is greater than `64-8 = 56 bits`.
///
/// Note that this only affects rare use cases spawning over
/// a very large range of values. Even in this case, it results
/// in an extra cost of at most 12% compared to the optimal
/// number of bits.
pub fn compute_num_bits(amplitude: u64) -> u8 {
    let amplitude = (64u32 - amplitude.leading_zeros()) as u8;
    if amplitude <= 64 - 8 { amplitude } else { 64 }
}

pub struct BitPacker {
    mini_buffer: u64,
    mini_buffer_written: usize,
    num_bits: usize,
}

impl BitPacker {
    pub fn new(num_bits: usize) -> BitPacker {
        BitPacker {
            mini_buffer: 0u64,
            mini_buffer_written: 0,
            num_bits: num_bits,
        }
    }

    pub fn write<TWrite: Write>(&mut self, val: u64, output: &mut TWrite) -> io::Result<()> {
        let val_u64 = val as u64;
        if self.mini_buffer_written + self.num_bits > 64 {
            self.mini_buffer |= val_u64.wrapping_shl(self.mini_buffer_written as u32);
            self.mini_buffer.serialize(output)?;
            self.mini_buffer = val_u64.wrapping_shr((64 - self.mini_buffer_written) as u32);
            self.mini_buffer_written = self.mini_buffer_written + (self.num_bits as usize) - 64;
        } else {
            self.mini_buffer |= val_u64 << self.mini_buffer_written;
            self.mini_buffer_written += self.num_bits;
            if self.mini_buffer_written == 64 {
                self.mini_buffer.serialize(output)?;
                self.mini_buffer_written = 0;
                self.mini_buffer = 0u64;
            }
        }
        Ok(())
    }

    pub(crate) fn flush<TWrite: Write>(&mut self, output: &mut TWrite) -> io::Result<()> {
        if self.mini_buffer_written > 0 {
            let num_bytes = (self.mini_buffer_written + 7) / 8;
            let arr: [u8; 8] = unsafe { mem::transmute::<u64, [u8; 8]>(self.mini_buffer) };
            output.write_all(&arr[..num_bytes])?;
            self.mini_buffer_written = 0;
        }
        Ok(())
    }

    pub fn close<TWrite: Write>(&mut self, output: &mut TWrite) -> io::Result<()> {
        self.flush(output)?;
        // Padding the write file to simplify reads.
        output.write_all(&[0u8; 7])?;
        Ok(())
    }
}

pub struct BitUnpacker<Data>
where
    Data: Deref<Target = [u8]>,
{
    num_bits: usize,
    mask: u64,
    data: Data,
}

impl<Data> BitUnpacker<Data>
where
    Data: Deref<Target = [u8]>,
{
    pub fn new(data: Data, num_bits: usize) -> BitUnpacker<Data> {
        let mask: u64 = if num_bits == 64 {
            !0u64
        } else {
            (1u64 << num_bits) - 1u64
        };
        BitUnpacker {
            num_bits: num_bits,
            mask: mask,
            data: data,
        }
    }

    pub fn get(&self, idx: usize) -> u64 {
        if self.num_bits == 0 {
            return 0;
        }
        let data: &[u8] = &*self.data;
        let num_bits = self.num_bits;
        let mask = self.mask;
        let addr_in_bits = idx * num_bits;
        let addr = addr_in_bits >> 3;
        let bit_shift = addr_in_bits & 7;
        debug_assert!(
            addr + 8 <= data.len(),
            "The fast field field should have been padded with 7 bytes."
        );
        let val_unshifted_unmasked: u64 = unsafe { *(data[addr..].as_ptr() as *const u64) };
        let val_shifted = (val_unshifted_unmasked >> bit_shift) as u64;
        (val_shifted & mask)
    }

    pub fn get_range(&self, start: u32, output: &mut [u64]) {
        if self.num_bits == 0 {
            for val in output.iter_mut() {
                *val = 0;
            }
        } else {
            let data: &[u8] = &*self.data;
            let num_bits = self.num_bits;
            let mask = self.mask;
            let mut addr_in_bits = (start as usize) * num_bits;
            for output_val in output.iter_mut() {
                let addr = addr_in_bits >> 3;
                let bit_shift = addr_in_bits & 7;
                let val_unshifted_unmasked: u64 = unsafe { *(data[addr..].as_ptr() as *const u64) };
                let val_shifted = (val_unshifted_unmasked >> bit_shift) as u64;
                *output_val = val_shifted & mask;
                addr_in_bits += num_bits;
            }
        }

    }
}

#[cfg(test)]
mod test {
    use super::{BitPacker, BitUnpacker, compute_num_bits};

    #[test]
    fn test_compute_num_bits() {
        assert_eq!(compute_num_bits(1), 1u8);
        assert_eq!(compute_num_bits(0), 0u8);
        assert_eq!(compute_num_bits(2), 2u8);
        assert_eq!(compute_num_bits(3), 2u8);
        assert_eq!(compute_num_bits(4), 3u8);
        assert_eq!(compute_num_bits(255), 8u8);
        assert_eq!(compute_num_bits(256), 9u8);
        assert_eq!(compute_num_bits(5_000_000_000), 33u8);
    }

    fn create_fastfield_bitpacker(len: usize, num_bits: usize) -> (BitUnpacker<Vec<u8>>, Vec<u64>) {
        let mut data = Vec::new();
        let mut bitpacker = BitPacker::new(num_bits);
        let max_val: u64 = (1 << num_bits) - 1;
        let vals: Vec<u64> = (0u64..len as u64)
            .map(|i| if max_val == 0 { 0 } else { i % max_val })
            .collect();
        for &val in &vals {
            bitpacker.write(val, &mut data).unwrap();
        }
        bitpacker.close(&mut data).unwrap();
        assert_eq!(data.len(), (num_bits * len + 7) / 8 + 7);
        let bitunpacker = BitUnpacker::new(data, num_bits);
        (bitunpacker, vals)
    }

    fn test_bitpacker_util(len: usize, num_bits: usize) {
        let (bitunpacker, vals) = create_fastfield_bitpacker(len, num_bits);
        for (i, val) in vals.iter().enumerate() {
            assert_eq!(bitunpacker.get(i), *val);
        }
    }

    #[test]
    fn test_bitpacker() {
        test_bitpacker_util(10, 3);
        test_bitpacker_util(10, 0);
        test_bitpacker_util(10, 1);
        test_bitpacker_util(6, 14);
        test_bitpacker_util(1000, 14);
    }

    #[test]
    fn test_bitpacker_range() {
        let (bitunpacker, vals) = create_fastfield_bitpacker(100_000, 12);
        let buffer_len = 100;
        let mut buffer = vec![0u64; buffer_len];
        for start in vec![0, 10, 20, 100, 1_000] {
            bitunpacker.get_range(start as u32, &mut buffer[..]);
            for i in 0..buffer_len {
                assert_eq!(buffer[i], vals[start + i]);
            }
        }
    }
}
<commit_msg>Readded fix for non-simd<commit_after>use std::io::Write;
use std::io;
use common::serialize::BinarySerializable;
use std::mem;
use std::ops::Deref;

/// Computes the number of bits that will be used for bitpacking.
///
/// In general the target is the minimum number of bits
/// required to express the amplitude given in argument.
///
/// e.g. If the amplitude is 10, we can store all ints on simply 4bits.
///
/// The logic is slightly more convoluted here as for optimization
/// reasons, we want to ensure that a value spawns over at most 8 bytes
/// of aligns bytes.
///
/// Spanning over 9 bytes is possible for instance, if we do
/// bitpacking with an amplitude of 63 bits.
/// In this case, the second int will start on bit
/// 63 (which belongs to byte 7) and ends at byte 15;
/// Hence 9 bytes (from byte 7 to byte 15 included).
///
/// To avoid this, we force the number of bits to 64bits
/// when the result is greater than `64-8 = 56 bits`.
///
/// Note that this only affects rare use cases spawning over
/// a very large range of values. Even in this case, it results
/// in an extra cost of at most 12% compared to the optimal
/// number of bits.
pub fn compute_num_bits(amplitude: u64) -> u8 {
    let amplitude = (64u32 - amplitude.leading_zeros()) as u8;
    if amplitude <= 64 - 8 { amplitude } else { 64 }
}

pub struct BitPacker {
    mini_buffer: u64,
    mini_buffer_written: usize,
    num_bits: usize,
}

impl BitPacker {
    pub fn new(num_bits: usize) -> BitPacker {
        BitPacker {
            mini_buffer: 0u64,
            mini_buffer_written: 0,
            num_bits: num_bits,
        }
    }

    pub fn write<TWrite: Write>(&mut self, val: u64, output: &mut TWrite) -> io::Result<()> {
        let val_u64 = val as u64;
        if self.mini_buffer_written + self.num_bits > 64 {
            self.mini_buffer |= val_u64.wrapping_shl(self.mini_buffer_written as u32);
            self.mini_buffer.serialize(output)?;
            self.mini_buffer = val_u64.wrapping_shr((64 - self.mini_buffer_written) as u32);
            self.mini_buffer_written = self.mini_buffer_written + (self.num_bits as usize) - 64;
        } else {
            self.mini_buffer |= val_u64 << self.mini_buffer_written;
            self.mini_buffer_written += self.num_bits;
            if self.mini_buffer_written == 64 {
                self.mini_buffer.serialize(output)?;
                self.mini_buffer_written = 0;
                self.mini_buffer = 0u64;
            }
        }
        Ok(())
    }

    pub(crate) fn flush<TWrite: Write>(&mut self, output: &mut TWrite) -> io::Result<()> {
        if self.mini_buffer_written > 0 {
            let num_bytes = (self.mini_buffer_written + 7) / 8;
            let arr: [u8; 8] = unsafe { mem::transmute::<u64, [u8; 8]>(self.mini_buffer) };
            output.write_all(&arr[..num_bytes])?;
            self.mini_buffer_written = 0;
        }
        Ok(())
    }

    pub fn close<TWrite: Write>(&mut self, output: &mut TWrite) -> io::Result<()> {
        self.flush(output)?;
        // Padding the write file to simplify reads.
        output.write_all(&[0u8; 7])?;
        Ok(())
    }
}

pub struct BitUnpacker<Data>
where
    Data: Deref<Target = [u8]>,
{
    num_bits: usize,
    mask: u64,
    data: Data,
}

impl<Data> BitUnpacker<Data>
where
    Data: Deref<Target = [u8]>,
{
    pub fn new(data: Data, num_bits: usize) -> BitUnpacker<Data> {
        let mask: u64 = if num_bits == 64 {
            !0u64
        } else {
            (1u64 << num_bits) - 1u64
        };
        BitUnpacker {
            num_bits: num_bits,
            mask: mask,
            data: data,
        }
    }

    pub fn get(&self, idx: usize) -> u64 {
        if self.num_bits == 0 {
            return 0;
        }
        let data: &[u8] = &*self.data;
        let num_bits = self.num_bits;
        let mask = self.mask;
        let addr_in_bits = idx * num_bits;
        let addr = addr_in_bits >> 3;
        let bit_shift = addr_in_bits & 7;
        if cfg!(feature = "simdcompression") {
            // for simdcompression,
            // the bitpacker is only used for fastfields,
            // and we expect them to be always padded.
            debug_assert!(
                addr + 8 <= data.len(),
                "The fast field field should have been padded with 7 bytes."
            );
            let val_unshifted_unmasked: u64 = unsafe { *(data[addr..].as_ptr() as *const u64) };
            let val_shifted = (val_unshifted_unmasked >> bit_shift) as u64;
            (val_shifted & mask)
        } else {
            let val_unshifted_unmasked: u64;
            if addr + 8 <= data.len() {
                val_unshifted_unmasked = unsafe { *(data[addr..].as_ptr() as *const u64) };
            } else {
                let mut buffer = [0u8; 8];
                for i in addr..data.len() {
                    buffer[i - addr] += data[i];
                }
                val_unshifted_unmasked = unsafe { *(buffer[..].as_ptr() as *const u64) };
            }
            let val_shifted = (val_unshifted_unmasked >> bit_shift) as u64;
            (val_shifted & mask)
        }
    }

    pub fn get_range(&self, start: u32, output: &mut [u64]) {
        if self.num_bits == 0 {
            for val in output.iter_mut() {
                *val = 0;
            }
        } else {
            let data: &[u8] = &*self.data;
            let num_bits = self.num_bits;
            let mask = self.mask;
            let mut addr_in_bits = (start as usize) * num_bits;
            for output_val in output.iter_mut() {
                let addr = addr_in_bits >> 3;
                let bit_shift = addr_in_bits & 7;
                let val_unshifted_unmasked: u64 = unsafe { *(data[addr..].as_ptr() as *const u64) };
                let val_shifted = (val_unshifted_unmasked >> bit_shift) as u64;
                *output_val = val_shifted & mask;
                addr_in_bits += num_bits;
            }
        }

    }
}

#[cfg(test)]
mod test {
    use super::{BitPacker, BitUnpacker, compute_num_bits};

    #[test]
    fn test_compute_num_bits() {
        assert_eq!(compute_num_bits(1), 1u8);
        assert_eq!(compute_num_bits(0), 0u8);
        assert_eq!(compute_num_bits(2), 2u8);
        assert_eq!(compute_num_bits(3), 2u8);
        assert_eq!(compute_num_bits(4), 3u8);
        assert_eq!(compute_num_bits(255), 8u8);
        assert_eq!(compute_num_bits(256), 9u8);
        assert_eq!(compute_num_bits(5_000_000_000), 33u8);
    }

    fn create_fastfield_bitpacker(len: usize, num_bits: usize) -> (BitUnpacker<Vec<u8>>, Vec<u64>) {
        let mut data = Vec::new();
        let mut bitpacker = BitPacker::new(num_bits);
        let max_val: u64 = (1 << num_bits) - 1;
        let vals: Vec<u64> = (0u64..len as u64)
            .map(|i| if max_val == 0 { 0 } else { i % max_val })
            .collect();
        for &val in &vals {
            bitpacker.write(val, &mut data).unwrap();
        }
        bitpacker.close(&mut data).unwrap();
        assert_eq!(data.len(), (num_bits * len + 7) / 8 + 7);
        let bitunpacker = BitUnpacker::new(data, num_bits);
        (bitunpacker, vals)
    }

    fn test_bitpacker_util(len: usize, num_bits: usize) {
        let (bitunpacker, vals) = create_fastfield_bitpacker(len, num_bits);
        for (i, val) in vals.iter().enumerate() {
            assert_eq!(bitunpacker.get(i), *val);
        }
    }

    #[test]
    fn test_bitpacker() {
        test_bitpacker_util(10, 3);
        test_bitpacker_util(10, 0);
        test_bitpacker_util(10, 1);
        test_bitpacker_util(6, 14);
        test_bitpacker_util(1000, 14);
    }

    #[test]
    fn test_bitpacker_range() {
        let (bitunpacker, vals) = create_fastfield_bitpacker(100_000, 12);
        let buffer_len = 100;
        let mut buffer = vec![0u64; buffer_len];
        for start in vec![0, 10, 20, 100, 1_000] {
            bitunpacker.get_range(start as u32, &mut buffer[..]);
            for i in 0..buffer_len {
                assert_eq!(buffer[i], vals[start + i]);
            }
        }
    }
}
<|endoftext|>


<commit_before>use lazy_static::lazy_static;
use std::env;
use std::path::PathBuf;

lazy_static! {
    pub static ref CARGO_TARGET_DIR: PathBuf = {
        match env::var_os("CARGO_TARGET_DIR") {
            Some(v) => v.into(),
            None => "target".into(),
        }
    };
    pub static ref TARGET_LIB: PathBuf = {
        if let Some(path) = option_env!("TARGET_LIBS") {
            path.into()
        } else {
            let mut dir = CARGO_TARGET_DIR.clone();
            if let Some(target) = env::var_os("CARGO_BUILD_TARGET") {
                dir.push(target);
            }
            dir.push(env!("PROFILE"));
            dir
        }
    };
}

#[must_use]
pub fn is_rustc_test_suite() -> bool {
    option_env!("RUSTC_TEST_SUITE").is_some()
}
<commit_msg>Auto merge of #5151 - flip1995:fix_run_pass_tests, r=flip1995<commit_after>use lazy_static::lazy_static;
use std::env;
use std::path::PathBuf;

lazy_static! {
    pub static ref CARGO_TARGET_DIR: PathBuf = {
        match env::var_os("CARGO_TARGET_DIR") {
            Some(v) => v.into(),
            None => env::current_dir().unwrap().join("target"),
        }
    };
    pub static ref TARGET_LIB: PathBuf = {
        if let Some(path) = option_env!("TARGET_LIBS") {
            path.into()
        } else {
            let mut dir = CARGO_TARGET_DIR.clone();
            if let Some(target) = env::var_os("CARGO_BUILD_TARGET") {
                dir.push(target);
            }
            dir.push(env!("PROFILE"));
            dir
        }
    };
}

#[must_use]
pub fn is_rustc_test_suite() -> bool {
    option_env!("RUSTC_TEST_SUITE").is_some()
}
<|endoftext|>


<commit_before>/*!

Module for wrapping freezable data structures in managed boxes.
Normally freezable data structures require an unaliased reference,
such as `T` or `~T`, so that the compiler can track when they are
being mutated.  The `rw<T>` type converts these static checks into
dynamic checks: your program will fail if you attempt to perform
mutation when the data structure should be immutable.

*/

#[forbid(non_camel_case_types)];
#[forbid(deprecated_mode)];
#[forbid(deprecated_pattern)];

import util::with;
import unsafe::transmute_immut;

export Managed;

enum Mode { ReadOnly, Mutable, Immutable }

struct Data<T> {
    mut value: T;
    mut mode: Mode;
}

type Managed<T> = @Data<T>;

fn Managed<T>(+t: T) -> Managed<T> {
    @Data {value: t, mode: ReadOnly}
}

impl<T> Data<T> {
    fn borrow_mut<R>(op: &fn(t: &mut T) -> R) -> R {
        match self.mode {
          Immutable => fail fmt!("%? currently immutable",
                                 self.value),
          ReadOnly | Mutable => {}
        }

        do with(&mut self.mode, Mutable) {
            op(&mut self.value)
        }
    }

    fn borrow_const<R>(op: &fn(t: &const T) -> R) -> R {
        op(&const self.value)
    }

    fn borrow_imm<R>(op: &fn(t: &T) -> R) -> R {
        match self.mode {
          Mutable => fail fmt!("%? currently mutable",
                               self.value),
          ReadOnly | Immutable => {}
        }

        do with(&mut self.mode, Immutable) {
            op(unsafe{transmute_immut(&mut self.value)})
        }
    }
}
<commit_msg>add tests to manage, fix test breakage I inadvertently introduced<commit_after>/*!

Module for wrapping freezable data structures in managed boxes.
Normally freezable data structures require an unaliased reference,
such as `T` or `~T`, so that the compiler can track when they are
being mutated.  The `managed<T>` type converts these static checks into
dynamic checks: your program will fail if you attempt to perform
mutation when the data structure should be immutable.

*/

#[forbid(non_camel_case_types)];
#[forbid(deprecated_mode)];
#[forbid(deprecated_pattern)];

import util::with;
import unsafe::transmute_immut;

export Managed;

enum Mode { ReadOnly, Mutable, Immutable }

struct Data<T> {
    priv mut value: T;
    priv mut mode: Mode;
}

type Managed<T> = @Data<T>;

fn Managed<T>(+t: T) -> Managed<T> {
    @Data {value: t, mode: ReadOnly}
}

impl<T> Data<T> {
    fn borrow_mut<R>(op: &fn(t: &mut T) -> R) -> R {
        match self.mode {
          Immutable => fail fmt!("%? currently immutable",
                                 self.value),
          ReadOnly | Mutable => {}
        }

        do with(&mut self.mode, Mutable) {
            op(&mut self.value)
        }
    }

    fn borrow_const<R>(op: &fn(t: &const T) -> R) -> R {
        op(&const self.value)
    }

    fn borrow_imm<R>(op: &fn(t: &T) -> R) -> R {
        match self.mode {
          Mutable => fail fmt!("%? currently mutable",
                               self.value),
          ReadOnly | Immutable => {}
        }

        do with(&mut self.mode, Immutable) {
            op(unsafe{transmute_immut(&mut self.value)})
        }
    }
}

#[test]
#[should_fail]
fn test_mut_in_imm() {
    let m = Managed(1);
    do m.borrow_imm |_p| {
        do m.borrow_mut |_q| {
            // should not be permitted
        }
    }
}

#[test]
#[should_fail]
fn test_imm_in_mut() {
    let m = Managed(1);
    do m.borrow_mut |_p| {
        do m.borrow_imm |_q| {
            // should not be permitted
        }
    }
}

#[test]
fn test_const_in_mut() {
    let m = Managed(1);
    do m.borrow_mut |p| {
        do m.borrow_const |q| {
            assert *p == *q;
            *p += 1;
            assert *p == *q;
        }
    }
}

#[test]
fn test_mut_in_const() {
    let m = Managed(1);
    do m.borrow_const |p| {
        do m.borrow_mut |q| {
            assert *p == *q;
            *q += 1;
            assert *p == *q;
        }
    }
}

#[test]
fn test_imm_in_const() {
    let m = Managed(1);
    do m.borrow_const |p| {
        do m.borrow_imm |q| {
            assert *p == *q;
        }
    }
}

#[test]
fn test_const_in_imm() {
    let m = Managed(1);
    do m.borrow_imm |p| {
        do m.borrow_const |q| {
            assert *p == *q;
        }
    }
}

#[test]
#[should_fail]
fn test_mut_in_imm_in_const() {
    let m = Managed(1);
    do m.borrow_const |_p| {
        do m.borrow_imm |_q| {
            do m.borrow_mut |_r| {
            }
        }
    }
}
<|endoftext|>


<commit_before>extern crate ndarray;

use ndarray::Array;
use ndarray::{Ix, Si, S, arr2};

#[test]
fn double_ended()
{
    let a = Array::range(0.0, 8.0f32);
    let mut it = a.iter().map(|x| *x);
    assert_eq!(it.next(), Some(0.));
    assert_eq!(it.next_back(), Some(7.));
    assert_eq!(it.next(), Some(1.));
    assert_eq!(it.rev().last(), Some(2.));
}

#[test]
fn indexed()
{
    let a = Array::range(0.0, 8.0f32);
    for (i, elt) in a.indexed_iter() {
        assert_eq!(i, *elt as Ix);
    }
    let a = a.reshape((2, 4, 1));
    let (mut i, mut j, k) = (0, 0, 0);
    for (idx, elt) in a.indexed_iter() {
        assert_eq!(idx, (i, j, k));
        j += 1;
        if j == 4 {
            j = 0;
            i += 1;
        }
        println!("{:?}", (idx, elt));
    }
}

#[test]
fn indexed2()
{
    let a = Array::range(0.0, 8.0f32);
    let mut iter = a.iter();
    iter.next();
    let mut iter = iter.indexed();
    for (i, elt) in iter {
        assert_eq!(i, *elt as Ix);
    }
    let a = a.reshape((2, 4, 1));
    let (mut i, mut j, k) = (0, 0, 0);
    for (idx, elt) in a.iter().indexed() {
        assert_eq!(idx, (i, j, k));
        j += 1;
        if j == 4 {
            j = 0;
            i += 1;
        }
        println!("{:?}", (idx, elt));
    }
}

#[test]
fn indexed3()
{
    let a = Array::range(0.0, 8.0f32);
    let mut a = a.reshape((2, 4, 1));
    let (mut i, mut j, k) = (0, 0, 0);
    for (idx, elt) in a.slice_iter_mut(&[S, Si(1, None, 2), S]).indexed()
    {
        assert_eq!(idx, (i, j, k));
        j += 1;
        if j == 2 {
            j = 0;
            i += 1;
        }
        *elt = -1.;
        println!("{:?}", (idx, elt));
    }
    let a = a.reshape((2, 4));
    assert_eq!( a, arr2(&[[0., -1., 2., -1.],
                          [4., -1., 6., -1.]]));
}
<commit_msg>fix warning<commit_after>extern crate ndarray;

use ndarray::Array;
use ndarray::{Ix, Si, S, arr2};

#[test]
fn double_ended()
{
    let a = Array::range(0.0, 8.0f32);
    let mut it = a.iter().map(|x| *x);
    assert_eq!(it.next(), Some(0.));
    assert_eq!(it.next_back(), Some(7.));
    assert_eq!(it.next(), Some(1.));
    assert_eq!(it.rev().last(), Some(2.));
}

#[test]
fn indexed()
{
    let a = Array::range(0.0, 8.0f32);
    for (i, elt) in a.indexed_iter() {
        assert_eq!(i, *elt as Ix);
    }
    let a = a.reshape((2, 4, 1));
    let (mut i, mut j, k) = (0, 0, 0);
    for (idx, elt) in a.indexed_iter() {
        assert_eq!(idx, (i, j, k));
        j += 1;
        if j == 4 {
            j = 0;
            i += 1;
        }
        println!("{:?}", (idx, elt));
    }
}

#[test]
fn indexed2()
{
    let a = Array::range(0.0, 8.0f32);
    let mut iter = a.iter();
    iter.next();
    for (i, elt) in iter.indexed() {
        assert_eq!(i, *elt as Ix);
    }
    let a = a.reshape((2, 4, 1));
    let (mut i, mut j, k) = (0, 0, 0);
    for (idx, elt) in a.iter().indexed() {
        assert_eq!(idx, (i, j, k));
        j += 1;
        if j == 4 {
            j = 0;
            i += 1;
        }
        println!("{:?}", (idx, elt));
    }
}

#[test]
fn indexed3()
{
    let a = Array::range(0.0, 8.0f32);
    let mut a = a.reshape((2, 4, 1));
    let (mut i, mut j, k) = (0, 0, 0);
    for (idx, elt) in a.slice_iter_mut(&[S, Si(1, None, 2), S]).indexed()
    {
        assert_eq!(idx, (i, j, k));
        j += 1;
        if j == 2 {
            j = 0;
            i += 1;
        }
        *elt = -1.;
        println!("{:?}", (idx, elt));
    }
    let a = a.reshape((2, 4));
    assert_eq!( a, arr2(&[[0., -1., 2., -1.],
                          [4., -1., 6., -1.]]));
}
<|endoftext|>


<commit_before>use clap::{Arg, App, ArgGroup, SubCommand};

pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> {
    app.subcommand(SubCommand::with_name("create")
                   .about("Create an entry from the store")
                   .version("0.1")
                   .arg(Arg::with_name("path")
                        .long("path")
                        .short("p")
                        .takes_value(true)
                        .required(false)
                        .help("Create at this store path"))
                   .arg(Arg::with_name("id")
                        .long("id")
                        .short("i")
                        .takes_value(true)
                        .required(false)
                        .help("Same as --path, for consistency"))
                   .arg(Arg::with_name("from-raw")
                        .long("from-raw")
                        .takes_value(true)
                        .help("Create a new entry by reading this file ('-' for stdin)"))

                   .group(ArgGroup::with_name("create-destination-group")
                          .args(&["path", "id"])
                          .required(true))

                   .subcommand(SubCommand::with_name("entry")
                               .about("Create an entry via commandline")
                               .version("0.1")
                               .arg(Arg::with_name("content")
                                    .long("content")
                                    .short("c")
                                    .takes_value(true)
                                    .help("Content for the Entry from commandline"))
                               .arg(Arg::with_name("content-from")
                                    .long("content-from")
                                    .short("f")
                                    .takes_value(true)
                                    .help("Content for the Entry from this file ('-' for stdin)"))

                               .group(ArgGroup::with_name("create-content-group")
                                      .args(&["content", "content-from"])
                                      .required(false))

                               .arg(Arg::with_name("header")
                                    .long("header")
                                    .short("h")
                                    .takes_value(true)
                                    .multiple(true)
                                    .help("Set a header field. Specify as 'header.field.value=value', multiple allowed"))
                               )
                   )

       .subcommand(SubCommand::with_name("retrieve")
                   .about("Retrieve an entry from the store (implicitely creates the entry)")
                   .version("0.1")
                   .arg(Arg::with_name("id")
                        .long("id")
                        .short("i")
                        .takes_value(true)
                        .required(true)
                        .help("Retreive by Store Path, where root (/) is the store itself"))
                   .arg(Arg::with_name("content")
                        .long("content")
                        .short("c")
                        .help("Print content"))
                   .arg(Arg::with_name("header")
                        .long("header")
                        .short("h")
                        .help("Print header"))
                   .arg(Arg::with_name("header-json")
                        .long("header-json")
                        .short("j")
                        .help("Print header as json"))
                   .arg(Arg::with_name("raw")
                        .long("raw")
                        .short("r")
                        .help("Print Entries as they are in the store"))

                   .subcommand(SubCommand::with_name("filter-header")
                               .about("Retrieve Entries by filtering")
                               .version("0.1")
                               .arg(Arg::with_name("header-field-where")
                                    .long("where")
                                    .short("w")
                                    .takes_value(true)
                                    .help("Filter with 'header.field=foo' where the header field 'header.field' equals 'foo'")
                               )
                               .arg(Arg::with_name("header-field-grep")
                                    .long("grep")
                                    .short("g")
                                    .takes_value(true)
                                    .help("Filter with 'header.field=[a-zA-Z0-9]*' where the header field 'header.field' matches '[a-zA-Z0-9]*'"))
                               )
                   )

       .subcommand(SubCommand::with_name("get")
                   .about("Get an entry from the store (fails if non-existent)")
                   .version("0.1")
                   .arg(Arg::with_name("id")
                        .long("id")
                        .short("i")
                        .takes_value(true)
                        .required(true)
                        .help("Retreive by Store Path, where root (/) is the store itself"))
                   .arg(Arg::with_name("content")
                        .long("content")
                        .short("c")
                        .help("Print content"))
                   .arg(Arg::with_name("header")
                        .long("header")
                        .short("h")
                        .help("Print header"))
                   .arg(Arg::with_name("header-json")
                        .long("header-json")
                        .short("j")
                        .help("Print header as json"))
                   .arg(Arg::with_name("raw")
                        .long("raw")
                        .short("r")
                        .help("Print Entries as they are in the store"))

                   .subcommand(SubCommand::with_name("filter-header")
                               .about("Retrieve Entries by filtering")
                               .version("0.1")
                               .arg(Arg::with_name("header-field-where")
                                    .long("where")
                                    .short("w")
                                    .takes_value(true)
                                    .help("Filter with 'header.field=foo' where the header field 'header.field' equals 'foo'")
                               )
                               .arg(Arg::with_name("header-field-grep")
                                    .long("grep")
                                    .short("g")
                                    .takes_value(true)
                                    .help("Filter with 'header.field=[a-zA-Z0-9]*' where the header field 'header.field' matches '[a-zA-Z0-9]*'"))
                               )
                   )

       .subcommand(SubCommand::with_name("update")
                   .about("Get an entry from the store")
                   .version("0.1")
                   .arg(Arg::with_name("id")
                        .long("id")
                        .short("i")
                        .takes_value(true)
                        .required(true)
                        .help("Update Store Entry with this path. Root (/) is the store itself"))
                   .arg(Arg::with_name("content")
                        .long("content")
                        .short("c")
                        .takes_value(true)
                        .help("Take the content for the new Entry from this file ('-' for stdin)"))
                   .arg(Arg::with_name("header")
                        .long("header")
                        .short("h")
                        .takes_value(true)
                        .multiple(true)
                        .help("Set a header field. Specify as 'header.field.value=value', multiple allowed"))
                   )

       .subcommand(SubCommand::with_name("delete")
                   .about("Delete an entry from the store")
                   .version("0.1")
                   .arg(Arg::with_name("id")
                        .long("id")
                        .short("i")
                        .takes_value(true)
                        .required(true)
                        .help("Remove Store Entry with this path. Root (/) is the store itself"))
                   )
}

<commit_msg>Add value_name() call in ui specification code<commit_after>use clap::{Arg, App, ArgGroup, SubCommand};

pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> {
    app.subcommand(SubCommand::with_name("create")
                   .about("Create an entry from the store")
                   .version("0.1")
                   .arg(Arg::with_name("path")
                        .long("path")
                        .short("p")
                        .takes_value(true)
                        .required(false)
                        .help("Create at this store path")
                        .value_name("PATH"))
                   .arg(Arg::with_name("id")
                        .long("id")
                        .short("i")
                        .takes_value(true)
                        .required(false)
                        .help("Same as --path, for consistency")
                        .value_name("PATH"))
                   .arg(Arg::with_name("from-raw")
                        .long("from-raw")
                        .takes_value(true)
                        .help("Create a new entry by reading this file ('-' for stdin)")
                        .value_name("FILE"))

                   .group(ArgGroup::with_name("create-destination-group")
                          .args(&["path", "id"])
                          .required(true))

                   .subcommand(SubCommand::with_name("entry")
                               .about("Create an entry via commandline")
                               .version("0.1")
                               .arg(Arg::with_name("content")
                                    .long("content")
                                    .short("c")
                                    .takes_value(true)
                                    .help("Content for the Entry from commandline")
                                    .value_name("CONTENT"))
                               .arg(Arg::with_name("content-from")
                                    .long("content-from")
                                    .short("f")
                                    .takes_value(true)
                                    .help("Content for the Entry from this file ('-' for stdin)")
                                    .value_name("CONTENT"))

                               .group(ArgGroup::with_name("create-content-group")
                                      .args(&["content", "content-from"])
                                      .required(false))

                               .arg(Arg::with_name("header")
                                    .long("header")
                                    .short("h")
                                    .takes_value(true)
                                    .multiple(true)
                                    .help("Set a header field. Specify as 'header.field.value=value', multiple allowed")
                                    .value_name("header.field.value=value"))
                               )
                   )

       .subcommand(SubCommand::with_name("retrieve")
                   .about("Retrieve an entry from the store (implicitely creates the entry)")
                   .version("0.1")
                   .arg(Arg::with_name("id")
                        .long("id")
                        .short("i")
                        .takes_value(true)
                        .required(true)
                        .help("Retreive by Store Path, where root (/) is the store itself"))
                   .arg(Arg::with_name("content")
                        .long("content")
                        .short("c")
                        .help("Print content"))
                   .arg(Arg::with_name("header")
                        .long("header")
                        .short("h")
                        .help("Print header"))
                   .arg(Arg::with_name("header-json")
                        .long("header-json")
                        .short("j")
                        .help("Print header as json"))
                   .arg(Arg::with_name("raw")
                        .long("raw")
                        .short("r")
                        .help("Print Entries as they are in the store"))

                   .subcommand(SubCommand::with_name("filter-header")
                               .about("Retrieve Entries by filtering")
                               .version("0.1")
                               .arg(Arg::with_name("header-field-where")
                                    .long("where")
                                    .short("w")
                                    .takes_value(true)
                                    .help("Filter with 'header.field=foo' where the header field 'header.field' equals 'foo'")
                               )
                               .arg(Arg::with_name("header-field-grep")
                                    .long("grep")
                                    .short("g")
                                    .takes_value(true)
                                    .help("Filter with 'header.field=[a-zA-Z0-9]*' where the header field 'header.field' matches '[a-zA-Z0-9]*'"))
                               )
                   )

       .subcommand(SubCommand::with_name("get")
                   .about("Get an entry from the store (fails if non-existent)")
                   .version("0.1")
                   .arg(Arg::with_name("id")
                        .long("id")
                        .short("i")
                        .takes_value(true)
                        .required(true)
                        .help("Retrieve by Store Path, where root (/) is the store itself")
                        .value_name("PATH"))
                   .arg(Arg::with_name("content")
                        .long("content")
                        .short("c")
                        .help("Print content"))
                   .arg(Arg::with_name("header")
                        .long("header")
                        .short("h")
                        .help("Print header"))
                   .arg(Arg::with_name("header-json")
                        .long("header-json")
                        .short("j")
                        .help("Print header as json"))
                   .arg(Arg::with_name("raw")
                        .long("raw")
                        .short("r")
                        .help("Print Entries as they are in the store"))

                   .subcommand(SubCommand::with_name("filter-header")
                               .about("Retrieve Entries by filtering")
                               .version("0.1")
                               .arg(Arg::with_name("header-field-where")
                                    .long("where")
                                    .short("w")
                                    .takes_value(true)
                                    .help("Filter with 'header.field=foo' where the header field 'header.field' equals 'foo'")
                                    .value_name("header.field=foo")
                               )
                               .arg(Arg::with_name("header-field-grep")
                                    .long("grep")
                                    .short("g")
                                    .takes_value(true)
                                    .help("Filter with 'header.field=[a-zA-Z0-9]*' where the header field 'header.field' matches '[a-zA-Z0-9]*'"))
                               )
                   )

       .subcommand(SubCommand::with_name("update")
                   .about("Get an entry from the store")
                   .version("0.1")
                   .arg(Arg::with_name("id")
                        .long("id")
                        .short("i")
                        .takes_value(true)
                        .required(true)
                        .help("Update Store Entry with this path. Root (/) is the store itself")
                        .value_name("PATH"))
                   .arg(Arg::with_name("content")
                        .long("content")
                        .short("c")
                        .takes_value(true)
                        .help("Take the content for the new Entry from this file ('-' for stdin)")
                        .value_name("CONTENT"))
                   .arg(Arg::with_name("header")
                        .long("header")
                        .short("h")
                        .takes_value(true)
                        .multiple(true)
                        .help("Set a header field. Specify as 'header.field.value=value', multiple allowed"))
                   )

       .subcommand(SubCommand::with_name("delete")
                   .about("Delete an entry from the store")
                   .version("0.1")
                   .arg(Arg::with_name("id")
                        .long("id")
                        .short("i")
                        .takes_value(true)
                        .required(true)
                        .help("Remove Store Entry with this path. Root (/) is the store itself")
                        .value_name("PATH"))
                   )
}
<|endoftext|>


<commit_before>// Copyright (c) 2013-2016 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.

use capnp_rpc::{RpcSystem, twoparty, rpc_twoparty_capnp};
use http_capnp::{outgoing_http, http_session};

use capnp::capability::Promise;
use capnp::Error;

use futures::{Future, Stream};

use tokio_core::reactor;
use tokio_io::AsyncRead;

struct OutgoingHttp {
    handle: reactor::Handle,
}

impl OutgoingHttp {
    fn new(handle: reactor::Handle) -> OutgoingHttp {
        OutgoingHttp {
            handle: handle,
        }
    }
}

impl outgoing_http::Server for OutgoingHttp {
    fn new_session(
        &mut self,
        params: outgoing_http::NewSessionParams,
        mut results: outgoing_http::NewSessionResults)
        -> Promise<(), Error>
    {
        let session = HttpSession::new(
            ::tokio_curl::Session::new(self.handle.clone()),
            pry!(pry!(params.get()).get_base_url()).to_string());
        results.get().set_session(
            http_session::ToClient::new(session).from_server::<::capnp_rpc::Server>());
        Promise::ok(())
    }
}

struct HttpSession {
    session: ::tokio_curl::Session,
    base_url: String,
}

impl HttpSession {
    fn new(session: ::tokio_curl::Session, base_url: String) -> HttpSession {
        HttpSession {
            session: session,
            base_url: base_url,
        }
    }
}

fn from_curl_error(e: ::curl::Error) -> Error {
    Error::failed(format!("curl error: {:?}", e))
}

fn from_perform_error(e: ::tokio_curl::PerformError) -> Error {
    Error::failed(format!("curl perform error: {:?}", e))
}

impl http_session::Server for HttpSession {
    fn get(
        &mut self,
        params: http_session::GetParams,
        mut results: http_session::GetResults)
        -> Promise<(), Error>
    {
        let path = pry!(pry!(params.get()).get_path());
        let mut url = self.base_url.clone();
        url.push_str(path);
        let mut easy = ::curl::easy::Easy::new();
        pry!(easy.url(&url).map_err(from_curl_error));
        pry!(easy.get(true).map_err(from_curl_error));

        // We need this channel to work around the `Send` bound required by write_function().
        let (tx, stream) = ::futures::sync::mpsc::unbounded::<Vec<u8>>();
        pry!(easy.write_function(move |data| {
            // Error case should only happen if this request has been canceled.
            let _ = tx.send(data.into());
            Ok(data.len())
        }).map_err(from_curl_error));

        Promise::from_future(
            self.session.perform(easy).map_err(from_perform_error).and_then(|mut response| {
                response.response_code().map_err(from_curl_error)
            }).and_then(move |code| {
                results.get().set_response_code(code);
                stream.collect().and_then(move |writes| {
                    results.get().set_body(
                        &writes.concat());
                    Ok(())
                }).map_err(|()| unreachable!())
            }))
    }

    fn post(
        &mut self,
        _params: http_session::PostParams,
        _results: http_session::PostResults)
        -> Promise<(), Error>
    {
        // TODO
        Promise::err(Error::unimplemented(format!("post() is unimplemented")))
    }
}

pub fn main() {
    use std::net::ToSocketAddrs;
    let args: Vec<String> = ::std::env::args().collect();
    if args.len() != 3 {
        println!("usage: {} server HOST:PORT", args[0]);
        return;
    }

    let mut core = reactor::Core::new().unwrap();
    let handle = core.handle();

    let addr = args[2].to_socket_addrs().unwrap().next().expect("could not parse address");
    let socket = ::tokio_core::net::TcpListener::bind(&addr, &handle).unwrap();

    let proxy = outgoing_http::ToClient::new(
        OutgoingHttp::new(handle.clone())).from_server::<::capnp_rpc::Server>();

    let handle1 = handle.clone();
    let done = socket.incoming().for_each(move |(socket, _addr)| {
        try!(socket.set_nodelay(true));
        let (reader, writer) = socket.split();
        let handle = handle1.clone();

        let network =
            twoparty::VatNetwork::new(reader, writer,
                                      rpc_twoparty_capnp::Side::Server, Default::default());

        let rpc_system = RpcSystem::new(Box::new(network), Some(proxy.clone().client));

        handle.spawn(rpc_system.map_err(|_| ()));
        Ok(())
    });

    core.run(done).unwrap();
}
<commit_msg>send -> unbounded send in http-requests example<commit_after>// Copyright (c) 2013-2016 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.

use capnp_rpc::{RpcSystem, twoparty, rpc_twoparty_capnp};
use http_capnp::{outgoing_http, http_session};

use capnp::capability::Promise;
use capnp::Error;

use futures::{Future, Stream};

use tokio_core::reactor;
use tokio_io::AsyncRead;

struct OutgoingHttp {
    handle: reactor::Handle,
}

impl OutgoingHttp {
    fn new(handle: reactor::Handle) -> OutgoingHttp {
        OutgoingHttp {
            handle: handle,
        }
    }
}

impl outgoing_http::Server for OutgoingHttp {
    fn new_session(
        &mut self,
        params: outgoing_http::NewSessionParams,
        mut results: outgoing_http::NewSessionResults)
        -> Promise<(), Error>
    {
        let session = HttpSession::new(
            ::tokio_curl::Session::new(self.handle.clone()),
            pry!(pry!(params.get()).get_base_url()).to_string());
        results.get().set_session(
            http_session::ToClient::new(session).from_server::<::capnp_rpc::Server>());
        Promise::ok(())
    }
}

struct HttpSession {
    session: ::tokio_curl::Session,
    base_url: String,
}

impl HttpSession {
    fn new(session: ::tokio_curl::Session, base_url: String) -> HttpSession {
        HttpSession {
            session: session,
            base_url: base_url,
        }
    }
}

fn from_curl_error(e: ::curl::Error) -> Error {
    Error::failed(format!("curl error: {:?}", e))
}

fn from_perform_error(e: ::tokio_curl::PerformError) -> Error {
    Error::failed(format!("curl perform error: {:?}", e))
}

impl http_session::Server for HttpSession {
    fn get(
        &mut self,
        params: http_session::GetParams,
        mut results: http_session::GetResults)
        -> Promise<(), Error>
    {
        let path = pry!(pry!(params.get()).get_path());
        let mut url = self.base_url.clone();
        url.push_str(path);
        let mut easy = ::curl::easy::Easy::new();
        pry!(easy.url(&url).map_err(from_curl_error));
        pry!(easy.get(true).map_err(from_curl_error));

        // We need this channel to work around the `Send` bound required by write_function().
        let (tx, stream) = ::futures::sync::mpsc::unbounded::<Vec<u8>>();
        pry!(easy.write_function(move |data| {
            // Error case should only happen if this request has been canceled.
            let _ = tx.unbounded_send(data.into());
            Ok(data.len())
        }).map_err(from_curl_error));

        Promise::from_future(
            self.session.perform(easy).map_err(from_perform_error).and_then(|mut response| {
                response.response_code().map_err(from_curl_error)
            }).and_then(move |code| {
                results.get().set_response_code(code);
                stream.collect().and_then(move |writes| {
                    results.get().set_body(
                        &writes.concat());
                    Ok(())
                }).map_err(|()| unreachable!())
            }))
    }

    fn post(
        &mut self,
        _params: http_session::PostParams,
        _results: http_session::PostResults)
        -> Promise<(), Error>
    {
        // TODO
        Promise::err(Error::unimplemented(format!("post() is unimplemented")))
    }
}

pub fn main() {
    use std::net::ToSocketAddrs;
    let args: Vec<String> = ::std::env::args().collect();
    if args.len() != 3 {
        println!("usage: {} server HOST:PORT", args[0]);
        return;
    }

    let mut core = reactor::Core::new().unwrap();
    let handle = core.handle();

    let addr = args[2].to_socket_addrs().unwrap().next().expect("could not parse address");
    let socket = ::tokio_core::net::TcpListener::bind(&addr, &handle).unwrap();

    let proxy = outgoing_http::ToClient::new(
        OutgoingHttp::new(handle.clone())).from_server::<::capnp_rpc::Server>();

    let handle1 = handle.clone();
    let done = socket.incoming().for_each(move |(socket, _addr)| {
        try!(socket.set_nodelay(true));
        let (reader, writer) = socket.split();
        let handle = handle1.clone();

        let network =
            twoparty::VatNetwork::new(reader, writer,
                                      rpc_twoparty_capnp::Side::Server, Default::default());

        let rpc_system = RpcSystem::new(Box::new(network), Some(proxy.clone().client));

        handle.spawn(rpc_system.map_err(|_| ()));
        Ok(())
    });

    core.run(done).unwrap();
}
<|endoftext|>