<commit_before>pub mod mut_message_client;

use std::env;
use std::io::*;
use std::mem;
use std::net::*;
use std::panic::{catch_unwind, UnwindSafe};
use std::process::{Command, Stdio};
use std::str::FromStr;
use std::sync::*;
use std::time::*;
use std::thread;

use tokio_core::reactor::Core;

use trust_dns::client::*;
use trust_dns::op::Message;
use trust_dns::rr::*;
use trust_dns::rr::rdata::{DNSSECRData, DNSSECRecordType};
use trust_dns::rr::dnssec::*;

use self::mut_message_client::MutMessageHandle;

/// Spins up a Server and handles shutting it down after running the test
#[allow(dead_code)]
pub fn named_test_harness<F, R>(toml: &str, test: F)
where
    F: FnOnce(u16, u16) -> R + UnwindSafe,
{
    // find a random port to listen on
    let (test_port, test_tls_port) = {
        let server = UdpSocket::bind(("0.0.0.0", 0)).unwrap();
        let server_addr = server.local_addr().unwrap();
        let test_port = server_addr.port();

        let server = UdpSocket::bind(("0.0.0.0", 0)).unwrap();
        let server_addr = server.local_addr().unwrap();
        let test_tls_port = server_addr.port();

        assert!(test_port != test_tls_port);
        (test_port, test_tls_port)
    };

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

    let mut named = Command::new(&format!("{}/../target/debug/named", server_path))
        .stdout(Stdio::piped())
        .arg("-d")
        .arg(&format!(
            "--config={}/tests/named_test_configs/{}",
            server_path,
            toml
        ))
        .arg(&format!(
            "--zonedir={}/tests/named_test_configs",
            server_path
        ))
        .arg(&format!("--port={}", test_port))
        .arg(&format!("--tls-port={}", test_tls_port))
        .spawn()
        .expect("failed to start named");

    let mut named_out = BufReader::new(mem::replace(&mut named.stdout, None).expect("no stdout"));

    // forced thread killer
    let succeeded = Arc::new(atomic::AtomicBool::new(false));
    let succeeded_clone = succeeded.clone();
    let killer_join = thread::Builder::new()
        .name("thread_killer".to_string())
        .spawn(move || {
            let succeeded = succeeded_clone;

            let mut kill_named = || {
                println!("killing named");
                named.kill().expect("could not kill process");
                named.wait().expect("waiting failed");
            };

            for _ in 0..15 {
                thread::sleep(Duration::from_secs(1));
                if succeeded.load(atomic::Ordering::Relaxed) {
                    kill_named();
                    return;
                }
            }

            kill_named();
            panic!("timeout");
        })
        .expect("could not start thread killer");

    // we should get the correct output before 1000 lines...
    let mut output = String::new();
    let mut found = false;
    for _ in 0..1000 {
        output.clear();
        named_out.read_line(&mut output).expect(
            "could not read stdout",
        );
        if !output.is_empty() {
            stdout().write(b"SRV: ").unwrap();
            stdout().write(output.as_bytes()).unwrap();
        }
        if output.ends_with("awaiting connections...\n") {
            found = true;
            break;
        }
    }

    stdout().flush().unwrap();
    assert!(found);

    // spawn a thread to capture stdout
    let succeeded_clone = succeeded.clone();
    thread::Builder::new()
        .name("named stdout".into())
        .spawn(move || {
            let succeeded = succeeded_clone;
            while !succeeded.load(atomic::Ordering::Relaxed) {
                output.clear();
                named_out.read_line(&mut output).expect(
                    "could not read stdout",
                );
                if !output.is_empty() {
                    stdout().write(b"SRV: ").unwrap();
                    stdout().write(output.as_bytes()).unwrap();
                }
            }
        })
        .expect("no thread available");

    println!("running test...");

    let result = catch_unwind(move || test(test_port, test_tls_port));

    println!("test completed");
    succeeded.store(true, atomic::Ordering::Relaxed);
    killer_join.join().expect("join failed");

    assert!(result.is_ok(), "test failed");
}

pub fn query_message<C: ClientHandle>(
    io_loop: &mut Core,
    client: &mut C,
    name: Name,
    record_type: RecordType,
) -> Message {
    println!("sending request");
    let response = io_loop.run(client.query(name.clone(), DNSClass::IN, record_type));
    println!("got response: {}", response.is_ok());
    assert!(response.is_ok());
    response.unwrap()
}

// This only validates that a query to the server works, it shouldn't be used for more than this.
//  i.e. more complex checks live with the clients and authorities to validate deeper funcionality
#[allow(dead_code)]
pub fn query_a<C: ClientHandle>(io_loop: &mut Core, client: &mut C) {
    let name = Name::from_labels(vec!["www", "example", "com"]);
    let response = query_message(io_loop, client, name, RecordType::A);
    let record = &response.answers()[0];

    if let &RData::A(ref address) = record.rdata() {
        assert!(address == &Ipv4Addr::new(127, 0, 0, 1))
    } else {
        panic!("wrong RDATA")
    }
}

// This only validates that a query to the server works, it shouldn't be used for more than this.
//  i.e. more complex checks live with the clients and authorities to validate deeper funcionality
#[allow(dead_code)]
pub fn query_all_dnssec(
    io_loop: &mut Core,
    client: BasicClientHandle,
    algorithm: Algorithm,
    with_rfc6975: bool,
) {
    let name = Name::from_str("example.com.").unwrap();
    let mut client = MutMessageHandle::new(client);
    client.dnssec_ok = true;
    if with_rfc6975 {
        client.support_algorithms = Some(SupportedAlgorithms::from_vec(&[algorithm]));
    }

    let response = query_message(io_loop, &mut client, name,
                                 RecordType::DNSSEC(DNSSECRecordType::DNSKEY));

    let dnskey = response
        .answers()
        .iter()
        .filter(|r| r.rr_type() == RecordType::DNSSEC(DNSSECRecordType::DNSKEY))
        .map(|r| if let &RData::DNSSEC(DNSSECRData::DNSKEY(ref dnskey)) = r.rdata() {
            dnskey.clone()
        } else {
            panic!("wrong RDATA")
        })
        .find(|d| d.algorithm() == algorithm);
    assert!(dnskey.is_some(), "DNSKEY not found");

    let rrsig = response
        .answers()
        .iter()
        .filter(|r| r.rr_type() == RecordType::DNSSEC(DNSSECRecordType::RRSIG))
        .map(|r| if let &RData::DNSSEC(DNSSECRData::SIG(ref rrsig)) = r.rdata() {
            rrsig.clone()
        } else {
            panic!("wrong RDATA")
        })
        .filter(|rrsig| rrsig.algorithm() == algorithm)
        .find(|rrsig| rrsig.type_covered() == RecordType::DNSSEC(DNSSECRecordType::DNSKEY));
    assert!(rrsig.is_some(), "Associated RRSIG not found");
}

#[allow(dead_code)]
pub fn query_all_dnssec_with_rfc6975(
    io_loop: &mut Core,
    client: BasicClientHandle,
    algorithm: Algorithm,
) {
    query_all_dnssec(io_loop, client, algorithm, true)
}

#[allow(dead_code)]
pub fn query_all_dnssec_wo_rfc6975(
    io_loop: &mut Core,
    client: BasicClientHandle,
    algorithm: Algorithm,
) {
    query_all_dnssec(io_loop, client, algorithm, false)
}
<commit_msg>extend thread timeout for test and ignore errors on kill<commit_after>pub mod mut_message_client;

use std::env;
use std::io::*;
use std::mem;
use std::net::*;
use std::panic::{catch_unwind, UnwindSafe};
use std::process::{Command, Stdio};
use std::str::FromStr;
use std::sync::*;
use std::time::*;
use std::thread;

use tokio_core::reactor::Core;

use trust_dns::client::*;
use trust_dns::op::Message;
use trust_dns::rr::*;
use trust_dns::rr::rdata::{DNSSECRData, DNSSECRecordType};
use trust_dns::rr::dnssec::*;

use self::mut_message_client::MutMessageHandle;

/// Spins up a Server and handles shutting it down after running the test
#[allow(dead_code)]
pub fn named_test_harness<F, R>(toml: &str, test: F)
where
    F: FnOnce(u16, u16) -> R + UnwindSafe,
{
    // find a random port to listen on
    let (test_port, test_tls_port) = {
        let server = UdpSocket::bind(("0.0.0.0", 0)).unwrap();
        let server_addr = server.local_addr().unwrap();
        let test_port = server_addr.port();

        let server = UdpSocket::bind(("0.0.0.0", 0)).unwrap();
        let server_addr = server.local_addr().unwrap();
        let test_tls_port = server_addr.port();

        assert!(test_port != test_tls_port);
        (test_port, test_tls_port)
    };

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

    let mut named = Command::new(&format!("{}/../target/debug/named", server_path))
        .stdout(Stdio::piped())
        .arg("-d")
        .arg(&format!(
            "--config={}/tests/named_test_configs/{}",
            server_path,
            toml
        ))
        .arg(&format!(
            "--zonedir={}/tests/named_test_configs",
            server_path
        ))
        .arg(&format!("--port={}", test_port))
        .arg(&format!("--tls-port={}", test_tls_port))
        .spawn()
        .expect("failed to start named");

    let mut named_out = BufReader::new(mem::replace(&mut named.stdout, None).expect("no stdout"));

    // forced thread killer
    let succeeded = Arc::new(atomic::AtomicBool::new(false));
    let succeeded_clone = succeeded.clone();
    let killer_join = thread::Builder::new()
        .name("thread_killer".to_string())
        .spawn(move || {
            let succeeded = succeeded_clone;

            let mut kill_named = || {
                println!("killing named");

                if let Err(e) = named.kill() {
                    println!("warning: failed to kill named: {:?}", e);
                }
            };

            for _ in 0..30 {
                thread::sleep(Duration::from_secs(1));
                if succeeded.load(atomic::Ordering::Relaxed) {
                    kill_named();
                    return;
                }
            }

            kill_named();
            panic!("timeout");
        })
        .expect("could not start thread killer");

    // we should get the correct output before 1000 lines...
    let mut output = String::new();
    let mut found = false;
    for _ in 0..1000 {
        output.clear();
        named_out.read_line(&mut output).expect(
            "could not read stdout",
        );
        if !output.is_empty() {
            stdout().write(b"SRV: ").unwrap();
            stdout().write(output.as_bytes()).unwrap();
        }
        if output.ends_with("awaiting connections...\n") {
            found = true;
            break;
        }
    }

    stdout().flush().unwrap();
    assert!(found);

    // spawn a thread to capture stdout
    let succeeded_clone = succeeded.clone();
    thread::Builder::new()
        .name("named stdout".into())
        .spawn(move || {
            let succeeded = succeeded_clone;
            while !succeeded.load(atomic::Ordering::Relaxed) {
                output.clear();
                named_out.read_line(&mut output).expect(
                    "could not read stdout",
                );
                if !output.is_empty() {
                    stdout().write(b"SRV: ").unwrap();
                    stdout().write(output.as_bytes()).unwrap();
                }
            }
        })
        .expect("no thread available");

    println!("running test...");

    let result = catch_unwind(move || test(test_port, test_tls_port));

    println!("test completed");
    succeeded.store(true, atomic::Ordering::Relaxed);
    killer_join.join().expect("join failed");

    assert!(result.is_ok(), "test failed");
}

pub fn query_message<C: ClientHandle>(
    io_loop: &mut Core,
    client: &mut C,
    name: Name,
    record_type: RecordType,
) -> Message {
    println!("sending request");
    let response = io_loop.run(client.query(name.clone(), DNSClass::IN, record_type));
    println!("got response: {}", response.is_ok());
    assert!(response.is_ok());
    response.unwrap()
}

// This only validates that a query to the server works, it shouldn't be used for more than this.
//  i.e. more complex checks live with the clients and authorities to validate deeper funcionality
#[allow(dead_code)]
pub fn query_a<C: ClientHandle>(io_loop: &mut Core, client: &mut C) {
    let name = Name::from_labels(vec!["www", "example", "com"]);
    let response = query_message(io_loop, client, name, RecordType::A);
    let record = &response.answers()[0];

    if let &RData::A(ref address) = record.rdata() {
        assert!(address == &Ipv4Addr::new(127, 0, 0, 1))
    } else {
        panic!("wrong RDATA")
    }
}

// This only validates that a query to the server works, it shouldn't be used for more than this.
//  i.e. more complex checks live with the clients and authorities to validate deeper funcionality
#[allow(dead_code)]
pub fn query_all_dnssec(
    io_loop: &mut Core,
    client: BasicClientHandle,
    algorithm: Algorithm,
    with_rfc6975: bool,
) {
    let name = Name::from_str("example.com.").unwrap();
    let mut client = MutMessageHandle::new(client);
    client.dnssec_ok = true;
    if with_rfc6975 {
        client.support_algorithms = Some(SupportedAlgorithms::from_vec(&[algorithm]));
    }

    let response = query_message(io_loop, &mut client, name,
                                 RecordType::DNSSEC(DNSSECRecordType::DNSKEY));

    let dnskey = response
        .answers()
        .iter()
        .filter(|r| r.rr_type() == RecordType::DNSSEC(DNSSECRecordType::DNSKEY))
        .map(|r| if let &RData::DNSSEC(DNSSECRData::DNSKEY(ref dnskey)) = r.rdata() {
            dnskey.clone()
        } else {
            panic!("wrong RDATA")
        })
        .find(|d| d.algorithm() == algorithm);
    assert!(dnskey.is_some(), "DNSKEY not found");

    let rrsig = response
        .answers()
        .iter()
        .filter(|r| r.rr_type() == RecordType::DNSSEC(DNSSECRecordType::RRSIG))
        .map(|r| if let &RData::DNSSEC(DNSSECRData::SIG(ref rrsig)) = r.rdata() {
            rrsig.clone()
        } else {
            panic!("wrong RDATA")
        })
        .filter(|rrsig| rrsig.algorithm() == algorithm)
        .find(|rrsig| rrsig.type_covered() == RecordType::DNSSEC(DNSSECRecordType::DNSKEY));
    assert!(rrsig.is_some(), "Associated RRSIG not found");
}

#[allow(dead_code)]
pub fn query_all_dnssec_with_rfc6975(
    io_loop: &mut Core,
    client: BasicClientHandle,
    algorithm: Algorithm,
) {
    query_all_dnssec(io_loop, client, algorithm, true)
}

#[allow(dead_code)]
pub fn query_all_dnssec_wo_rfc6975(
    io_loop: &mut Core,
    client: BasicClientHandle,
    algorithm: Algorithm,
) {
    query_all_dnssec(io_loop, client, algorithm, false)
}
<|endoftext|>


<commit_before>/// This module provides default futures that can be used for
/// sending request to other microservices by proxy engine.
///

use std::collections::HashMap;
use std::str::from_utf8;
use std::sync::Arc;

use futures::future::{Future};
use futures::Stream;
use json::parse as json_parse;
use lapin_futures_rustls::lapin::channel::{
    BasicConsumeOptions, BasicProperties, BasicPublishOptions, QueueBindOptions,
    QueueDeclareOptions, QueueDeleteOptions, QueueUnbindOptions,
};
use lapin_futures_rustls::lapin::types::{AMQPValue, FieldTable};
use log::error;

use crate::error::PathfinderError;
use crate::rabbitmq::RabbitMQClient;
use crate::engine::MessageSender;
use crate::engine::options::RpcOptions;
use crate::engine::serializer::Serializer;

/// Simple future that sends a RPC request to the certain microservice,
/// consumes from a response from a separate queue and then returns a
/// response to the caller via transmitter.
pub fn rpc_request_future(
    transmitter: MessageSender,
    rabbitmq_client: Arc<RabbitMQClient>,
    options: Arc<RpcOptions>,
    headers: HashMap<String, String>
) -> Box<Future<Item=(), Error=PathfinderError> + Send + Sync + 'static> {
    let rabbitmq_client_local = rabbitmq_client.clone();

    Box::new(
        // 1. Create a channel
        rabbitmq_client_local.get_channel()
        // 2. Declare a response queue
        .and_then(move |channel| {
            let queue_name = options.get_queue_name().unwrap().clone();
            let queue_declare_options = QueueDeclareOptions {
                passive: false,
                durable: true,
                exclusive: true,
                auto_delete: false,
                ..Default::default()
            };

            channel
                .queue_declare(&queue_name, queue_declare_options, FieldTable::new())
                .map(move |queue| (channel, queue, options))
        })
        // 3. Link the response queue the exchange
        .and_then(move |(channel, queue, options)| {
            let queue_name = options.get_queue_name().unwrap().clone();
            let endpoint = options.get_endpoint().unwrap().clone();
            let routing_key = options.get_queue_name().unwrap().clone();

            channel
                .queue_bind(
                    &queue_name,
                    &endpoint.get_response_exchange(),
                    &routing_key,
                    QueueBindOptions::default(),
                    FieldTable::new()
                )
                .map(move |_| (channel, queue, options))
        })
        // 4. Publish message into the microservice queue and make ensure that it's delivered
        .and_then(move |(channel, queue, options)| {
            let publish_message_options = BasicPublishOptions {
                mandatory: true,
                immediate: false,
                ..Default::default()
            };

            let mut message_headers = FieldTable::new();
            for (key, value) in headers.clone().iter() {
                let header_name = key.clone();
                let header_value = AMQPValue::LongString(value.clone());
                message_headers.insert(header_name, header_value);
            }

            let endpoint = options.get_endpoint().unwrap().clone();
            let message = options.get_message().unwrap().clone();
            let queue_name_response = options.get_queue_name().unwrap().clone();
            let event_name = message["event-name"].as_str().unwrap_or("null");
            let basic_properties = BasicProperties::default()
                .with_content_type("application/json".to_string())    // Content type
                .with_headers(message_headers)                        // Headers for the message
                .with_delivery_mode(2)                                // Message must be persistent
                .with_reply_to(queue_name_response.to_string())       // Response queue
                .with_correlation_id(event_name.clone().to_string()); // Event name

            channel
                .basic_publish(
                    &endpoint.get_request_exchange(),
                    &endpoint.get_routing_key(),
                    message["content"].dump().as_bytes().to_vec(),
                    publish_message_options,
                    basic_properties
                )
                .map(move |_confirmation| (channel, queue, options))
        })
        // 5. Consume a response message from the queue, that was declared on the 2nd step
        .and_then(move |(channel, queue, options)| {
            channel
                .basic_consume(
                    &queue,
                    "response_consumer",
                    BasicConsumeOptions::default(),
                    FieldTable::new()
                )
                .and_then(move |stream| {
                    stream
                        .take(1)
                        .into_future()
                        .map_err(|(err, _)| err)
                        .map(move |(message, _)| (channel, queue, message.unwrap(), options))
                })
        })
        // 6. Prepare a response for a client, serialize and sent via WebSocket transmitter
        .and_then(move |(channel, queue, message, options)| {
            let raw_data = from_utf8(&message.data).unwrap();
            let json = Arc::new(Box::new(json_parse(raw_data).unwrap()));
            let serializer = Serializer::new();
            let response = serializer.serialize(json.dump()).unwrap();
            let transmitter_local = transmitter.clone();
            transmitter_local.unbounded_send(response).unwrap_or(());

            channel
                .basic_ack(message.delivery_tag, false)
                .map(move |_confirmation| (channel, queue, options))
        })
        // 7. Unbind the response queue from the exchange point
        .and_then(move |(channel, _queue, options)| {
            let queue_name = options.get_queue_name().unwrap().clone();
            let routing_key = options.get_queue_name().unwrap().clone();
            let endpoint = options.get_endpoint().unwrap().clone();

            channel
                .queue_unbind(
                    &queue_name,
                    &endpoint.get_response_exchange(),
                    &routing_key,
                    QueueUnbindOptions::default(),
                    FieldTable::new(),
                )
                .map(move |_| (channel, options))
        })
        // 8. Delete the response queue
        .and_then(move |(channel, options)| {
            let queue_delete_options = QueueDeleteOptions {
                if_unused: false,
                if_empty: false,
                ..Default::default()
            };
            let queue_name = options.get_queue_name().unwrap().clone();

            channel
                .queue_delete(&queue_name, queue_delete_options)
                .map(move |_| channel)
        })
        // 9. Close the channel
        .and_then(move |channel| {
            channel.close(200, "Close the channel.")
        })
        // 10. Returns the result to the caller as future
        .then(move |result| match result {
            Ok(_) => Ok(()),
            Err(err) => {
                error!("Error in RabbitMQ client. Reason: {}", err);
                let message = String::from("The request wasn't processed. Please, try once again.");
                Err(PathfinderError::MessageBrokerError(message))
            }
        })
    )
}
<commit_msg>Refactored  function<commit_after>/// This module provides default futures that can be used for
/// sending request to other microservices by proxy engine.
///

use std::collections::HashMap;
use std::str::from_utf8;
use std::sync::Arc;

use futures::future::{Future};
use futures::Stream;
use json::parse as json_parse;
use lapin_futures_rustls::lapin::channel::{
    BasicConsumeOptions, BasicProperties, BasicPublishOptions, QueueBindOptions,
    QueueDeclareOptions, QueueDeleteOptions, QueueUnbindOptions,
};
use lapin_futures_rustls::lapin::types::{AMQPValue, FieldTable};
use log::error;

use crate::error::PathfinderError;
use crate::rabbitmq::{RabbitMQContext};
use crate::engine::MessageSender;
use crate::engine::options::RpcOptions;
use crate::engine::serializer::Serializer;

/// Simple future that sends a RPC request to the certain microservice,
/// consumes from a response from a separate queue and then returns a
/// response to the caller via transmitter.
pub fn rpc_request_future(
    transmitter: MessageSender,
    rabbitmq_context: Arc<RabbitMQContext>,
    options: Arc<RpcOptions>,
    headers: HashMap<String, String>
) -> Box<Future<Item=(), Error=PathfinderError> + Send + Sync + 'static> {
    let rabbitmq_context_local = rabbitmq_context.clone();
    let publish_channel = rabbitmq_context_local.publish_channel.clone();
    let consume_channel = rabbitmq_context_local.consume_channel.clone();

    let queue_name = options.get_queue_name().unwrap().clone();
    let queue_declare_options = QueueDeclareOptions {
        passive: false,
        durable: true,
        exclusive: true,
        auto_delete: false,
        ..Default::default()
    };

    Box::new(
        // 1. Declare a response queue
        consume_channel
            .queue_declare(&queue_name, queue_declare_options, FieldTable::new())
            .map(move |queue| (publish_channel, consume_channel, queue, options))
        // 2. Link the response queue the exchange
        .and_then(move |(publish_channel, consume_channel, queue, options)| {
            let queue_name = options.get_queue_name().unwrap().clone();
            let endpoint = options.get_endpoint().unwrap().clone();
            let routing_key = options.get_queue_name().unwrap().clone();

            consume_channel
                .queue_bind(
                    &queue_name,
                    &endpoint.get_response_exchange(),
                    &routing_key,
                    QueueBindOptions::default(),
                    FieldTable::new()
                )
                .map(move |_| (publish_channel, consume_channel, queue, options))
        })
        // 3. Publish message into the microservice queue and make ensure that it's delivered
        .and_then(move |(publish_channel, consume_channel, queue, options)| {
            let publish_message_options = BasicPublishOptions {
                mandatory: true,
                immediate: false,
                ..Default::default()
            };

            let mut message_headers = FieldTable::new();
            for (key, value) in headers.clone().iter() {
                let header_name = key.clone();
                let header_value = AMQPValue::LongString(value.clone());
                message_headers.insert(header_name, header_value);
            }

            let endpoint = options.get_endpoint().unwrap().clone();
            let message = options.get_message().unwrap().clone();
            let queue_name_response = options.get_queue_name().unwrap().clone();
            let event_name = message["event-name"].as_str().unwrap_or("null");
            let basic_properties = BasicProperties::default()
                .with_content_type("application/json".to_string())    // Content type
                .with_headers(message_headers)                        // Headers for the message
                .with_delivery_mode(2)                                // Message must be persistent
                .with_reply_to(queue_name_response.to_string())       // Response queue
                .with_correlation_id(event_name.clone().to_string()); // Event name

            publish_channel
                .basic_publish(
                    &endpoint.get_request_exchange(),
                    &endpoint.get_routing_key(),
                    message["content"].dump().as_bytes().to_vec(),
                    publish_message_options,
                    basic_properties
                )
                .map(move |_confirmation| (publish_channel, consume_channel, queue, options))
        })
        // 4. Consume a response message from the queue, that was declared on the 1st step
        .and_then(move |(publish_channel, consume_channel, queue, options)| {
            consume_channel
                .basic_consume(
                    &queue,
                    "response_consumer",
                    BasicConsumeOptions::default(),
                    FieldTable::new()
                )
                .and_then(move |stream| {
                    stream
                        .take(1)
                        .into_future()
                        .map_err(|(err, _)| err)
                        .map(move |(message, _)| (publish_channel, consume_channel, queue, message.unwrap(), options))
                })
        })
        // 5. Prepare a response for a client, serialize and sent via WebSocket transmitter
        .and_then(move |(publish_channel, consume_channel, queue, message, options)| {
            let raw_data = from_utf8(&message.data).unwrap();
            let json = Arc::new(Box::new(json_parse(raw_data).unwrap()));
            let serializer = Serializer::new();
            let response = serializer.serialize(json.dump()).unwrap();
            let transmitter_local = transmitter.clone();
            transmitter_local.unbounded_send(response).unwrap_or(());

            consume_channel
                .basic_ack(message.delivery_tag, false)
                .map(move |_confirmation| (publish_channel, consume_channel, queue, options))
        })
        // 6. Unbind the response queue from the exchange point
        .and_then(move |(publish_channel, consume_channel, _queue, options)| {
            let queue_name = options.get_queue_name().unwrap().clone();
            let routing_key = options.get_queue_name().unwrap().clone();
            let endpoint = options.get_endpoint().unwrap().clone();

            consume_channel
                .queue_unbind(
                    &queue_name,
                    &endpoint.get_response_exchange(),
                    &routing_key,
                    QueueUnbindOptions::default(),
                    FieldTable::new(),
                )
                .map(move |_| (publish_channel, consume_channel, options))
        })
        // 7. Delete the response queue
        .and_then(move |(publish_channel, consume_channel, options)| {
            let queue_delete_options = QueueDeleteOptions {
                if_unused: false,
                if_empty: false,
                ..Default::default()
            };
            let queue_name = options.get_queue_name().unwrap().clone();

            consume_channel
                .queue_delete(&queue_name, queue_delete_options)
                .map(move |_| ())
        })
        // 8. Returns the result to the caller as future
        .then(move |result| match result {
            Ok(_) => Ok(()),
            Err(err) => {
                error!("Error in RabbitMQ client. Reason: {}", err);
                let message = String::from("The request wasn't processed. Please, try once again.");
                Err(PathfinderError::MessageBrokerError(message))
            }
        })
    )
}
<|endoftext|>


<commit_before>use std::env;
extern crate clingo;
use clingo::*;
extern crate libc;
use libc::c_void;
use std::ffi::CString;

extern "C" fn on_model(model: *mut clingo_model_t, data: *mut c_void, goon: *mut u8) -> u8 {

    // retrieve the symbols in the model
    let atoms = safe_clingo_model_symbols(model, clingo_show_type::clingo_show_type_shown)
        .expect("Failed to retrieve symbols in the model");

    println!("Model:");
    for atom in &atoms {
        // retrieve the symbol's string
        let atom_string = safe_clingo_symbol_to_string(atom).unwrap();
        println!(" {}", atom_string.to_str().unwrap());
    }
    return 1;
}

fn error_main() {
    let error_message = safe_clingo_error_message();
    println!("{}", error_message);
    safe_clingo_error_code();
}

fn main() {

    // create a control object and pass command line arguments
    let logger: clingo_logger_t = None;
    let logger_data: *mut c_void = std::ptr::null_mut();
    let control = safe_clingo_control_new(env::args(), logger, logger_data, 20)
        .expect("Failed creating clingo_control");

    // add a logic program to the base part
    let parameters: Vec<&str> = Vec::new();
    if !safe_clingo_control_add(control, "base", parameters, "a :- not b. b :- not a.") {
        return error_main();
    }
    println!("");

    // ground the base part
    let part = safe_clingo_part {
        params: 0,
        size: 0,
        name: CString::new("base").unwrap(),
    };
    let parts = vec![part];
    let ground_callback: clingo_ground_callback_t = None;
    let ground_callback_data: *mut c_void = std::ptr::null_mut();

    if !safe_clingo_control_ground(control, parts, ground_callback, ground_callback_data) {
        return error_main();
    }

    // solve using a model callback
    let mut sret = 0 as ::std::os::raw::c_uint;
    let solve_ret: *mut clingo_solve_result_bitset_t = &mut sret;
    let solve_callback: clingo_model_callback_t = Some(on_model);
    let solve_callback_data: *mut c_void = std::ptr::null_mut();
    let assumptions = vec![];

    if !safe_clingo_control_solve(control,
                                  solve_callback,
                                  solve_callback_data,
                                  assumptions,
                                  solve_ret) {
        return error_main();
    }

    //   safe_clingo_control_free(control);
}
<commit_msg>cleanup<commit_after>use std::env;
extern crate clingo;
use clingo::*;
extern crate libc;
use libc::c_void;
use std::ffi::CString;

extern "C" fn on_model(model: *mut clingo_model_t, data: *mut c_void, goon: *mut u8) -> u8 {

    // retrieve the symbols in the model
    let atoms = safe_clingo_model_symbols(model, clingo_show_type::clingo_show_type_shown)
        .expect("Failed to retrieve symbols in the model");

    println!("Model:");
    for atom in &atoms {
        // retrieve and print the symbol's string
        let atom_string = safe_clingo_symbol_to_string(atom).unwrap();
        println!(" {}", atom_string.to_str().unwrap());
    }
    return 1;
}

fn error_main() {
    let error_message = safe_clingo_error_message();
    println!("{}", error_message);
    safe_clingo_error_code();
}

fn main() {

    // create a control object and pass command line arguments
    let logger: clingo_logger_t = None;
    let logger_data: *mut c_void = std::ptr::null_mut();
    let ctl = safe_clingo_control_new(env::args(), logger, logger_data, 20)
        .expect("Failed creating clingo_control");

    // add a logic program to the base part
    let parameters: Vec<&str> = Vec::new();
    if !safe_clingo_control_add(ctl, "base", parameters, "a :- not b. b :- not a.") {
        return error_main();
    }
    println!("");

    // ground the base part
    let part = safe_clingo_part {
        params: 0,
        size: 0,
        name: CString::new("base").unwrap(),
    };
    let parts = vec![part];
    let ground_callback: clingo_ground_callback_t = None;
    let ground_callback_data: *mut c_void = std::ptr::null_mut();

    if !safe_clingo_control_ground(ctl, parts, ground_callback, ground_callback_data) {
        return error_main();
    }

    // solve using a model callback
    let mut sret = 0 as ::std::os::raw::c_uint;
    let solve_ret: *mut clingo_solve_result_bitset_t = &mut sret;
    let solve_callback: clingo_model_callback_t = Some(on_model);
    let solve_callback_data: *mut c_void = std::ptr::null_mut();
    let assumptions = vec![];

    if !safe_clingo_control_solve(ctl,
                                  solve_callback,
                                  solve_callback_data,
                                  assumptions,
                                  solve_ret) {
        return error_main();
    }

    //     safe_clingo_control_free(ctl);
}
<|endoftext|>


<commit_before>use llvm_sys::core::LLVMDisposeMessage;
use llvm_sys::execution_engine::{LLVMGetExecutionEngineTargetData, LLVMExecutionEngineRef, LLVMRunFunction, LLVMRunFunctionAsMain, LLVMDisposeExecutionEngine, LLVMGetFunctionAddress, LLVMAddModule, LLVMFindFunction, LLVMLinkInMCJIT, LLVMLinkInInterpreter, LLVMRemoveModule, LLVMGenericValueRef, LLVMFreeMachineCodeForFunction, LLVMAddGlobalMapping};

use module::Module;
use targets::TargetData;
use values::{AnyValue, AsValueRef, FunctionValue, GenericValue};

use std::rc::Rc;
use std::ops::Deref;
use std::ffi::{CStr, CString};
use std::mem::{forget, uninitialized, zeroed, transmute_copy, size_of};

#[derive(Debug, PartialEq, Eq)]
pub enum FunctionLookupError {
    JITNotEnabled,
    FunctionNotFound, // 404!
}

#[derive(PartialEq, Eq, Debug)]
pub struct ExecutionEngine {
    pub(crate) execution_engine: Rc<LLVMExecutionEngineRef>,
    target_data: Option<TargetData>,
    jit_mode: bool,
}

impl ExecutionEngine {
    pub(crate) fn new(execution_engine: Rc<LLVMExecutionEngineRef>, jit_mode: bool) -> ExecutionEngine {
        assert!(!execution_engine.is_null());

        // REVIEW: Will we have to do this for LLVMGetExecutionEngineTargetMachine too?
        let target_data = unsafe {
            LLVMGetExecutionEngineTargetData(*execution_engine)
        };

        ExecutionEngine {
            execution_engine: execution_engine,
            target_data: Some(TargetData::new(target_data)),
            jit_mode: jit_mode,
        }
    }

    pub fn link_in_mc_jit() {
        unsafe {
            LLVMLinkInMCJIT()
        }
    }

    pub fn link_in_interpreter() {
        unsafe {
            LLVMLinkInInterpreter();
        }
    }

    /// Maps the specified value to an address.
    ///
    /// # Example
    /// ```no_run
    /// use inkwell::targets::{InitializationConfig, Target};
    /// use inkwell::context::Context;
    /// use inkwell::OptimizationLevel;
    ///
    /// Target::initialize_native(&InitializationConfig::default()).unwrap();
    ///
    /// extern fn sumf(a: f64, b: f64) -> f64 {
    ///     a + b
    /// }
    ///
    /// let context = Context::create();
    /// let module = context.create_module("test");
    /// let builder = context.create_builder();
    ///
    /// let ft = context.f64_type();
    /// let fnt = ft.fn_type(&[], false);
    ///
    /// let f = module.add_function("test_fn", &fnt, None);
    /// let b = context.append_basic_block(&f, "entry");
    /// builder.position_at_end(&b);
    ///
    /// let extf = module.add_function("sumf", &ft.fn_type(&[ &ft, &ft ], false), None);
    ///
    /// let argf = ft.const_float(64.);
    /// let retv = builder.build_call(&extf, &[ &argf, &argf ], "retv", false).left().unwrap().into_float_value();
    ///
    /// builder.build_return(Some(&retv));
    ///
    /// let mut ee = module.create_jit_execution_engine(OptimizationLevel::None).unwrap();
    /// ee.add_global_mapping(&extf, sumf as usize);
    ///
    /// let result = unsafe { ee.run_function(&f, &[]) }.as_float(&ft);
    ///
    /// assert_eq!(result, 128.);
    /// ```
    pub fn add_global_mapping(&self, value: &AnyValue, addr: usize) {
        unsafe {
            LLVMAddGlobalMapping(*self.execution_engine, value.as_value_ref(), addr as *mut _)
        }
    }

    /// Adds a module to an `ExecutionEngine`.
    ///
    /// The method will be `Ok(())` if the module does not belong to an `ExecutionEngine` already and `Err(())` otherwise.
    ///
    /// ```rust,no_run
    /// use inkwell::targets::{InitializationConfig, Target};
    /// use inkwell::context::Context;
    /// use inkwell::OptimizationLevel;
    ///
    /// Target::initialize_native(&InitializationConfig::default()).unwrap();
    ///
    /// let context = Context::create();
    /// let module = context.create_module("test");
    /// let mut ee = module.create_jit_execution_engine(OptimizationLevel::None).unwrap();
    ///
    /// assert!(ee.add_module(&module).is_err());
    /// ```
    pub fn add_module(&self, module: &Module) -> Result<(), ()> {
        unsafe {
            LLVMAddModule(*self.execution_engine, module.module.get())
        }

        if module.owned_by_ee.borrow().is_some() {
            return Err(());
        }

        *module.owned_by_ee.borrow_mut() = Some(ExecutionEngine::new(self.execution_engine.clone(), self.jit_mode));

        Ok(())
    }

    pub fn remove_module(&self, module: &Module) -> Result<(), String> {
        match *module.owned_by_ee.borrow() {
            Some(ref ee) if *ee.execution_engine != *self.execution_engine => return Err("Module is not owned by this Execution Engine".into()),
            None => return Err("Module is not owned by an Execution Engine".into()),
            _ => ()
        }

        let mut new_module = unsafe { uninitialized() };
        let mut err_str = unsafe { zeroed() };

        let code = unsafe {
            LLVMRemoveModule(*self.execution_engine, module.module.get(), &mut new_module, &mut err_str)
        };

        if code == 1 {
            let rust_str = unsafe {
                let rust_str = CStr::from_ptr(err_str).to_string_lossy().into_owned();

                LLVMDisposeMessage(err_str);

                rust_str
            };

            return Err(rust_str);
        }

        module.module.set(new_module);
        *module.owned_by_ee.borrow_mut() = None;

        Ok(())
    }

    /// Try to load a function from the execution engine.
    ///
    /// If a target hasn't already been initialized, spurious "function not
    /// found" errors may be encountered.
    ///
    /// # Safety
    ///
    /// It is the caller's responsibility to ensure they call the function with
    /// the correct signature and calling convention.
    ///
    /// The `Symbol` wrapper ensures a function won't accidentally outlive the
    /// execution engine it came from, but adding functions after calling this
    /// method *may* invalidate the function pointer.
    pub unsafe fn get_function<F>(&self, fn_name: &str) -> Result<Symbol<F>, FunctionLookupError> {
        if !self.jit_mode {
            return Err(FunctionLookupError::JITNotEnabled);
        }

        let c_string = CString::new(fn_name).expect("Conversion to CString failed unexpectedly");

        let address = LLVMGetFunctionAddress(*self.execution_engine, c_string.as_ptr());

        // REVIEW: Can also return 0 if no targets are initialized.
        // One option might be to set a global to true if any at all of the targets have been
        // initialized (maybe we could figure out which config in particular is the trigger)
        // and if not return an "NoTargetsInitialized" error, instead of not found.
        if address == 0 {
            return Err(FunctionLookupError::FunctionNotFound);
        }

        assert_eq!(size_of::<F>(), size_of::<usize>(),
            "The type `F` must have the same size as a function pointer");

        Ok(Symbol {
            execution_engine: self.execution_engine.clone(),
            inner: transmute_copy(&address),
        })
    }

    // REVIEW: Not sure if an EE's target data can change.. if so we might want to update the value
    // when making this call
    pub fn get_target_data(&self) -> &TargetData {
        self.target_data.as_ref().expect("TargetData should always exist until Drop")
    }

    // REVIEW: Can also find nothing if no targeting is initialized. Maybe best to
    // do have a global flag for anything initialized. Catch is that it must be initialized
    // before EE is created
    pub fn get_function_value(&self, fn_name: &str) -> Result<FunctionValue, FunctionLookupError> {
        if !self.jit_mode {
            return Err(FunctionLookupError::JITNotEnabled);
        }

        let c_string = CString::new(fn_name).expect("Conversion to CString failed unexpectedly");
        let mut function = unsafe { zeroed() };

        let code = unsafe {
            LLVMFindFunction(*self.execution_engine, c_string.as_ptr(), &mut function)
        };

        if code == 0 {
            return FunctionValue::new(function).ok_or(FunctionLookupError::FunctionNotFound)
        };

        Err(FunctionLookupError::FunctionNotFound)
    }

    // TODOC: Marked as unsafe because input function could very well do something unsafe. It's up to the caller
    // to ensure that doesn't happen by defining their function correctly.
    pub unsafe fn run_function(&self, function: &FunctionValue, args: &[&GenericValue]) -> GenericValue {
        let mut args: Vec<LLVMGenericValueRef> = args.iter()
                                                     .map(|val| val.generic_value)
                                                     .collect();

        let value = LLVMRunFunction(*self.execution_engine, function.as_value_ref(), args.len() as u32, args.as_mut_ptr()); // REVIEW: usize to u32 ok??

        GenericValue::new(value)
    }

    pub fn run_function_as_main(&self, function: &FunctionValue) {
        let args = vec![]; // TODO: Support argc, argv
        let env_p = vec![]; // REVIEW: No clue what this is

        unsafe {
            LLVMRunFunctionAsMain(*self.execution_engine, function.as_value_ref(), args.len() as u32, args.as_ptr(), env_p.as_ptr()); // REVIEW: usize to u32 cast ok??
        }
    }

    pub fn free_fn_machine_code(&self, function: &FunctionValue) {
        unsafe {
            LLVMFreeMachineCodeForFunction(*self.execution_engine, function.as_value_ref())
        }
    }
}

/// A wrapper around a function pointer which ensures the symbol being pointed
/// to doesn't accidentally outlive its execution engine.
#[derive(Debug, Clone)]
pub struct Symbol<F> {
    pub(crate) execution_engine: Rc<LLVMExecutionEngineRef>,
    inner: F,
}

impl<F> Deref for Symbol<F> {
    type Target = F;

    fn deref(&self) -> &Self::Target {
        &self.inner
    }
}

// Modules owned by the EE will be discarded by the EE so we don't
// want owned modules to drop.
impl Drop for ExecutionEngine {
    fn drop(&mut self) {
        forget(self.target_data.take().expect("TargetData should always exist until Drop"));

        if Rc::strong_count(&self.execution_engine) == 1 {
            unsafe {
                LLVMDisposeExecutionEngine(*self.execution_engine);
            }
        }
    }
}
<commit_msg>Added docs to the get_function method<commit_after>use llvm_sys::core::LLVMDisposeMessage;
use llvm_sys::execution_engine::{LLVMGetExecutionEngineTargetData, LLVMExecutionEngineRef, LLVMRunFunction, LLVMRunFunctionAsMain, LLVMDisposeExecutionEngine, LLVMGetFunctionAddress, LLVMAddModule, LLVMFindFunction, LLVMLinkInMCJIT, LLVMLinkInInterpreter, LLVMRemoveModule, LLVMGenericValueRef, LLVMFreeMachineCodeForFunction, LLVMAddGlobalMapping};

use module::Module;
use targets::TargetData;
use values::{AnyValue, AsValueRef, FunctionValue, GenericValue};

use std::rc::Rc;
use std::ops::Deref;
use std::ffi::{CStr, CString};
use std::mem::{forget, uninitialized, zeroed, transmute_copy, size_of};

#[derive(Debug, PartialEq, Eq)]
pub enum FunctionLookupError {
    JITNotEnabled,
    FunctionNotFound, // 404!
}

#[derive(PartialEq, Eq, Debug)]
pub struct ExecutionEngine {
    pub(crate) execution_engine: Rc<LLVMExecutionEngineRef>,
    target_data: Option<TargetData>,
    jit_mode: bool,
}

impl ExecutionEngine {
    pub(crate) fn new(execution_engine: Rc<LLVMExecutionEngineRef>, jit_mode: bool) -> ExecutionEngine {
        assert!(!execution_engine.is_null());

        // REVIEW: Will we have to do this for LLVMGetExecutionEngineTargetMachine too?
        let target_data = unsafe {
            LLVMGetExecutionEngineTargetData(*execution_engine)
        };

        ExecutionEngine {
            execution_engine: execution_engine,
            target_data: Some(TargetData::new(target_data)),
            jit_mode: jit_mode,
        }
    }

    pub fn link_in_mc_jit() {
        unsafe {
            LLVMLinkInMCJIT()
        }
    }

    pub fn link_in_interpreter() {
        unsafe {
            LLVMLinkInInterpreter();
        }
    }

    /// Maps the specified value to an address.
    ///
    /// # Example
    /// ```no_run
    /// use inkwell::targets::{InitializationConfig, Target};
    /// use inkwell::context::Context;
    /// use inkwell::OptimizationLevel;
    ///
    /// Target::initialize_native(&InitializationConfig::default()).unwrap();
    ///
    /// extern fn sumf(a: f64, b: f64) -> f64 {
    ///     a + b
    /// }
    ///
    /// let context = Context::create();
    /// let module = context.create_module("test");
    /// let builder = context.create_builder();
    ///
    /// let ft = context.f64_type();
    /// let fnt = ft.fn_type(&[], false);
    ///
    /// let f = module.add_function("test_fn", &fnt, None);
    /// let b = context.append_basic_block(&f, "entry");
    /// builder.position_at_end(&b);
    ///
    /// let extf = module.add_function("sumf", &ft.fn_type(&[ &ft, &ft ], false), None);
    ///
    /// let argf = ft.const_float(64.);
    /// let retv = builder.build_call(&extf, &[ &argf, &argf ], "retv", false).left().unwrap().into_float_value();
    ///
    /// builder.build_return(Some(&retv));
    ///
    /// let mut ee = module.create_jit_execution_engine(OptimizationLevel::None).unwrap();
    /// ee.add_global_mapping(&extf, sumf as usize);
    ///
    /// let result = unsafe { ee.run_function(&f, &[]) }.as_float(&ft);
    ///
    /// assert_eq!(result, 128.);
    /// ```
    pub fn add_global_mapping(&self, value: &AnyValue, addr: usize) {
        unsafe {
            LLVMAddGlobalMapping(*self.execution_engine, value.as_value_ref(), addr as *mut _)
        }
    }

    /// Adds a module to an `ExecutionEngine`.
    ///
    /// The method will be `Ok(())` if the module does not belong to an `ExecutionEngine` already and `Err(())` otherwise.
    ///
    /// ```rust,no_run
    /// use inkwell::targets::{InitializationConfig, Target};
    /// use inkwell::context::Context;
    /// use inkwell::OptimizationLevel;
    ///
    /// Target::initialize_native(&InitializationConfig::default()).unwrap();
    ///
    /// let context = Context::create();
    /// let module = context.create_module("test");
    /// let mut ee = module.create_jit_execution_engine(OptimizationLevel::None).unwrap();
    ///
    /// assert!(ee.add_module(&module).is_err());
    /// ```
    pub fn add_module(&self, module: &Module) -> Result<(), ()> {
        unsafe {
            LLVMAddModule(*self.execution_engine, module.module.get())
        }

        if module.owned_by_ee.borrow().is_some() {
            return Err(());
        }

        *module.owned_by_ee.borrow_mut() = Some(ExecutionEngine::new(self.execution_engine.clone(), self.jit_mode));

        Ok(())
    }

    pub fn remove_module(&self, module: &Module) -> Result<(), String> {
        match *module.owned_by_ee.borrow() {
            Some(ref ee) if *ee.execution_engine != *self.execution_engine => return Err("Module is not owned by this Execution Engine".into()),
            None => return Err("Module is not owned by an Execution Engine".into()),
            _ => ()
        }

        let mut new_module = unsafe { uninitialized() };
        let mut err_str = unsafe { zeroed() };

        let code = unsafe {
            LLVMRemoveModule(*self.execution_engine, module.module.get(), &mut new_module, &mut err_str)
        };

        if code == 1 {
            let rust_str = unsafe {
                let rust_str = CStr::from_ptr(err_str).to_string_lossy().into_owned();

                LLVMDisposeMessage(err_str);

                rust_str
            };

            return Err(rust_str);
        }

        module.module.set(new_module);
        *module.owned_by_ee.borrow_mut() = None;

        Ok(())
    }

    /// Try to load a function from the execution engine.
    ///
    /// If a target hasn't already been initialized, spurious "function not
    /// found" errors may be encountered.
    ///
    /// # Examples
    ///
    ///
    /// ```rust
    /// # use inkwell::targets::{InitializationConfig, Target};
    /// # use inkwell::context::Context;
    /// # use inkwell::OptimizationLevel;
    /// # Target::initialize_native(&InitializationConfig::default()).unwrap();
    /// let context = Context::create();
    /// let module = context.create_module("test");
    /// let builder = context.create_builder();
    ///
    /// // Set up the function signature
    /// let double = context.f64_type();
    /// let sig = double.fn_type(&[], false);
    ///
    /// // Add the function to our module
    /// let f = module.add_function("test_fn", &sig, None);
    /// let b = context.append_basic_block(&f, "entry");
    /// builder.position_at_end(&b);
    ///
    /// // Insert a return statement
    /// let ret = double.const_float(64.0);
    /// builder.build_return(Some(&ret));
    ///
    /// // create the JIT engine
    /// let mut ee = module.create_jit_execution_engine(OptimizationLevel::None).unwrap();
    ///
    /// // fetch our JIT'd function and execute it
    /// unsafe {
    ///     let test_fn = ee.get_function::<fn() -> f64>("test_fn").unwrap();
    ///     let return_value = test_fn();
    ///     assert_eq!(return_value, 64.0);
    /// }
    /// ```
    ///
    ///
    /// # Safety
    ///
    /// It is the caller's responsibility to ensure they call the function with
    /// the correct signature and calling convention.
    ///
    /// The `Symbol` wrapper ensures a function won't accidentally outlive the
    /// execution engine it came from, but adding functions after calling this
    /// method *may* invalidate the function pointer.
    pub unsafe fn get_function<F>(&self, fn_name: &str) -> Result<Symbol<F>, FunctionLookupError> {
        if !self.jit_mode {
            return Err(FunctionLookupError::JITNotEnabled);
        }

        let c_string = CString::new(fn_name).expect("Conversion to CString failed unexpectedly");

        let address = LLVMGetFunctionAddress(*self.execution_engine, c_string.as_ptr());

        // REVIEW: Can also return 0 if no targets are initialized.
        // One option might be to set a global to true if any at all of the targets have been
        // initialized (maybe we could figure out which config in particular is the trigger)
        // and if not return an "NoTargetsInitialized" error, instead of not found.
        if address == 0 {
            return Err(FunctionLookupError::FunctionNotFound);
        }

        assert_eq!(size_of::<F>(), size_of::<usize>(),
            "The type `F` must have the same size as a function pointer");

        Ok(Symbol {
            execution_engine: self.execution_engine.clone(),
            inner: transmute_copy(&address),
        })
    }

    // REVIEW: Not sure if an EE's target data can change.. if so we might want to update the value
    // when making this call
    pub fn get_target_data(&self) -> &TargetData {
        self.target_data.as_ref().expect("TargetData should always exist until Drop")
    }

    // REVIEW: Can also find nothing if no targeting is initialized. Maybe best to
    // do have a global flag for anything initialized. Catch is that it must be initialized
    // before EE is created
    pub fn get_function_value(&self, fn_name: &str) -> Result<FunctionValue, FunctionLookupError> {
        if !self.jit_mode {
            return Err(FunctionLookupError::JITNotEnabled);
        }

        let c_string = CString::new(fn_name).expect("Conversion to CString failed unexpectedly");
        let mut function = unsafe { zeroed() };

        let code = unsafe {
            LLVMFindFunction(*self.execution_engine, c_string.as_ptr(), &mut function)
        };

        if code == 0 {
            return FunctionValue::new(function).ok_or(FunctionLookupError::FunctionNotFound)
        };

        Err(FunctionLookupError::FunctionNotFound)
    }

    // TODOC: Marked as unsafe because input function could very well do something unsafe. It's up to the caller
    // to ensure that doesn't happen by defining their function correctly.
    pub unsafe fn run_function(&self, function: &FunctionValue, args: &[&GenericValue]) -> GenericValue {
        let mut args: Vec<LLVMGenericValueRef> = args.iter()
                                                     .map(|val| val.generic_value)
                                                     .collect();

        let value = LLVMRunFunction(*self.execution_engine, function.as_value_ref(), args.len() as u32, args.as_mut_ptr()); // REVIEW: usize to u32 ok??

        GenericValue::new(value)
    }

    pub fn run_function_as_main(&self, function: &FunctionValue) {
        let args = vec![]; // TODO: Support argc, argv
        let env_p = vec![]; // REVIEW: No clue what this is

        unsafe {
            LLVMRunFunctionAsMain(*self.execution_engine, function.as_value_ref(), args.len() as u32, args.as_ptr(), env_p.as_ptr()); // REVIEW: usize to u32 cast ok??
        }
    }

    pub fn free_fn_machine_code(&self, function: &FunctionValue) {
        unsafe {
            LLVMFreeMachineCodeForFunction(*self.execution_engine, function.as_value_ref())
        }
    }
}

/// A wrapper around a function pointer which ensures the symbol being pointed
/// to doesn't accidentally outlive its execution engine.
#[derive(Debug, Clone)]
pub struct Symbol<F> {
    pub(crate) execution_engine: Rc<LLVMExecutionEngineRef>,
    inner: F,
}

impl<F> Deref for Symbol<F> {
    type Target = F;

    fn deref(&self) -> &Self::Target {
        &self.inner
    }
}

// Modules owned by the EE will be discarded by the EE so we don't
// want owned modules to drop.
impl Drop for ExecutionEngine {
    fn drop(&mut self) {
        forget(self.target_data.take().expect("TargetData should always exist until Drop"));

        if Rc::strong_count(&self.execution_engine) == 1 {
            unsafe {
                LLVMDisposeExecutionEngine(*self.execution_engine);
            }
        }
    }
}
<|endoftext|>


<commit_before>use crate::convert::From;
use crate::fmt;
use crate::marker::{PhantomData, Unsize};
use crate::mem;
use crate::ops::{CoerceUnsized, DispatchFromDyn};

// ignore-tidy-undocumented-unsafe

/// A wrapper around a raw non-null `*mut T` that indicates that the possessor
/// of this wrapper owns the referent. Useful for building abstractions like
/// `Box<T>`, `Vec<T>`, `String`, and `HashMap<K, V>`.
///
/// Unlike `*mut T`, `Unique<T>` behaves "as if" it were an instance of `T`.
/// It implements `Send`/`Sync` if `T` is `Send`/`Sync`. It also implies
/// the kind of strong aliasing guarantees an instance of `T` can expect:
/// the referent of the pointer should not be modified without a unique path to
/// its owning Unique.
///
/// If you're uncertain of whether it's correct to use `Unique` for your purposes,
/// consider using `NonNull`, which has weaker semantics.
///
/// Unlike `*mut T`, the pointer must always be non-null, even if the pointer
/// is never dereferenced. This is so that enums may use this forbidden value
/// as a discriminant -- `Option<Unique<T>>` has the same size as `Unique<T>`.
/// However the pointer may still dangle if it isn't dereferenced.
///
/// Unlike `*mut T`, `Unique<T>` is covariant over `T`. This should always be correct
/// for any type which upholds Unique's aliasing requirements.
#[unstable(
    feature = "ptr_internals",
    issue = "none",
    reason = "use `NonNull` instead and consider `PhantomData<T>` \
              (if you also use `#[may_dangle]`), `Send`, and/or `Sync`"
)]
#[doc(hidden)]
#[repr(transparent)]
#[rustc_layout_scalar_valid_range_start(1)]
pub struct Unique<T: ?Sized> {
    pointer: *const T,
    // NOTE: this marker has no consequences for variance, but is necessary
    // for dropck to understand that we logically own a `T`.
    //
    // For details, see:
    // https://github.com/rust-lang/rfcs/blob/master/text/0769-sound-generic-drop.md#phantom-data
    _marker: PhantomData<T>,
}

/// `Unique` pointers are `Send` if `T` is `Send` because the data they
/// reference is unaliased. Note that this aliasing invariant is
/// unenforced by the type system; the abstraction using the
/// `Unique` must enforce it.
#[unstable(feature = "ptr_internals", issue = "none")]
unsafe impl<T: Send + ?Sized> Send for Unique<T> {}

/// `Unique` pointers are `Sync` if `T` is `Sync` because the data they
/// reference is unaliased. Note that this aliasing invariant is
/// unenforced by the type system; the abstraction using the
/// `Unique` must enforce it.
#[unstable(feature = "ptr_internals", issue = "none")]
unsafe impl<T: Sync + ?Sized> Sync for Unique<T> {}

#[unstable(feature = "ptr_internals", issue = "none")]
impl<T: Sized> Unique<T> {
    /// Creates a new `Unique` that is dangling, but well-aligned.
    ///
    /// This is useful for initializing types which lazily allocate, like
    /// `Vec::new` does.
    ///
    /// Note that the pointer value may potentially represent a valid pointer to
    /// a `T`, which means this must not be used as a "not yet initialized"
    /// sentinel value. Types that lazily allocate must track initialization by
    /// some other means.
    #[inline]
    pub const fn dangling() -> Self {
        // SAFETY: mem::align_of() returns a valid, non-null pointer. The
        // conditions to call new_unchecked() are thus respected.
        unsafe { Unique::new_unchecked(mem::align_of::<T>() as *mut T) }
    }
}

#[unstable(feature = "ptr_internals", issue = "none")]
impl<T: ?Sized> Unique<T> {
    /// Creates a new `Unique`.
    ///
    /// # Safety
    ///
    /// `ptr` must be non-null.
    #[inline]
    pub const unsafe fn new_unchecked(ptr: *mut T) -> Self {
        // SAFETY: the caller must guarantee that `ptr` is non-null.
        unsafe { Unique { pointer: ptr as _, _marker: PhantomData } }
    }

    /// Creates a new `Unique` if `ptr` is non-null.
    #[inline]
    pub fn new(ptr: *mut T) -> Option<Self> {
        if !ptr.is_null() {
            // SAFETY: The pointer has already been checked and is not null.
            Some(unsafe { Unique { pointer: ptr as _, _marker: PhantomData } })
        } else {
            None
        }
    }

    /// Acquires the underlying `*mut` pointer.
    #[inline]
    pub const fn as_ptr(self) -> *mut T {
        self.pointer as *mut T
    }

    /// Dereferences the content.
    ///
    /// The resulting lifetime is bound to self so this behaves "as if"
    /// it were actually an instance of T that is getting borrowed. If a longer
    /// (unbound) lifetime is needed, use `&*my_ptr.as_ptr()`.
    #[inline]
    pub unsafe fn as_ref(&self) -> &T {
        // SAFETY: the caller must guarantee that `self` meets all the
        // requirements for a reference.
        unsafe { &*self.as_ptr() }
    }

    /// Mutably dereferences the content.
    ///
    /// The resulting lifetime is bound to self so this behaves "as if"
    /// it were actually an instance of T that is getting borrowed. If a longer
    /// (unbound) lifetime is needed, use `&mut *my_ptr.as_ptr()`.
    #[inline]
    pub unsafe fn as_mut(&mut self) -> &mut T {
        // SAFETY: the caller must guarantee that `self` meets all the
        // requirements for a mutable reference.
        unsafe { &mut *self.as_ptr() }
    }

    /// Casts to a pointer of another type.
    #[inline]
    pub const fn cast<U>(self) -> Unique<U> {
        // SAFETY: Unique::new_unchecked() creates a new unique and needs
        // the given pointer to not be null.
        // Since we are passing self as a pointer, it cannot be null.
        unsafe { Unique::new_unchecked(self.as_ptr() as *mut U) }
    }
}

#[unstable(feature = "ptr_internals", issue = "none")]
impl<T: ?Sized> Clone for Unique<T> {
    #[inline]
    fn clone(&self) -> Self {
        *self
    }
}

#[unstable(feature = "ptr_internals", issue = "none")]
impl<T: ?Sized> Copy for Unique<T> {}

#[unstable(feature = "ptr_internals", issue = "none")]
impl<T: ?Sized, U: ?Sized> CoerceUnsized<Unique<U>> for Unique<T> where T: Unsize<U> {}

#[unstable(feature = "ptr_internals", issue = "none")]
impl<T: ?Sized, U: ?Sized> DispatchFromDyn<Unique<U>> for Unique<T> where T: Unsize<U> {}

#[unstable(feature = "ptr_internals", issue = "none")]
impl<T: ?Sized> fmt::Debug for Unique<T> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        fmt::Pointer::fmt(&self.as_ptr(), f)
    }
}

#[unstable(feature = "ptr_internals", issue = "none")]
impl<T: ?Sized> fmt::Pointer for Unique<T> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        fmt::Pointer::fmt(&self.as_ptr(), f)
    }
}

#[unstable(feature = "ptr_internals", issue = "none")]
impl<T: ?Sized> From<&mut T> for Unique<T> {
    #[inline]
    fn from(reference: &mut T) -> Self {
        // SAFETY: A mutable reference cannot be null
        unsafe { Unique { pointer: reference as *mut T, _marker: PhantomData } }
    }
}
<commit_msg>Remove a stray ignore-tidy-undocumented-unsafe There were no undocumented unsafe blocks in the file.<commit_after>use crate::convert::From;
use crate::fmt;
use crate::marker::{PhantomData, Unsize};
use crate::mem;
use crate::ops::{CoerceUnsized, DispatchFromDyn};

/// A wrapper around a raw non-null `*mut T` that indicates that the possessor
/// of this wrapper owns the referent. Useful for building abstractions like
/// `Box<T>`, `Vec<T>`, `String`, and `HashMap<K, V>`.
///
/// Unlike `*mut T`, `Unique<T>` behaves "as if" it were an instance of `T`.
/// It implements `Send`/`Sync` if `T` is `Send`/`Sync`. It also implies
/// the kind of strong aliasing guarantees an instance of `T` can expect:
/// the referent of the pointer should not be modified without a unique path to
/// its owning Unique.
///
/// If you're uncertain of whether it's correct to use `Unique` for your purposes,
/// consider using `NonNull`, which has weaker semantics.
///
/// Unlike `*mut T`, the pointer must always be non-null, even if the pointer
/// is never dereferenced. This is so that enums may use this forbidden value
/// as a discriminant -- `Option<Unique<T>>` has the same size as `Unique<T>`.
/// However the pointer may still dangle if it isn't dereferenced.
///
/// Unlike `*mut T`, `Unique<T>` is covariant over `T`. This should always be correct
/// for any type which upholds Unique's aliasing requirements.
#[unstable(
    feature = "ptr_internals",
    issue = "none",
    reason = "use `NonNull` instead and consider `PhantomData<T>` \
              (if you also use `#[may_dangle]`), `Send`, and/or `Sync`"
)]
#[doc(hidden)]
#[repr(transparent)]
#[rustc_layout_scalar_valid_range_start(1)]
pub struct Unique<T: ?Sized> {
    pointer: *const T,
    // NOTE: this marker has no consequences for variance, but is necessary
    // for dropck to understand that we logically own a `T`.
    //
    // For details, see:
    // https://github.com/rust-lang/rfcs/blob/master/text/0769-sound-generic-drop.md#phantom-data
    _marker: PhantomData<T>,
}

/// `Unique` pointers are `Send` if `T` is `Send` because the data they
/// reference is unaliased. Note that this aliasing invariant is
/// unenforced by the type system; the abstraction using the
/// `Unique` must enforce it.
#[unstable(feature = "ptr_internals", issue = "none")]
unsafe impl<T: Send + ?Sized> Send for Unique<T> {}

/// `Unique` pointers are `Sync` if `T` is `Sync` because the data they
/// reference is unaliased. Note that this aliasing invariant is
/// unenforced by the type system; the abstraction using the
/// `Unique` must enforce it.
#[unstable(feature = "ptr_internals", issue = "none")]
unsafe impl<T: Sync + ?Sized> Sync for Unique<T> {}

#[unstable(feature = "ptr_internals", issue = "none")]
impl<T: Sized> Unique<T> {
    /// Creates a new `Unique` that is dangling, but well-aligned.
    ///
    /// This is useful for initializing types which lazily allocate, like
    /// `Vec::new` does.
    ///
    /// Note that the pointer value may potentially represent a valid pointer to
    /// a `T`, which means this must not be used as a "not yet initialized"
    /// sentinel value. Types that lazily allocate must track initialization by
    /// some other means.
    #[inline]
    pub const fn dangling() -> Self {
        // SAFETY: mem::align_of() returns a valid, non-null pointer. The
        // conditions to call new_unchecked() are thus respected.
        unsafe { Unique::new_unchecked(mem::align_of::<T>() as *mut T) }
    }
}

#[unstable(feature = "ptr_internals", issue = "none")]
impl<T: ?Sized> Unique<T> {
    /// Creates a new `Unique`.
    ///
    /// # Safety
    ///
    /// `ptr` must be non-null.
    #[inline]
    pub const unsafe fn new_unchecked(ptr: *mut T) -> Self {
        // SAFETY: the caller must guarantee that `ptr` is non-null.
        unsafe { Unique { pointer: ptr as _, _marker: PhantomData } }
    }

    /// Creates a new `Unique` if `ptr` is non-null.
    #[inline]
    pub fn new(ptr: *mut T) -> Option<Self> {
        if !ptr.is_null() {
            // SAFETY: The pointer has already been checked and is not null.
            Some(unsafe { Unique { pointer: ptr as _, _marker: PhantomData } })
        } else {
            None
        }
    }

    /// Acquires the underlying `*mut` pointer.
    #[inline]
    pub const fn as_ptr(self) -> *mut T {
        self.pointer as *mut T
    }

    /// Dereferences the content.
    ///
    /// The resulting lifetime is bound to self so this behaves "as if"
    /// it were actually an instance of T that is getting borrowed. If a longer
    /// (unbound) lifetime is needed, use `&*my_ptr.as_ptr()`.
    #[inline]
    pub unsafe fn as_ref(&self) -> &T {
        // SAFETY: the caller must guarantee that `self` meets all the
        // requirements for a reference.
        unsafe { &*self.as_ptr() }
    }

    /// Mutably dereferences the content.
    ///
    /// The resulting lifetime is bound to self so this behaves "as if"
    /// it were actually an instance of T that is getting borrowed. If a longer
    /// (unbound) lifetime is needed, use `&mut *my_ptr.as_ptr()`.
    #[inline]
    pub unsafe fn as_mut(&mut self) -> &mut T {
        // SAFETY: the caller must guarantee that `self` meets all the
        // requirements for a mutable reference.
        unsafe { &mut *self.as_ptr() }
    }

    /// Casts to a pointer of another type.
    #[inline]
    pub const fn cast<U>(self) -> Unique<U> {
        // SAFETY: Unique::new_unchecked() creates a new unique and needs
        // the given pointer to not be null.
        // Since we are passing self as a pointer, it cannot be null.
        unsafe { Unique::new_unchecked(self.as_ptr() as *mut U) }
    }
}

#[unstable(feature = "ptr_internals", issue = "none")]
impl<T: ?Sized> Clone for Unique<T> {
    #[inline]
    fn clone(&self) -> Self {
        *self
    }
}

#[unstable(feature = "ptr_internals", issue = "none")]
impl<T: ?Sized> Copy for Unique<T> {}

#[unstable(feature = "ptr_internals", issue = "none")]
impl<T: ?Sized, U: ?Sized> CoerceUnsized<Unique<U>> for Unique<T> where T: Unsize<U> {}

#[unstable(feature = "ptr_internals", issue = "none")]
impl<T: ?Sized, U: ?Sized> DispatchFromDyn<Unique<U>> for Unique<T> where T: Unsize<U> {}

#[unstable(feature = "ptr_internals", issue = "none")]
impl<T: ?Sized> fmt::Debug for Unique<T> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        fmt::Pointer::fmt(&self.as_ptr(), f)
    }
}

#[unstable(feature = "ptr_internals", issue = "none")]
impl<T: ?Sized> fmt::Pointer for Unique<T> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        fmt::Pointer::fmt(&self.as_ptr(), f)
    }
}

#[unstable(feature = "ptr_internals", issue = "none")]
impl<T: ?Sized> From<&mut T> for Unique<T> {
    #[inline]
    fn from(reference: &mut T) -> Self {
        // SAFETY: A mutable reference cannot be null
        unsafe { Unique { pointer: reference as *mut T, _marker: PhantomData } }
    }
}
<|endoftext|>


<commit_before>use std::io;
use tokio_io::codec::{Decoder, Encoder};

use bytes::BytesMut;
use cmd::Command;
use error::Error;
use ftp::Answer;

pub struct FtpCodec;

fn find_crlf(buf: &mut BytesMut) -> Option<usize> {
    buf.windows(2).position(|bytes| bytes == b"\r\n")
}

impl Decoder for FtpCodec {
    type Item = Command;
    type Error = io::Error;

    fn decode(&mut self, buf:  &mut BytesMut) -> io::Result<Option<Command>> {
            if let Some(index) = find_crlf(buf) {
                let line = buf.split_to(index);
                buf.split_to(2);
                Command::new(line.to_vec()).map(|command| Some(command)).map_err(Error::to_io_error)
            } else {
                Ok(None)
            }
    }
}

impl Encoder for FtpCodec {
    type Item = Answer;
    type Error = io::Error;

    fn encode(&mut self, answer: Answer, buf: &mut BytesMut) -> io::Result<()> {
        let answer =
            if answer.message.is_empty() {
                format!("{}\r\n", answer.code as u32);
            } else  {
                format!("{} {}\r\n", answer.code as u32, answer.message);
            };
        buf.extend(answer.as_bytes());
        Ok(())
    }
}

<commit_msg>Fixed error to compile<commit_after>use std::io;
use tokio_io::codec::{Decoder, Encoder};

use bytes::BytesMut;
use cmd::Command;
use error::Error;
use ftp::Answer;

pub struct FtpCodec;

fn find_crlf(buf: &mut BytesMut) -> Option<usize> {
    buf.windows(2).position(|bytes| bytes == b"\r\n")
}

impl Decoder for FtpCodec {
    type Item = Command;
    type Error = io::Error;

    fn decode(&mut self, buf:  &mut BytesMut) -> io::Result<Option<Command>> {
            if let Some(index) = find_crlf(buf) {
                let line = buf.split_to(index);
                buf.split_to(2);
                Command::new(line.to_vec()).map(|command| Some(command)).map_err(Error::to_io_error)
            } else {
                Ok(None)
            }
    }
}

impl Encoder for FtpCodec {
    type Item = Answer;
    type Error = io::Error;

    fn encode(&mut self, answer: Answer, buf: &mut BytesMut) -> io::Result<()> {
            if answer.message.is_empty() {
                format!("{}\r\n", answer.code as u32);
            } else  {
                format!("{} {}\r\n", answer.code as u32, answer.message);
            };
        buf.extend(answer.message.as_bytes());
        Ok(())
    }
}

<|endoftext|>


<commit_before>/// A trait for calculating hamming distance
pub trait HammingDistancable<RHS = Self> {
    /// The output type of the hamming distance
    type Output;
    fn hamming_distance(self, other: RHS) -> Self::Output;
}

impl<'a, 'b, T> HammingDistancable<&'b Vec<T>> for &'a Vec<T>
    where T : Eq {
    type Output = Result<u32, &'static str>;
    /// Calculate the hamming distance between vectors
    fn hamming_distance(self, other: &'b Vec<T>) -> Result<u32, &'static str> {
        if self.len() != other.len() {
            return Err("Vectors do not have equal length");
        }

        let mut distance = 0;
        for (a, b) in self.iter().zip(other.iter()) {
            if a != b {
                distance += 1;
            }
        }

        return Ok(distance);
    }
}

impl<'a, 'b, T> HammingDistancable<&'b [T]> for &'a [T]
    where T : Eq {
    type Output = Result<u32, &'static str>;
    /// Calculate the hamming distance between slices
    fn hamming_distance(self, other: &'b [T]) -> Result<u32, &'static str> {
        if self.len() != other.len() {
            return Err("Slices do not have equal length");
        }

        let mut distance = 0;
        for (a, b) in self.iter().zip(other.iter()) {
            if a != b {
                distance += 1;
            }
        }

        return Ok(distance);
    }
}

impl <'a, 'b> HammingDistancable<&'b String> for &'a String {
    type Output = Result<u32, &'static str>;
    /// Calculate the hamming distance between strings
     fn hamming_distance(self, other: &'b String) -> Result<u32, &'static str> {
        if self.len() != other.len() {
            return Err("Strings do not have equal length");
        }

        let mut distance = 0;
        for (a, b) in self.chars().zip(other.chars()) {
            if a != b {
                distance += 1;
            }
        }

        return Ok(distance);
    }
}

impl <'a, 'b> HammingDistancable<&'b str> for &'a str {
    type Output = Result<u32, &'static str>;
    /// Calculate the hamming distance between borrowed strings
     fn hamming_distance(self, other: &'b str) -> Result<u32, &'static str> {
        if self.len() != other.len() {
            return Err("Strings do not have equal length");
        }

        let mut distance = 0;
        for (a, b) in self.chars().zip(other.chars()) {
            if a != b {
                distance += 1;
            }
        }

        return Ok(distance);
    }
}

#[cfg(test)]
mod tests {
    use hamming_distance::HammingDistancable;

    #[test]
    fn string_hamming_distance() {
        let string1 = "Cat";
        let string2 = "Hat";

        assert!(string1.hamming_distance(string2).unwrap() == 1);
    }
}<commit_msg>Add tests for hamming_distance<commit_after>/// A trait for calculating hamming distance
pub trait HammingDistancable<RHS = Self> {
    /// The output type of the hamming distance
    type Output;
    fn hamming_distance(self, other: RHS) -> Self::Output;
}

impl<'a, 'b, T> HammingDistancable<&'b Vec<T>> for &'a Vec<T>
    where T : Eq {
    type Output = Result<u32, &'static str>;
    /// Calculate the hamming distance between vectors
    fn hamming_distance(self, other: &'b Vec<T>) -> Result<u32, &'static str> {
        if self.len() != other.len() {
            return Err("Vectors do not have equal length");
        }

        let mut distance = 0;
        for (a, b) in self.iter().zip(other.iter()) {
            if a != b {
                distance += 1;
            }
        }

        return Ok(distance);
    }
}

impl<'a, 'b, T> HammingDistancable<&'b [T]> for &'a [T]
    where T : Eq {
    type Output = Result<u32, &'static str>;
    /// Calculate the hamming distance between slices
    fn hamming_distance(self, other: &'b [T]) -> Result<u32, &'static str> {
        if self.len() != other.len() {
            return Err("Slices do not have equal length");
        }

        let mut distance = 0;
        for (a, b) in self.iter().zip(other.iter()) {
            if a != b {
                distance += 1;
            }
        }

        return Ok(distance);
    }
}

impl <'a, 'b> HammingDistancable<&'b String> for &'a String {
    type Output = Result<u32, &'static str>;
    /// Calculate the hamming distance between strings
     fn hamming_distance(self, other: &'b String) -> Result<u32, &'static str> {
        if self.len() != other.len() {
            return Err("Strings do not have equal length");
        }

        let mut distance = 0;
        for (a, b) in self.chars().zip(other.chars()) {
            if a != b {
                distance += 1;
            }
        }

        return Ok(distance);
    }
}

impl <'a, 'b> HammingDistancable<&'b str> for &'a str {
    type Output = Result<u32, &'static str>;
    /// Calculate the hamming distance between borrowed strings
     fn hamming_distance(self, other: &'b str) -> Result<u32, &'static str> {
        if self.len() != other.len() {
            return Err("Strings do not have equal length");
        }

        let mut distance = 0;
        for (a, b) in self.chars().zip(other.chars()) {
            if a != b {
                distance += 1;
            }
        }

        return Ok(distance);
    }
}

#[cfg(test)]
mod tests {
    use hamming_distance::HammingDistancable;

    #[test]
    fn vec_hamming_distance() {
        let mut vec1 : Vec<char> = Vec::new();
        let mut vec2 : Vec<char> = Vec::new();

        vec1.push('a');
        vec1.push('b');

        vec2.push('c');
        vec2.push('d');

        assert!(vec1.hamming_distance(&vec2).unwrap() == 2);
    }

    #[test]
    fn vec_hamming_distance_error() {
        let mut vec1 : Vec<char> = Vec::new();
        let mut vec2 : Vec<char> = Vec::new();

        vec1.push('a');
        vec1.push('b');

        vec2.push('c');

        assert!(vec1.hamming_distance(&vec2).unwrap_err() ==
            "Vectors do not have equal length");
    }

    #[test]
    fn slice_hamming_distance() {
        let byte_slice1 : &[u8] = &[0x01, 0x01];
        let byte_slice2 : &[u8] = &[0x01, 0xFF];

        assert!(byte_slice1.hamming_distance(byte_slice2).unwrap() == 1);
    }

    #[test]
    fn slice_hamming_distance_error() {
        let byte_slice1 : &[u8] = &[0x01];
        let byte_slice2 : &[u8] = &[0x01, 0xFF];

        assert!(byte_slice1.hamming_distance(byte_slice2).unwrap_err() ==
            "Slices do not have equal length");
    }

    #[test]
    fn string_hamming_distance() {
        let string1 : String = "Cat".to_owned();
        let string2 : String = "Hat".to_owned();

        assert!(string1.hamming_distance(&string2).unwrap() == 1);
    }

    #[test]
    fn string_hamming_distance_error() {
        let string1 : String = "Cats".to_owned();
        let string2 : String = "Hat".to_owned();

        assert!(string1.hamming_distance(&string2).unwrap_err() ==
            "Strings do not have equal length");
    }

    #[test]
    fn borrowed_string_hamming_distance() {
        let string1 : &str = "Cat";
        let string2 : &str = "Hat";

        assert!(string1.hamming_distance(string2).unwrap() == 1);
    }

    #[test]
    fn borrowed_string_hamming_distance_error() {
        let string1 : &str = "Cats";
        let string2 : &str = "Hat";

        assert!(string1.hamming_distance(string2).unwrap_err() ==
            "Strings do not have equal length");
    }
}<|endoftext|>


<commit_before>pub mod client;
pub mod lsm;
pub mod sm;
mod trees;

#[cfg(test)]
mod tests {
    use super::lsm::btree::storage;
    use super::*;
    use crate::client::*;
    use crate::index::ranged::lsm::btree;
    use crate::index::ranged::lsm::tree::LAST_LEVEL_MULT_FACTOR;
    use crate::index::EntryKey;
    use crate::ram::types::Id;
    use crate::server::*;
    use futures::stream::FuturesUnordered;
    use itertools::Itertools;
    use rand::seq::SliceRandom;
    use std::sync::Arc;
    use std::time::Duration;
    use tokio::stream::StreamExt;

    #[ignore]
    #[tokio::test(threaded_scheduler)]
    async fn general() {
        let _ = env_logger::try_init();
        let server_group = "ranged_index_test";
        let server_addr = String::from("127.0.0.1:5711");
        let server = NebServer::new_from_opts(
            &ServerOptions {
                chunk_count: 1,
                memory_size: 32 * 1024 * 1024 * 1024, // 1G
                backup_storage: None,
                wal_storage: None,
                services: vec![Service::Cell, Service::RangedIndexer],
            },
            &server_addr,
            server_group,
        )
        .await;
        let client = Arc::new(
            AsyncClient::new(
                &server.rpc,
                &server.membership,
                &vec![server_addr],
                server_group,
            )
            .await
            .unwrap(),
        );
        let index_client = Arc::new(
            client::RangedQueryClient::new(&server.consh, &server.raft_client, &client).await,
        );
        let test_capacity = btree::ideal_capacity_from_node_size(btree::level::LEVEL_2)
            * LAST_LEVEL_MULT_FACTOR
            * 8;
        let mut futs = FuturesUnordered::new();
        info!(
            "Testing ranged indexer preesure test with {} items",
            test_capacity
        );
        debug!("Generating test set");
        let mut rng = rand::thread_rng();
        let mut nums = (0..test_capacity).collect_vec();
        nums.as_mut_slice().shuffle(&mut rng);
        debug!("Adding insertion tasks");
        for i in nums {
            let index_client = index_client.clone();
            futs.push(tokio::spawn(async move {
                let id = Id::new(1, i as u64);
                let key = EntryKey::from_id(&id);
                index_client.insert(&key).await
            }));
        }
        info!("All tasks queued, waiting for finish");
        while let Some(result) = futs.next().await {
            assert!(result.unwrap().unwrap(), "Insertion return false");
        }
        info!("Waiting for 10 secs");
        tokio::time::delay_for(Duration::from_secs(10)).await;
        info!("Waiting tree storage");
        storage::wait_until_updated().await;
        info!("Total cells {}", client.count().await.unwrap());
    }
}
<commit_msg>productive check for indexing<commit_after>pub mod client;
pub mod lsm;
pub mod sm;
mod trees;

#[cfg(test)]
mod tests {
    use super::lsm::btree::storage;
    use super::lsm::btree::Ordering;
    use super::*;
    use crate::client::*;
    use crate::index::ranged::lsm::btree;
    use crate::index::ranged::lsm::tree::LAST_LEVEL_MULT_FACTOR;
    use crate::index::EntryKey;
    use crate::ram::types::Id;
    use crate::server::*;
    use crate::ram::cell::*;
    use crate::ram::types::*;
    use crate::ram::schema::*;
    use futures::stream::FuturesUnordered;
    use itertools::Itertools;
    use rand::seq::SliceRandom;
    use std::sync::Arc;
    use std::time::Duration;
    use tokio::stream::StreamExt;

    #[ignore]
    #[tokio::test(threaded_scheduler)]
    async fn general() {
        let _ = env_logger::try_init();
        let server_group = "ranged_index_test";
        let server_addr = String::from("127.0.0.1:5711");
        let server = NebServer::new_from_opts(
            &ServerOptions {
                chunk_count: 1,
                memory_size: 32 * 1024 * 1024 * 1024, // 1G
                backup_storage: None,
                wal_storage: None,
                services: vec![Service::Cell, Service::RangedIndexer],
            },
            &server_addr,
            server_group,
        )
        .await;
        let client = Arc::new(
            AsyncClient::new(
                &server.rpc,
                &server.membership,
                &vec![server_addr],
                server_group,
            )
            .await
            .unwrap(),
        );
        let index_client = Arc::new(
            client::RangedQueryClient::new(&server.consh, &server.raft_client, &client).await,
        );
        client.new_schema_with_id(schema()).await.unwrap().unwrap();
        let test_capacity = btree::ideal_capacity_from_node_size(btree::level::LEVEL_2)
            * LAST_LEVEL_MULT_FACTOR
            * 8;
        let mut futs = FuturesUnordered::new();
        info!(
            "Testing ranged indexer preesure test with {} items",
            test_capacity
        );
        debug!("Generating test set");
        let mut rng = rand::thread_rng();
        let mut nums = (0..test_capacity).collect_vec();
        let mut nums_2 = nums.clone();
        nums.as_mut_slice().shuffle(&mut rng);
        nums_2.as_mut_slice().shuffle(&mut rng);
        debug!("Adding insertion tasks");
        for i in nums {
            let index_client = index_client.clone();
            let client = client.clone();
            futs.push(tokio::spawn(async move {
                let id = Id::new(1, i as u64);
                let key = EntryKey::from_id(&id);
                let mut data_map = Map::new();
                data_map.insert("data", Value::U64(i as u64));
                let cell = Cell::new_with_id(11, &id, Value::Map(data_map));
                client.write_cell(cell).await.unwrap().unwrap();
                index_client.insert(&key).await
            }));
        }
        info!("All tasks queued, waiting for finish");
        while let Some(result) = futs.next().await {
            assert!(result.unwrap().unwrap(), "Insertion return false");
        }
        info!("All keys inserted. The background task should merging trees. Doing searches.");
        for (i, num) in nums_2.iter().enumerate() {
            let id = Id::new(1, *num as u64);
            let key = EntryKey::from_id(&id);
            let rt_cursor = client::RangedQueryClient::seek(&index_client, &key, Ordering::Forward).await.unwrap().unwrap();
            assert_eq!(id, rt_cursor.current().unwrap().id());
            debug!("Id at {}, index {} have been checked", num, i);
        }
        tokio::time::delay_for(Duration::from_secs(10)).await;
        info!("Waiting tree storage");
        storage::wait_until_updated().await;
        info!("Total cells {}", client.count().await.unwrap());
    }

    fn schema() -> Schema {
        Schema {
            id: 11,
            name: String::from("test"),
            key_field: None,
            str_key_field: None,
            fields: Field::new(
                "*",
                0,
                false,
                false,
                Some(vec![
                    Field::new("data", 10, false, false, None, vec![])
                ]),
                vec![]
            ),
            is_dynamic: false,
        }
    }
}<|endoftext|>