<commit_before>pub use amq_protocol::protocol::BasicProperties;

use amq_protocol::frame::AMQPFrame;
use crossbeam_channel::Sender;
use log::error;

use std::result;
use std::collections::{HashMap, HashSet, VecDeque};

use crate::api::{Answer, ChannelState};
use crate::error::{Error, ErrorKind};
use crate::message::BasicGetMessage;
use crate::queue::Queue;

#[derive(Debug)]
pub struct Channel {
  pub id:             u16,
  pub state:          ChannelState,
  pub send_flow:      bool,
  pub receive_flow:   bool,
  pub queues:         HashMap<String, Queue>,
  pub prefetch_size:  u32,
  pub prefetch_count: u16,
  pub confirm:        bool,
  pub acked:          HashSet<u64>,
  pub nacked:         HashSet<u64>,
  pub unacked:        HashSet<u64>,
  pub awaiting:       VecDeque<Answer>,
      delivery_tag:   u64,
      frame_sender:   Sender<AMQPFrame>,
}

impl Channel {
  pub fn new(channel_id: u16, frame_sender: Sender<AMQPFrame>) -> Channel {
    Channel {
      id:             channel_id,
      state:          ChannelState::Initial,
      send_flow:      true,
      receive_flow:   true,
      queues:         HashMap::new(),
      prefetch_size:  0,
      prefetch_count: 0,
      confirm:        false,
      acked:          HashSet::new(),
      nacked:         HashSet::new(),
      unacked:        HashSet::new(),
      awaiting:       VecDeque::new(),
      delivery_tag:   1,
      frame_sender,
    }
  }

  /// verifies if the channel's state is the one passed as argument
  pub fn check_state(&self, state: ChannelState) -> result::Result<(), Error> {
    if self.state == state {
      Ok(())
    } else {
      Err(ErrorKind::InvalidState {
        expected: state,
        actual:   self.state.clone(),
      }.into())
    }
  }

  /// gets the next message corresponding to a queue, in response to a basic.get
  ///
  /// If there is no message, the method will return None
  pub fn next_basic_get_message(&mut self, queue_name: &str) -> Option<BasicGetMessage> {
      self.queues.get_mut(queue_name).and_then(|queue| queue.next_basic_get_message())
  }

  #[doc(hidden)]
  pub fn handle_content_header_frame(&mut self, size: u64, properties: BasicProperties) {
    if let ChannelState::WillReceiveContent(queue_name, consumer_tag) = self.state.clone() {
      if size > 0 {
        self.state = ChannelState::ReceivingContent(queue_name.clone(), consumer_tag.clone(), size as usize);
      } else {
        self.state = ChannelState::Connected;
      }
      if let Some(ref mut q) = self.queues.get_mut(&queue_name) {
        if let Some(ref consumer_tag) = consumer_tag {
          if let Some(ref mut cs) = q.consumers.get_mut(consumer_tag) {
            cs.set_delivery_properties(properties);
            if size == 0 {
              cs.new_delivery_complete();
            }
          }
        } else {
          q.set_delivery_properties(properties);
          if size == 0 {
            q.new_delivery_complete();
          }
        }
      }
    } else {
      self.state = ChannelState::Error;
    }
  }

  #[doc(hidden)]
  pub fn handle_body_frame(&mut self, payload: Vec<u8>) {
    let payload_size = payload.len();

    if let ChannelState::ReceivingContent(queue_name, opt_consumer_tag, remaining_size) = self.state.clone() {
      if remaining_size >= payload_size {
        if let Some(ref mut q) = self.queues.get_mut(&queue_name) {
          if let Some(ref consumer_tag) = opt_consumer_tag {
            if let Some(ref mut cs) = q.consumers.get_mut(consumer_tag) {
              cs.receive_delivery_content(payload);
              if remaining_size == payload_size {
                cs.new_delivery_complete();
              }
            }
          } else {
            q.receive_delivery_content(payload);
            if remaining_size == payload_size {
              q.new_delivery_complete();
            }
          }
        }

        if remaining_size == payload_size {
          self.state = ChannelState::Connected;
        } else {
          self.state = ChannelState::ReceivingContent(queue_name, opt_consumer_tag, remaining_size - payload_size);
        }
      } else {
        error!("body frame too large");
        self.state = ChannelState::Error;
      }
    } else {
      self.state = ChannelState::Error;
    }
  }

  pub fn is_connected(&self) -> bool {
    self.state != ChannelState::Initial && self.state != ChannelState::Closed && self.state != ChannelState::Error
  }

  pub fn next_delivery_tag(&mut self) -> u64 {
    let tag = self.delivery_tag;
    self.delivery_tag += 1;
    if self.delivery_tag == 0 {
      self.delivery_tag = 1;
    }
    tag
  }

  pub fn ack(&mut self, delivery_tag: u64) -> Result<(), Error> {
    self.drop_unacked(delivery_tag)?;
    self.acked.insert(delivery_tag);
    Ok(())
  }

  pub fn nack(&mut self, delivery_tag: u64) -> Result<(), Error> {
    self.drop_unacked(delivery_tag)?;
    self.nacked.insert(delivery_tag);
    Ok(())
  }

  fn drop_unacked(&mut self, delivery_tag: u64) -> Result<(), Error> {
    if !self.unacked.remove(&delivery_tag) {
      return Err(ErrorKind::PreconditionFailed.into());
    }
    Ok(())
  }
}
<commit_msg>async: give channel more methods<commit_after>pub use amq_protocol::protocol::BasicProperties;

use amq_protocol::protocol::AMQPClass;
use amq_protocol::frame::AMQPFrame;
use crossbeam_channel::Sender;
use log::error;

use std::result;
use std::collections::{HashMap, HashSet, VecDeque};

use crate::api::{Answer, ChannelState};
use crate::error::{Error, ErrorKind};
use crate::message::BasicGetMessage;
use crate::queue::Queue;

#[derive(Debug)]
pub struct Channel {
  pub id:             u16,
  pub state:          ChannelState,
  pub send_flow:      bool,
  pub receive_flow:   bool,
  pub queues:         HashMap<String, Queue>,
  pub prefetch_size:  u32,
  pub prefetch_count: u16,
  pub confirm:        bool,
  pub acked:          HashSet<u64>,
  pub nacked:         HashSet<u64>,
  pub unacked:        HashSet<u64>,
  pub awaiting:       VecDeque<Answer>,
      delivery_tag:   u64,
      frame_sender:   Sender<AMQPFrame>,
}

impl Channel {
  pub fn new(channel_id: u16, frame_sender: Sender<AMQPFrame>) -> Channel {
    Channel {
      id:             channel_id,
      state:          ChannelState::Initial,
      send_flow:      true,
      receive_flow:   true,
      queues:         HashMap::new(),
      prefetch_size:  0,
      prefetch_count: 0,
      confirm:        false,
      acked:          HashSet::new(),
      nacked:         HashSet::new(),
      unacked:        HashSet::new(),
      awaiting:       VecDeque::new(),
      delivery_tag:   1,
      frame_sender,
    }
  }

  /// verifies if the channel's state is the one passed as argument
  pub fn check_state(&self, state: ChannelState) -> result::Result<(), Error> {
    if self.state == state {
      Ok(())
    } else {
      Err(ErrorKind::InvalidState {
        expected: state,
        actual:   self.state.clone(),
      }.into())
    }
  }

  #[doc(hidden)]
  pub fn send_method_frame(&mut self, method: AMQPClass) {
    self.send_frame(AMQPFrame::Method(self.id, method));
  }

  #[doc(hidden)]
  pub fn send_frame(&mut self, frame: AMQPFrame) {
    // We always hold a reference to the receiver so it's safe to unwrap
    self.frame_sender.send(frame).unwrap();
  }

  /// gets the next message corresponding to a queue, in response to a basic.get
  ///
  /// If there is no message, the method will return None
  pub fn next_basic_get_message(&mut self, queue_name: &str) -> Option<BasicGetMessage> {
      self.queues.get_mut(queue_name).and_then(|queue| queue.next_basic_get_message())
  }

  #[doc(hidden)]
  pub fn handle_content_header_frame(&mut self, size: u64, properties: BasicProperties) {
    if let ChannelState::WillReceiveContent(queue_name, consumer_tag) = self.state.clone() {
      if size > 0 {
        self.state = ChannelState::ReceivingContent(queue_name.clone(), consumer_tag.clone(), size as usize);
      } else {
        self.state = ChannelState::Connected;
      }
      if let Some(ref mut q) = self.queues.get_mut(&queue_name) {
        if let Some(ref consumer_tag) = consumer_tag {
          if let Some(ref mut cs) = q.consumers.get_mut(consumer_tag) {
            cs.set_delivery_properties(properties);
            if size == 0 {
              cs.new_delivery_complete();
            }
          }
        } else {
          q.set_delivery_properties(properties);
          if size == 0 {
            q.new_delivery_complete();
          }
        }
      }
    } else {
      self.state = ChannelState::Error;
    }
  }

  #[doc(hidden)]
  pub fn handle_body_frame(&mut self, payload: Vec<u8>) {
    let payload_size = payload.len();

    if let ChannelState::ReceivingContent(queue_name, opt_consumer_tag, remaining_size) = self.state.clone() {
      if remaining_size >= payload_size {
        if let Some(ref mut q) = self.queues.get_mut(&queue_name) {
          if let Some(ref consumer_tag) = opt_consumer_tag {
            if let Some(ref mut cs) = q.consumers.get_mut(consumer_tag) {
              cs.receive_delivery_content(payload);
              if remaining_size == payload_size {
                cs.new_delivery_complete();
              }
            }
          } else {
            q.receive_delivery_content(payload);
            if remaining_size == payload_size {
              q.new_delivery_complete();
            }
          }
        }

        if remaining_size == payload_size {
          self.state = ChannelState::Connected;
        } else {
          self.state = ChannelState::ReceivingContent(queue_name, opt_consumer_tag, remaining_size - payload_size);
        }
      } else {
        error!("body frame too large");
        self.state = ChannelState::Error;
      }
    } else {
      self.state = ChannelState::Error;
    }
  }

  pub fn is_connected(&self) -> bool {
    self.state != ChannelState::Initial && self.state != ChannelState::Closed && self.state != ChannelState::Error
  }

  pub fn next_delivery_tag(&mut self) -> u64 {
    let tag = self.delivery_tag;
    self.delivery_tag += 1;
    if self.delivery_tag == 0 {
      self.delivery_tag = 1;
    }
    tag
  }

  pub fn ack(&mut self, delivery_tag: u64) -> Result<(), Error> {
    self.drop_unacked(delivery_tag)?;
    self.acked.insert(delivery_tag);
    Ok(())
  }

  pub fn nack(&mut self, delivery_tag: u64) -> Result<(), Error> {
    self.drop_unacked(delivery_tag)?;
    self.nacked.insert(delivery_tag);
    Ok(())
  }

  fn drop_unacked(&mut self, delivery_tag: u64) -> Result<(), Error> {
    if !self.unacked.remove(&delivery_tag) {
      return Err(ErrorKind::PreconditionFailed.into());
    }
    Ok(())
  }
}
<|endoftext|>


<commit_before>#![allow(unused_parens)] // FIXME: Remove this attribute once false positive is resolved.

use super::backend::{FailedToLookupTypeError, InnerPgTypeMetadata};
use super::{Pg, PgTypeMetadata};
use crate::prelude::*;

use std::borrow::Cow;
use std::cell::RefCell;
use std::collections::HashMap;

/// Determines the OID of types at runtime
///
/// Most connections do not have to implement this manually.
/// It is much easier to implement [`GetPgMetadataCache`] for a type that implements `Connection<Backend=Pg>`.
/// This will cause this trait to be auto implemented.
///
/// If this is implemented manually, make sure to use some sort of cache so that lookup
/// don't cause a database query for types that have been seen before.
pub trait PgMetadataLookup {
    /// Determine the type metadata for the given `type_name`
    ///
    /// This function should only be used for user defined types, or types which
    /// come from an extension. This function may perform a SQL query to look
    /// up the type. For built-in types, a static OID should be preferred.
    fn lookup_type(&self, type_name: &str, schema: Option<&str>) -> PgTypeMetadata;
}

impl<T> PgMetadataLookup for T
where
    T: Connection<Backend = Pg> + GetPgMetadataCache,
{
    fn lookup_type(&self, type_name: &str, schema: Option<&str>) -> PgTypeMetadata {
        let metadata_cache = self.get_metadata_cache();
        let cache_key = PgMetadataCacheKey {
            schema: schema.map(Cow::Borrowed),
            type_name: Cow::Borrowed(type_name),
        };

        metadata_cache.lookup_type(&cache_key).unwrap_or_else(|| {
            let r = lookup_type(&cache_key, self);

            match r {
                Ok(type_metadata) => {
                    metadata_cache.store_type(cache_key, type_metadata);
                    PgTypeMetadata(Ok(type_metadata))
                }
                Err(_e) => {
                    PgTypeMetadata(Err(FailedToLookupTypeError::new(cache_key.into_owned())))
                }
            }
        })
    }
}

/// Gets the [`PgMetadataCache`] for a `Connection<Backend=Pg>`
/// so that the lookup of user defined types, or types which come from an extension can be cached.
///
/// Implementing this trait for a `Connection<Backend=Pg>` will cause [`PgMetadataLookup`] to be auto implemented.
pub trait GetPgMetadataCache {
    /// Get the [`PgMetadataCache`]
    fn get_metadata_cache(&self) -> &PgMetadataCache;
}

fn lookup_type<T: Connection<Backend = Pg>>(
    cache_key: &PgMetadataCacheKey<'_>,
    conn: &T,
) -> QueryResult<InnerPgTypeMetadata> {
    let search_path: String;
    let mut search_path_has_temp_schema = false;

    let search_schema = match cache_key.schema.as_deref() {
        Some("pg_temp") => {
            search_path_has_temp_schema = true;
            Vec::new()
        }
        Some(schema) => vec![schema],
        None => {
            search_path = crate::dsl::sql("SHOW search_path").get_result::<String>(conn)?;

            search_path
                .split(',')
                // skip the `$user` entry for now
                .filter(|f| !f.starts_with("\"$"))
                .map(|s| s.trim())
                .filter(|&f| {
                    let is_temp = f == "pg_temp";
                    search_path_has_temp_schema |= is_temp;
                    !is_temp
                })
                .collect()
        }
    };

    let metadata_query = pg_type::table
        .inner_join(pg_namespace::table)
        .filter(pg_type::typname.eq(&cache_key.type_name))
        .select((pg_type::oid, pg_type::typarray));
    let nspname_filter = pg_namespace::nspname.eq(crate::dsl::any(search_schema));

    let metadata = if search_path_has_temp_schema {
        metadata_query
            .filter(nspname_filter.or(pg_namespace::oid.eq(pg_my_temp_schema())))
            .first(conn)?
    } else {
        metadata_query.filter(nspname_filter).first(conn)?
    };

    Ok(metadata)
}

#[derive(Hash, PartialEq, Eq, Debug, Clone)]
pub(in crate::pg) struct PgMetadataCacheKey<'a> {
    pub(crate) schema: Option<Cow<'a, str>>,
    pub(crate) type_name: Cow<'a, str>,
}

impl<'a> PgMetadataCacheKey<'a> {
    fn into_owned(self) -> PgMetadataCacheKey<'static> {
        let PgMetadataCacheKey { schema, type_name } = self;
        PgMetadataCacheKey {
            schema: schema.map(|s| Cow::Owned(s.into_owned())),
            type_name: Cow::Owned(type_name.into_owned()),
        }
    }
}

/// Stores a cache for the OID of custom types
#[allow(missing_debug_implementations)]
pub struct PgMetadataCache {
    cache: RefCell<HashMap<PgMetadataCacheKey<'static>, InnerPgTypeMetadata>>,
}

/// Cache for the [OIDs] of custom Postgres types
///
/// [OIDs]: https://www.postgresql.org/docs/current/static/datatype-oid.html
impl PgMetadataCache {
    /// Construct a new `PgMetadataCache`
    pub fn new() -> Self {
        PgMetadataCache {
            cache: RefCell::new(HashMap::new()),
        }
    }

    /// Lookup the OID of a custom type
    fn lookup_type(&self, type_name: &PgMetadataCacheKey) -> Option<PgTypeMetadata> {
        Some(PgTypeMetadata(Ok(*self.cache.borrow().get(type_name)?)))
    }

    /// Store the OID of a custom type
    fn store_type(&self, type_name: PgMetadataCacheKey, type_metadata: InnerPgTypeMetadata) {
        self.cache
            .borrow_mut()
            .insert(type_name.into_owned(), type_metadata);
    }
}

table! {
    pg_type (oid) {
        oid -> Oid,
        typname -> Text,
        typarray -> Oid,
        typnamespace -> Oid,
    }
}

table! {
    pg_namespace (oid) {
        oid -> Oid,
        nspname -> Text,
    }
}

joinable!(pg_type -> pg_namespace(typnamespace));
allow_tables_to_appear_in_same_query!(pg_type, pg_namespace);

sql_function! { fn pg_my_temp_schema() -> Oid; }
<commit_msg>fix: :rotating_light: fix clippy warning<commit_after>#![allow(unused_parens)] // FIXME: Remove this attribute once false positive is resolved.

use super::backend::{FailedToLookupTypeError, InnerPgTypeMetadata};
use super::{Pg, PgTypeMetadata};
use crate::prelude::*;

use std::borrow::Cow;
use std::cell::RefCell;
use std::collections::HashMap;

/// Determines the OID of types at runtime
///
/// Most connections do not have to implement this manually.
/// It is much easier to implement [`GetPgMetadataCache`] for a type that implements `Connection<Backend=Pg>`.
/// This will cause this trait to be auto implemented.
///
/// If this is implemented manually, make sure to use some sort of cache so that lookup
/// don't cause a database query for types that have been seen before.
pub trait PgMetadataLookup {
    /// Determine the type metadata for the given `type_name`
    ///
    /// This function should only be used for user defined types, or types which
    /// come from an extension. This function may perform a SQL query to look
    /// up the type. For built-in types, a static OID should be preferred.
    fn lookup_type(&self, type_name: &str, schema: Option<&str>) -> PgTypeMetadata;
}

impl<T> PgMetadataLookup for T
where
    T: Connection<Backend = Pg> + GetPgMetadataCache,
{
    fn lookup_type(&self, type_name: &str, schema: Option<&str>) -> PgTypeMetadata {
        let metadata_cache = self.get_metadata_cache();
        let cache_key = PgMetadataCacheKey {
            schema: schema.map(Cow::Borrowed),
            type_name: Cow::Borrowed(type_name),
        };

        metadata_cache.lookup_type(&cache_key).unwrap_or_else(|| {
            let r = lookup_type(&cache_key, self);

            match r {
                Ok(type_metadata) => {
                    metadata_cache.store_type(cache_key, type_metadata);
                    PgTypeMetadata(Ok(type_metadata))
                }
                Err(_e) => {
                    PgTypeMetadata(Err(FailedToLookupTypeError::new(cache_key.into_owned())))
                }
            }
        })
    }
}

/// Gets the [`PgMetadataCache`] for a `Connection<Backend=Pg>`
/// so that the lookup of user defined types, or types which come from an extension can be cached.
///
/// Implementing this trait for a `Connection<Backend=Pg>` will cause [`PgMetadataLookup`] to be auto implemented.
pub trait GetPgMetadataCache {
    /// Get the [`PgMetadataCache`]
    fn get_metadata_cache(&self) -> &PgMetadataCache;
}

fn lookup_type<T: Connection<Backend = Pg>>(
    cache_key: &PgMetadataCacheKey<'_>,
    conn: &T,
) -> QueryResult<InnerPgTypeMetadata> {
    let search_path: String;
    let mut search_path_has_temp_schema = false;

    let search_schema = match cache_key.schema.as_deref() {
        Some("pg_temp") => {
            search_path_has_temp_schema = true;
            Vec::new()
        }
        Some(schema) => vec![schema],
        None => {
            search_path = crate::dsl::sql("SHOW search_path").get_result::<String>(conn)?;

            search_path
                .split(',')
                // skip the `$user` entry for now
                .filter(|f| !f.starts_with("\"$"))
                .map(|s| s.trim())
                .filter(|&f| {
                    let is_temp = f == "pg_temp";
                    search_path_has_temp_schema |= is_temp;
                    !is_temp
                })
                .collect()
        }
    };

    let metadata_query = pg_type::table
        .inner_join(pg_namespace::table)
        .filter(pg_type::typname.eq(&cache_key.type_name))
        .select((pg_type::oid, pg_type::typarray));
    let nspname_filter = pg_namespace::nspname.eq(crate::dsl::any(search_schema));

    let metadata = if search_path_has_temp_schema {
        metadata_query
            .filter(nspname_filter.or(pg_namespace::oid.eq(pg_my_temp_schema())))
            .first(conn)?
    } else {
        metadata_query.filter(nspname_filter).first(conn)?
    };

    Ok(metadata)
}

#[derive(Hash, PartialEq, Eq, Debug, Clone)]
pub(in crate::pg) struct PgMetadataCacheKey<'a> {
    pub(crate) schema: Option<Cow<'a, str>>,
    pub(crate) type_name: Cow<'a, str>,
}

impl<'a> PgMetadataCacheKey<'a> {
    fn into_owned(self) -> PgMetadataCacheKey<'static> {
        let PgMetadataCacheKey { schema, type_name } = self;
        PgMetadataCacheKey {
            schema: schema.map(|s| Cow::Owned(s.into_owned())),
            type_name: Cow::Owned(type_name.into_owned()),
        }
    }
}

/// Cache for the [OIDs] of custom Postgres types
///
/// [OIDs]: https://www.postgresql.org/docs/current/static/datatype-oid.html
#[allow(missing_debug_implementations)]
#[derive(Default)]
pub struct PgMetadataCache {
    cache: RefCell<HashMap<PgMetadataCacheKey<'static>, InnerPgTypeMetadata>>,
}

impl PgMetadataCache {
    /// Construct a new `PgMetadataCache`
    pub fn new() -> Self {
        Default::default()
    }

    /// Lookup the OID of a custom type
    fn lookup_type(&self, type_name: &PgMetadataCacheKey) -> Option<PgTypeMetadata> {
        Some(PgTypeMetadata(Ok(*self.cache.borrow().get(type_name)?)))
    }

    /// Store the OID of a custom type
    fn store_type(&self, type_name: PgMetadataCacheKey, type_metadata: InnerPgTypeMetadata) {
        self.cache
            .borrow_mut()
            .insert(type_name.into_owned(), type_metadata);
    }
}

table! {
    pg_type (oid) {
        oid -> Oid,
        typname -> Text,
        typarray -> Oid,
        typnamespace -> Oid,
    }
}

table! {
    pg_namespace (oid) {
        oid -> Oid,
        nspname -> Text,
    }
}

joinable!(pg_type -> pg_namespace(typnamespace));
allow_tables_to_appear_in_same_query!(pg_type, pg_namespace);

sql_function! { fn pg_my_temp_schema() -> Oid; }
<|endoftext|>


<commit_before>use crate::time::driver::{Handle, TimerEntry};
use crate::time::{error::Error, Duration, Instant};

use pin_project_lite::pin_project;
use std::future::Future;
use std::pin::Pin;
use std::task::{self, Poll};

/// Waits until `deadline` is reached.
///
/// No work is performed while awaiting on the sleep future to complete. `Sleep`
/// operates at millisecond granularity and should not be used for tasks that
/// require high-resolution timers.
///
/// # Cancellation
///
/// Canceling a sleep instance is done by dropping the returned future. No additional
/// cleanup work is required.
pub fn sleep_until(deadline: Instant) -> Sleep {
    Sleep::new_timeout(deadline)
}

/// Waits until `duration` has elapsed.
///
/// Equivalent to `sleep_until(Instant::now() + duration)`. An asynchronous
/// analog to `std::thread::sleep`.
///
/// No work is performed while awaiting on the sleep future to complete. `Sleep`
/// operates at millisecond granularity and should not be used for tasks that
/// require high-resolution timers.
///
/// To run something regularly on a schedule, see [`interval`].
///
/// The maximum duration for a sleep is 68719476734 milliseconds (approximately 2.2 years).
///
/// # Cancellation
///
/// Canceling a sleep instance is done by dropping the returned future. No additional
/// cleanup work is required.
///
/// # Examples
///
/// Wait 100ms and print "100 ms have elapsed".
///
/// ```
/// use tokio::time::{sleep, Duration};
///
/// #[tokio::main]
/// async fn main() {
///     sleep(Duration::from_millis(100)).await;
///     println!("100 ms have elapsed");
/// }
/// ```
///
/// [`interval`]: crate::time::interval()
pub fn sleep(duration: Duration) -> Sleep {
    sleep_until(Instant::now() + duration)
}

pin_project! {
    /// Future returned by [`sleep`](sleep) and [`sleep_until`](sleep_until).
    ///
    /// This type does not implement the `Unpin` trait, which means that if you
    /// use it with [`select!`] or by calling `poll`, you have to pin it first.
    /// If you use it with `.await`, this does not apply.
    ///
    /// # Examples
    ///
    /// Wait 100ms and print "100 ms have elapsed".
    ///
    /// ```
    /// use tokio::time::{sleep, Duration};
    ///
    /// #[tokio::main]
    /// async fn main() {
    ///     sleep(Duration::from_millis(100)).await;
    ///     println!("100 ms have elapsed");
    /// }
    /// ```
    ///
    /// Use with [`select!`]. Pinning the `Sleep` with [`tokio::pin!`] is
    /// necessary when the same `Sleep` is selected on multiple times.
    /// ```no_run
    /// use tokio::time::{self, Duration, Instant};
    ///
    /// #[tokio::main]
    /// async fn main() {
    ///     let sleep = time::sleep(Duration::from_millis(10));
    ///     tokio::pin!(sleep);
    ///
    ///     loop {
    ///         tokio::select! {
    ///             () = &mut sleep => {
    ///                 println!("timer elapsed");
    ///                 sleep.as_mut().reset(Instant::now() + Duration::from_millis(50));
    ///             },
    ///         }
    ///     }
    /// }
    /// ```
    /// Use in a struct with boxing. By pinning the `Sleep` with a `Box`, the
    /// `HasSleep` struct implements `Unpin`, even though `Sleep` does not.
    /// ```
    /// use std::future::Future;
    /// use std::pin::Pin;
    /// use std::task::{Context, Poll};
    /// use tokio::time::Sleep;
    ///
    /// struct HasSleep {
    ///     sleep: Pin<Box<Sleep>>,
    /// }
    ///
    /// impl Future for HasSleep {
    ///     type Output = ();
    ///
    ///     fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
    ///         self.sleep.as_mut().poll(cx)
    ///     }
    /// }
    /// ```
    /// Use in a struct with pin projection. This method avoids the `Box`, but
    /// the `HasSleep` struct will not be `Unpin` as a consequence.
    /// ```
    /// use std::future::Future;
    /// use std::pin::Pin;
    /// use std::task::{Context, Poll};
    /// use tokio::time::Sleep;
    /// use pin_project_lite::pin_project;
    ///
    /// pin_project! {
    ///     struct HasSleep {
    ///         #[pin]
    ///         sleep: Sleep,
    ///     }
    /// }
    ///
    /// impl Future for HasSleep {
    ///     type Output = ();
    ///
    ///     fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
    ///         self.project().sleep.poll(cx)
    ///     }
    /// }
    /// ```
    ///
    /// [`select!`]: ../macro.select.html
    /// [`tokio::pin!`]: ../macro.pin.html
    #[derive(Debug)]
    #[must_use = "futures do nothing unless you `.await` or poll them"]
    pub struct Sleep {
        deadline: Instant,

        // The link between the `Sleep` instance and the timer that drives it.
        #[pin]
        entry: TimerEntry,
    }
}

impl Sleep {
    pub(crate) fn new_timeout(deadline: Instant) -> Sleep {
        let handle = Handle::current();
        let entry = TimerEntry::new(&handle, deadline);

        Sleep { deadline, entry }
    }

    /// Returns the instant at which the future will complete.
    pub fn deadline(&self) -> Instant {
        self.deadline
    }

    /// Returns `true` if `Sleep` has elapsed.
    ///
    /// A `Sleep` instance is elapsed when the requested duration has elapsed.
    pub fn is_elapsed(&self) -> bool {
        self.entry.is_elapsed()
    }

    /// Resets the `Sleep` instance to a new deadline.
    ///
    /// Calling this function allows changing the instant at which the `Sleep`
    /// future completes without having to create new associated state.
    ///
    /// This function can be called both before and after the future has
    /// completed.
    ///
    /// To call this method, you will usually combine the call with
    /// [`Pin::as_mut`], which lets you call the method with consuming the
    /// `Sleep` itself.
    ///
    /// # Example
    ///
    /// ```
    /// use tokio::time::{Duration, Instant};
    ///
    /// # #[tokio::main(flavor = "current_thread")]
    /// # async fn main() {
    /// let sleep = tokio::time::sleep(Duration::from_millis(10));
    /// tokio::pin!(sleep);
    ///
    /// sleep.as_mut().reset(Instant::now() + Duration::from_millis(20));
    /// # }
    /// ```
    ///
    /// [`Pin::as_mut`]: fn@std::pin::Pin::as_mut
    pub fn reset(self: Pin<&mut Self>, deadline: Instant) {
        let me = self.project();
        me.entry.reset(deadline);
        *me.deadline = deadline;
    }

    fn poll_elapsed(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Result<(), Error>> {
        let me = self.project();

        // Keep track of task budget
        let coop = ready!(crate::coop::poll_proceed(cx));

        me.entry.poll_elapsed(cx).map(move |r| {
            coop.made_progress();
            r
        })
    }
}

impl Future for Sleep {
    type Output = ();

    fn poll(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> {
        // `poll_elapsed` can return an error in two cases:
        //
        // - AtCapacity: this is a pathological case where far too many
        //   sleep instances have been scheduled.
        // - Shutdown: No timer has been setup, which is a mis-use error.
        //
        // Both cases are extremely rare, and pretty accurately fit into
        // "logic errors", so we just panic in this case. A user couldn't
        // really do much better if we passed the error onwards.
        match ready!(self.as_mut().poll_elapsed(cx)) {
            Ok(()) => Poll::Ready(()),
            Err(e) => panic!("timer error: {}", e),
        }
    }
}
<commit_msg>time: fix typo in Sleep doc (#3515)<commit_after>use crate::time::driver::{Handle, TimerEntry};
use crate::time::{error::Error, Duration, Instant};

use pin_project_lite::pin_project;
use std::future::Future;
use std::pin::Pin;
use std::task::{self, Poll};

/// Waits until `deadline` is reached.
///
/// No work is performed while awaiting on the sleep future to complete. `Sleep`
/// operates at millisecond granularity and should not be used for tasks that
/// require high-resolution timers.
///
/// # Cancellation
///
/// Canceling a sleep instance is done by dropping the returned future. No additional
/// cleanup work is required.
pub fn sleep_until(deadline: Instant) -> Sleep {
    Sleep::new_timeout(deadline)
}

/// Waits until `duration` has elapsed.
///
/// Equivalent to `sleep_until(Instant::now() + duration)`. An asynchronous
/// analog to `std::thread::sleep`.
///
/// No work is performed while awaiting on the sleep future to complete. `Sleep`
/// operates at millisecond granularity and should not be used for tasks that
/// require high-resolution timers.
///
/// To run something regularly on a schedule, see [`interval`].
///
/// The maximum duration for a sleep is 68719476734 milliseconds (approximately 2.2 years).
///
/// # Cancellation
///
/// Canceling a sleep instance is done by dropping the returned future. No additional
/// cleanup work is required.
///
/// # Examples
///
/// Wait 100ms and print "100 ms have elapsed".
///
/// ```
/// use tokio::time::{sleep, Duration};
///
/// #[tokio::main]
/// async fn main() {
///     sleep(Duration::from_millis(100)).await;
///     println!("100 ms have elapsed");
/// }
/// ```
///
/// [`interval`]: crate::time::interval()
pub fn sleep(duration: Duration) -> Sleep {
    sleep_until(Instant::now() + duration)
}

pin_project! {
    /// Future returned by [`sleep`](sleep) and [`sleep_until`](sleep_until).
    ///
    /// This type does not implement the `Unpin` trait, which means that if you
    /// use it with [`select!`] or by calling `poll`, you have to pin it first.
    /// If you use it with `.await`, this does not apply.
    ///
    /// # Examples
    ///
    /// Wait 100ms and print "100 ms have elapsed".
    ///
    /// ```
    /// use tokio::time::{sleep, Duration};
    ///
    /// #[tokio::main]
    /// async fn main() {
    ///     sleep(Duration::from_millis(100)).await;
    ///     println!("100 ms have elapsed");
    /// }
    /// ```
    ///
    /// Use with [`select!`]. Pinning the `Sleep` with [`tokio::pin!`] is
    /// necessary when the same `Sleep` is selected on multiple times.
    /// ```no_run
    /// use tokio::time::{self, Duration, Instant};
    ///
    /// #[tokio::main]
    /// async fn main() {
    ///     let sleep = time::sleep(Duration::from_millis(10));
    ///     tokio::pin!(sleep);
    ///
    ///     loop {
    ///         tokio::select! {
    ///             () = &mut sleep => {
    ///                 println!("timer elapsed");
    ///                 sleep.as_mut().reset(Instant::now() + Duration::from_millis(50));
    ///             },
    ///         }
    ///     }
    /// }
    /// ```
    /// Use in a struct with boxing. By pinning the `Sleep` with a `Box`, the
    /// `HasSleep` struct implements `Unpin`, even though `Sleep` does not.
    /// ```
    /// use std::future::Future;
    /// use std::pin::Pin;
    /// use std::task::{Context, Poll};
    /// use tokio::time::Sleep;
    ///
    /// struct HasSleep {
    ///     sleep: Pin<Box<Sleep>>,
    /// }
    ///
    /// impl Future for HasSleep {
    ///     type Output = ();
    ///
    ///     fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
    ///         self.sleep.as_mut().poll(cx)
    ///     }
    /// }
    /// ```
    /// Use in a struct with pin projection. This method avoids the `Box`, but
    /// the `HasSleep` struct will not be `Unpin` as a consequence.
    /// ```
    /// use std::future::Future;
    /// use std::pin::Pin;
    /// use std::task::{Context, Poll};
    /// use tokio::time::Sleep;
    /// use pin_project_lite::pin_project;
    ///
    /// pin_project! {
    ///     struct HasSleep {
    ///         #[pin]
    ///         sleep: Sleep,
    ///     }
    /// }
    ///
    /// impl Future for HasSleep {
    ///     type Output = ();
    ///
    ///     fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
    ///         self.project().sleep.poll(cx)
    ///     }
    /// }
    /// ```
    ///
    /// [`select!`]: ../macro.select.html
    /// [`tokio::pin!`]: ../macro.pin.html
    #[derive(Debug)]
    #[must_use = "futures do nothing unless you `.await` or poll them"]
    pub struct Sleep {
        deadline: Instant,

        // The link between the `Sleep` instance and the timer that drives it.
        #[pin]
        entry: TimerEntry,
    }
}

impl Sleep {
    pub(crate) fn new_timeout(deadline: Instant) -> Sleep {
        let handle = Handle::current();
        let entry = TimerEntry::new(&handle, deadline);

        Sleep { deadline, entry }
    }

    /// Returns the instant at which the future will complete.
    pub fn deadline(&self) -> Instant {
        self.deadline
    }

    /// Returns `true` if `Sleep` has elapsed.
    ///
    /// A `Sleep` instance is elapsed when the requested duration has elapsed.
    pub fn is_elapsed(&self) -> bool {
        self.entry.is_elapsed()
    }

    /// Resets the `Sleep` instance to a new deadline.
    ///
    /// Calling this function allows changing the instant at which the `Sleep`
    /// future completes without having to create new associated state.
    ///
    /// This function can be called both before and after the future has
    /// completed.
    ///
    /// To call this method, you will usually combine the call with
    /// [`Pin::as_mut`], which lets you call the method without consuming the
    /// `Sleep` itself.
    ///
    /// # Example
    ///
    /// ```
    /// use tokio::time::{Duration, Instant};
    ///
    /// # #[tokio::main(flavor = "current_thread")]
    /// # async fn main() {
    /// let sleep = tokio::time::sleep(Duration::from_millis(10));
    /// tokio::pin!(sleep);
    ///
    /// sleep.as_mut().reset(Instant::now() + Duration::from_millis(20));
    /// # }
    /// ```
    ///
    /// [`Pin::as_mut`]: fn@std::pin::Pin::as_mut
    pub fn reset(self: Pin<&mut Self>, deadline: Instant) {
        let me = self.project();
        me.entry.reset(deadline);
        *me.deadline = deadline;
    }

    fn poll_elapsed(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Result<(), Error>> {
        let me = self.project();

        // Keep track of task budget
        let coop = ready!(crate::coop::poll_proceed(cx));

        me.entry.poll_elapsed(cx).map(move |r| {
            coop.made_progress();
            r
        })
    }
}

impl Future for Sleep {
    type Output = ();

    fn poll(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> {
        // `poll_elapsed` can return an error in two cases:
        //
        // - AtCapacity: this is a pathological case where far too many
        //   sleep instances have been scheduled.
        // - Shutdown: No timer has been setup, which is a mis-use error.
        //
        // Both cases are extremely rare, and pretty accurately fit into
        // "logic errors", so we just panic in this case. A user couldn't
        // really do much better if we passed the error onwards.
        match ready!(self.as_mut().poll_elapsed(cx)) {
            Ok(()) => Poll::Ready(()),
            Err(e) => panic!("timer error: {}", e),
        }
    }
}
<|endoftext|>


<commit_before>/*!

Contains utilities such as `Registry` to build centralized value
construction `Container`.
*/

use std::any::Any;
use std::collections::{ BTreeMap, BTreeSet, HashMap };
use std::collections::btree_map;

use metafactory::{ ToMetaFactory, MetaFactory };
use metafactory::aggregate::{ Aggregate };

use container::Container;

use self::new_definition::{ NewDefinition };
use self::candidate::{ GroupCandidate, DefinitionCandidate };
use self::error::{ CompileError, CircularDependency };

mod candidate;

pub mod new_definition;
pub mod error;
pub mod validator;

/**
Use `Registry` to build and initialize `Container`.

The `Registry` is mutable container of value factory `definitions` and their
groups. Definition is added using `one` method variants, method group
is added by registering a definition that belongs to group using `one_of`
method variants.

Definition value must implement `ToMetafactory` trait. Currently possible
definition sources are any clonable value or closure.

## `One` definitions

```
let mut registry = di::Registry::new();

// Insert value from cloneable source immediately, but no arguments possible.
registry.insert_one("a", 5i);

// Same, but from closure.
registry.insert_one("a", || 5i);

// Same, but using the fluent interface.
registry
    .one("a", || 5i)
    .insert();

// When definition requires arguments, their source need to be explicitly
// defined using "with_arg", "with_args" or "add_arg":
registry
    .one("b", |a: int| a + 1i)
    .with_arg("a")
    .insert();

// The definition will have a value that can be known to compiler at compile
// time:
registry
    .one("sum", |a: int, b:int| a + b) // "sum" will be "int"
    .with_args(&["a", "b"])
    .insert();
```

## `One_of` definition groups

```
let mut registry = di::Registry::new();

// Definition can be assigned to a group.
registry
    .one("a", 5i)
    .in_group("integers")
    .insert();

// If the name "a" is not important, "one_of" method can be used:
registry.insert_one_of("integers", 5i);

// The same can be written using fluent interface:
registry
    .one_of("integers", 5i)
    .insert();

// If using the fluent interface, the name can be added back:
registry
    .one_of("integers", 5i)
    .with_id("a")
    .insert();

// Group members can depend on other definitions:
registry
    .one_of("integers", |previous: int| previous + 1)
    .with_arg("a")
    .with_id("b")
    .insert();

// Defined "integers" group can be used as Vec<int> argument in other
// definitions:
registry
    .one("sum", |items: Vec<int>| items.into_iter().fold(0i, |a, i| a + i))
    .with_arg("integers")
    .insert();
```

## Compiling the container

When the registry is configured, we can check for errors and build the
`Container`, that contains clonable factories for all the registered
definitions and definition groups.

This is recommended pattern:

```
let mut registry = di::Registry::new();

// Build the registry.
registry.insert_one("a", 5i);
// < registry ... >

match registry.compile() {
    Ok(container) => {
        // Get a factory which will be used for the application lifetime
        // to construct a value.
        if let Some(a_factory) = container.get::<int>("a") {
            assert_eq!(5i, a_factory.take());
        }
    },
    Err(errors) => di::error_printer::pretty_print(&errors),
}
```

The errors contains detailed information about all errors at once. Console
applications can use provided pretty printer.
*/
pub struct Registry {
    /// Contains a list of group candidates.
    groups: BTreeMap<String, GroupCandidate>,
    /// Contains a list of definition candidates.
    definitions: BTreeMap<String, DefinitionCandidate>,
    /// Contains a list of definitions that were overriden while building
    /// the registry - so we can at least show some kind of warning.
    overriden_definitions: BTreeMap<String, Vec<DefinitionCandidate>>,
    /// Validator list that is run before the compilation.
    validators: Vec<Box<validator::Validator + 'static>>,
}

impl Registry {
    /// Produces a new `Registry`.
    ///
    /// ## Example
    ///
    /// ```
    /// let mut registry = di::Registry::new();
    /// ```
    pub fn new() -> Registry {
        let mut registry = Registry {
            groups: BTreeMap::new(),
            definitions: BTreeMap::new(),
            overriden_definitions: BTreeMap::new(),
            validators: Vec::new(),
        };

        registry.push_validator(validator::argument_count::ArgumentCountValidator);
        registry.push_validator(validator::overrides::NoOverridesValidator);
        registry.push_validator(validator::dependencies::DependencyValidator);

        registry
    }

    fn push_validator<T: validator::Validator + 'static>(
        &mut self,
        validator: T
    ) {
        self.validators.push(box validator);
    }

    pub fn compile(&self) -> Result<Container, Vec<CompileError>> {
        let mut error_summary = Vec::<CompileError>::new();

        for validator in self.validators.iter() {
            validator.validate(self, &mut error_summary);
        }

        let mut factory_map = HashMap::<String, Box<Any>>::new();
        let groups = self.collect_group_dependencies();

        if error_summary.len() == 0 {
            // Compile definitions.
            for id in self.definitions.keys() {
                let create_factory_result = self.create_factory(
                    &groups,
                    &mut Vec::<String>::new(),
                    id.as_slice()
                );
                match create_factory_result {
                    Err(error) => {
                        error_summary.push(CompileError::CircularDependency(error));
                        break;
                    },
                    Ok(factory) => { factory_map.insert(id.to_string(), factory); },
                };
            }
            // Compile groups.
            for group in groups.keys() {
                let create_factory_result = self.create_factory(
                    &groups,
                    &mut Vec::<String>::new(),
                    group.as_slice()
                );
                match create_factory_result {
                    Err(error) => {
                        error_summary.push(CompileError::CircularDependency(error));
                        break;
                    },
                    Ok(factory) => { factory_map.insert(group.clone(), factory); },
                };
            }
        }

        if error_summary.len() == 0 {
            Ok(Container::new(factory_map))
        } else {
            Err(error_summary)
        }
    }

    pub fn may_be_empty<T: 'static>(&mut self, collection_id: &str) {
        self.define_group_if_not_exists(collection_id, Aggregate::new::<T>());
    }

    pub fn one_of<'r, T: 'static + ToMetaFactory>(&'r mut self, collection_id: &str, value: T)
        -> NewDefinition<'r>
    {
        let mut id;
        let metafactory = value.to_metafactory();

        self.define_group_if_not_exists(collection_id, metafactory.new_aggregate());

        if let Some(group) = self.groups.get_mut(collection_id) {
            group.member_count += 1;
            id = format!("{}`{}", collection_id, group.member_count);
        } else {
            panic!("Expected to find defined group.")
        }

        NewDefinition::new(
            self,
            Some(collection_id.to_string()),
            id.as_slice(),
            metafactory
        )
    }

    pub fn one<'r, T: 'static + ToMetaFactory>(&'r mut self, id: &str, value: T)
        -> NewDefinition<'r>
    {
        NewDefinition::new(
            self,
            None,
            id,
            value.to_metafactory()
        )
    }

    pub fn insert_one<T: 'static + ToMetaFactory>(&mut self, id: &str, value: T) {
        self.define(
            None,
            id,
            value.to_metafactory(),
            Vec::new()
        );
    }

    pub fn insert_one_of<T: 'static + ToMetaFactory>(&mut self, collection_id: &str, value: T) {
        let mut id;
        let metafactory = value.to_metafactory();

        self.define_group_if_not_exists(collection_id, metafactory.new_aggregate());

        if let Some(group) = self.groups.get_mut(collection_id) {
            group.member_count += 1;
            id = format!("{}`{}", collection_id, group.member_count);
        } else {
            panic!("Expected to find defined group.")
        }

        self.define(
            Some(collection_id.to_string()),
            id.as_slice(),
            metafactory,
            Vec::new()
        );
    }

    fn collect_group_dependencies<'r>(&'r self) -> BTreeMap<String, BTreeSet<&'r str>> {
        let mut groups: BTreeMap<String, BTreeSet<&str>> = BTreeMap::new();

        for (id, value) in self.definitions.iter()
            .filter(|&(_, v)| v.collection_id != None)
        {
            match groups.entry(value.collection_id.clone().unwrap()) {
                btree_map::Entry::Occupied(mut entry) => {
                    entry.get_mut().insert(id.as_slice());
                },
                btree_map::Entry::Vacant(entry) => {
                    let mut set: BTreeSet<&str> = BTreeSet::new();
                    set.insert(id.as_slice());
                    entry.set(set);
                }
            }
        }

        groups
    }

    fn define_group_if_not_exists(&mut self, collection_id: &str, type_aggregate: Aggregate<'static>) {
        if !self.groups.contains_key(collection_id) {
            self.groups.insert(
                collection_id.to_string(),
                GroupCandidate::new(type_aggregate)
            );
        }
    }

    fn define(&mut self, collection_id: Option<String>, id: &str, value: Box<MetaFactory + 'static>, args: Vec<String>) {
        if let Some(overriden_candidate) = self.definitions.remove(id) {
            match self.overriden_definitions.entry(id.to_string()) {
                btree_map::Entry::Vacant(entry) => { entry.set(vec![overriden_candidate]); },
                btree_map::Entry::Occupied(mut entry) => { entry.get_mut().push(overriden_candidate); },
            };
        }

        let candidate = DefinitionCandidate::new(
            value,
            args,
            collection_id
        );

        self.definitions.insert(
            id.to_string(),
            candidate
        );
    }

    fn create_factory(
        &self,
        groups: &BTreeMap<String, BTreeSet<&str>>,
        dependency_chain: &mut Vec<String>,
        id: &str
    ) -> Result<Box<Any>, CircularDependency> {
        dependency_chain.push(id.to_string());

        // Find if this is a definition or a group.
        let mut result = match self.definitions.get(id) {
            Some(definition) => {
                // Check for circular dependencies.

                for source in definition.arg_sources.iter() {
                    if dependency_chain.contains(source) {
                        dependency_chain.push(source.clone());
                        return Err(CircularDependency::new(dependency_chain.clone()));
                    }
                }

                // Create definition factory.

                Some(self.create_definition_factory(
                    groups,
                    dependency_chain,
                    id,
                    definition
                ))
            },
            None => None,
        };

        if let None = result {
            result = match self.groups.get(id) {
                Some(group) => {
                    // Collect users of this group.
                    let group_dependencies = groups.get(id).expect(format!("expected to find dependencies for group {}", id).as_slice());

                    // Check for circular dependencies.
                    for source in group_dependencies.iter() {
                        if dependency_chain.contains(&source.to_string()) {
                            dependency_chain.push(source.to_string());
                            return Err(CircularDependency::new(dependency_chain.clone()));
                        }
                    }

                    Some(self.create_group_factory(
                        groups,
                        dependency_chain,
                        group,
                        group_dependencies
                    ))
                },
                None => None,
            }
        }

        dependency_chain.pop();

        result.expect(format!("expected definition or group {} was not found", id).as_slice())
    }

    fn create_definition_factory(
        &self,
        groups: &BTreeMap<String, BTreeSet<&str>>,
        dependency_chain: &mut Vec<String>,
        id: &str,
        definition: &DefinitionCandidate
    ) -> Result<Box<Any>, CircularDependency> {

        let mut argument_factories = Vec::<Box<Any>>::with_capacity(definition.arg_sources.len());

        for source in definition.arg_sources.iter() {
            match self.create_factory(
                groups,
                dependency_chain,
                source.as_slice()
            ) {
                Err(error) => return Err(error),
                Ok(factory) => argument_factories.push(factory),
            };
        }

        Ok(
            definition.metafactory.new(argument_factories)
                .ok()
                .expect(
                    format!(
                        "failed to create factory {} with arguments \"{}\" - most likely argument types are not the same",
                        id,
                        definition.arg_sources.connect("\", \"")
                    ).as_slice()
                )
        )
    }

    fn create_group_factory(
        &self,
        groups: &BTreeMap<String, BTreeSet<&str>>,
        dependency_chain: &mut Vec<String>,
        group: &GroupCandidate,
        group_sources: &BTreeSet<&str>
    )
        -> Result<Box<Any>, CircularDependency>
    {
        let mut argument_factories = Vec::<Box<Any>>::with_capacity(group_sources.len());

        for source in group_sources.iter() {
            match self.create_factory(
                groups,
                dependency_chain,
                *source
            ) {
                Err(error) => return Err(error),
                Ok(factory) => argument_factories.push(factory),
            };
        }

        Ok(group.aggregate.new_factory(
            argument_factories
        ))
    }
}
<commit_msg>Documentation for Registry.<commit_after>/*!

Contains utilities such as `Registry` to build centralized value
construction `Container`.
*/

use std::any::Any;
use std::collections::{ BTreeMap, BTreeSet, HashMap };
use std::collections::btree_map;

use metafactory::{ ToMetaFactory, MetaFactory };
use metafactory::aggregate::{ Aggregate };

use container::Container;

use self::new_definition::{ NewDefinition };
use self::candidate::{ GroupCandidate, DefinitionCandidate };
use self::error::{ CompileError, CircularDependency };

mod candidate;

pub mod new_definition;
pub mod error;
pub mod validator;

/**
Use `Registry` to build and initialize `Container`.

The `Registry` is mutable container of value factory `definitions` and their
groups. Definition is added using `one` method variants, method group
is added by registering a definition that belongs to group using `one_of`
method variants.

Definition value must implement `ToMetafactory` trait. Currently possible
definition sources are any clonable value or closure.

## `One` definitions

```
let mut registry = di::Registry::new();

// Insert value from cloneable source immediately, but no arguments possible.
registry.insert_one("a", 5i);

// Same, but from closure.
registry.insert_one("a", || 5i);

// Same, but using the fluent interface.
registry
    .one("a", || 5i)
    .insert();

// When definition requires arguments, their source need to be explicitly
// defined using "with_arg", "with_args" or "add_arg":
registry
    .one("b", |a: int| a + 1i)
    .with_arg("a")
    .insert();

// The definition will have a value that can be known to compiler at compile
// time:
registry
    .one("sum", |a: int, b:int| a + b) // "sum" will be "int"
    .with_args(&["a", "b"])
    .insert();
```

## `One_of` definition groups

```
let mut registry = di::Registry::new();

// Definition can be assigned to a group.
registry
    .one("a", 5i)
    .in_group("integers")
    .insert();

// If the name "a" is not important, "one_of" method can be used:
registry.insert_one_of("integers", 5i);

// The same can be written using fluent interface:
registry
    .one_of("integers", 5i)
    .insert();

// If using the fluent interface, the name can be added back:
registry
    .one_of("integers", 5i)
    .with_id("a")
    .insert();

// Group members can depend on other definitions:
registry
    .one_of("integers", |previous: int| previous + 1)
    .with_arg("a")
    .with_id("b")
    .insert();

// Defined "integers" group can be used as Vec<int> argument in other
// definitions:
registry
    .one("sum", |items: Vec<int>| items.into_iter().fold(0i, |a, i| a + i))
    .with_arg("integers")
    .insert();
```

## Compiling the container

When the registry is configured, we can check for errors and build the
`Container`, that contains clonable factories for all the registered
definitions and definition groups.

This is recommended pattern:

```
let mut registry = di::Registry::new();

// Build the registry.
registry.insert_one("a", 5i32);
// < registry ... >

match registry.compile() {
    Ok(container) => {
        // Get a factory which will be used for the application lifetime
        // to construct a value.
        if let Some(a_factory) = container.get::<i32>("a") {
            assert_eq!(5, a_factory.take());
        }
    },
    Err(errors) => di::error_printer::pretty_print(&errors),
}
```

The errors contains detailed information about all errors at once. Console
applications can use provided pretty printer.
*/
pub struct Registry {
    /// Contains a list of group candidates.
    groups: BTreeMap<String, GroupCandidate>,
    /// Contains a list of definition candidates.
    definitions: BTreeMap<String, DefinitionCandidate>,
    /// Contains a list of definitions that were overriden while building
    /// the registry - so we can at least show some kind of warning.
    overriden_definitions: BTreeMap<String, Vec<DefinitionCandidate>>,
    /// Validator list that is run before the compilation.
    validators: Vec<Box<validator::Validator + 'static>>,
}

impl Registry {
    /// Produces a new `Registry`.
    ///
    /// ## Example
    ///
    /// ```
    /// let mut registry = di::Registry::new();
    /// ```
    pub fn new() -> Registry {
        let mut registry = Registry {
            groups: BTreeMap::new(),
            definitions: BTreeMap::new(),
            overriden_definitions: BTreeMap::new(),
            validators: Vec::new(),
        };

        registry.push_validator(validator::argument_count::ArgumentCountValidator);
        registry.push_validator(validator::overrides::NoOverridesValidator);
        registry.push_validator(validator::dependencies::DependencyValidator);

        registry
    }

    fn push_validator<T: validator::Validator + 'static>(
        &mut self,
        validator: T
    ) {
        self.validators.push(box validator);
    }

    /**
    Compile a new `Container` that contains validated factories for
    all definitions.

    ## Example

    ```
    # let mut registry = di::Registry::new();
    match registry.compile() {
        Ok(container) => {
            // Validated successfuly, can be used.
        },
        Err(errors) => di::error_printer::pretty_print(&errors),
    }
    ```
    */
    pub fn compile(&self) -> Result<Container, Vec<CompileError>> {
        let mut error_summary = Vec::<CompileError>::new();

        for validator in self.validators.iter() {
            validator.validate(self, &mut error_summary);
        }

        let mut factory_map = HashMap::<String, Box<Any>>::new();
        let groups = self.collect_group_dependencies();

        if error_summary.len() == 0 {
            // Compile definitions.
            for id in self.definitions.keys() {
                let create_factory_result = self.create_factory(
                    &groups,
                    &mut Vec::<String>::new(),
                    id.as_slice()
                );
                match create_factory_result {
                    Err(error) => {
                        error_summary.push(CompileError::CircularDependency(error));
                        break;
                    },
                    Ok(factory) => { factory_map.insert(id.to_string(), factory); },
                };
            }
            // Compile groups.
            for group in groups.keys() {
                let create_factory_result = self.create_factory(
                    &groups,
                    &mut Vec::<String>::new(),
                    group.as_slice()
                );
                match create_factory_result {
                    Err(error) => {
                        error_summary.push(CompileError::CircularDependency(error));
                        break;
                    },
                    Ok(factory) => { factory_map.insert(group.clone(), factory); },
                };
            }
        }

        if error_summary.len() == 0 {
            Ok(Container::new(factory_map))
        } else {
            Err(error_summary)
        }
    }

    /**
    Insert a new definition without arguments.

    ## Example

    ```
    # let mut registry = di::Registry::new();
    registry.insert_one("a", 5i32); // Clonable value
    registry.insert_one("b", || -> i32 { 5 }); // Closure

    match registry.compile() {
        Ok(container) => {
            if let Some(a) = container.get::<i32>("a") {
                assert_eq!(5, a.take());
            }
            if let Some(b) = container.get::<i32>("b") {
                assert_eq!(5, b.take());
            }
        },
        Err(errors) => di::error_printer::pretty_print(&errors),
    }
    ```

    */
    pub fn insert_one<T: 'static + ToMetaFactory>(&mut self, id: &str, value: T) {
        self.define(
            None,
            id,
            value.to_metafactory(),
            Vec::new()
        );
    }

    /**
    Insert a new definition into a group, without arguments.

    Definition group has the Vec<T> for the definition of T type.

    ## Example

    ```
    # let mut registry = di::Registry::new();
    registry.insert_one_of("a", 1i32); // Clonable value
    registry.insert_one_of("a", || -> i32 { 2 }); // Closure

    match registry.compile() {
        Ok(container) => {
            if let Some(a) = container.get::<Vec<i32>>("a") {
                assert_eq!(vec![ 1, 2 ], a.take());
            }
        },
        Err(errors) => di::error_printer::pretty_print(&errors),
    }
    ```
    */
    pub fn insert_one_of<T: 'static + ToMetaFactory>(&mut self, collection_id: &str, value: T) {
        let mut id;
        let metafactory = value.to_metafactory();

        self.define_group_if_not_exists(collection_id, metafactory.new_aggregate());

        if let Some(group) = self.groups.get_mut(collection_id) {
            group.member_count += 1;
            id = format!("{}`{}", collection_id, group.member_count);
        } else {
            panic!("Expected to find defined group.")
        }

        self.define(
            Some(collection_id.to_string()),
            id.as_slice(),
            metafactory,
            Vec::new()
        );
    }

    /**
    Insert a new definition using fluent interface.

    This allows to specify definition dependencies and use closures with
    arguments.

    Browse [`NewDefinition`](new_definition/struct.NewDefinition.html)
    documentation for complete examples.

    ## Example

    ```
    # let mut registry = di::Registry::new();
    registry
        .one("a", || -> i32 { 5 })
        .insert();

    registry
        .one("b", |a: i32| -> i32 { a + 3 })
        .with_arg("a")
        .insert();

    match registry.compile() {
        Ok(container) => {
            if let Some(a) = container.get::<i32>("a") {
                assert_eq!(5, a.take());
            }
            if let Some(b) = container.get::<i32>("b") {
                assert_eq!(5 + 3, b.take());
            }
        },
        Err(errors) => di::error_printer::pretty_print(&errors),
    }
    ```
    */
    pub fn one<'r, T: 'static + ToMetaFactory>(&'r mut self, id: &str, value: T)
        -> NewDefinition<'r>
    {
        NewDefinition::new(
            self,
            None,
            id,
            value.to_metafactory()
        )
    }

    /**
    Insert a new definition into a group using fluent interface.

    This allows to specify definition dependencies and use closures with
    arguments.

    Definition group has the Vec<T> for the definition of T type.

    ## Example

    ```
    # let mut registry = di::Registry::new();
    registry
        .one_of("values", 1i32)
        .with_id("a")
        .insert();

    registry
        .one_of("values", |a: i32| -> i32 { a + 2 })
        .with_arg("a")
        .insert();

    match registry.compile() {
        Ok(container) => {
            if let Some(a) = container.get::<Vec<i32>>("values") {
                assert_eq!(vec![ 1, 1 + 2 ], a.take());
            }
        },
        Err(errors) => di::error_printer::pretty_print(&errors),
    }
    ```
    */
    pub fn one_of<'r, T: 'static + ToMetaFactory>(&'r mut self, collection_id: &str, value: T)
        -> NewDefinition<'r>
    {
        let mut id;
        let metafactory = value.to_metafactory();

        self.define_group_if_not_exists(collection_id, metafactory.new_aggregate());

        if let Some(group) = self.groups.get_mut(collection_id) {
            group.member_count += 1;
            id = format!("{}`{}", collection_id, group.member_count);
        } else {
            panic!("Expected to find defined group.")
        }

        NewDefinition::new(
            self,
            Some(collection_id.to_string()),
            id.as_slice(),
            metafactory
        )
    }

    /**
    Specify that a group can be empty.

    ## Example

    ```
    # let mut registry = di::Registry::new();
    registry
        .one("sum", |values: Vec<i32>| values.into_iter().fold(0i32, |a, i| a + 1))
        .with_arg("values")
        .insert();

    // If there is no definition of any member of "values", our "sum"
    // will still work and receive empty list.
    registry.may_be_empty::<i32>("values");

    match registry.compile() {
        Ok(container) => {
            if let Some(sum) = container.get::<i32>("sum") {
                assert_eq!(0, sum.take());
            }
        },
        Err(errors) => di::error_printer::pretty_print(&errors),
    }
    ```
    */
    pub fn may_be_empty<T: 'static>(&mut self, collection_id: &str) {
        self.define_group_if_not_exists(collection_id, Aggregate::new::<T>());
    }

    fn collect_group_dependencies<'r>(&'r self) -> BTreeMap<String, BTreeSet<&'r str>> {
        let mut groups: BTreeMap<String, BTreeSet<&str>> = BTreeMap::new();

        for (id, value) in self.definitions.iter()
            .filter(|&(_, v)| v.collection_id != None)
        {
            match groups.entry(value.collection_id.clone().unwrap()) {
                btree_map::Entry::Occupied(mut entry) => {
                    entry.get_mut().insert(id.as_slice());
                },
                btree_map::Entry::Vacant(entry) => {
                    let mut set: BTreeSet<&str> = BTreeSet::new();
                    set.insert(id.as_slice());
                    entry.set(set);
                }
            }
        }

        for id in self.groups.keys() {
            if !groups.contains_key(id) {
                groups.insert(id.to_string(), BTreeSet::new());
            }
        }

        groups
    }

    fn define_group_if_not_exists(&mut self, collection_id: &str, type_aggregate: Aggregate<'static>) {
        if !self.groups.contains_key(collection_id) {
            self.groups.insert(
                collection_id.to_string(),
                GroupCandidate::new(type_aggregate)
            );
        }
    }

    fn define(&mut self, collection_id: Option<String>, id: &str, value: Box<MetaFactory + 'static>, args: Vec<String>) {
        if let Some(overriden_candidate) = self.definitions.remove(id) {
            match self.overriden_definitions.entry(id.to_string()) {
                btree_map::Entry::Vacant(entry) => { entry.set(vec![overriden_candidate]); },
                btree_map::Entry::Occupied(mut entry) => { entry.get_mut().push(overriden_candidate); },
            };
        }

        let candidate = DefinitionCandidate::new(
            value,
            args,
            collection_id
        );

        self.definitions.insert(
            id.to_string(),
            candidate
        );
    }

    fn create_factory(
        &self,
        groups: &BTreeMap<String, BTreeSet<&str>>,
        dependency_chain: &mut Vec<String>,
        id: &str
    ) -> Result<Box<Any>, CircularDependency> {
        dependency_chain.push(id.to_string());

        // Find if this is a definition or a group.
        let mut result = match self.definitions.get(id) {
            Some(definition) => {
                // Check for circular dependencies.

                for source in definition.arg_sources.iter() {
                    if dependency_chain.contains(source) {
                        dependency_chain.push(source.clone());
                        return Err(CircularDependency::new(dependency_chain.clone()));
                    }
                }

                // Create definition factory.

                Some(self.create_definition_factory(
                    groups,
                    dependency_chain,
                    id,
                    definition
                ))
            },
            None => None,
        };

        if let None = result {
            result = match self.groups.get(id) {
                Some(group) => {
                    // Collect users of this group.
                    let group_dependencies = groups.get(id).expect(format!("expected to find dependencies for group {}", id).as_slice());

                    // Check for circular dependencies.
                    for source in group_dependencies.iter() {
                        if dependency_chain.contains(&source.to_string()) {
                            dependency_chain.push(source.to_string());
                            return Err(CircularDependency::new(dependency_chain.clone()));
                        }
                    }

                    Some(self.create_group_factory(
                        groups,
                        dependency_chain,
                        group,
                        group_dependencies
                    ))
                },
                None => None,
            }
        }

        dependency_chain.pop();

        result.expect(format!("expected definition or group {} was not found", id).as_slice())
    }

    fn create_definition_factory(
        &self,
        groups: &BTreeMap<String, BTreeSet<&str>>,
        dependency_chain: &mut Vec<String>,
        id: &str,
        definition: &DefinitionCandidate
    ) -> Result<Box<Any>, CircularDependency> {

        let mut argument_factories = Vec::<Box<Any>>::with_capacity(definition.arg_sources.len());

        for source in definition.arg_sources.iter() {
            match self.create_factory(
                groups,
                dependency_chain,
                source.as_slice()
            ) {
                Err(error) => return Err(error),
                Ok(factory) => argument_factories.push(factory),
            };
        }

        Ok(
            definition.metafactory.new(argument_factories)
                .ok()
                .expect(
                    format!(
                        "failed to create factory {} with arguments \"{}\" - most likely argument types are not the same",
                        id,
                        definition.arg_sources.connect("\", \"")
                    ).as_slice()
                )
        )
    }

    fn create_group_factory(
        &self,
        groups: &BTreeMap<String, BTreeSet<&str>>,
        dependency_chain: &mut Vec<String>,
        group: &GroupCandidate,
        group_sources: &BTreeSet<&str>
    )
        -> Result<Box<Any>, CircularDependency>
    {
        let mut argument_factories = Vec::<Box<Any>>::with_capacity(group_sources.len());

        for source in group_sources.iter() {
            match self.create_factory(
                groups,
                dependency_chain,
                *source
            ) {
                Err(error) => return Err(error),
                Ok(factory) => argument_factories.push(factory),
            };
        }

        Ok(group.aggregate.new_factory(
            argument_factories
        ))
    }
}
<|endoftext|>


<commit_before>// TODO: COPYRIGHT, USE & AUTHORS
// TODO: RUST DOCS!

extern crate rust_monster;
#[macro_use]
extern crate log;
extern crate env_logger;
#[cfg(test)]
mod tests
{
    use rust_monster::ga::ga_core::{GeneticAlgorithm, GASolution, GAFactory, DEBUG_FLAG};
    use rust_monster::ga::ga_population::{GAPopulation, GAPopulationSortOrder, GAPopulationSortBasis};
    use rust_monster::ga::ga_simple::{SimpleGeneticAlgorithm, SimpleGeneticAlgorithmCfg};
    use rust_monster::ga::ga_selectors::{GASelector, GARankSelector};

    use env_logger;
    use std::sync::{Once, ONCE_INIT};

    static INIT: Once = ONCE_INIT;
    const VAL: f32 = 3.14159;

    struct TestSolution
    {
        fitness: f32
    }
    impl GASolution for TestSolution
    {
        fn new() -> TestSolution
        {
            TestSolution{ fitness: VAL }
        }

        fn clone(&self) -> Self { TestSolution::new() }
        fn evaluate(&mut self) -> f32 { self.fitness }
    #[allow(unused_variables)]
        fn crossover(&self, other : &Self) -> Self { TestSolution::new() }
    #[allow(unused_variables)]
        fn mutate(&mut self, pm : f32) {}
        fn fitness(&self) -> f32 { (1.0 / self.fitness) }
        fn score(&self) -> f32 { self.fitness }
    }

    #[allow(dead_code)]
    struct TestFactory
    {
        starting_fitness: f32
    }
    impl GAFactory<TestSolution> for TestFactory
    {
        fn initial_population(&mut self) -> GAPopulation<TestSolution> {
            GAPopulation::new(vec![TestSolution { fitness: self.starting_fitness }], GAPopulationSortOrder::HighIsBest)
        }
    }

////////////////////////////////////////
// Utility functions

    fn ga_test_setup()
    {
        // This is only called once, works nicely as a Setup mechanism
        // TODO: Can we do somethign similar for teardown?
        INIT.call_once(||{
            env_logger::init().unwrap();
        });
    }

    fn simple_ga_validation(sga:&mut SimpleGeneticAlgorithm<TestSolution>)
    {
        sga.initialize();
        assert_eq!(sga.step(), 1);
        assert_eq!(sga.done(), false);
        assert_eq!(sga.population().size(), 1);
        assert_eq!(sga.population().best().score(), VAL);
    }

////////////////////////////////////////
// Tests

    #[test]
    fn init_test_with_initial_population()
    {
        ga_test_setup();
        let initial_population = GAPopulation::new(vec![TestSolution { fitness: VAL}], GAPopulationSortOrder::HighIsBest);
        let mut ga : SimpleGeneticAlgorithm<TestSolution> =
                     SimpleGeneticAlgorithm::new(SimpleGeneticAlgorithmCfg {
                                                   d_seed : 1,
                                                   flags : DEBUG_FLAG,
                                                   max_generations: 100,
                                                   ..Default::default()
                                                 },
                                                 None,
                                                 Some(initial_population)
                                                 );
        simple_ga_validation(&mut ga);
    }

    #[test]
    fn init_test_with_factory()
    {
        ga_test_setup();
        let mut factory = TestFactory { starting_fitness: VAL };
        let mut ga : SimpleGeneticAlgorithm<TestSolution> =
                     SimpleGeneticAlgorithm::new(SimpleGeneticAlgorithmCfg {
                                                   d_seed : 1,
                                                   flags : DEBUG_FLAG,
                                                   max_generations: 100,
                                                   ..Default::default()
                                                 },
                                                 Some(&mut factory as &mut GAFactory<TestSolution>),
                                                 None
                                                 );
        simple_ga_validation(&mut ga);
    }

    #[test]
    #[should_panic]
    #[allow(unused_variables)]
    fn init_test_missing_args()
    {
        ga_test_setup();
        let ga : SimpleGeneticAlgorithm<TestSolution> =
                 SimpleGeneticAlgorithm::new(SimpleGeneticAlgorithmCfg {
                                               d_seed : 1,
                                               flags : DEBUG_FLAG,
                                               max_generations: 100,
                                               ..Default::default()
                                             },
                                             None,
                                             None
                                             );
        // Not reached
    }

    #[test]
    #[should_panic]
    fn init_test_empty_initial_pop()
    {
        ga_test_setup();
        let empty_initial_population : GAPopulation<TestSolution> = GAPopulation::new(vec![], GAPopulationSortOrder::HighIsBest);
        let mut ga : SimpleGeneticAlgorithm<TestSolution> =
                     SimpleGeneticAlgorithm::new(SimpleGeneticAlgorithmCfg {
                                                   d_seed : 1,
                                                   flags : DEBUG_FLAG,
                                                   max_generations: 100,
                                                   ..Default::default()
                                                 },
                                                 None,
                                                 Some(empty_initial_population)
                                                 );
        ga.initialize()
        //Not reached
    }

    // This test should live in the ga_population file directly,
    // but since it requires GASolution objects it is here for now.
    // Maybe we could use a Mocking library.
    // TODO: This doesn't go here.
    #[test]
    fn test_sort_population()
    {
        let f = VAL;
        let f_m = VAL - 1.0;
        let i_f = 1.0 / f;
        let i_f_m = 1.0 / f_m;

        let mut population = GAPopulation::new(vec![TestSolution { fitness: f }, TestSolution { fitness: f_m }], GAPopulationSortOrder::HighIsBest);
        population.sort();

        //TestSolution's Fitness is the inverse of the Score (F = 1/S)
        assert_eq!(population.individual(0, GAPopulationSortBasis::Raw).score(), f);
        assert_eq!(population.individual(1, GAPopulationSortBasis::Raw).score(), f_m);
        assert_eq!(population.individual(0, GAPopulationSortBasis::Scaled).fitness(), i_f_m);
        assert_eq!(population.individual(1, GAPopulationSortBasis::Scaled).fitness(), i_f);
    }

    #[test]
    #[allow(unused_variables)]
    fn test_rank_selector()
    {
        let f = VAL;
        let f_m = VAL - 1.0;
        let i_f = 1.0 / f;
        let i_f_m = 1.0 / f_m;

        let mut population
          = GAPopulation::new(vec![TestSolution { fitness: f },
                                   TestSolution { fitness: f_m }],
                              GAPopulationSortOrder::HighIsBest);

        let mut rank_selector = GARankSelector { population: &mut population };

        // Best Raw score is that of 1st solution.
        assert_eq!(rank_selector.select(GAPopulationSortBasis::Raw).score(), f);
        // Best Scaled score is that of 2nd solution (because fitness is inverse of score). Weird. In this case, LowIsBest.
        assert_eq!(rank_selector.select(GAPopulationSortBasis::Scaled).fitness(), i_f_m);
    }
}
<commit_msg>Add GAUniformSelector test.<commit_after>// TODO: COPYRIGHT, USE & AUTHORS
// TODO: RUST DOCS!

extern crate rust_monster;
#[macro_use]
extern crate log;
extern crate env_logger;
#[cfg(test)]
mod tests
{
    use rust_monster::ga::ga_core::{GeneticAlgorithm, GASolution, GAFactory, DEBUG_FLAG};
    use rust_monster::ga::ga_population::{GAPopulation, GAPopulationSortOrder, GAPopulationSortBasis};
    use rust_monster::ga::ga_simple::{SimpleGeneticAlgorithm, SimpleGeneticAlgorithmCfg};
    use rust_monster::ga::ga_selectors::{GASelector, GARankSelector, GAUniformSelector};

    use env_logger;
    use std::sync::{Once, ONCE_INIT};

    static INIT: Once = ONCE_INIT;
    const VAL: f32 = 3.14159;

    struct TestSolution
    {
        fitness: f32
    }
    impl GASolution for TestSolution
    {
        fn new() -> TestSolution
        {
            TestSolution{ fitness: VAL }
        }

        fn clone(&self) -> Self { TestSolution::new() }
        fn evaluate(&mut self) -> f32 { self.fitness }
    #[allow(unused_variables)]
        fn crossover(&self, other : &Self) -> Self { TestSolution::new() }
    #[allow(unused_variables)]
        fn mutate(&mut self, pm : f32) {}
        fn fitness(&self) -> f32 { (1.0 / self.fitness) }
        fn score(&self) -> f32 { self.fitness }
    }

    #[allow(dead_code)]
    struct TestFactory
    {
        starting_fitness: f32
    }
    impl GAFactory<TestSolution> for TestFactory
    {
        fn initial_population(&mut self) -> GAPopulation<TestSolution> {
            GAPopulation::new(vec![TestSolution { fitness: self.starting_fitness }], GAPopulationSortOrder::HighIsBest)
        }
    }

////////////////////////////////////////
// Utility functions

    fn ga_test_setup()
    {
        // This is only called once, works nicely as a Setup mechanism
        // TODO: Can we do somethign similar for teardown?
        INIT.call_once(||{
            env_logger::init().unwrap();
        });
    }

    fn simple_ga_validation(sga:&mut SimpleGeneticAlgorithm<TestSolution>)
    {
        sga.initialize();
        assert_eq!(sga.step(), 1);
        assert_eq!(sga.done(), false);
        assert_eq!(sga.population().size(), 1);
        assert_eq!(sga.population().best().score(), VAL);
    }

////////////////////////////////////////
// Tests

    #[test]
    fn init_test_with_initial_population()
    {
        ga_test_setup();
        let initial_population = GAPopulation::new(vec![TestSolution { fitness: VAL}], GAPopulationSortOrder::HighIsBest);
        let mut ga : SimpleGeneticAlgorithm<TestSolution> =
                     SimpleGeneticAlgorithm::new(SimpleGeneticAlgorithmCfg {
                                                   d_seed : 1,
                                                   flags : DEBUG_FLAG,
                                                   max_generations: 100,
                                                   ..Default::default()
                                                 },
                                                 None,
                                                 Some(initial_population)
                                                 );
        simple_ga_validation(&mut ga);
    }

    #[test]
    fn init_test_with_factory()
    {
        ga_test_setup();
        let mut factory = TestFactory { starting_fitness: VAL };
        let mut ga : SimpleGeneticAlgorithm<TestSolution> =
                     SimpleGeneticAlgorithm::new(SimpleGeneticAlgorithmCfg {
                                                   d_seed : 1,
                                                   flags : DEBUG_FLAG,
                                                   max_generations: 100,
                                                   ..Default::default()
                                                 },
                                                 Some(&mut factory as &mut GAFactory<TestSolution>),
                                                 None
                                                 );
        simple_ga_validation(&mut ga);
    }

    #[test]
    #[should_panic]
    #[allow(unused_variables)]
    fn init_test_missing_args()
    {
        ga_test_setup();
        let ga : SimpleGeneticAlgorithm<TestSolution> =
                 SimpleGeneticAlgorithm::new(SimpleGeneticAlgorithmCfg {
                                               d_seed : 1,
                                               flags : DEBUG_FLAG,
                                               max_generations: 100,
                                               ..Default::default()
                                             },
                                             None,
                                             None
                                             );
        // Not reached
    }

    #[test]
    #[should_panic]
    fn init_test_empty_initial_pop()
    {
        ga_test_setup();
        let empty_initial_population : GAPopulation<TestSolution> = GAPopulation::new(vec![], GAPopulationSortOrder::HighIsBest);
        let mut ga : SimpleGeneticAlgorithm<TestSolution> =
                     SimpleGeneticAlgorithm::new(SimpleGeneticAlgorithmCfg {
                                                   d_seed : 1,
                                                   flags : DEBUG_FLAG,
                                                   max_generations: 100,
                                                   ..Default::default()
                                                 },
                                                 None,
                                                 Some(empty_initial_population)
                                                 );
        ga.initialize()
        //Not reached
    }

    // This test should live in the ga_population file directly,
    // but since it requires GASolution objects it is here for now.
    // Maybe we could use a Mocking library.
    // TODO: This doesn't go here.
    #[test]
    fn test_sort_population()
    {
        let f = VAL;
        let f_m = VAL - 1.0;
        let i_f = 1.0 / f;
        let i_f_m = 1.0 / f_m;

        let mut population = GAPopulation::new(vec![TestSolution { fitness: f }, TestSolution { fitness: f_m }], GAPopulationSortOrder::HighIsBest);
        population.sort();

        //TestSolution's Fitness is the inverse of the Score (F = 1/S)
        assert_eq!(population.individual(0, GAPopulationSortBasis::Raw).score(), f);
        assert_eq!(population.individual(1, GAPopulationSortBasis::Raw).score(), f_m);
        assert_eq!(population.individual(0, GAPopulationSortBasis::Scaled).fitness(), i_f_m);
        assert_eq!(population.individual(1, GAPopulationSortBasis::Scaled).fitness(), i_f);
    }

    #[test]
    #[allow(unused_variables)]
    fn test_rank_selector()
    {
        let f = VAL;
        let f_m = VAL - 1.0;
        let i_f = 1.0 / f;
        let i_f_m = 1.0 / f_m;

        let mut population
          = GAPopulation::new(vec![TestSolution { fitness: f },
                                   TestSolution { fitness: f_m }],
                              GAPopulationSortOrder::HighIsBest);

        {
            let mut raw_rank_selector = GARankSelector::new(&mut population, GAPopulationSortBasis::Raw);

            // Best Raw score is that of 1st solution.
            assert_eq!(raw_rank_selector.select().score(), f);
        }

        {
            let mut scaled_rank_selector = GARankSelector::new(&mut population, GAPopulationSortBasis::Scaled);

            // Best Scaled score is that of 2nd solution (because fitness is inverse of score). Weird. In this case, LowIsBest.
            assert_eq!(scaled_rank_selector.select().fitness(), i_f_m);
        }
    }

    #[test]
    fn test_uniform_selector()
    {
        let f = VAL;
        let f_m = VAL - 1.0;

        let mut population
          = GAPopulation::new(vec![TestSolution { fitness: f },
                                   TestSolution { fitness: f_m }],
                              GAPopulationSortOrder::HighIsBest);

        let mut uniform_selector = GAUniformSelector::new(&mut population);

        assert!(uniform_selector.select().score() == f || uniform_selector.select().score() == f_m);
    }
}
<|endoftext|>


<commit_before>extern crate file;
extern crate itertools;
extern crate walkdir;

use walkdir::WalkDir;
use itertools::Itertools;

use std::path::{Path, PathBuf};
use std::collections::HashSet;
use std::fs;

fn main() {
    let verify = ::std::env::args().any(|arg| arg == "--verify");

    let d = grammar_dir();
    let tests = tests_from_dir(&d);
    let existing = existing_tests();

    for t in existing.difference(&tests) {
        panic!("Test is deleted: {}\n{}", t.name, t.text);
    }

    let new_tests = tests.difference(&existing);
    for (i, t) in new_tests.enumerate() {
        if verify {
            panic!("Inline test is not recorded: {}", t.name);
        }

        let name = format!("{:04}_{}.rs", existing.len() + i + 1, t.name);
        println!("Creating {}", name);
        let path = inline_tests_dir().join(name);
        file::put_text(&path, &t.text).unwrap();
    }
}

#[derive(Debug, Eq)]
struct Test {
    name: String,
    text: String,
}

impl PartialEq for Test {
    fn eq(&self, other: &Test) -> bool {
        self.name.eq(&other.name)
    }
}

impl ::std::hash::Hash for Test {
    fn hash<H: ::std::hash::Hasher>(&self, state: &mut H) {
        self.name.hash(state)
    }
}

fn tests_from_dir(dir: &Path) -> HashSet<Test> {
    let mut res = HashSet::new();
    for entry in WalkDir::new(dir) {
        let entry = entry.unwrap();
        if !entry.file_type().is_file() {
            continue;
        }
        if entry.path().extension().unwrap_or_default() != "rs" {
            continue;
        }
        let text = file::get_text(entry.path()).unwrap();

        for test in collect_tests(&text) {
            if let Some(old_test) = res.replace(test) {
                panic!("Duplicate test: {}", old_test.name)
            }
        }
    }
    res
}

fn collect_tests(s: &str) -> Vec<Test> {
    let mut res = vec![];
    let prefix = "// ";
    let comment_blocks = s.lines()
        .map(str::trim_left)
        .group_by(|line| line.starts_with(prefix));

    'outer: for (is_comment, block) in comment_blocks.into_iter() {
        if !is_comment {
            continue;
        }
        let mut block = block.map(|line| &line[prefix.len()..]);

        let name = loop {
            match block.next() {
                Some(line) if line.starts_with("test ") => break line["test ".len()..].to_string(),
                Some(_) => (),
                None => continue 'outer,
            }
        };
        let text: String = itertools::join(block.chain(::std::iter::once("")), "\n");
        assert!(!text.trim().is_empty() && text.ends_with("\n"));
        res.push(Test { name, text })
    }
    res
}

fn existing_tests() -> HashSet<Test> {
    let mut res = HashSet::new();
    for file in fs::read_dir(&inline_tests_dir()).unwrap() {
        let file = file.unwrap();
        let path = file.path();
        if path.extension().unwrap_or_default() != "rs" {
            continue;
        }
        let name = path.file_name().unwrap().to_str().unwrap();
        let name = name["0000_".len()..name.len() - 3].to_string();
        let text = file::get_text(&path).unwrap();
        res.insert(Test { name, text });
    }
    res
}

fn inline_tests_dir() -> PathBuf {
    let res = base_dir().join("tests/data/parser/inline");
    if !res.is_dir() {
        fs::create_dir_all(&res).unwrap();
    }
    res
}

fn grammar_dir() -> PathBuf {
    base_dir().join("src/parser/event_parser/grammar")
}

fn base_dir() -> PathBuf {
    let dir = env!("CARGO_MANIFEST_DIR");
    PathBuf::from(dir).parent().unwrap().to_owned()
}
<commit_msg>Fix test collection<commit_after>extern crate file;
extern crate itertools;
extern crate walkdir;

use walkdir::WalkDir;
use itertools::Itertools;

use std::path::{Path, PathBuf};
use std::collections::HashSet;
use std::fs;

fn main() {
    let verify = ::std::env::args().any(|arg| arg == "--verify");

    let d = grammar_dir();
    let tests = tests_from_dir(&d);
    let existing = existing_tests();

    for t in existing.difference(&tests) {
        panic!("Test is deleted: {}\n{}", t.name, t.text);
    }

    let new_tests = tests.difference(&existing);
    for (i, t) in new_tests.enumerate() {
        if verify {
            panic!("Inline test is not recorded: {}", t.name);
        }

        let name = format!("{:04}_{}.rs", existing.len() + i + 1, t.name);
        println!("Creating {}", name);
        let path = inline_tests_dir().join(name);
        file::put_text(&path, &t.text).unwrap();
    }
}

#[derive(Debug, Eq)]
struct Test {
    name: String,
    text: String,
}

impl PartialEq for Test {
    fn eq(&self, other: &Test) -> bool {
        self.name.eq(&other.name)
    }
}

impl ::std::hash::Hash for Test {
    fn hash<H: ::std::hash::Hasher>(&self, state: &mut H) {
        self.name.hash(state)
    }
}

fn tests_from_dir(dir: &Path) -> HashSet<Test> {
    let mut res = HashSet::new();
    for entry in WalkDir::new(dir) {
        let entry = entry.unwrap();
        if !entry.file_type().is_file() {
            continue;
        }
        if entry.path().extension().unwrap_or_default() != "rs" {
            continue;
        }
        let text = file::get_text(entry.path()).unwrap();

        for test in collect_tests(&text) {
            if let Some(old_test) = res.replace(test) {
                panic!("Duplicate test: {}", old_test.name)
            }
        }
    }
    res
}

fn collect_tests(s: &str) -> Vec<Test> {
    let mut res = vec![];
    let prefix = "// ";
    let comment_blocks = s.lines()
        .map(str::trim_left)
        .group_by(|line| line.starts_with(prefix));

    'outer: for (is_comment, block) in comment_blocks.into_iter() {
        if !is_comment {
            continue;
        }
        let mut block = block.map(|line| &line[prefix.len()..]);

        let name = loop {
            match block.next() {
                Some(line) if line.starts_with("test ") => break line["test ".len()..].to_string(),
                Some(_) => (),
                None => continue 'outer,
            }
        };
        let text: String = itertools::join(block.chain(::std::iter::once("")), "\n");
        assert!(!text.trim().is_empty() && text.ends_with("\n"));
        res.push(Test { name, text })
    }
    res
}

fn existing_tests() -> HashSet<Test> {
    let mut res = HashSet::new();
    for file in fs::read_dir(&inline_tests_dir()).unwrap() {
        let file = file.unwrap();
        let path = file.path();
        if path.extension().unwrap_or_default() != "rs" {
            continue;
        }
        let name = path.file_name().unwrap().to_str().unwrap();
        let name = name["0000_".len()..name.len() - 3].to_string();
        let text = file::get_text(&path).unwrap();
        res.insert(Test { name, text });
    }
    res
}

fn inline_tests_dir() -> PathBuf {
    let res = base_dir().join("tests/data/parser/inline");
    if !res.is_dir() {
        fs::create_dir_all(&res).unwrap();
    }
    res
}

fn grammar_dir() -> PathBuf {
    base_dir().join("src/parser/grammar")
}

fn base_dir() -> PathBuf {
    let dir = env!("CARGO_MANIFEST_DIR");
    PathBuf::from(dir).parent().unwrap().to_owned()
}
<|endoftext|>