<commit_before>// Copyright 2017 The Exonum Team
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! The time oracle service for Exonum.

#![deny(missing_debug_implementations, missing_docs)]

extern crate serde;
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate serde_json;
#[macro_use]
extern crate exonum;
extern crate router;
extern crate bodyparser;
extern crate iron;

use iron::prelude::*;
use iron::Handler;
use router::Router;

use std::sync::{Arc, RwLock};
use std::time::{Duration, SystemTime, UNIX_EPOCH};

use exonum::blockchain::{Blockchain, Service, ServiceContext, Schema, Transaction, ApiContext,
                         ExecutionResult};
use exonum::messages::{RawTransaction, Message};
use exonum::encoding::serialize::json::reexport::Value;
use exonum::storage::{Fork, Snapshot, ProofMapIndex, Entry};
use exonum::crypto::{Hash, PublicKey};
use exonum::encoding;
use exonum::helpers::fabric::{ServiceFactory, Context};
use exonum::api::Api;

/// Time service id.
const SERVICE_ID: u16 = 4;
/// `TxTime` transaction id.
const TX_TIME_ID: u16 = 1;
/// Time service name.
const SERVICE_NAME: &str = "exonum_time";

/// `Exonum-time` service database schema.
#[derive(Debug)]
pub struct TimeSchema<T> {
    view: T,
}

impl<T: AsRef<Snapshot>> TimeSchema<T> {
    /// Constructs schema for the given `snapshot`.
    pub fn new(view: T) -> Self {
        TimeSchema { view }
    }

    /// Returns the table that stores `SystemTime` for every validator.
    pub fn validators_times(&self) -> ProofMapIndex<&Snapshot, PublicKey, SystemTime> {
        ProofMapIndex::new(
            format!("{}.validators_times", SERVICE_NAME),
            self.view.as_ref(),
        )
    }

    /// Returns stored time.
    pub fn time(&self) -> Entry<&Snapshot, SystemTime> {
        Entry::new(format!("{}.time", SERVICE_NAME), self.view.as_ref())
    }

    /// Returns hashes for stored tables.
    pub fn state_hash(&self) -> Vec<Hash> {
        vec![self.validators_times().root_hash(), self.time().hash()]
    }
}

impl<'a> TimeSchema<&'a mut Fork> {
    /// Mutable reference to the ['validators_times'][1] index.
    ///
    /// [1]: struct.TimeSchema.html#method.validators_times
    pub fn validators_times_mut(&mut self) -> ProofMapIndex<&mut Fork, PublicKey, SystemTime> {
        ProofMapIndex::new(format!("{}.validators_times", SERVICE_NAME), self.view)
    }

    /// Mutable reference to the ['time'][1] index.
    ///
    /// [1]: struct.TimeSchema.html#method.time
    pub fn time_mut(&mut self) -> Entry<&mut Fork, SystemTime> {
        Entry::new(format!("{}.time", SERVICE_NAME), self.view)
    }
}

message! {
    /// Transaction that is sent by the validator after the commit of the block.
    struct TxTime {
        const TYPE = SERVICE_ID;
        const ID = TX_TIME_ID;
        /// Validator's time.
        time: SystemTime,
        /// Validator's public key.
        pub_key: &PublicKey,
    }
}

impl Transaction for TxTime {
    fn verify(&self) -> bool {
        self.verify_signature(self.pub_key())
    }

    fn execute(&self, view: &mut Fork) -> ExecutionResult {
        let validator_keys = Schema::new(&view).actual_configuration().validator_keys;

        // The transaction must be signed by the validator.
        let signed = validator_keys.iter().any(|&validator| {
            validator.service_key == *self.pub_key()
        });
        if !signed {
            return Ok(());
        }

        let mut schema = TimeSchema::new(view);
        match schema.validators_times().get(self.pub_key()) {
            // The validator time in the storage should be less than in the transaction.
            Some(storage_time) if storage_time >= self.time() => {
                return Ok(());
            }
            // Write the time for the validator.
            _ => {
                schema.validators_times_mut().put(
                    self.pub_key(),
                    self.time(),
                )
            }
        }

        // Find all known times for the validators.
        let mut validator_times: Vec<SystemTime>;
        {
            let idx = schema.validators_times();
            validator_times = idx.iter()
                .filter_map(|(public_key, time)| {
                    validator_keys
                        .iter()
                        .find(|validator| validator.service_key == public_key)
                        .map(|_| time)
                })
                .collect();
        }

        // The largest number of Byzantine nodes.
        let max_byzantine_nodes = (validator_keys.len() - 1) / 3;
        if validator_times.len() <= 2 * max_byzantine_nodes {
            return Ok(());
        }
        // Ordering time from highest to lowest.
        validator_times.sort_by(|a, b| b.cmp(a));

        match schema.time().get() {
            // Selected time should be longer than the time in the storage.
            Some(current_time) if current_time >= validator_times[max_byzantine_nodes] => {
            }
            _ => {
                // Change the time in the storage.
                schema.time_mut().set(validator_times[max_byzantine_nodes]);
            }
        }

        Ok(())
    }
}

/// Implements the node API.
#[derive(Clone)]
struct TimeApi {
    blockchain: Blockchain,
}

/// Structure for saving validator's public key and last known local time.
#[derive(Debug, Serialize, Deserialize)]
pub struct ValidatorTime {
    /// Validator's public key.
    pub public_key: PublicKey,
    /// Validator's time.
    pub time: Option<SystemTime>,
}

/// Shortcut to get data from storage.
impl TimeApi {
    /// Endpoint for getting value of the time that is saved in storage.
    fn get_current_time(&self, _: &mut Request) -> IronResult<Response> {
        let view = self.blockchain.snapshot();
        let schema = TimeSchema::new(&view);
        self.ok_response(&json!(schema.time().get()))
    }

    /// Endpoint for getting time values for all validators.
    fn get_all_validators_times(&self, _: &mut Request) -> IronResult<Response> {
        let view = self.blockchain.snapshot();
        let schema = TimeSchema::new(&view);
        let idx = schema.validators_times();

        // The times of all validators for which time is known.
        let validators_times = idx.iter()
            .map(|(public_key, time)| {
                ValidatorTime {
                    public_key,
                    time: Some(time),
                }
            })
            .collect::<Vec<_>>();

        self.ok_response(&serde_json::to_value(validators_times).unwrap())
    }

    /// Endpoint for getting time values for current validators.
    fn get_current_validators_times(&self, _: &mut Request) -> IronResult<Response> {
        let view = self.blockchain.snapshot();
        let validator_keys = Schema::new(&view).actual_configuration().validator_keys;
        let schema = TimeSchema::new(&view);
        let idx = schema.validators_times();

        // The times of current validators.
        // `None` if the time of the validator is unknown.
        let validators_times = validator_keys
            .iter()
            .map(|validator| {
                ValidatorTime {
                    public_key: validator.service_key,
                    time: idx.get(&validator.service_key),
                }
            })
            .collect::<Vec<_>>();

        self.ok_response(&serde_json::to_value(validators_times).unwrap())
    }

    fn wire_private(&self, router: &mut Router) {
        let self_ = self.clone();
        let get_current_validators_times =
            move |req: &mut Request| self_.get_current_validators_times(req);

        let self_ = self.clone();
        let get_all_validators_times = move |req: &mut Request| self_.get_all_validators_times(req);

        router.get(
            "v1/validators_times",
            get_current_validators_times,
            "get_current_validators_times",
        );

        router.get(
            "v1/validators_times/all",
            get_all_validators_times,
            "get_all_validators_times",
        );
    }
}

impl Api for TimeApi {
    fn wire(&self, router: &mut Router) {
        let self_ = self.clone();
        let get_current_time = move |req: &mut Request| self_.get_current_time(req);
        router.get("v1/current_time", get_current_time, "get_current_time");
    }
}

/// A helper trait that provides the node with a current time.
pub trait TimeProvider: Send + Sync + ::std::fmt::Debug {
    /// Returns the current time.
    fn current_time(&self) -> SystemTime;
}

#[derive(Debug)]
struct SystemTimeProvider;

impl TimeProvider for SystemTimeProvider {
    fn current_time(&self) -> SystemTime {
        SystemTime::now()
    }
}

/// Mock time provider for service testing.
///
/// In terms of use, the mock time provider is similar to [`Arc`]; that is, clones of the provider
/// control the same time record as the original instance. Therefore, to use the mock provider,
/// one may clone its instance and use the clone to construct a [`TimeService`],
/// while keeping the original instance to adjust the time reported to the validators
/// along various test scenarios.
///
/// # Examples
///
/// ```
/// # extern crate exonum;
/// # extern crate exonum_testkit;
/// # extern crate exonum_time;
/// use std::time::{Duration, UNIX_EPOCH};
/// use exonum::helpers::Height;
/// use exonum_testkit::TestKitBuilder;
/// use exonum_time::{MockTimeProvider, TimeSchema, TimeService};
///
/// # fn main() {
/// let mock_provider = MockTimeProvider::default();
/// let mut testkit = TestKitBuilder::validator()
///     .with_service(TimeService::with_provider(mock_provider.clone()))
///     .create();
/// mock_provider.add_time(Duration::new(15, 0));
/// testkit.create_blocks_until(Height(2));
///
/// // The time reported by the mock time provider is reflected by the service.
/// let snapshot = testkit.snapshot();
/// let schema = TimeSchema::new(snapshot);
/// assert_eq!(
///     Some(UNIX_EPOCH + Duration::new(15, 0)),
///     schema.time().get().map(|time| time)
/// );
/// # }
/// ```
///
/// [`Arc`]: https://doc.rust-lang.org/std/sync/struct.Arc.html
/// [`TimeService`]: struct.TimeService.html
#[derive(Debug, Clone)]
pub struct MockTimeProvider {
    /// Local time value.
    time: Arc<RwLock<SystemTime>>,
}

impl Default for MockTimeProvider {
    /// Initializes the provider with the time set to the Unix epoch start.
    fn default() -> Self {
        Self::new(UNIX_EPOCH)
    }
}

impl MockTimeProvider {
    /// Creates a new `MockTimeProvider` with time value equal to `time`.
    pub fn new(time: SystemTime) -> Self {
        Self { time: Arc::new(RwLock::new(time)) }
    }

    /// Gets the time value currently reported by the provider.
    pub fn time(&self) -> SystemTime {
        *self.time.read().unwrap()
    }

    /// Sets the time value to `new_time`.
    pub fn set_time(&self, new_time: SystemTime) {
        let mut time = self.time.write().unwrap();
        *time = new_time;
    }

    /// Adds `duration` to the value of `time`.
    pub fn add_time(&self, duration: Duration) {
        let mut time = self.time.write().unwrap();
        *time += duration;
    }
}

impl TimeProvider for MockTimeProvider {
    fn current_time(&self) -> SystemTime {
        self.time()
    }
}

impl From<MockTimeProvider> for Box<TimeProvider> {
    fn from(mock_time_provider: MockTimeProvider) -> Self {
        Box::new(mock_time_provider) as Box<TimeProvider>
    }
}

/// Define the service.
#[derive(Debug)]
pub struct TimeService {
    /// Current time.
    time: Box<TimeProvider>,
}

impl Default for TimeService {
    fn default() -> TimeService {
        TimeService { time: Box::new(SystemTimeProvider) as Box<TimeProvider> }
    }
}

impl TimeService {
    /// Create a new `TimeService`.
    pub fn new() -> TimeService {
        TimeService::default()
    }

    /// Create a new `TimeService` with time provider `T`.
    pub fn with_provider<T: Into<Box<TimeProvider>>>(time_provider: T) -> TimeService {
        TimeService { time: time_provider.into() }
    }
}

impl Service for TimeService {
    fn service_name(&self) -> &'static str {
        SERVICE_NAME
    }

    fn state_hash(&self, snapshot: &Snapshot) -> Vec<Hash> {
        let schema = TimeSchema::new(snapshot);
        schema.state_hash()
    }

    fn service_id(&self) -> u16 {
        SERVICE_ID
    }

    fn tx_from_raw(&self, raw: RawTransaction) -> Result<Box<Transaction>, encoding::Error> {
        match raw.message_type() {
            TX_TIME_ID => Ok(Box::new(TxTime::from_raw(raw)?)),
            _ => {
                let error =
                    encoding::Error::IncorrectMessageType { message_type: raw.message_type() };
                Err(error)
            }
        }
    }

    fn initialize(&self, _fork: &mut Fork) -> Value {
        Value::Null
    }

    /// Creates transaction after commit of the block.
    fn handle_commit(&self, context: &ServiceContext) {
        // The transaction must be created by the validator.
        if context.validator_id().is_none() {
            return;
        }
        let (pub_key, sec_key) = (*context.public_key(), context.secret_key().clone());
        context
            .transaction_sender()
            .send(Box::new(
                TxTime::new(self.time.current_time(), &pub_key, &sec_key),
            ))
            .unwrap();
    }

    fn private_api_handler(&self, ctx: &ApiContext) -> Option<Box<Handler>> {
        let mut router = Router::new();
        let api = TimeApi { blockchain: ctx.blockchain().clone() };
        api.wire_private(&mut router);
        Some(Box::new(router))
    }

    fn public_api_handler(&self, ctx: &ApiContext) -> Option<Box<Handler>> {
        let mut router = Router::new();
        let api = TimeApi { blockchain: ctx.blockchain().clone() };
        api.wire(&mut router);
        Some(Box::new(router))
    }
}

/// A time service creator for the `NodeBuilder`.
#[derive(Debug)]
pub struct TimeServiceFactory;

impl ServiceFactory for TimeServiceFactory {
    fn make_service(&mut self, _: &Context) -> Box<Service> {
        Box::new(TimeService::new())
    }
}
<commit_msg>Fix formatting<commit_after>// Copyright 2017 The Exonum Team
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! The time oracle service for Exonum.

#![deny(missing_debug_implementations, missing_docs)]

extern crate serde;
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate serde_json;
#[macro_use]
extern crate exonum;
extern crate router;
extern crate bodyparser;
extern crate iron;

use iron::prelude::*;
use iron::Handler;
use router::Router;

use std::sync::{Arc, RwLock};
use std::time::{Duration, SystemTime, UNIX_EPOCH};

use exonum::blockchain::{Blockchain, Service, ServiceContext, Schema, Transaction, ApiContext,
                         ExecutionResult};
use exonum::messages::{RawTransaction, Message};
use exonum::encoding::serialize::json::reexport::Value;
use exonum::storage::{Fork, Snapshot, ProofMapIndex, Entry};
use exonum::crypto::{Hash, PublicKey};
use exonum::encoding;
use exonum::helpers::fabric::{ServiceFactory, Context};
use exonum::api::Api;

/// Time service id.
const SERVICE_ID: u16 = 4;
/// `TxTime` transaction id.
const TX_TIME_ID: u16 = 1;
/// Time service name.
const SERVICE_NAME: &str = "exonum_time";

/// `Exonum-time` service database schema.
#[derive(Debug)]
pub struct TimeSchema<T> {
    view: T,
}

impl<T: AsRef<Snapshot>> TimeSchema<T> {
    /// Constructs schema for the given `snapshot`.
    pub fn new(view: T) -> Self {
        TimeSchema { view }
    }

    /// Returns the table that stores `SystemTime` for every validator.
    pub fn validators_times(&self) -> ProofMapIndex<&Snapshot, PublicKey, SystemTime> {
        ProofMapIndex::new(
            format!("{}.validators_times", SERVICE_NAME),
            self.view.as_ref(),
        )
    }

    /// Returns stored time.
    pub fn time(&self) -> Entry<&Snapshot, SystemTime> {
        Entry::new(format!("{}.time", SERVICE_NAME), self.view.as_ref())
    }

    /// Returns hashes for stored tables.
    pub fn state_hash(&self) -> Vec<Hash> {
        vec![self.validators_times().root_hash(), self.time().hash()]
    }
}

impl<'a> TimeSchema<&'a mut Fork> {
    /// Mutable reference to the ['validators_times'][1] index.
    ///
    /// [1]: struct.TimeSchema.html#method.validators_times
    pub fn validators_times_mut(&mut self) -> ProofMapIndex<&mut Fork, PublicKey, SystemTime> {
        ProofMapIndex::new(format!("{}.validators_times", SERVICE_NAME), self.view)
    }

    /// Mutable reference to the ['time'][1] index.
    ///
    /// [1]: struct.TimeSchema.html#method.time
    pub fn time_mut(&mut self) -> Entry<&mut Fork, SystemTime> {
        Entry::new(format!("{}.time", SERVICE_NAME), self.view)
    }
}

message! {
    /// Transaction that is sent by the validator after the commit of the block.
    struct TxTime {
        const TYPE = SERVICE_ID;
        const ID = TX_TIME_ID;
        /// Validator's time.
        time: SystemTime,
        /// Validator's public key.
        pub_key: &PublicKey,
    }
}

impl Transaction for TxTime {
    fn verify(&self) -> bool {
        self.verify_signature(self.pub_key())
    }

    fn execute(&self, view: &mut Fork) -> ExecutionResult {
        let validator_keys = Schema::new(&view).actual_configuration().validator_keys;

        // The transaction must be signed by the validator.
        let signed = validator_keys.iter().any(|&validator| {
            validator.service_key == *self.pub_key()
        });
        if !signed {
            return Ok(());
        }

        let mut schema = TimeSchema::new(view);
        match schema.validators_times().get(self.pub_key()) {
            // The validator time in the storage should be less than in the transaction.
            Some(storage_time) if storage_time >= self.time() => {
                return Ok(());
            }
            // Write the time for the validator.
            _ => {
                schema.validators_times_mut().put(
                    self.pub_key(),
                    self.time(),
                )
            }
        }

        // Find all known times for the validators.
        let mut validator_times: Vec<SystemTime>;
        {
            let idx = schema.validators_times();
            validator_times = idx.iter()
                .filter_map(|(public_key, time)| {
                    validator_keys
                        .iter()
                        .find(|validator| validator.service_key == public_key)
                        .map(|_| time)
                })
                .collect();
        }

        // The largest number of Byzantine nodes.
        let max_byzantine_nodes = (validator_keys.len() - 1) / 3;
        if validator_times.len() <= 2 * max_byzantine_nodes {
            return Ok(());
        }
        // Ordering time from highest to lowest.
        validator_times.sort_by(|a, b| b.cmp(a));

        match schema.time().get() {
            // Selected time should be longer than the time in the storage.
            Some(current_time) if current_time >= validator_times[max_byzantine_nodes] => {}
            _ => {
                // Change the time in the storage.
                schema.time_mut().set(validator_times[max_byzantine_nodes]);
            }
        }

        Ok(())
    }
}

/// Implements the node API.
#[derive(Clone)]
struct TimeApi {
    blockchain: Blockchain,
}

/// Structure for saving validator's public key and last known local time.
#[derive(Debug, Serialize, Deserialize)]
pub struct ValidatorTime {
    /// Validator's public key.
    pub public_key: PublicKey,
    /// Validator's time.
    pub time: Option<SystemTime>,
}

/// Shortcut to get data from storage.
impl TimeApi {
    /// Endpoint for getting value of the time that is saved in storage.
    fn get_current_time(&self, _: &mut Request) -> IronResult<Response> {
        let view = self.blockchain.snapshot();
        let schema = TimeSchema::new(&view);
        self.ok_response(&json!(schema.time().get()))
    }

    /// Endpoint for getting time values for all validators.
    fn get_all_validators_times(&self, _: &mut Request) -> IronResult<Response> {
        let view = self.blockchain.snapshot();
        let schema = TimeSchema::new(&view);
        let idx = schema.validators_times();

        // The times of all validators for which time is known.
        let validators_times = idx.iter()
            .map(|(public_key, time)| {
                ValidatorTime {
                    public_key,
                    time: Some(time),
                }
            })
            .collect::<Vec<_>>();

        self.ok_response(&serde_json::to_value(validators_times).unwrap())
    }

    /// Endpoint for getting time values for current validators.
    fn get_current_validators_times(&self, _: &mut Request) -> IronResult<Response> {
        let view = self.blockchain.snapshot();
        let validator_keys = Schema::new(&view).actual_configuration().validator_keys;
        let schema = TimeSchema::new(&view);
        let idx = schema.validators_times();

        // The times of current validators.
        // `None` if the time of the validator is unknown.
        let validators_times = validator_keys
            .iter()
            .map(|validator| {
                ValidatorTime {
                    public_key: validator.service_key,
                    time: idx.get(&validator.service_key),
                }
            })
            .collect::<Vec<_>>();

        self.ok_response(&serde_json::to_value(validators_times).unwrap())
    }

    fn wire_private(&self, router: &mut Router) {
        let self_ = self.clone();
        let get_current_validators_times =
            move |req: &mut Request| self_.get_current_validators_times(req);

        let self_ = self.clone();
        let get_all_validators_times = move |req: &mut Request| self_.get_all_validators_times(req);

        router.get(
            "v1/validators_times",
            get_current_validators_times,
            "get_current_validators_times",
        );

        router.get(
            "v1/validators_times/all",
            get_all_validators_times,
            "get_all_validators_times",
        );
    }
}

impl Api for TimeApi {
    fn wire(&self, router: &mut Router) {
        let self_ = self.clone();
        let get_current_time = move |req: &mut Request| self_.get_current_time(req);
        router.get("v1/current_time", get_current_time, "get_current_time");
    }
}

/// A helper trait that provides the node with a current time.
pub trait TimeProvider: Send + Sync + ::std::fmt::Debug {
    /// Returns the current time.
    fn current_time(&self) -> SystemTime;
}

#[derive(Debug)]
struct SystemTimeProvider;

impl TimeProvider for SystemTimeProvider {
    fn current_time(&self) -> SystemTime {
        SystemTime::now()
    }
}

/// Mock time provider for service testing.
///
/// In terms of use, the mock time provider is similar to [`Arc`]; that is, clones of the provider
/// control the same time record as the original instance. Therefore, to use the mock provider,
/// one may clone its instance and use the clone to construct a [`TimeService`],
/// while keeping the original instance to adjust the time reported to the validators
/// along various test scenarios.
///
/// # Examples
///
/// ```
/// # extern crate exonum;
/// # extern crate exonum_testkit;
/// # extern crate exonum_time;
/// use std::time::{Duration, UNIX_EPOCH};
/// use exonum::helpers::Height;
/// use exonum_testkit::TestKitBuilder;
/// use exonum_time::{MockTimeProvider, TimeSchema, TimeService};
///
/// # fn main() {
/// let mock_provider = MockTimeProvider::default();
/// let mut testkit = TestKitBuilder::validator()
///     .with_service(TimeService::with_provider(mock_provider.clone()))
///     .create();
/// mock_provider.add_time(Duration::new(15, 0));
/// testkit.create_blocks_until(Height(2));
///
/// // The time reported by the mock time provider is reflected by the service.
/// let snapshot = testkit.snapshot();
/// let schema = TimeSchema::new(snapshot);
/// assert_eq!(
///     Some(UNIX_EPOCH + Duration::new(15, 0)),
///     schema.time().get().map(|time| time)
/// );
/// # }
/// ```
///
/// [`Arc`]: https://doc.rust-lang.org/std/sync/struct.Arc.html
/// [`TimeService`]: struct.TimeService.html
#[derive(Debug, Clone)]
pub struct MockTimeProvider {
    /// Local time value.
    time: Arc<RwLock<SystemTime>>,
}

impl Default for MockTimeProvider {
    /// Initializes the provider with the time set to the Unix epoch start.
    fn default() -> Self {
        Self::new(UNIX_EPOCH)
    }
}

impl MockTimeProvider {
    /// Creates a new `MockTimeProvider` with time value equal to `time`.
    pub fn new(time: SystemTime) -> Self {
        Self { time: Arc::new(RwLock::new(time)) }
    }

    /// Gets the time value currently reported by the provider.
    pub fn time(&self) -> SystemTime {
        *self.time.read().unwrap()
    }

    /// Sets the time value to `new_time`.
    pub fn set_time(&self, new_time: SystemTime) {
        let mut time = self.time.write().unwrap();
        *time = new_time;
    }

    /// Adds `duration` to the value of `time`.
    pub fn add_time(&self, duration: Duration) {
        let mut time = self.time.write().unwrap();
        *time += duration;
    }
}

impl TimeProvider for MockTimeProvider {
    fn current_time(&self) -> SystemTime {
        self.time()
    }
}

impl From<MockTimeProvider> for Box<TimeProvider> {
    fn from(mock_time_provider: MockTimeProvider) -> Self {
        Box::new(mock_time_provider) as Box<TimeProvider>
    }
}

/// Define the service.
#[derive(Debug)]
pub struct TimeService {
    /// Current time.
    time: Box<TimeProvider>,
}

impl Default for TimeService {
    fn default() -> TimeService {
        TimeService { time: Box::new(SystemTimeProvider) as Box<TimeProvider> }
    }
}

impl TimeService {
    /// Create a new `TimeService`.
    pub fn new() -> TimeService {
        TimeService::default()
    }

    /// Create a new `TimeService` with time provider `T`.
    pub fn with_provider<T: Into<Box<TimeProvider>>>(time_provider: T) -> TimeService {
        TimeService { time: time_provider.into() }
    }
}

impl Service for TimeService {
    fn service_name(&self) -> &'static str {
        SERVICE_NAME
    }

    fn state_hash(&self, snapshot: &Snapshot) -> Vec<Hash> {
        let schema = TimeSchema::new(snapshot);
        schema.state_hash()
    }

    fn service_id(&self) -> u16 {
        SERVICE_ID
    }

    fn tx_from_raw(&self, raw: RawTransaction) -> Result<Box<Transaction>, encoding::Error> {
        match raw.message_type() {
            TX_TIME_ID => Ok(Box::new(TxTime::from_raw(raw)?)),
            _ => {
                let error =
                    encoding::Error::IncorrectMessageType { message_type: raw.message_type() };
                Err(error)
            }
        }
    }

    fn initialize(&self, _fork: &mut Fork) -> Value {
        Value::Null
    }

    /// Creates transaction after commit of the block.
    fn handle_commit(&self, context: &ServiceContext) {
        // The transaction must be created by the validator.
        if context.validator_id().is_none() {
            return;
        }
        let (pub_key, sec_key) = (*context.public_key(), context.secret_key().clone());
        context
            .transaction_sender()
            .send(Box::new(
                TxTime::new(self.time.current_time(), &pub_key, &sec_key),
            ))
            .unwrap();
    }

    fn private_api_handler(&self, ctx: &ApiContext) -> Option<Box<Handler>> {
        let mut router = Router::new();
        let api = TimeApi { blockchain: ctx.blockchain().clone() };
        api.wire_private(&mut router);
        Some(Box::new(router))
    }

    fn public_api_handler(&self, ctx: &ApiContext) -> Option<Box<Handler>> {
        let mut router = Router::new();
        let api = TimeApi { blockchain: ctx.blockchain().clone() };
        api.wire(&mut router);
        Some(Box::new(router))
    }
}

/// A time service creator for the `NodeBuilder`.
#[derive(Debug)]
pub struct TimeServiceFactory;

impl ServiceFactory for TimeServiceFactory {
    fn make_service(&mut self, _: &Context) -> Box<Service> {
        Box::new(TimeService::new())
    }
}
<|endoftext|>


<commit_before>//! One-way socket wrapper data structures.

use nanomsg::{Endpoint, Socket, Protocol, Error};
use std;
use std::convert::AsRef;
use std::io::{Read, Write};
use std::time::Duration;

/// A send-only socket.
pub struct SendSocket {
  socket: Socket,
  endpoint: Endpoint,
}

fn as_millis(duration: Duration) -> isize {
  (duration.as_secs() * 1_000) as isize + (duration.subsec_nanos() / 1_000_000) as isize
}

impl SendSocket {
  #[allow(missing_docs)]
  pub fn new(url: &str, timeout: Option<Duration>) -> SendSocket {
    let mut socket = Socket::new(Protocol::Push).unwrap();
    timeout.map(|timeout| socket.set_receive_timeout(as_millis(timeout)).unwrap());
    let endpoint = socket.connect(url).unwrap();

    SendSocket {
      socket: socket,
      endpoint: endpoint,
    }
  }

  /// Block until we can send this socket a message.
  pub fn write(&mut self, msg: &[u8]) -> std::io::Result<()> {
    self.socket.write(msg).map(|_| ())
  }

  /// Terminate this connection.
  pub fn close(self) {
    // The `drop` takes care of everything.
  }
}

impl Drop for SendSocket {
  fn drop(&mut self) {
    self.endpoint.shutdown().unwrap();
  }
}

/// A receive-only socket.
pub struct ReceiveSocket {
  socket: Socket,
  endpoint: Endpoint,
}

impl ReceiveSocket {
  #[allow(missing_docs)]
  pub fn new(url: &str, timeout: Option<Duration>) -> ReceiveSocket {
    let mut socket = Socket::new(Protocol::Pull).unwrap();
    timeout.map(|timeout| socket.set_receive_timeout(as_millis(timeout)).unwrap());
    let endpoint = socket.bind(url.as_ref()).unwrap();

    ReceiveSocket {
      socket: socket,
      endpoint: endpoint,
    }
  }

  /// Block until a message can be fetched from this socket.
  pub fn read(&mut self) -> Vec<u8> {
    let mut msg = Vec::new();
    self.socket.read_to_end(&mut msg).unwrap();
    msg
  }

  /// Try to read a message from this socket.
  pub fn try_read(&mut self) -> Option<Vec<u8>> {
    let mut msg = Vec::new();
    let result = self.socket.nb_read_to_end(&mut msg);
    match result {
      Ok(_) => Some(msg),
      Err(Error::TryAgain) => None,
      _ => {
        result.unwrap();
        unreachable!()
      }
    }
  }

  /// Terminate this connection.
  pub fn close(self) {
    // The `drop` takes care of everything.
  }
}

impl Drop for ReceiveSocket {
  fn drop(&mut self) {
    self.endpoint.shutdown().unwrap();
  }
}
<commit_msg>safe server shutdown<commit_after>//! One-way socket wrapper data structures.

use nanomsg::{Endpoint, Socket, Protocol, Error};
use std;
use std::convert::AsRef;
use std::io::{Read, Write};
use std::time::Duration;

/// A send-only socket.
pub struct SendSocket {
  socket: Socket,
  endpoint: Endpoint,
}

fn as_millis(duration: Duration) -> isize {
  (duration.as_secs() * 1_000) as isize + (duration.subsec_nanos() / 1_000_000) as isize
}

impl SendSocket {
  #[allow(missing_docs)]
  pub fn new(url: &str, timeout: Option<Duration>) -> SendSocket {
    let mut socket = Socket::new(Protocol::Push).unwrap();
    timeout.map(|timeout| socket.set_receive_timeout(as_millis(timeout)).unwrap());
    let endpoint = socket.connect(url).unwrap();

    SendSocket {
      socket: socket,
      endpoint: endpoint,
    }
  }

  /// Block until we can send this socket a message.
  pub fn write(&mut self, msg: &[u8]) -> std::io::Result<()> {
    self.socket.write(msg).map(|_| ())
  }

  /// Terminate this connection.
  pub fn close(self) {
    // The `drop` takes care of everything.
  }
}

impl Drop for SendSocket {
  fn drop(&mut self) {
    self.endpoint.shutdown().unwrap_or(());
  }
}

/// A receive-only socket.
pub struct ReceiveSocket {
  socket: Socket,
  endpoint: Endpoint,
}

impl ReceiveSocket {
  #[allow(missing_docs)]
  pub fn new(url: &str, timeout: Option<Duration>) -> ReceiveSocket {
    let mut socket = Socket::new(Protocol::Pull).unwrap();
    timeout.map(|timeout| socket.set_receive_timeout(as_millis(timeout)).unwrap());
    let endpoint = socket.bind(url.as_ref()).unwrap();

    ReceiveSocket {
      socket: socket,
      endpoint: endpoint,
    }
  }

  /// Block until a message can be fetched from this socket.
  pub fn read(&mut self) -> Vec<u8> {
    let mut msg = Vec::new();
    self.socket.read_to_end(&mut msg).unwrap();
    msg
  }

  /// Try to read a message from this socket.
  pub fn try_read(&mut self) -> Option<Vec<u8>> {
    let mut msg = Vec::new();
    let result = self.socket.nb_read_to_end(&mut msg);
    match result {
      Ok(_) => Some(msg),
      Err(Error::TryAgain) => None,
      _ => {
        result.unwrap();
        unreachable!()
      }
    }
  }

  /// Terminate this connection.
  pub fn close(self) {
    // The `drop` takes care of everything.
  }
}

impl Drop for ReceiveSocket {
  fn drop(&mut self) {
    self.endpoint.shutdown().unwrap_or(());
  }
}
<|endoftext|>


<commit_before>/*!
*/

#![crate_name = "simplemad_sys"]

extern crate libc;

use libc::types::os::arch::c95::{c_int, c_uint, c_ushort, size_t, c_long};
use libc::types::common::c99::*;
use libc::types::common::c95::c_void;
use std::convert::From;
use std::fmt::{self, Result, Debug};
use std::ptr;

pub use libc::c_ulong;

#[allow(dead_code)]
#[link(name = "mad")]
extern {
    pub fn mad_decoder_init(decoder: *mut MadDecoder,
                            message: *mut c_void,
                            input_cb: extern fn(message: *mut c_void,
                                                stream: &MadStream) -> MadFlow,
                            header_cb: extern fn(message: *mut c_void,
                                                 header: &MadHeader) -> MadFlow,
                            filter_cb: extern fn(),
                            output_cb: extern fn(message: *mut c_void,
                                                 header: &MadHeader,
                                                 pcm: &MadPcm) -> MadFlow,
                            error_cb: extern fn(message: *mut c_void,
                                                stream: &MadStream,
                                                frame: *const c_void) -> MadFlow,
                            message_cb: extern fn());

    pub fn mad_decoder_run(decoder: &mut MadDecoder, mode: MadDecoderMode) -> c_int;
    pub fn mad_decoder_finish(decoder: &mut MadDecoder) -> c_int;
    pub fn mad_stream_buffer(stream: &MadStream,
                             buf_start: *const u8,
                             buf_len: c_ulong);

    pub fn mad_header_init(header: &mut MadHeader);
    pub fn mad_stream_init(stream: &mut MadStream);
    pub fn mad_frame_init(frame: &mut MadFrame);
    pub fn mad_synth_init(synth: &mut MadSynth);

    pub fn mad_stream_finish(stream: &mut MadStream);
    pub fn mad_frame_finish(frame: &mut MadFrame);

    pub fn mad_header_decode(header: &mut MadHeader, stream: &mut MadStream);
    pub fn mad_frame_decode(frame: &mut MadFrame, stream: &mut MadStream);
    pub fn mad_synth_frame(synth: &mut MadSynth, frame: &mut MadFrame);
}

/// libmad callbacks return MadFlow values, which are used to control the decoding process
#[allow(dead_code)]
#[derive(Debug, Clone)]
#[repr(C)]
pub enum MadFlow {
    /// continue normally
    Continue = 0x0000,

    /// stop decoding normally
    Stop = 0x0010,

    /// stop decoding and signal an error
    Break = 0x0011,

    /// ignore the current frame
    Ignore = 0x0020,

}

/// Errors generated by libmad
#[derive(Debug, Clone, PartialEq)]
#[repr(C)]
pub enum MadError {
    /// no error
    None = 0x0000,

    /// input buffer too small (or eof)
    BufLen = 0x0001,

    /// invalid (null) buffer pointer
    BufPtr = 0x0002,

    /// not enough memory
    NoMem = 0x0031,

    /// lost synchronization
    LostSync = 0x0101,

    /// reserved header layer value
    BadLayer = 0x0102,

    /// forbidden bitrate value
    BadBitRate = 0x0103,

    /// reserved sample frequency value
    BadSampleRate = 0x0104,

    /// reserved emphasis value
    BadEmphasis = 0x0105,

    /// crc check failed
    BadCRC = 0x0201,

    /// forbidden bit allocation value
    BadBitAlloc = 0x0211,

    /// bad scalefactor index
    BadScaleFactor = 0x0221,

    /// bad bitrate/mode combination
    BadMode = 0x0222,

    /// bad frame length
    BadFrameLen = 0x0231,

    /// bad big_values count
    BadBigValues = 0x0232,

    /// reserved block_type
    BadBlockType = 0x0233,

    /// bad scalefactor selection info
    BadScFSI = 0x0234,

    /// bad main_data_begin pointer
    BadDataPtr = 0x0235,

    /// bad audio data length
    BadPart3Len = 0x0236,

    /// bad huffman table select
    BadHuffTable = 0x0237,

    /// huffman data overrun
    BadHuffData = 0x0238,

    /// incompatible block_type for joint stereo
    BadStereo = 0x0239,
}

impl Default for MadError {
    fn default() -> MadError {
        MadError::None
    }
}

#[derive(Default, Debug, Clone)]
#[repr(C)]
pub struct MadBitPtr {
    pub byte: size_t,
    pub cache: uint16_t,
    pub left: uint16_t,
}

#[allow(dead_code)]
#[derive(Default, Debug, Clone)]
#[repr(C)]
pub struct MadStream {
    pub buffer: size_t,
    pub buff_end: size_t,
    pub skip_len: c_ulong,
    pub sync: c_int,
    pub free_rate: c_ulong,
    pub this_frame: size_t,
    pub next_frame: size_t,
    pub ptr: MadBitPtr,
    pub anc_ptr: MadBitPtr,
    pub anc_bitlen: c_uint,
    pub buffer_mdlen: size_t,
    pub md_len: c_uint,
    pub options: c_int,
    pub error: MadError,
}

#[allow(dead_code, raw_pointer_derive)]
#[derive(Clone)]
#[repr(C)]
pub struct MadFrame {
    pub header: MadHeader,
    pub options: c_int,
    pub sbsample: [[[i32; 32]; 36]; 2],
    pub overlap: *mut i32,
}

impl Default for MadFrame {
    fn default() -> MadFrame {
        MadFrame {
            header: Default::default(),
            options: 0,
            sbsample: [[[0; 32]; 36]; 2],
            overlap: ptr::null::<i32>() as *mut i32,
        }
    }
}

unsafe impl std::marker::Send for MadFrame { }

#[allow(dead_code)]
#[derive(Clone)]
#[repr(C)]
pub struct MadSynth {
    pub filter: [[[[[i32; 8]; 16]; 2]; 2]; 2],
    pub phase: c_uint,
    pub pcm: MadPcm,
}

impl Default for MadSynth {
    fn default() -> MadSynth {
        MadSynth {
            filter: [[[[[0; 8]; 16]; 2]; 2]; 2],
            phase: 0,
            pcm: Default::default()
        }
    }
}

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

#[allow(dead_code)]
#[derive(Debug, Clone)]
#[repr(C)]
pub enum MadLayer {
    Layer1 = 1,
    Layer2 = 2,
    Layer3 = 3,
}

impl Default for MadLayer {
    fn default() -> MadLayer {
        MadLayer::Layer1
    }
}

#[allow(dead_code)]
#[derive(Debug, Clone)]
#[repr(C)]
pub enum MadMode {
    SingleChannel = 0,
    DualChannel = 1,
    JointStereo = 2,
    Stereo = 3,
}

impl Default for MadMode {
    fn default() -> MadMode {
        MadMode::SingleChannel
    }
}

#[allow(dead_code)]
#[derive(Debug, Clone)]
#[repr(C)]
pub enum MadEmphasis {
    None = 0,
    Fifty15Us = 1,
    CcittJ17 = 3,
    Reserved = 2,
}

impl Default for MadEmphasis {
    fn default() -> MadEmphasis {
        MadEmphasis::None
    }
}

#[derive(Default)]
#[derive(Debug, Clone)]
#[repr(C)]
pub struct MadTimer {
    pub seconds: c_long,
    pub fraction: c_ulong,
}

#[allow(dead_code)]
#[derive(Default, Debug, Clone)]
#[repr(C)]
pub struct MadHeader {
    pub layer: MadLayer,
    pub mode: MadMode,
    pub mode_extension: c_int,
    pub emphasis: MadEmphasis,
    pub bit_rate: c_ulong,
    pub sample_rate: c_uint,
    pub crc_check: c_ushort,
    pub crc_target: c_ushort,
    pub flags: c_int,
    pub private_bits: c_int,
    pub duration: MadTimer,
}

#[allow(dead_code)]
#[derive(Clone)]
#[repr(C)]
pub struct MadPcm {
    pub sample_rate: c_uint,
    pub channels: uint16_t,
    pub length: uint16_t,
    pub samples: [[i32; 1152]; 2],
}

impl Default for MadPcm {
    fn default() -> MadPcm {
        MadPcm {
            sample_rate: 0,
            channels: 0,
            length: 0,
            samples: [[0; 1152]; 2],
        }
    }
}

impl fmt::Debug for MadPcm {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "MadPcm {{sample_rate: {}, channels: {}, length: {}}}",
                  self.sample_rate,
                  self.channels,
                  self.length)
    }
}

#[allow(dead_code)]
#[derive(Debug, Clone)]
#[repr(C)]
pub enum MadDecoderMode {
    Sync = 0,
    Async = 1,
}

impl Default for MadDecoderMode {
    fn default() -> MadDecoderMode {
        MadDecoderMode::Sync
    }
}

#[derive(Default)]
#[derive(Debug, Clone)]
#[repr(C)]
struct MadAsyncParameters {
    pid: c_long,
    ain: c_int,
    aout: c_int,
}

#[allow(dead_code, raw_pointer_derive)]
#[derive(Debug, Clone)]
#[repr(C)]
pub struct MadDecoder {
    mode: MadDecoderMode,
    options: c_int,
    async: MadAsyncParameters,
    sync: *const c_void,
    cb_data: *const c_void,
    input_func: *const c_void,
    header_func: *const c_void,
    filter_func: *const c_void,
    output_func: *const c_void,
    error_func: *const c_void,
    message_func: *const c_void,
}

impl Default for MadDecoder {
    fn default() -> MadDecoder {
        MadDecoder {
            mode: MadDecoderMode::Sync,
            options: 0,
            async: Default::default(),
            sync: ptr::null::<c_void>(),
            cb_data: ptr::null::<c_void>(),
            input_func: ptr::null::<c_void>(),
            header_func: ptr::null::<c_void>(),
            filter_func: ptr::null::<c_void>(),
            output_func: ptr::null::<c_void>(),
            error_func: ptr::null::<c_void>(),
            message_func: ptr::null::<c_void>(),
        }
    }
}

#[cfg(test)]
mod test {
}
<commit_msg>Removed unused dependency<commit_after>#![crate_name = "simplemad_sys"]

extern crate libc;

use libc::types::os::arch::c95::{c_int, c_uint, c_ushort, size_t, c_long};
use libc::types::common::c99::*;
use libc::types::common::c95::c_void;
use std::fmt::{self, Result, Debug};
use std::ptr;

pub use libc::c_ulong;

#[allow(dead_code)]
#[link(name = "mad")]
extern {
    pub fn mad_decoder_init(decoder: *mut MadDecoder,
                            message: *mut c_void,
                            input_cb: extern fn(message: *mut c_void,
                                                stream: &MadStream) -> MadFlow,
                            header_cb: extern fn(message: *mut c_void,
                                                 header: &MadHeader) -> MadFlow,
                            filter_cb: extern fn(),
                            output_cb: extern fn(message: *mut c_void,
                                                 header: &MadHeader,
                                                 pcm: &MadPcm) -> MadFlow,
                            error_cb: extern fn(message: *mut c_void,
                                                stream: &MadStream,
                                                frame: *const c_void) -> MadFlow,
                            message_cb: extern fn());

    pub fn mad_decoder_run(decoder: &mut MadDecoder, mode: MadDecoderMode) -> c_int;
    pub fn mad_decoder_finish(decoder: &mut MadDecoder) -> c_int;
    pub fn mad_stream_buffer(stream: &MadStream,
                             buf_start: *const u8,
                             buf_len: c_ulong);

    pub fn mad_header_init(header: &mut MadHeader);
    pub fn mad_stream_init(stream: &mut MadStream);
    pub fn mad_frame_init(frame: &mut MadFrame);
    pub fn mad_synth_init(synth: &mut MadSynth);

    pub fn mad_stream_finish(stream: &mut MadStream);
    pub fn mad_frame_finish(frame: &mut MadFrame);

    pub fn mad_header_decode(header: &mut MadHeader, stream: &mut MadStream);
    pub fn mad_frame_decode(frame: &mut MadFrame, stream: &mut MadStream);
    pub fn mad_synth_frame(synth: &mut MadSynth, frame: &mut MadFrame);
}

/// libmad callbacks return MadFlow values, which are used to control the decoding process
#[allow(dead_code)]
#[derive(Debug, Clone)]
#[repr(C)]
pub enum MadFlow {
    /// continue normally
    Continue = 0x0000,

    /// stop decoding normally
    Stop = 0x0010,

    /// stop decoding and signal an error
    Break = 0x0011,

    /// ignore the current frame
    Ignore = 0x0020,

}

/// Errors generated by libmad
#[derive(Debug, Clone, PartialEq)]
#[repr(C)]
pub enum MadError {
    /// no error
    None = 0x0000,

    /// input buffer too small (or eof)
    BufLen = 0x0001,

    /// invalid (null) buffer pointer
    BufPtr = 0x0002,

    /// not enough memory
    NoMem = 0x0031,

    /// lost synchronization
    LostSync = 0x0101,

    /// reserved header layer value
    BadLayer = 0x0102,

    /// forbidden bitrate value
    BadBitRate = 0x0103,

    /// reserved sample frequency value
    BadSampleRate = 0x0104,

    /// reserved emphasis value
    BadEmphasis = 0x0105,

    /// crc check failed
    BadCRC = 0x0201,

    /// forbidden bit allocation value
    BadBitAlloc = 0x0211,

    /// bad scalefactor index
    BadScaleFactor = 0x0221,

    /// bad bitrate/mode combination
    BadMode = 0x0222,

    /// bad frame length
    BadFrameLen = 0x0231,

    /// bad big_values count
    BadBigValues = 0x0232,

    /// reserved block_type
    BadBlockType = 0x0233,

    /// bad scalefactor selection info
    BadScFSI = 0x0234,

    /// bad main_data_begin pointer
    BadDataPtr = 0x0235,

    /// bad audio data length
    BadPart3Len = 0x0236,

    /// bad huffman table select
    BadHuffTable = 0x0237,

    /// huffman data overrun
    BadHuffData = 0x0238,

    /// incompatible block_type for joint stereo
    BadStereo = 0x0239,
}

impl Default for MadError {
    fn default() -> MadError {
        MadError::None
    }
}

#[derive(Default, Debug, Clone)]
#[repr(C)]
pub struct MadBitPtr {
    pub byte: size_t,
    pub cache: uint16_t,
    pub left: uint16_t,
}

#[allow(dead_code)]
#[derive(Default, Debug, Clone)]
#[repr(C)]
pub struct MadStream {
    pub buffer: size_t,
    pub buff_end: size_t,
    pub skip_len: c_ulong,
    pub sync: c_int,
    pub free_rate: c_ulong,
    pub this_frame: size_t,
    pub next_frame: size_t,
    pub ptr: MadBitPtr,
    pub anc_ptr: MadBitPtr,
    pub anc_bitlen: c_uint,
    pub buffer_mdlen: size_t,
    pub md_len: c_uint,
    pub options: c_int,
    pub error: MadError,
}

#[allow(dead_code, raw_pointer_derive)]
#[derive(Clone)]
#[repr(C)]
pub struct MadFrame {
    pub header: MadHeader,
    pub options: c_int,
    pub sbsample: [[[i32; 32]; 36]; 2],
    pub overlap: *mut i32,
}

impl Default for MadFrame {
    fn default() -> MadFrame {
        MadFrame {
            header: Default::default(),
            options: 0,
            sbsample: [[[0; 32]; 36]; 2],
            overlap: ptr::null::<i32>() as *mut i32,
        }
    }
}

unsafe impl std::marker::Send for MadFrame { }

#[allow(dead_code)]
#[derive(Clone)]
#[repr(C)]
pub struct MadSynth {
    pub filter: [[[[[i32; 8]; 16]; 2]; 2]; 2],
    pub phase: c_uint,
    pub pcm: MadPcm,
}

impl Default for MadSynth {
    fn default() -> MadSynth {
        MadSynth {
            filter: [[[[[0; 8]; 16]; 2]; 2]; 2],
            phase: 0,
            pcm: Default::default()
        }
    }
}

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

#[allow(dead_code)]
#[derive(Debug, Clone)]
#[repr(C)]
pub enum MadLayer {
    Layer1 = 1,
    Layer2 = 2,
    Layer3 = 3,
}

impl Default for MadLayer {
    fn default() -> MadLayer {
        MadLayer::Layer1
    }
}

#[allow(dead_code)]
#[derive(Debug, Clone)]
#[repr(C)]
pub enum MadMode {
    SingleChannel = 0,
    DualChannel = 1,
    JointStereo = 2,
    Stereo = 3,
}

impl Default for MadMode {
    fn default() -> MadMode {
        MadMode::SingleChannel
    }
}

#[allow(dead_code)]
#[derive(Debug, Clone)]
#[repr(C)]
pub enum MadEmphasis {
    None = 0,
    Fifty15Us = 1,
    CcittJ17 = 3,
    Reserved = 2,
}

impl Default for MadEmphasis {
    fn default() -> MadEmphasis {
        MadEmphasis::None
    }
}

#[derive(Default)]
#[derive(Debug, Clone)]
#[repr(C)]
pub struct MadTimer {
    pub seconds: c_long,
    pub fraction: c_ulong,
}

#[allow(dead_code)]
#[derive(Default, Debug, Clone)]
#[repr(C)]
pub struct MadHeader {
    pub layer: MadLayer,
    pub mode: MadMode,
    pub mode_extension: c_int,
    pub emphasis: MadEmphasis,
    pub bit_rate: c_ulong,
    pub sample_rate: c_uint,
    pub crc_check: c_ushort,
    pub crc_target: c_ushort,
    pub flags: c_int,
    pub private_bits: c_int,
    pub duration: MadTimer,
}

#[allow(dead_code)]
#[derive(Clone)]
#[repr(C)]
pub struct MadPcm {
    pub sample_rate: c_uint,
    pub channels: uint16_t,
    pub length: uint16_t,
    pub samples: [[i32; 1152]; 2],
}

impl Default for MadPcm {
    fn default() -> MadPcm {
        MadPcm {
            sample_rate: 0,
            channels: 0,
            length: 0,
            samples: [[0; 1152]; 2],
        }
    }
}

impl fmt::Debug for MadPcm {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "MadPcm {{sample_rate: {}, channels: {}, length: {}}}",
                  self.sample_rate,
                  self.channels,
                  self.length)
    }
}

#[allow(dead_code)]
#[derive(Debug, Clone)]
#[repr(C)]
pub enum MadDecoderMode {
    Sync = 0,
    Async = 1,
}

impl Default for MadDecoderMode {
    fn default() -> MadDecoderMode {
        MadDecoderMode::Sync
    }
}

#[derive(Default)]
#[derive(Debug, Clone)]
#[repr(C)]
struct MadAsyncParameters {
    pid: c_long,
    ain: c_int,
    aout: c_int,
}

#[allow(dead_code, raw_pointer_derive)]
#[derive(Debug, Clone)]
#[repr(C)]
pub struct MadDecoder {
    mode: MadDecoderMode,
    options: c_int,
    async: MadAsyncParameters,
    sync: *const c_void,
    cb_data: *const c_void,
    input_func: *const c_void,
    header_func: *const c_void,
    filter_func: *const c_void,
    output_func: *const c_void,
    error_func: *const c_void,
    message_func: *const c_void,
}

impl Default for MadDecoder {
    fn default() -> MadDecoder {
        MadDecoder {
            mode: MadDecoderMode::Sync,
            options: 0,
            async: Default::default(),
            sync: ptr::null::<c_void>(),
            cb_data: ptr::null::<c_void>(),
            input_func: ptr::null::<c_void>(),
            header_func: ptr::null::<c_void>(),
            filter_func: ptr::null::<c_void>(),
            output_func: ptr::null::<c_void>(),
            error_func: ptr::null::<c_void>(),
            message_func: ptr::null::<c_void>(),
        }
    }
}

#[cfg(test)]
mod test {
}
<|endoftext|>


<commit_before>mod types;

use gl;
use glutin;
use glutin::GlContext;

use application::events::Event;
use errors::*;
use math::prelude::Vector2;

use super::super::settings::WindowParams;
use super::Visitor;

pub struct GlutinVisitor {
    window: glutin::GlWindow,
    events_loop: glutin::EventsLoop,
}

impl GlutinVisitor {
    pub fn new(params: WindowParams) -> Result<Self> {
        let builder = glutin::WindowBuilder::new()
            .with_title(params.title)
            .with_dimensions(glutin::dpi::LogicalSize::new(
                params.size.x as f64,
                params.size.y as f64,
            )).with_multitouch();

        let context = glutin::ContextBuilder::new()
            .with_multisampling(params.multisample as u16)
            .with_gl_profile(glutin::GlProfile::Core)
            .with_gl(glutin::GlRequest::Latest)
            .with_vsync(params.vsync);

        let events_loop = glutin::EventsLoop::new();
        let device = glutin::GlWindow::new(builder, context, &events_loop).unwrap();

        unsafe {
            device.make_current()?;
            gl::load_with(|symbol| device.get_proc_address(symbol) as *const _);
        }

        Ok(GlutinVisitor {
            window: device,
            events_loop: events_loop,
        })
    }
}

impl Visitor for GlutinVisitor {
    #[inline]
    fn show(&self) {
        self.window.show();
    }

    #[inline]
    fn hide(&self) {
        self.window.hide();
    }

    #[inline]
    fn position_in_points(&self) -> Vector2<i32> {
        let pos = self.window.get_position().unwrap();
        Vector2::new(pos.x as i32, pos.y as i32)
    }

    #[inline]
    fn dimensions_in_points(&self) -> Vector2<u32> {
        let size = self.window.get_inner_size().unwrap();
        Vector2::new(size.width as u32, size.height as u32)
    }

    #[inline]
    fn hidpi(&self) -> f32 {
        self.window.get_hidpi_factor() as f32
    }

    #[inline]
    fn resize(&self, dimensions: Vector2<u32>) {
        let size = glutin::dpi::PhysicalSize::new(dimensions.x as f64, dimensions.y as f64);
        self.window.resize(size)
    }

    #[inline]
    fn poll_events(&mut self, events: &mut Vec<Event>) {
        let dims = self.dimensions_in_points();
        self.events_loop.poll_events(|v| {
            if let Some(e) = types::from_event(v, dims) {
                events.push(e);
            }
        });
    }

    #[inline]
    fn is_current(&self) -> bool {
        self.window.is_current()
    }

    #[inline]
    fn make_current(&self) -> Result<()> {
        unsafe {
            self.window.make_current()?;
            Ok(())
        }
    }

    #[inline]
    fn swap_buffers(&self) -> Result<()> {
        self.window.swap_buffers()?;
        Ok(())
    }
}
<commit_msg>Workaround for empty window under macOS Mojava (10.14).<commit_after>mod types;

use gl;
use glutin;
use glutin::GlContext;

use application::events::Event;
use errors::*;
use math::prelude::Vector2;

use super::super::settings::WindowParams;
use super::Visitor;

pub struct GlutinVisitor {
    window: glutin::GlWindow,
    events_loop: glutin::EventsLoop,
}

impl GlutinVisitor {
    pub fn new(params: WindowParams) -> Result<Self> {
        let builder = glutin::WindowBuilder::new()
            .with_title(params.title)
            .with_dimensions(glutin::dpi::LogicalSize::new(
                params.size.x as f64,
                params.size.y as f64,
            )).with_multitouch();

        let context = glutin::ContextBuilder::new()
            .with_multisampling(params.multisample as u16)
            .with_gl_profile(glutin::GlProfile::Core)
            .with_gl(glutin::GlRequest::Latest)
            .with_vsync(params.vsync);

        let events_loop = glutin::EventsLoop::new();
        let window = glutin::GlWindow::new(builder, context, &events_loop).unwrap();
        let mut visitor = GlutinVisitor {
            window: window,
            events_loop: events_loop,
        };

        let size = visitor.dimensions_in_points();
        let hi = visitor.hidpi();
        let dims = Vector2::new((size.x as f32 * hi) as u32, (size.y as f32 * hi) as u32);
        visitor.events_loop.poll_events(|_| {});
        visitor.resize(dims);

        unsafe {
            visitor.window.make_current()?;
            gl::load_with(|symbol| visitor.window.get_proc_address(symbol) as *const _);
        }

        Ok(visitor)
    }
}

impl Visitor for GlutinVisitor {
    #[inline]
    fn show(&self) {
        self.window.show();
    }

    #[inline]
    fn hide(&self) {
        self.window.hide();
    }

    #[inline]
    fn position_in_points(&self) -> Vector2<i32> {
        let pos = self.window.get_position().unwrap();
        Vector2::new(pos.x as i32, pos.y as i32)
    }

    #[inline]
    fn dimensions_in_points(&self) -> Vector2<u32> {
        let size = self.window.get_inner_size().unwrap();
        Vector2::new(size.width as u32, size.height as u32)
    }

    #[inline]
    fn hidpi(&self) -> f32 {
        self.window.get_hidpi_factor() as f32
    }

    #[inline]
    fn resize(&self, dimensions: Vector2<u32>) {
        let size = glutin::dpi::PhysicalSize::new(dimensions.x as f64, dimensions.y as f64);
        self.window.resize(size)
    }

    #[inline]
    fn poll_events(&mut self, events: &mut Vec<Event>) {
        let dims = self.dimensions_in_points();
        self.events_loop.poll_events(|v| {
            if let Some(e) = types::from_event(v, dims) {
                events.push(e);
            }
        });
    }

    #[inline]
    fn is_current(&self) -> bool {
        self.window.is_current()
    }

    #[inline]
    fn make_current(&self) -> Result<()> {
        unsafe {
            self.window.make_current()?;
            Ok(())
        }
    }

    #[inline]
    fn swap_buffers(&self) -> Result<()> {
        self.window.swap_buffers()?;
        Ok(())
    }
}
<|endoftext|>


<commit_before>use geojson::Geometry;
use serde_json::json;

use super::coord::Coord;
use super::{filters, settings};

pub fn build_query(
    q: &str,
    filters: filters::Filters,
    _langs: &[&str],
    settings: &settings::QuerySettings,
) -> serde_json::Value {
    let string_query = build_string_query(q, &settings.string_query);
    let boosts = build_boosts(q, settings, &filters);
    let filters = build_filters(filters.shape, filters.poi_types, filters.zone_types);
    if filters.is_empty() {
        json!({
            "query": {
                "bool": {
                    "must": [ string_query ],
                    "should": boosts
                }
            }
        })
    } else {
        json!({
            "query": {
                "bool": {
                    "must": [ string_query ],
                    "should": boosts,
                    "filter": {
                        "bool": {
                            "must": filters
                        }
                    }
                }
            }
        })
    }
}

fn build_string_query(q: &str, settings: &settings::StringQuery) -> serde_json::Value {
    json!({
        "bool": {
            "boost": settings.global,
            "should": [
                {
                    "multi_match": {
                        "query": q,
                        "type": "bool_prefix",
                        "fields": [
                            "label", "label._2gram", "label._3gram", "name"
                        ]
                    }
                }
            ]
        }
    })
}

fn build_filters(
    shape: Option<(Geometry, Vec<String>)>,
    poi_types: Option<Vec<String>>,
    zone_types: Option<Vec<String>>,
) -> Vec<serde_json::Value> {
    let mut filters: Vec<Option<serde_json::Value>> = Vec::new();
    let geoshape_filter = shape.map(|(geometry, scope)| build_shape_query(geometry, scope));
    filters.push(geoshape_filter);
    let poi_types_filter = poi_types.map(build_poi_types_filter);
    filters.push(poi_types_filter);
    let zone_types_filter = zone_types.map(build_zone_types_filter);
    filters.push(zone_types_filter);
    filters.into_iter().flatten().collect()
}

fn build_boosts(
    _q: &str,
    settings: &settings::QuerySettings,
    filters: &filters::Filters,
) -> Vec<serde_json::Value> {
    let mut boosts: Vec<Option<serde_json::Value>> = Vec::new();
    // TODO: in production, admins are boosted by their weight only in prefix mode.
    let admin_weight_boost = Some(build_admin_weight_query(&settings.importance_query));
    boosts.push(admin_weight_boost);
    let mut decay = settings.importance_query.proximity.decay.clone();
    if let Some(proximity) = &filters.proximity {
        decay.scale = proximity.scale;
        decay.offset = proximity.offset;
        decay.decay = proximity.decay;
    }
    let proximity_boost = filters
        .coord
        .clone()
        .map(|coord| build_proximity_boost(coord, &decay));
    boosts.push(proximity_boost);
    let place_type_boost = Some(build_place_type_boost(&settings.type_query.boosts));
    boosts.push(place_type_boost);
    boosts.into_iter().flatten().collect()
}

fn build_admin_weight_query(settings: &settings::ImportanceQueryBoosts) -> serde_json::Value {
    json!({
        "function_score": {
            "query": { "term": { "type": "admin" } },
            "boost_mode": "replace",
            "functions": [
                {
                    "field_value_factor": {
                        "field": "weight",
                        "factor": 1e6,
                        "modifier": "log1p",
                        "missing": 0
                    }
                },
                {
                    // TODO: in production, this weight depends of the focus radius
                    "weight": settings.weights.max_radius.admin
                }
            ]
        }
    })
}

fn build_place_type_boost(settings: &settings::Types) -> serde_json::Value {
    json!({
        "bool": {
            "should": [
                { "term": { "type": { "value": "admin", "boost": settings.admin } } },
                { "term": { "type": { "value": "addr", "boost": settings.address } } },
                { "term": { "type": { "value": "stop", "boost": settings.stop } } },
                { "term": { "type": { "value": "poi", "boost": settings.poi } } },
                { "term": { "type": { "value": "street", "boost": settings.street } } },
            ]
        }
    })
}

fn build_proximity_boost(coord: Coord, settings_decay: &settings::Decay) -> serde_json::Value {
    let settings::Decay {
        func,
        scale,
        offset,
        decay,
    } = settings_decay;

    json!({
        "function_score": {
            func.clone(): {
                "coord": {
                    "origin": {
                        "lat": coord.lat,
                        "lon": coord.lon
                    },
                    "scale": format!("{}km", scale),
                    "offset": format!("{}km", offset),
                    "decay": decay
                }
            }
        }
    })
}

pub fn build_reverse_query(distance: &str, lat: f64, lon: f64) -> serde_json::Value {
    json!({
    "query": {
        "bool": {
            "must": {
                "match_all": {}
            },
            "filter": {
                "geo_distance": {
                    "distance": distance,
                    "coord": {
                        "lat": lat,
                        "lon": lon
                    }
                }
            }
        }
    },
    "sort": [{
         "_geo_distance": {
             "coord": {
                 "lat": lat,
                 "lon": lon
             },
             "order": "asc",
             "unit": "m",
             "mode": "min",
             "distance_type": "arc",
             "ignore_unmapped": true
         }
     }]
    })
}

// If there is a shape, all the places listed in shape_scope are restricted to the shape.
// and the places that are not listed are not restricted.
// So if shape_scope = {A, B}, we should end up with something like
// should [
//   must {               => filwer_w_shape
//     term: _type in {A, B}
//     filter: geoshape
//   },
//   must_not {            => filter_wo_shape
//      term: _type in {A, B}
//   }
// ]
//
pub fn build_shape_query(shape: Geometry, scope: Vec<String>) -> serde_json::Value {
    json!({
        "bool": {
            "should": [
            {
                "bool": {
                    "must": {
                        "terms": {
                            "type": scope
                        }
                    },
                    "filter": {
                        "geo_shape": {
                            "approx_coord": {
                                "shape": shape,
                            "relation": "intersects"
                            }
                        }
                    }
                }
            },
            {
                "bool": {
                    "must_not": {
                        "terms": {
                            "type": scope
                        }
                    }
                }
            }
            ]
        }
    })
}

// If we search for POIs and we specify poi_types, then we add a filter that should say something
// like:
// If the place is a POI, then its poi_type must be part of the given list
// So if poi_types = {A, B}, we should end up with something like
// should [
//   must {               => for pois, filter their poi types
//     type: poi
//     filter: poi_types = {A, B}
//   },
//   must_not {            => or don't filter for poi types on other places
//      type: poi
//   }
// ]
pub fn build_poi_types_filter(poi_types: Vec<String>) -> serde_json::Value {
    json!({
        "bool": {
            "should": [
            {
                "bool": {
                    "must": {
                        "term": {
                            "_source.type": "poi"
                        }
                    },
                    "filter": {
                        "terms": {
                            "_source.poi_type.id": poi_types
                        }
                    }
                }
            },
            {
                "bool": {
                    "must_not": {
                        "term": {
                            "_source.type": "poi"
                        }
                    }
                }
            }
            ]
        }
    })
}

// If we search for administrative regions and we specify zone_types, then we add a filter that should say something
// like:
// If the place is an administrative region, then its zone_type must be part of the given list
// So if zone_type = {A, B}, we should end up with something like
// should [
//   must {               => for admins, make sure they have the right zone type
//     type: admin
//     filter: zone_types
//   },
//   must_not {            => no filter on zone types for other places
//      type: admin
//   }
// ]
//
//
pub fn build_zone_types_filter(zone_types: Vec<String>) -> serde_json::Value {
    json!({
        "bool": {
            "should": [
                {
                    "bool": {
                        "must": {
                            "term": {
                                "type": "admin"
                            }
                        },
                        "filter": {
                            "terms": {
                                "zone_type":zone_types
                            }
                        }
                    }
                },
                {
                    "bool": {
                        "must_not": {
                            "term": {
                                "type": "admin"
                            }
                        }
                    }
                }
            ]
        }
    })
}

pub fn build_features_query(indices: &[String], doc_id: &str) -> serde_json::Value {
    let vec: Vec<BTreeMap<&str, &str>> = indices
        .iter()
        .map(|index| {
            vec![("_index", index.as_str()), ("_id", doc_id)]
                .into_iter()
                .collect()
        })
        .collect();
    json!({ "docs": vec })
}
<commit_msg>Fix GA<commit_after>use geojson::Geometry;
use serde_json::json;
use std::collections::BTreeMap;

use super::coord::Coord;
use super::{filters, settings};

pub fn build_query(
    q: &str,
    filters: filters::Filters,
    _langs: &[&str],
    settings: &settings::QuerySettings,
) -> serde_json::Value {
    let string_query = build_string_query(q, &settings.string_query);
    let boosts = build_boosts(q, settings, &filters);
    let filters = build_filters(filters.shape, filters.poi_types, filters.zone_types);
    if filters.is_empty() {
        json!({
            "query": {
                "bool": {
                    "must": [ string_query ],
                    "should": boosts
                }
            }
        })
    } else {
        json!({
            "query": {
                "bool": {
                    "must": [ string_query ],
                    "should": boosts,
                    "filter": {
                        "bool": {
                            "must": filters
                        }
                    }
                }
            }
        })
    }
}

fn build_string_query(q: &str, settings: &settings::StringQuery) -> serde_json::Value {
    json!({
        "bool": {
            "boost": settings.global,
            "should": [
                {
                    "multi_match": {
                        "query": q,
                        "type": "bool_prefix",
                        "fields": [
                            "label", "label._2gram", "label._3gram", "name"
                        ]
                    }
                }
            ]
        }
    })
}

fn build_filters(
    shape: Option<(Geometry, Vec<String>)>,
    poi_types: Option<Vec<String>>,
    zone_types: Option<Vec<String>>,
) -> Vec<serde_json::Value> {
    let mut filters: Vec<Option<serde_json::Value>> = Vec::new();
    let geoshape_filter = shape.map(|(geometry, scope)| build_shape_query(geometry, scope));
    filters.push(geoshape_filter);
    let poi_types_filter = poi_types.map(build_poi_types_filter);
    filters.push(poi_types_filter);
    let zone_types_filter = zone_types.map(build_zone_types_filter);
    filters.push(zone_types_filter);
    filters.into_iter().flatten().collect()
}

fn build_boosts(
    _q: &str,
    settings: &settings::QuerySettings,
    filters: &filters::Filters,
) -> Vec<serde_json::Value> {
    let mut boosts: Vec<Option<serde_json::Value>> = Vec::new();
    // TODO: in production, admins are boosted by their weight only in prefix mode.
    let admin_weight_boost = Some(build_admin_weight_query(&settings.importance_query));
    boosts.push(admin_weight_boost);
    let mut decay = settings.importance_query.proximity.decay.clone();
    if let Some(proximity) = &filters.proximity {
        decay.scale = proximity.scale;
        decay.offset = proximity.offset;
        decay.decay = proximity.decay;
    }
    let proximity_boost = filters
        .coord
        .clone()
        .map(|coord| build_proximity_boost(coord, &decay));
    boosts.push(proximity_boost);
    let place_type_boost = Some(build_place_type_boost(&settings.type_query.boosts));
    boosts.push(place_type_boost);
    boosts.into_iter().flatten().collect()
}

fn build_admin_weight_query(settings: &settings::ImportanceQueryBoosts) -> serde_json::Value {
    json!({
        "function_score": {
            "query": { "term": { "type": "admin" } },
            "boost_mode": "replace",
            "functions": [
                {
                    "field_value_factor": {
                        "field": "weight",
                        "factor": 1e6,
                        "modifier": "log1p",
                        "missing": 0
                    }
                },
                {
                    // TODO: in production, this weight depends of the focus radius
                    "weight": settings.weights.max_radius.admin
                }
            ]
        }
    })
}

fn build_place_type_boost(settings: &settings::Types) -> serde_json::Value {
    json!({
        "bool": {
            "should": [
                { "term": { "type": { "value": "admin", "boost": settings.admin } } },
                { "term": { "type": { "value": "addr", "boost": settings.address } } },
                { "term": { "type": { "value": "stop", "boost": settings.stop } } },
                { "term": { "type": { "value": "poi", "boost": settings.poi } } },
                { "term": { "type": { "value": "street", "boost": settings.street } } },
            ]
        }
    })
}

fn build_proximity_boost(coord: Coord, settings_decay: &settings::Decay) -> serde_json::Value {
    let settings::Decay {
        func,
        scale,
        offset,
        decay,
    } = settings_decay;

    json!({
        "function_score": {
            func.clone(): {
                "coord": {
                    "origin": {
                        "lat": coord.lat,
                        "lon": coord.lon
                    },
                    "scale": format!("{}km", scale),
                    "offset": format!("{}km", offset),
                    "decay": decay
                }
            }
        }
    })
}

pub fn build_reverse_query(distance: &str, lat: f64, lon: f64) -> serde_json::Value {
    json!({
    "query": {
        "bool": {
            "must": {
                "match_all": {}
            },
            "filter": {
                "geo_distance": {
                    "distance": distance,
                    "coord": {
                        "lat": lat,
                        "lon": lon
                    }
                }
            }
        }
    },
    "sort": [{
         "_geo_distance": {
             "coord": {
                 "lat": lat,
                 "lon": lon
             },
             "order": "asc",
             "unit": "m",
             "mode": "min",
             "distance_type": "arc",
             "ignore_unmapped": true
         }
     }]
    })
}

// If there is a shape, all the places listed in shape_scope are restricted to the shape.
// and the places that are not listed are not restricted.
// So if shape_scope = {A, B}, we should end up with something like
// should [
//   must {               => filwer_w_shape
//     term: _type in {A, B}
//     filter: geoshape
//   },
//   must_not {            => filter_wo_shape
//      term: _type in {A, B}
//   }
// ]
//
pub fn build_shape_query(shape: Geometry, scope: Vec<String>) -> serde_json::Value {
    json!({
        "bool": {
            "should": [
            {
                "bool": {
                    "must": {
                        "terms": {
                            "type": scope
                        }
                    },
                    "filter": {
                        "geo_shape": {
                            "approx_coord": {
                                "shape": shape,
                            "relation": "intersects"
                            }
                        }
                    }
                }
            },
            {
                "bool": {
                    "must_not": {
                        "terms": {
                            "type": scope
                        }
                    }
                }
            }
            ]
        }
    })
}

// If we search for POIs and we specify poi_types, then we add a filter that should say something
// like:
// If the place is a POI, then its poi_type must be part of the given list
// So if poi_types = {A, B}, we should end up with something like
// should [
//   must {               => for pois, filter their poi types
//     type: poi
//     filter: poi_types = {A, B}
//   },
//   must_not {            => or don't filter for poi types on other places
//      type: poi
//   }
// ]
pub fn build_poi_types_filter(poi_types: Vec<String>) -> serde_json::Value {
    json!({
        "bool": {
            "should": [
            {
                "bool": {
                    "must": {
                        "term": {
                            "_source.type": "poi"
                        }
                    },
                    "filter": {
                        "terms": {
                            "_source.poi_type.id": poi_types
                        }
                    }
                }
            },
            {
                "bool": {
                    "must_not": {
                        "term": {
                            "_source.type": "poi"
                        }
                    }
                }
            }
            ]
        }
    })
}

// If we search for administrative regions and we specify zone_types, then we add a filter that should say something
// like:
// If the place is an administrative region, then its zone_type must be part of the given list
// So if zone_type = {A, B}, we should end up with something like
// should [
//   must {               => for admins, make sure they have the right zone type
//     type: admin
//     filter: zone_types
//   },
//   must_not {            => no filter on zone types for other places
//      type: admin
//   }
// ]
//
//
pub fn build_zone_types_filter(zone_types: Vec<String>) -> serde_json::Value {
    json!({
        "bool": {
            "should": [
                {
                    "bool": {
                        "must": {
                            "term": {
                                "type": "admin"
                            }
                        },
                        "filter": {
                            "terms": {
                                "zone_type":zone_types
                            }
                        }
                    }
                },
                {
                    "bool": {
                        "must_not": {
                            "term": {
                                "type": "admin"
                            }
                        }
                    }
                }
            ]
        }
    })
}

pub fn build_features_query(indices: &[String], doc_id: &str) -> serde_json::Value {
    let vec: Vec<BTreeMap<&str, &str>> = indices
        .iter()
        .map(|index| {
            vec![("_index", index.as_str()), ("_id", doc_id)]
                .into_iter()
                .collect()
        })
        .collect();
    json!({ "docs": vec })
}
<|endoftext|>


<commit_before>use compact::CVec;
use descartes::{P2, V2, Segment, clipper, SimpleShape, Shape, Path, FiniteCurve,
                WithUniqueOrthogonal};
use stagemaster::geometry::{CShape, CPath};
use land_use::buildings::BuildingStyle;
use itertools::Itertools;

use transport::transport_planning::RoadPrototype;

use planning::{Plan, PlanResult, Prototype, GestureIntent, Version};

pub mod interaction;

#[derive(Compact, Clone)]
pub enum ZoneIntent {
    LandUse(LandUse),
    MaxHeight(u8),
    SetBack(u8),
}

#[derive(Copy, Clone)]
pub enum LandUse {
    Residential,
    Commercial,
    Industrial,
    Agricultural,
    Recreational,
    Official,
}

#[derive(Compact, Clone)]
pub struct Lot {
    pub shape: CShape,
    pub land_uses: CVec<LandUse>,
    pub max_height: u8,
    pub set_back: u8,
    pub connection_points: CVec<(P2, V2)>,
}

impl Lot {
    pub fn center_point(&self) -> P2 {
        P2::from_coordinates(
            self.shape.outline().segments().iter().fold(
                V2::new(0.0, 0.0),
                |sum_point,
                 segment| {
                    sum_point + segment.start().coords
                },
            ) / self.shape.outline().segments().len() as f32,
        )
    }
}

#[derive(Compact, Clone)]
pub struct BuildingIntent {
    pub lot: Lot,
    pub building_style: BuildingStyle,
}

#[derive(Compact, Clone)]
pub struct LotPrototype {
    pub lot: Lot,
    pub occupancy: LotOccupancy,
    pub based_on: Version,
}

#[derive(Copy, Clone, PartialEq, Eq)]
pub enum LotOccupancy {
    Vacant,
    Occupied(BuildingStyle),
}

pub fn calculate_prototypes(
    plan: &Plan,
    current_result: &PlanResult,
    based_on: Version,
) -> Vec<Prototype> {
    println!("Calculating protos");
    let paved_area_shapes = current_result
        .prototypes
        .values()
        .filter_map(|prototype| {
            if let Prototype::Road(RoadPrototype::PavedArea(ref shape)) = *prototype {
                Some(shape)
            } else {
                None
            }
        })
        .collect::<Vec<_>>();

    let building_prototypes = plan.gestures
        .values()
        .filter_map(|gesture| {
            if let GestureIntent::Building(BuildingIntent { ref lot, building_style }) =
                gesture.intent
            {
                let mut shape = lot.shape.clone();

                for paved_area_shape in &paved_area_shapes {

                    if let Ok(clip_results) = clipper::clip(
                        clipper::Mode::Difference,
                        &shape,
                        paved_area_shape,
                    )
                    {
                        if let Some(main_piece) = clip_results.into_iter().find(|piece| {
                            piece.contains(lot.center_point())
                        })
                        {
                            shape = main_piece;
                        } else {
                            println!("No piece contains center");
                            return None;
                        }
                    } else {
                        println!("Building lot clip error");
                        return None;
                    }
                }

                Some(Prototype::Lot(LotPrototype {
                    lot: Lot { shape: shape, ..lot.clone() },
                    occupancy: LotOccupancy::Occupied(building_style),
                    based_on,
                }))
            } else {
                None
            }
        })
        .collect::<Vec<_>>();

    let vacant_lot_prototypes = {
        let building_shapes = building_prototypes
            .iter()
            .filter_map(|prototype| if let Prototype::Lot(LotPrototype {
                                                  occupancy: LotOccupancy::Occupied(_),
                                                  lot: Lot { ref shape, .. },
                                                  based_on,
                                              }) = *prototype
            {
                Some(shape)
            } else {
                None
            })
            .collect::<Vec<_>>();

        let mut land_use_shapes = plan.gestures
            .values()
            .filter_map(|gesture| {
                if let GestureIntent::Zone(ZoneIntent::LandUse(land_use)) = gesture.intent {
                    Some((land_use, &gesture.points))
                } else {
                    None
                }
            })
            .filter_map(|(land_use, points)| {
                Some((
                    land_use,
                    CShape::new(CPath::new(
                        points
                            .iter()
                            .chain(points.first())
                            .tuple_windows()
                            .filter_map(|(start, end)| Segment::line(*start, *end))
                            .collect(),
                    ).ok()?).ok()?,
                ))
            })
            .collect::<Vec<_>>();

        for paved_area_or_building_shape in paved_area_shapes.iter().chain(building_shapes.iter()) {
            land_use_shapes = land_use_shapes
                .into_iter()
                .flat_map(|(land_use, shape)| {
                    clipper::clip(
                        clipper::Mode::Difference,
                        &shape,
                        paved_area_or_building_shape,
                    ).ok()
                        .map(|cut_shapes| {
                            cut_shapes
                                .into_iter()
                                .map(|cut_shape| (land_use, cut_shape))
                                .collect()
                        })
                        .unwrap_or_else(Vec::new)
                })
                .collect()
        }

        println!("{} land use shapes", land_use_shapes.len());

        land_use_shapes
            .into_iter()
            .filter_map(|(land_use, shape)| {
                let connection_points = shape
                    .outline()
                    .segments()
                    .iter()
                    .flat_map(|segment| {
                        let length = segment.length();
                        (&[0.25, 0.5, 0.75])
                            .iter()
                            .map(|ratio| {
                                (
                                    segment.along(length * ratio),
                                    -segment.direction_along(length * ratio).orthogonal(),
                                )
                            })
                            .collect::<Vec<_>>()
                    })
                    .filter(|&(point, _dir)| {
                        // TODO: this is a horribly slow way to find connection points
                        paved_area_shapes.iter().any(|paved_area| {
                            paved_area.contains(point)
                        })
                    })
                    .collect::<CVec<_>>();

                if connection_points.is_empty() {
                    println!("No connection point found");
                    None
                } else {
                    Some(Prototype::Lot(LotPrototype {
                        lot: Lot {
                            land_uses: vec![land_use].into(),
                            max_height: 0,
                            set_back: 0,
                            connection_points,
                            shape,
                        },
                        occupancy: LotOccupancy::Vacant,
                        based_on,
                    }))
                }
            })
            .collect::<Vec<_>>()
    };

    vacant_lot_prototypes
        .into_iter()
        .chain(building_prototypes)
        .collect()
}
<commit_msg>Better lot center calculation<commit_after>use compact::CVec;
use descartes::{P2, V2, Segment, clipper, SimpleShape, Shape, Path, FiniteCurve,
                WithUniqueOrthogonal};
use stagemaster::geometry::{CShape, CPath};
use land_use::buildings::BuildingStyle;
use itertools::Itertools;

use transport::transport_planning::RoadPrototype;

use planning::{Plan, PlanResult, Prototype, GestureIntent, Version};

pub mod interaction;

#[derive(Compact, Clone)]
pub enum ZoneIntent {
    LandUse(LandUse),
    MaxHeight(u8),
    SetBack(u8),
}

#[derive(Copy, Clone)]
pub enum LandUse {
    Residential,
    Commercial,
    Industrial,
    Agricultural,
    Recreational,
    Official,
}

#[derive(Compact, Clone)]
pub struct Lot {
    pub shape: CShape,
    pub land_uses: CVec<LandUse>,
    pub max_height: u8,
    pub set_back: u8,
    pub connection_points: CVec<(P2, V2)>,
}

impl Lot {
    pub fn center_point(&self) -> P2 {
        let outline = self.shape.outline();
        P2::from_coordinates(
            (0..10u8).into_iter().fold(
                V2::new(0.0, 0.0),
                |sum_point, i| {
                    sum_point + outline.along(f32::from(i) * outline.length() / 10.0).coords
                },
            ) / 10.0,
        )
    }
}

#[derive(Compact, Clone)]
pub struct BuildingIntent {
    pub lot: Lot,
    pub building_style: BuildingStyle,
}

#[derive(Compact, Clone)]
pub struct LotPrototype {
    pub lot: Lot,
    pub occupancy: LotOccupancy,
    pub based_on: Version,
}

#[derive(Copy, Clone, PartialEq, Eq)]
pub enum LotOccupancy {
    Vacant,
    Occupied(BuildingStyle),
}

pub fn calculate_prototypes(
    plan: &Plan,
    current_result: &PlanResult,
    based_on: Version,
) -> Vec<Prototype> {
    println!("Calculating protos");
    let paved_area_shapes = current_result
        .prototypes
        .values()
        .filter_map(|prototype| {
            if let Prototype::Road(RoadPrototype::PavedArea(ref shape)) = *prototype {
                Some(shape)
            } else {
                None
            }
        })
        .collect::<Vec<_>>();

    let building_prototypes = plan.gestures
        .values()
        .filter_map(|gesture| {
            if let GestureIntent::Building(BuildingIntent { ref lot, building_style }) =
                gesture.intent
            {
                let mut shape = lot.shape.clone();

                for paved_area_shape in &paved_area_shapes {

                    if let Ok(clip_results) = clipper::clip(
                        clipper::Mode::Difference,
                        &shape,
                        paved_area_shape,
                    )
                    {
                        if let Some(main_piece) = clip_results.into_iter().find(|piece| {
                            piece.contains(lot.center_point())
                        })
                        {
                            shape = main_piece;
                        } else {
                            println!("No piece contains center");
                            return None;
                        }
                    } else {
                        println!("Building lot clip error");
                        return None;
                    }
                }

                Some(Prototype::Lot(LotPrototype {
                    lot: Lot { shape: shape, ..lot.clone() },
                    occupancy: LotOccupancy::Occupied(building_style),
                    based_on,
                }))
            } else {
                None
            }
        })
        .collect::<Vec<_>>();

    let vacant_lot_prototypes = {
        let building_shapes = building_prototypes
            .iter()
            .filter_map(|prototype| if let Prototype::Lot(LotPrototype {
                                                  occupancy: LotOccupancy::Occupied(_),
                                                  lot: Lot { ref shape, .. },
                                                  based_on,
                                              }) = *prototype
            {
                Some(shape)
            } else {
                None
            })
            .collect::<Vec<_>>();

        let mut land_use_shapes = plan.gestures
            .values()
            .filter_map(|gesture| {
                if let GestureIntent::Zone(ZoneIntent::LandUse(land_use)) = gesture.intent {
                    Some((land_use, &gesture.points))
                } else {
                    None
                }
            })
            .filter_map(|(land_use, points)| {
                Some((
                    land_use,
                    CShape::new(CPath::new(
                        points
                            .iter()
                            .chain(points.first())
                            .tuple_windows()
                            .filter_map(|(start, end)| Segment::line(*start, *end))
                            .collect(),
                    ).ok()?).ok()?,
                ))
            })
            .collect::<Vec<_>>();

        for paved_area_or_building_shape in paved_area_shapes.iter().chain(building_shapes.iter()) {
            land_use_shapes = land_use_shapes
                .into_iter()
                .flat_map(|(land_use, shape)| {
                    clipper::clip(
                        clipper::Mode::Difference,
                        &shape,
                        paved_area_or_building_shape,
                    ).ok()
                        .map(|cut_shapes| {
                            cut_shapes
                                .into_iter()
                                .map(|cut_shape| (land_use, cut_shape))
                                .collect()
                        })
                        .unwrap_or_else(Vec::new)
                })
                .collect()
        }

        println!("{} land use shapes", land_use_shapes.len());

        land_use_shapes
            .into_iter()
            .filter_map(|(land_use, shape)| {
                let connection_points = shape
                    .outline()
                    .segments()
                    .iter()
                    .flat_map(|segment| {
                        let length = segment.length();
                        (&[0.25, 0.5, 0.75])
                            .iter()
                            .map(|ratio| {
                                (
                                    segment.along(length * ratio),
                                    -segment.direction_along(length * ratio).orthogonal(),
                                )
                            })
                            .collect::<Vec<_>>()
                    })
                    .filter(|&(point, _dir)| {
                        // TODO: this is a horribly slow way to find connection points
                        paved_area_shapes.iter().any(|paved_area| {
                            paved_area.contains(point)
                        })
                    })
                    .collect::<CVec<_>>();

                if connection_points.is_empty() {
                    println!("No connection point found");
                    None
                } else {
                    Some(Prototype::Lot(LotPrototype {
                        lot: Lot {
                            land_uses: vec![land_use].into(),
                            max_height: 0,
                            set_back: 0,
                            connection_points,
                            shape,
                        },
                        occupancy: LotOccupancy::Vacant,
                        based_on,
                    }))
                }
            })
            .collect::<Vec<_>>()
    };

    vacant_lot_prototypes
        .into_iter()
        .chain(building_prototypes)
        .collect()
}
<|endoftext|>