<commit_before>use metric::{Measured, Line, Grapheme, Metric};
use super::{NodeLink, LeafRepr };

use self::Value::*;

use std::cell::Cell;
use std::convert;
use std::default::Default;
use std::fmt;
use std::ops;

/// A lazily-evaluated field
#[derive(Clone)]
struct Lazy<T: Copy>(Cell<Option<T>>);

impl<T> Lazy<T>
where T: Copy {

    #[inline]
    pub fn get(&self) -> Option<T> { self.0.get() }

    #[inline]
    pub fn get_or_else<F>(&self, f: F) -> T
    where F: FnOnce() -> T {
        if let Some(value) = self.0.get() {
            value
        } else {
            let value = f();
            self.0.set(Some(value));
            value
        }
    }

    #[inline]
    pub fn new() -> Self {
        Lazy(Cell::new(None))
    }

}

impl<T> Default for Lazy<T>
where T: Copy {
    fn default() -> Self {
        Self::new()
    }
}

impl<T> fmt::Debug for Lazy<T>
where T: fmt::Debug
    , T: Copy {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self.0.get() { Some(value) => value.fmt(f)
                           , None => write!(f, "?")

        }
    }
}

macro_rules! lazy_field {
    ($method: ident, $field: ident, $ty:ty) => {
        #[inline] fn $method(&self) -> $ty {
            self.$field.get_or_else(|| { self.value.$method() })
        }

    }
}

/// A `Node`.
#[derive(Clone, Debug, Default)]
pub struct Node { len: Lazy<usize>
                , weight: Lazy<usize>
                , line_count: Lazy<Line>
                , line_weight: Lazy<Line>
                , grapheme_count: Lazy<Grapheme>
                , grapheme_weight: Lazy<Grapheme>
                , pub value: Value
                }

impl Node {
    pub fn new(value: Value) -> Self {
        Node { value: value, ..Default::default() }
    }

    pub fn spanning(&self, i: usize, span_len: usize) -> (&Node, usize)
    where Node: Measured<usize> {
        assert!(self.len() >= span_len);
        match **self {
            Branch { ref right, ref left } if <Node as Measured<usize>>::measure_weight(self) < i => {
                // if this node is a branch, and the weight is less than the
                // index, where the span begins, then the first index of the
                // span is on the right side
                let span_i = or_zero!(i, left.len());
                assert!(or_zero!(right.len(), span_i) >= span_len);
                right.spanning(span_i, span_len)
            }
          , Branch { ref left, .. }
            // if the left child is long enough to contain the entire span,
            // walk to the left child
            if or_zero!(left.len(), i) >= span_len => left.spanning(i, span_len)
         ,  Leaf(_) | Branch {..} =>
            // if this function has walked as far as a leaf node,
            // then that leaf must be the spanning node. return it;
            //
            // otherwise, if the node is a branch node and the span is longer
            // than the left child, then this node must be the minimum
            // spanning node
            (self, i)
        }
    }
}

impl fmt::Display for Node {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.strings()
            .fold(Ok(()), |r, string| r.and_then(|_| write!(f, "{}", string)))
    }
}

impl convert::Into<NodeLink> for Node {
    #[inline] fn into(self) -> NodeLink {
        NodeLink::new(self)
    }
}

impl ops::Deref for Node {
    type Target = Value;
    fn deref(&self) -> &Value { &self.value }
}

impl Measured<usize> for Node {

        #[inline] fn to_byte_index(&self, index: usize) -> Option<usize>  {
             Some(index)
        }

        lazy_field!(measure, len, usize);
        lazy_field!(measure_weight, weight, usize);

}

impl Measured<Grapheme> for Node {

        #[inline] fn to_byte_index(&self, index: Grapheme) -> Option<usize>  {
            self.value.to_byte_index(index)
        }

        lazy_field!(measure, grapheme_count, Grapheme);
        lazy_field!(measure_weight, grapheme_weight, Grapheme);

}

impl Measured<Line> for Node {

        #[inline] fn to_byte_index(&self, index: Line) -> Option<usize>  {
            self.value.to_byte_index(index)
        }

        lazy_field!(measure, line_count, Line);
        lazy_field!(measure_weight, line_weight, Line);

}

impl<M> ops::Index<M> for Node
where M: Metric
    , Node: Measured<M>
    , LeafRepr: Measured<M>
    {
    type Output = str;

    fn index(&self, i: M) -> &str {
        let len = self.measure();
        assert!( i < len
               , "Node::index: index {:?} out of bounds (length {:?})", i, len);
        match **self {
            Leaf(ref string) => {
                let idx = string.to_byte_index(i)
                                .expect("index out of bounds!");
                &string[idx..idx+1]
            }
          , Branch { ref right, .. } if len < i =>
                &right[i - len]
          , Branch { ref left, .. } => &left[i]
        }
    }
}

/// A `Node` in the `Rope`'s tree.
///
/// A `Node` is either a `Leaf` holding a `String`, or a
/// a `Branch` concatenating together two `Node`s.
#[derive(Clone, Debug)]
pub enum Value {
    /// A leaf node
    Leaf(LeafRepr)
  , /// A branch concatenating together `l`eft and `r`ight nodes.
    Branch { /// The left branch node
             left: NodeLink
           , /// The right branch node
             right: NodeLink }
}

impl Value {
    #[inline]
    pub fn new_branch(left: NodeLink, right: NodeLink) -> Self {
        Branch { left: left, right: right }
    }
}

impl<M> Measured<M> for Value
where M: Metric
    , LeafRepr: Measured<M>
    , Node: Measured<M>
{
    fn to_byte_index(&self, index: M) -> Option<usize> {
        unimplemented!()
    }

    fn measure(&self) -> M {
        match *self {
            Leaf(ref r) => r.measure()
          , Branch { ref left, ref right } =>
                left.measure() + right.measure()
        }
    }

    fn measure_weight(&self) -> M {
        match *self {
            Leaf(ref r) => r.measure_weight()
          , Branch { ref left, ref right } =>
                left.measure()
        }
    }

}

impl convert::Into<Node> for Value {
    #[inline] fn into(self) -> Node {
        Node::new(self)
    }
}

impl Default for Value {
    fn default() -> Self {
        Leaf(LeafRepr::default())
    }
}
<commit_msg>docs(node): add docs to lazy fields<commit_after>use metric::{Measured, Line, Grapheme, Metric};
use super::{NodeLink, LeafRepr };

use self::Value::*;

use std::cell::Cell;
use std::convert;
use std::default::Default;
use std::fmt;
use std::ops;

/// A lazily-evaluated field
#[derive(Clone)]
struct Lazy<T: Copy>(Cell<Option<T>>);

impl<T> Lazy<T>
where T: Copy {

    /// Get the value of the field if it has been computed
    ///
    /// # Returns
    /// - `Some(T)` if the value of this field has been computed
    /// - `None` if the field has yet to be computed
    #[inline]
    pub fn get(&self) -> Option<T> { self.0.get() }

    /// Get the value of the field, or compute it
    ///
    /// # Arguments
    /// - `f`: a function returning type `T` to use to calculate the value of
    ///        the field if it has not already been calculated
    ///
    /// # Returns
    /// - If the field has already been evaluated, the value of the field.
    /// - If the field has not been evaluated, the value of `f`
    #[inline]
    pub fn get_or_else<F>(&self, f: F) -> T
    where F: FnOnce() -> T {
        if let Some(value) = self.0.get() {
            value
        } else {
            let value = f();
            self.0.set(Some(value));
            value
        }
    }

    #[inline]
    pub fn new() -> Self {
        Lazy(Cell::new(None))
    }

}

impl<T> Default for Lazy<T>
where T: Copy {
    fn default() -> Self {
        Self::new()
    }
}

impl<T> fmt::Debug for Lazy<T>
where T: fmt::Debug
    , T: Copy {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self.0.get() { Some(value) => value.fmt(f)
                           , None => write!(f, "?")

        }
    }
}

macro_rules! lazy_field {
    ($method: ident, $field: ident, $ty:ty) => {
        #[inline] fn $method(&self) -> $ty {
            self.$field.get_or_else(|| { self.value.$method() })
        }

    }
}

/// A `Node`.
#[derive(Clone, Debug, Default)]
pub struct Node { len: Lazy<usize>
                , weight: Lazy<usize>
                , line_count: Lazy<Line>
                , line_weight: Lazy<Line>
                , grapheme_count: Lazy<Grapheme>
                , grapheme_weight: Lazy<Grapheme>
                , pub value: Value
                }

impl Node {
    pub fn new(value: Value) -> Self {
        Node { value: value, ..Default::default() }
    }

    pub fn spanning(&self, i: usize, span_len: usize) -> (&Node, usize)
    where Node: Measured<usize> {
        assert!(self.len() >= span_len);
        match **self {
            Branch { ref right, ref left } if <Node as Measured<usize>>::measure_weight(self) < i => {
                // if this node is a branch, and the weight is less than the
                // index, where the span begins, then the first index of the
                // span is on the right side
                let span_i = or_zero!(i, left.len());
                assert!(or_zero!(right.len(), span_i) >= span_len);
                right.spanning(span_i, span_len)
            }
          , Branch { ref left, .. }
            // if the left child is long enough to contain the entire span,
            // walk to the left child
            if or_zero!(left.len(), i) >= span_len => left.spanning(i, span_len)
         ,  Leaf(_) | Branch {..} =>
            // if this function has walked as far as a leaf node,
            // then that leaf must be the spanning node. return it;
            //
            // otherwise, if the node is a branch node and the span is longer
            // than the left child, then this node must be the minimum
            // spanning node
            (self, i)
        }
    }
}

impl fmt::Display for Node {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.strings()
            .fold(Ok(()), |r, string| r.and_then(|_| write!(f, "{}", string)))
    }
}

impl convert::Into<NodeLink> for Node {
    #[inline] fn into(self) -> NodeLink {
        NodeLink::new(self)
    }
}

impl ops::Deref for Node {
    type Target = Value;
    fn deref(&self) -> &Value { &self.value }
}

impl Measured<usize> for Node {

        #[inline] fn to_byte_index(&self, index: usize) -> Option<usize>  {
             Some(index)
        }

        lazy_field!(measure, len, usize);
        lazy_field!(measure_weight, weight, usize);

}

impl Measured<Grapheme> for Node {

        #[inline] fn to_byte_index(&self, index: Grapheme) -> Option<usize>  {
            self.value.to_byte_index(index)
        }

        lazy_field!(measure, grapheme_count, Grapheme);
        lazy_field!(measure_weight, grapheme_weight, Grapheme);

}

impl Measured<Line> for Node {

        #[inline] fn to_byte_index(&self, index: Line) -> Option<usize>  {
            self.value.to_byte_index(index)
        }

        lazy_field!(measure, line_count, Line);
        lazy_field!(measure_weight, line_weight, Line);

}

impl<M> ops::Index<M> for Node
where M: Metric
    , Node: Measured<M>
    , LeafRepr: Measured<M>
    {
    type Output = str;

    fn index(&self, i: M) -> &str {
        let len = self.measure();
        assert!( i < len
               , "Node::index: index {:?} out of bounds (length {:?})", i, len);
        match **self {
            Leaf(ref string) => {
                let idx = string.to_byte_index(i)
                                .expect("index out of bounds!");
                &string[idx..idx+1]
            }
          , Branch { ref right, .. } if len < i =>
                &right[i - len]
          , Branch { ref left, .. } => &left[i]
        }
    }
}

/// A `Node` in the `Rope`'s tree.
///
/// A `Node` is either a `Leaf` holding a `String`, or a
/// a `Branch` concatenating together two `Node`s.
#[derive(Clone, Debug)]
pub enum Value {
    /// A leaf node
    Leaf(LeafRepr)
  , /// A branch concatenating together `l`eft and `r`ight nodes.
    Branch { /// The left branch node
             left: NodeLink
           , /// The right branch node
             right: NodeLink }
}

impl Value {
    #[inline]
    pub fn new_branch(left: NodeLink, right: NodeLink) -> Self {
        Branch { left: left, right: right }
    }
}

impl<M> Measured<M> for Value
where M: Metric
    , LeafRepr: Measured<M>
    , Node: Measured<M>
{
    fn to_byte_index(&self, index: M) -> Option<usize> {
        unimplemented!()
    }

    fn measure(&self) -> M {
        match *self {
            Leaf(ref r) => r.measure()
          , Branch { ref left, ref right } =>
                left.measure() + right.measure()
        }
    }

    fn measure_weight(&self) -> M {
        match *self {
            Leaf(ref r) => r.measure_weight()
          , Branch { ref left, ref right } =>
                left.measure()
        }
    }

}

impl convert::Into<Node> for Value {
    #[inline] fn into(self) -> Node {
        Node::new(self)
    }
}

impl Default for Value {
    fn default() -> Self {
        Leaf(LeafRepr::default())
    }
}
<|endoftext|>


<commit_before>use {node, routing, rpc, bus, time, SubotaiError, SubotaiResult};
use std::{net, sync};
use rpc::Rpc;
use hash::Hash;
use node::receptions;

/// Node resources for synchronous operations.
///
/// All methods on this module are synchronous, and will wait for any
/// remote nodes queried to reply to the RPCs sent, up to the timeout
/// defined at `node::node::NETWORK_TIMEOUT_S`. The node layer above is in
/// charge of parallelizing those operations by spawning threads when
/// adequate.
pub struct Resources {
   pub id       : Hash,
   pub table    : routing::Table,
   pub outbound : net::UdpSocket,
   pub inbound  : net::UdpSocket,
   pub state    : sync::Mutex<node::State>,
   pub updates  : sync::Mutex<bus::Bus<Update>>,
}

#[derive(Clone)]
pub enum Update {
   RpcReceived(Rpc),
   Tick,
   Shutdown,
}

impl Resources {
   pub fn local_info(&self) -> routing::NodeInfo {
      routing::NodeInfo {
         id      : self.id.clone(),
         address : self.inbound.local_addr().unwrap(),
      }
   }

   /// Pings a node, blocking until ping response.
   pub fn ping(&self, id: Hash) -> SubotaiResult<()> {
      let node = try!(self.find_node(&id));
      let rpc = Rpc::ping(self.id.clone(), self.inbound.local_addr().unwrap().port());
      let packet = rpc.serialize();
      let responses = self.receptions().during(time::Duration::seconds(node::NETWORK_TIMEOUT_S))
         .rpc(receptions::RpcFilter::PingResponse).from(id.clone()).take(1);
      try!(self.outbound.send_to(&packet, node.address));

      match responses.count() {
         1 => Ok(()),
         _ => Err(SubotaiError::NoResponse),
      }
   }

   /// Sends a ping and doesn't wait for a response. Used by the maintenance thread.
   pub fn ping_and_forget(&self, id: Hash) -> SubotaiResult<()> {
      let node = try!(self.find_node(&id));
      let rpc = Rpc::ping(self.id.clone(), self.inbound.local_addr().unwrap().port());
      let packet = rpc.serialize();
      try!(self.outbound.send_to(&packet, node.address));

      Ok(())
   }

   pub fn receptions(&self) -> receptions::Receptions {
      receptions::Receptions::new(self)
   }

   /// Attempts to find a node through the network.
   pub fn find_node(&self, id_to_find: &Hash) -> SubotaiResult<routing::NodeInfo> {
      // If the node is already present in our table, we are done early.
      if let Some(node) = self.table.specific_node(id_to_find) {
         return Ok(node);
      }

      let mut queried_ids = Vec::<Hash>::with_capacity(routing::K);
      let all_receptions = self.receptions();
      let loop_timeout = time::Duration::seconds(2 * node::NETWORK_TIMEOUT_S);
      let deadline = time::SteadyTime::now() + loop_timeout;

      while queried_ids.len() < routing::K && time::SteadyTime::now() < deadline {
         // We query the 'ALPHA' nodes closest to the target we haven't yet queried.
         let nodes_to_query: Vec<routing::NodeInfo> = self.table.closest_nodes_to(id_to_find)
            .filter(|ref info| !queried_ids.contains(&info.id))
            .take(routing::ALPHA)
            .collect();

         // We wait for the response from the same number of nodes, minus the 'IMPATIENCE' factor.
         let responses = self.receptions()
            .during(time::Duration::seconds(node::NETWORK_TIMEOUT_S))
            .filter(|ref rpc| rpc.is_finding_node(id_to_find))
            .take(usize::saturating_sub(nodes_to_query.len(), routing::IMPATIENCE));

         // We compose the RPCs and send the UDP packets.
         try!(self.lookup_wave(id_to_find, &nodes_to_query, &mut queried_ids));

         // We check the responses and return if the node was found.
         for response in responses {
            println!("<-- Response from {}", response.sender_id);
            if response.found_node(id_to_find) {
               return self.table.specific_node(id_to_find).ok_or(SubotaiError::NodeNotFound);
            }
         }
      }

      // One last wait until success or timeout, to compensate for impatience
      // (It could be that the nodes we ignored earlier come back with the response)
      all_receptions.during(time::Duration::seconds(node::NETWORK_TIMEOUT_S))
         .filter(|ref rpc| rpc.found_node(id_to_find))
         .take(1)
         .count();
      self.table.specific_node(id_to_find).ok_or(SubotaiError::NodeNotFound)
   }

   pub fn bootstrap(&self, seed: routing::NodeInfo, network_size: Option<usize>) -> SubotaiResult<()>  {
      self.table.insert_node(seed);

      // Timeout for the entire operation.
      let total_timeout = time::Duration::seconds(2 * node::NETWORK_TIMEOUT_S);
      let deadline = time::SteadyTime::now() + total_timeout;
      let mut responses = self.receptions()
         .rpc(receptions::RpcFilter::BootstrapResponse)
         .during(total_timeout);

      // We want our network to be as big as the K factor, or the user supplied limit.
      let expected_length = match network_size {
         Some(size) => size,
         None => routing::K,
      };

      let mut queried_ids = Vec::<Hash>::with_capacity(routing::K);
      while queried_ids.len() < expected_length {
         let nodes_to_query: Vec<routing::NodeInfo> = self.table.all_nodes()
            .filter(|ref node_info| !queried_ids.contains(&node_info.id))
            .collect();

         try!(self.bootstrap_wave(&nodes_to_query, &mut queried_ids));
         responses.next();

         if time::SteadyTime::now() >= deadline {
            return Err(SubotaiError::UnresponsiveNetwork);
         }
      }
      Ok(())
   }

   fn bootstrap_wave(&self, nodes_to_query: &[routing::NodeInfo], queried: &mut Vec<Hash>) -> SubotaiResult<()> {
      let rpc = Rpc::bootstrap(self.id.clone(), self.inbound.local_addr().unwrap().port());
      let packet = rpc.serialize();
      for node in nodes_to_query {
         try!(self.outbound.send_to(&packet, node.address));
         queried.push(node.id.clone());
      }
      Ok(())
   }

   fn lookup_wave(&self, id_to_find: &Hash, nodes_to_query: &[routing::NodeInfo], queried: &mut Vec<Hash>) -> SubotaiResult<()> {
      let rpc = Rpc::find_node(
         self.id.clone(),
         self.inbound.local_addr().unwrap().port(),
         id_to_find.clone(),
         routing::K,
      );
      let packet = rpc.serialize();
      for node in nodes_to_query {
         println!("--> Sending to {}", node.id);
         try!(self.outbound.send_to(&packet, node.address));
         queried.push(node.id.clone());
      }

      Ok(())
   }

   pub fn process_incoming_rpc(&self, rpc: Rpc, mut source: net::SocketAddr) -> SubotaiResult<()>{
      source.set_port(rpc.reply_port);
      let sender = routing::NodeInfo {
         id      : rpc.sender_id.clone(),
         address : source,
      };

      let result = match rpc.kind {
         rpc::Kind::Ping                           => self.handle_ping(sender),
         rpc::Kind::PingResponse                   => self.handle_ping_response(sender),
         rpc::Kind::FindNode(ref payload)          => self.handle_find_node(payload.clone(), sender),
         rpc::Kind::FindNodeResponse(ref payload)  => self.handle_find_node_response(payload.clone(), sender),
         rpc::Kind::Bootstrap                      => self.handle_bootstrap(sender),
         rpc::Kind::BootstrapResponse(ref payload) => self.handle_bootstrap_response(payload.clone(),sender),
         _ => unimplemented!(),
      };

      self.updates.lock().unwrap().broadcast(Update::RpcReceived(rpc));
      result
   }

   fn handle_ping(&self, sender: routing::NodeInfo) -> SubotaiResult<()> {
      self.table.insert_node(sender.clone());
      let rpc = Rpc::ping_response(self.id.clone(), self.inbound.local_addr().unwrap().port());
      let packet = rpc.serialize();
      try!(self.outbound.send_to(&packet, sender.address));
      Ok(())
   }

   fn handle_bootstrap(&self, sender: routing::NodeInfo) -> SubotaiResult<()> {
      self.table.insert_node(sender.clone());
      let closest_to_sender: Vec<_> = self.table.closest_nodes_to(&sender.id)
         .filter(|ref info| &info.id != &sender.id) // We don't want to reply with the sender itself
         .take(routing::K)
         .collect();

      let rpc = Rpc::bootstrap_response(self.id.clone(), self.inbound.local_addr().unwrap().port(), closest_to_sender);
      let packet = rpc.serialize();
      try!(self.outbound.send_to(&packet, sender.address));
      Ok(())
   }

   fn handle_bootstrap_response(&self, payload: sync::Arc<rpc::BootstrapResponsePayload>, sender: routing::NodeInfo) -> SubotaiResult<()> {
      self.table.insert_node(sender.clone());
      for node in &payload.nodes {
         self.table.insert_node(node.clone());
      }
      Ok(())
   }

   fn handle_ping_response(&self, sender: routing::NodeInfo) -> SubotaiResult<()> {
      self.table.insert_node(sender);
      Ok(())
   }

   fn handle_find_node(&self, payload: sync::Arc<rpc::FindNodePayload>, sender: routing::NodeInfo) -> SubotaiResult<()> {
      self.table.insert_node(sender.clone());
      let lookup_results = self.table.lookup(&payload.id_to_find, payload.nodes_wanted, None);
      let rpc = Rpc::find_node_response(self.id.clone(),
                                        self.inbound.local_addr().unwrap().port(),
                                        payload.id_to_find.clone(),
                                        lookup_results);
      let packet = rpc.serialize();
      try!(self.outbound.send_to(&packet, sender.address));
      Ok(())
   }

   fn handle_find_node_response(&self, payload: sync::Arc<rpc::FindNodeResponsePayload>, sender: routing::NodeInfo) -> SubotaiResult<()> {
      self.table.insert_node(sender);
      match payload.result {
         routing::LookupResult::ClosestNodes(ref nodes) => for node in nodes { self.table.insert_node(node.clone()) },
         routing::LookupResult::Found(ref node) => self.table.insert_node(node.clone()),
         _ => (),
      }
      Ok(())
   }
}
<commit_msg>Refactoring<commit_after>use {node, routing, rpc, bus, time, SubotaiError, SubotaiResult};
use std::{net, sync};
use rpc::Rpc;
use hash::Hash;
use node::receptions;

/// Node resources for synchronous operations.
///
/// All methods on this module are synchronous, and will wait for any
/// remote nodes queried to reply to the RPCs sent, up to the timeout
/// defined at `node::node::NETWORK_TIMEOUT_S`. The node layer above is in
/// charge of parallelizing those operations by spawning threads when
/// adequate.
pub struct Resources {
   pub id       : Hash,
   pub table    : routing::Table,
   pub outbound : net::UdpSocket,
   pub inbound  : net::UdpSocket,
   pub state    : sync::Mutex<node::State>,
   pub updates  : sync::Mutex<bus::Bus<Update>>,
}

#[derive(Clone)]
pub enum Update {
   RpcReceived(Rpc),
   Tick,
   Shutdown,
}

impl Resources {
   pub fn local_info(&self) -> routing::NodeInfo {
      routing::NodeInfo {
         id      : self.id.clone(),
         address : self.inbound.local_addr().unwrap(),
      }
   }

   /// Pings a node, blocking until ping response.
   pub fn ping(&self, id: Hash) -> SubotaiResult<()> {
      let node = try!(self.find_node(&id));
      let rpc = Rpc::ping(self.id.clone(), self.inbound.local_addr().unwrap().port());
      let packet = rpc.serialize();
      let responses = self.receptions()
         .during(time::Duration::seconds(node::NETWORK_TIMEOUT_S))
         .rpc(receptions::RpcFilter::PingResponse)
         .from(id.clone())
         .take(1);
      try!(self.outbound.send_to(&packet, node.address));

      match responses.count() {
         1 => Ok(()),
         _ => Err(SubotaiError::NoResponse),
      }
   }

   /// Sends a ping and doesn't wait for a response. Used by the maintenance thread.
   pub fn ping_and_forget(&self, id: Hash) -> SubotaiResult<()> {
      let node = try!(self.find_node(&id));
      let rpc = Rpc::ping(self.id.clone(), self.inbound.local_addr().unwrap().port());
      let packet = rpc.serialize();
      try!(self.outbound.send_to(&packet, node.address));

      Ok(())
   }

   pub fn receptions(&self) -> receptions::Receptions {
      receptions::Receptions::new(self)
   }

   /// Attempts to find a node through the network.
   pub fn find_node(&self, id_to_find: &Hash) -> SubotaiResult<routing::NodeInfo> {
      // If the node is already present in our table, we are done early.
      if let Some(node) = self.table.specific_node(id_to_find) {
         return Ok(node);
      }

      let mut queried_ids = Vec::<Hash>::with_capacity(routing::K);
      let all_receptions = self.receptions();
      let loop_timeout = time::Duration::seconds(2 * node::NETWORK_TIMEOUT_S);
      let deadline = time::SteadyTime::now() + loop_timeout;

      while queried_ids.len() < routing::K && time::SteadyTime::now() < deadline {
         // We query the 'ALPHA' nodes closest to the target we haven't yet queried.
         let nodes_to_query: Vec<routing::NodeInfo> = self.table.closest_nodes_to(id_to_find)
            .filter(|ref info| !queried_ids.contains(&info.id))
            .take(routing::ALPHA)
            .collect();

         // We wait for the response from the same number of nodes, minus the 'IMPATIENCE' factor.
         let responses = self.receptions()
            .during(time::Duration::seconds(node::NETWORK_TIMEOUT_S))
            .filter(|ref rpc| rpc.is_finding_node(id_to_find))
            .take(usize::saturating_sub(nodes_to_query.len(), routing::IMPATIENCE));

         // We compose the RPCs and send the UDP packets.
         try!(self.lookup_wave(id_to_find, &nodes_to_query, &mut queried_ids));

         // We check the responses and return if the node was found.
         for response in responses {
            println!("<-- Response from {}", response.sender_id);
            if response.found_node(id_to_find) {
               return self.table.specific_node(id_to_find).ok_or(SubotaiError::NodeNotFound);
            }
         }
      }

      // One last wait until success or timeout, to compensate for impatience
      // (It could be that the nodes we ignored earlier come back with the response)
      all_receptions.during(time::Duration::seconds(node::NETWORK_TIMEOUT_S))
         .filter(|ref rpc| rpc.found_node(id_to_find))
         .take(1)
         .count();
      self.table.specific_node(id_to_find).ok_or(SubotaiError::NodeNotFound)
   }

   pub fn bootstrap(&self, seed: routing::NodeInfo, network_size: Option<usize>) -> SubotaiResult<()>  {
      self.table.insert_node(seed);

      // Timeout for the entire operation.
      let total_timeout = time::Duration::seconds(2 * node::NETWORK_TIMEOUT_S);
      let deadline = time::SteadyTime::now() + total_timeout;
      let mut responses = self.receptions()
         .rpc(receptions::RpcFilter::BootstrapResponse)
         .during(total_timeout);

      // We want our network to be as big as the K factor, or the user supplied limit.
      let expected_length = match network_size {
         Some(size) => size,
         None => routing::K,
      };

      let mut queried_ids = Vec::<Hash>::with_capacity(routing::K);
      while queried_ids.len() < expected_length {
         let nodes_to_query: Vec<routing::NodeInfo> = self.table.all_nodes()
            .filter(|ref node_info| !queried_ids.contains(&node_info.id))
            .collect();

         try!(self.bootstrap_wave(&nodes_to_query, &mut queried_ids));
         responses.next();

         if time::SteadyTime::now() >= deadline {
            return Err(SubotaiError::UnresponsiveNetwork);
         }
      }
      Ok(())
   }

   fn bootstrap_wave(&self, nodes_to_query: &[routing::NodeInfo], queried: &mut Vec<Hash>) -> SubotaiResult<()> {
      let rpc = Rpc::bootstrap(self.id.clone(), self.inbound.local_addr().unwrap().port());
      let packet = rpc.serialize();
      for node in nodes_to_query {
         try!(self.outbound.send_to(&packet, node.address));
         queried.push(node.id.clone());
      }
      Ok(())
   }

   fn lookup_wave(&self, id_to_find: &Hash, nodes_to_query: &[routing::NodeInfo], queried: &mut Vec<Hash>) -> SubotaiResult<()> {
      let rpc = Rpc::find_node(
         self.id.clone(),
         self.inbound.local_addr().unwrap().port(),
         id_to_find.clone(),
         routing::K,
      );
      let packet = rpc.serialize();
      for node in nodes_to_query {
         println!("--> Sending to {}", node.id);
         try!(self.outbound.send_to(&packet, node.address));
         queried.push(node.id.clone());
      }

      Ok(())
   }

   pub fn process_incoming_rpc(&self, rpc: Rpc, mut source: net::SocketAddr) -> SubotaiResult<()>{
      source.set_port(rpc.reply_port);
      let sender = routing::NodeInfo {
         id      : rpc.sender_id.clone(),
         address : source,
      };

      let result = match rpc.kind {
         rpc::Kind::Ping                           => self.handle_ping(sender),
         rpc::Kind::PingResponse                   => self.handle_ping_response(sender),
         rpc::Kind::FindNode(ref payload)          => self.handle_find_node(payload.clone(), sender),
         rpc::Kind::FindNodeResponse(ref payload)  => self.handle_find_node_response(payload.clone(), sender),
         rpc::Kind::Bootstrap                      => self.handle_bootstrap(sender),
         rpc::Kind::BootstrapResponse(ref payload) => self.handle_bootstrap_response(payload.clone(),sender),
         _ => unimplemented!(),
      };

      self.updates.lock().unwrap().broadcast(Update::RpcReceived(rpc));
      result
   }

   fn handle_ping(&self, sender: routing::NodeInfo) -> SubotaiResult<()> {
      self.table.insert_node(sender.clone());
      let rpc = Rpc::ping_response(self.id.clone(), self.inbound.local_addr().unwrap().port());
      let packet = rpc.serialize();
      try!(self.outbound.send_to(&packet, sender.address));
      Ok(())
   }

   fn handle_bootstrap(&self, sender: routing::NodeInfo) -> SubotaiResult<()> {
      self.table.insert_node(sender.clone());
      let closest_to_sender: Vec<_> = self.table.closest_nodes_to(&sender.id)
         .filter(|ref info| &info.id != &sender.id) // We don't want to reply with the sender itself
         .take(routing::K)
         .collect();

      let rpc = Rpc::bootstrap_response(self.id.clone(), self.inbound.local_addr().unwrap().port(), closest_to_sender);
      let packet = rpc.serialize();
      try!(self.outbound.send_to(&packet, sender.address));
      Ok(())
   }

   fn handle_bootstrap_response(&self, payload: sync::Arc<rpc::BootstrapResponsePayload>, sender: routing::NodeInfo) -> SubotaiResult<()> {
      self.table.insert_node(sender.clone());
      for node in &payload.nodes {
         self.table.insert_node(node.clone());
      }
      Ok(())
   }

   fn handle_ping_response(&self, sender: routing::NodeInfo) -> SubotaiResult<()> {
      self.table.insert_node(sender);
      Ok(())
   }

   fn handle_find_node(&self, payload: sync::Arc<rpc::FindNodePayload>, sender: routing::NodeInfo) -> SubotaiResult<()> {
      self.table.insert_node(sender.clone());
      let lookup_results = self.table.lookup(&payload.id_to_find, payload.nodes_wanted, None);
      let rpc = Rpc::find_node_response(self.id.clone(),
                                        self.inbound.local_addr().unwrap().port(),
                                        payload.id_to_find.clone(),
                                        lookup_results);
      let packet = rpc.serialize();
      try!(self.outbound.send_to(&packet, sender.address));
      Ok(())
   }

   fn handle_find_node_response(&self, payload: sync::Arc<rpc::FindNodeResponsePayload>, sender: routing::NodeInfo) -> SubotaiResult<()> {
      self.table.insert_node(sender);
      match payload.result {
         routing::LookupResult::ClosestNodes(ref nodes) => for node in nodes { self.table.insert_node(node.clone()) },
         routing::LookupResult::Found(ref node) => self.table.insert_node(node.clone()),
         _ => (),
      }
      Ok(())
   }
}
<|endoftext|>


<commit_before>use socket::Socket;

pub struct Trigger {
    socket: Socket,
}

impl Trigger {
    pub fn new(socket: Socket) -> Self {
        Trigger {
            socket: socket,
        }
    }

    pub fn enable(&mut self, source: &str) {
        self.socket.send(format!("ACQ:TRIG {}", source));
    }

    pub fn disable(&mut self) {
        self.enable("DISABLED");
    }

    pub fn get_state(&mut self) -> String {
        self.socket.send("ACQ:TRIG:STAT?");

        self.socket.receive()
    }

    pub fn set_delay(&mut self, delay: u8) {
        self.socket.send(format!("ACQ:TRIG:DLY {}", delay));
    }

    pub fn get_delay(&mut self) -> u16 {
        self.socket.send("ACQ:TRIG:DLY?");

        self.socket.receive()
            .parse()
            .unwrap()
    }

    pub fn set_delay_in_ns(&mut self, delay: u8) {
        self.socket.send(format!("ACQ:TRIG:DLY:NS {}", delay));
    }

    pub fn get_delay_in_ns(&mut self) -> String {
        self.socket.send("ACQ:TRIG:DLY:NS?");

        self.socket.receive()
    }

    pub fn set_level(&mut self, level: u8) {
        self.socket.send(format!("ACQ:TRIG:LEV {}", level));
    }

    pub fn get_level(&mut self) -> String {
        self.socket.send("ACQ:TRIG:LEV?");

        self.socket.receive()
    }
}

#[cfg(test)]
mod test {
    macro_rules! trigger_assert {
        ($f:ident, $e:expr) => {
            let (rx, mut trigger) = create_trigger();

            trigger.$f();
            assert_eq!($e, rx.recv().unwrap());
        }
    }

    #[test]
    fn test_enable() {
        let (rx, mut trigger) = create_trigger();

        trigger.enable("NOW");
        assert_eq!("ACQ:TRIG NOW\r\n", rx.recv().unwrap());
    }

    #[test]
    fn test_disable() {
        trigger_assert!(disable, "ACQ:TRIG DISABLED\r\n");
    }

    #[test]
    fn test_get_state() {
        let (_, mut trigger) = create_trigger();

        assert_eq!(trigger.get_state(), "WAIT");
    }

    #[test]
    fn test_set_delay() {
        let (rx, mut trigger) = create_trigger();

        trigger.set_delay(0);
        assert_eq!("ACQ:TRIG:DLY 0\r\n", rx.recv().unwrap());
    }

    #[test]
    fn test_get_delay() {
        let (_, mut trigger) = create_trigger();

        assert_eq!(trigger.get_delay(), 2314);
    }

    #[test]
    fn test_set_delay_in_ns() {
        let (rx, mut trigger) = create_trigger();

        trigger.set_delay_in_ns(0);
        assert_eq!("ACQ:TRIG:DLY:NS 0\r\n", rx.recv().unwrap());
    }

    #[test]
    fn test_get_delay_in_ns() {
        let (_, mut trigger) = create_trigger();

        assert_eq!(trigger.get_delay_in_ns().as_str(), "128ns");
    }

    #[test]
    fn test_set_level() {
        let (rx, mut trigger) = create_trigger();

        trigger.set_level(0);
        assert_eq!("ACQ:TRIG:LEV 0\r\n", rx.recv().unwrap());
    }

    #[test]
    fn test_get_level() {
        let (_, mut trigger) = create_trigger();

        assert_eq!(trigger.get_level().as_str(), "123mV");
    }

    fn create_trigger() -> (::std::sync::mpsc::Receiver<String>, ::trigger::Trigger) {
        let (addr, rx) = ::test::launch_server();
        let socket = ::socket::Socket::new(
            format!("{}", addr.ip()).as_str(),
            addr.port()
        );

        (rx, ::trigger::Trigger::new(socket))
    }
}
<commit_msg>[trigger] Add trigger::Source enum<commit_after>use socket::Socket;

pub enum Source {
    DISABLED,
    NOW,
    CH1_PE,
    CH1_NE,
    CH2_PE,
    CH2_NE,
    EXT_PE,
    EXT_NE,
    AWG_PE,
    AWG_NE,
}

impl ::std::fmt::Display for Source {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        let display = match self {
            &Source::DISABLED => "DISABLED",
            &Source::NOW => "NOW",
            &Source::CH1_PE => "CH1_PE",
            &Source::CH1_NE => "CH1_NE",
            &Source::CH2_PE => "CH2_PE",
            &Source::CH2_NE => "CH2_NE",
            &Source::EXT_PE => "EXT_PE",
            &Source::EXT_NE => "EXT_NE",
            &Source::AWG_PE => "AWG_PE",
            &Source::AWG_NE => "AWG_NE",
        };

        write!(f, "{}", display)
    }
}

pub struct Trigger {
    socket: Socket,
}

impl Trigger {
    pub fn new(socket: Socket) -> Self {
        Trigger {
            socket: socket,
        }
    }

    pub fn enable(&mut self, source: Source) {
        self.socket.send(format!("ACQ:TRIG {}", source));
    }

    pub fn disable(&mut self) {
        self.enable(Source::DISABLED);
    }

    pub fn get_state(&mut self) -> String {
        self.socket.send("ACQ:TRIG:STAT?");

        self.socket.receive()
    }

    pub fn set_delay(&mut self, delay: u8) {
        self.socket.send(format!("ACQ:TRIG:DLY {}", delay));
    }

    pub fn get_delay(&mut self) -> u16 {
        self.socket.send("ACQ:TRIG:DLY?");

        self.socket.receive()
            .parse()
            .unwrap()
    }

    pub fn set_delay_in_ns(&mut self, delay: u8) {
        self.socket.send(format!("ACQ:TRIG:DLY:NS {}", delay));
    }

    pub fn get_delay_in_ns(&mut self) -> String {
        self.socket.send("ACQ:TRIG:DLY:NS?");

        self.socket.receive()
    }

    pub fn set_level(&mut self, level: u8) {
        self.socket.send(format!("ACQ:TRIG:LEV {}", level));
    }

    pub fn get_level(&mut self) -> String {
        self.socket.send("ACQ:TRIG:LEV?");

        self.socket.receive()
    }
}

#[cfg(test)]
mod test {
    macro_rules! trigger_assert {
        ($f:ident, $e:expr) => {
            let (rx, mut trigger) = create_trigger();

            trigger.$f();
            assert_eq!($e, rx.recv().unwrap());
        }
    }

    #[test]
    fn test_enable() {
        let (rx, mut trigger) = create_trigger();

        trigger.enable(::trigger::Source::NOW);
        assert_eq!("ACQ:TRIG NOW\r\n", rx.recv().unwrap());
    }

    #[test]
    fn test_disable() {
        trigger_assert!(disable, "ACQ:TRIG DISABLED\r\n");
    }

    #[test]
    fn test_get_state() {
        let (_, mut trigger) = create_trigger();

        assert_eq!(trigger.get_state(), "WAIT");
    }

    #[test]
    fn test_set_delay() {
        let (rx, mut trigger) = create_trigger();

        trigger.set_delay(0);
        assert_eq!("ACQ:TRIG:DLY 0\r\n", rx.recv().unwrap());
    }

    #[test]
    fn test_get_delay() {
        let (_, mut trigger) = create_trigger();

        assert_eq!(trigger.get_delay(), 2314);
    }

    #[test]
    fn test_set_delay_in_ns() {
        let (rx, mut trigger) = create_trigger();

        trigger.set_delay_in_ns(0);
        assert_eq!("ACQ:TRIG:DLY:NS 0\r\n", rx.recv().unwrap());
    }

    #[test]
    fn test_get_delay_in_ns() {
        let (_, mut trigger) = create_trigger();

        assert_eq!(trigger.get_delay_in_ns().as_str(), "128ns");
    }

    #[test]
    fn test_set_level() {
        let (rx, mut trigger) = create_trigger();

        trigger.set_level(0);
        assert_eq!("ACQ:TRIG:LEV 0\r\n", rx.recv().unwrap());
    }

    #[test]
    fn test_get_level() {
        let (_, mut trigger) = create_trigger();

        assert_eq!(trigger.get_level().as_str(), "123mV");
    }

    fn create_trigger() -> (::std::sync::mpsc::Receiver<String>, ::trigger::Trigger) {
        let (addr, rx) = ::test::launch_server();
        let socket = ::socket::Socket::new(
            format!("{}", addr.ip()).as_str(),
            addr.port()
        );

        (rx, ::trigger::Trigger::new(socket))
    }
}
<|endoftext|>


<commit_before>//! Endpoints for server-side key backups.

pub mod add_backup_key_session;
pub mod add_backup_key_sessions;
pub mod add_backup_keys;
pub mod create_backup;
pub mod delete_backup;
pub mod delete_backup_key_session;
pub mod delete_backup_key_sessions;
pub mod delete_backup_keys;
pub mod get_backup;
pub mod get_backup_key_session;
pub mod get_backup_key_sessions;
pub mod get_backup_keys;
pub mod get_latest_backup;
pub mod update_backup;

use js_int::UInt;
use ruma_identifiers::{DeviceKeyId, RoomId, UserId};
use serde::{Deserialize, Serialize};
use std::collections::BTreeMap;

/// A map from room IDs to session IDs to key data.
///
/// Note: synapse has the `sessions: {}` wrapper, the Matrix spec does not.
#[cfg(not(feature = "unstable-synapse-quirks"))]
pub type Rooms = BTreeMap<RoomId, BTreeMap<String, KeyData>>;

/// A map from room IDs to session IDs to key data.
#[cfg(feature = "unstable-synapse-quirks")]
pub type Rooms = BTreeMap<RoomId, Sessions>;

// TODO: remove
/// A wrapper around a mapping of session IDs to key data.
#[cfg(feature = "unstable-synapse-quirks")]
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Sessions {
    /// A map of session IDs to key data.
    pub sessions: BTreeMap<String, KeyData>,
}

/// The algorithm used for storing backups.
#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(tag = "algorithm", content = "auth_data")]
pub enum BackupAlgorithm {
    /// `m.megolm_backup.v1.curve25519-aes-sha2` backup algorithm.
    #[serde(rename = "m.megolm_backup.v1.curve25519-aes-sha2")]
    MegolmBackupV1Curve25519AesSha2 {
        /// The curve25519 public key used to encrypt the backups, encoded in unpadded base64.
        public_key: String,

        /// Signatures of the auth_data as Signed JSON.
        signatures: BTreeMap<UserId, BTreeMap<DeviceKeyId, String>>,
    },
}

/// Information about the backup key.
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct KeyData {
    /// The index of the first message in the session that the key can decrypt.
    pub first_message_index: UInt,

    /// The number of times this key has been forwarded via key-sharing between devices.
    pub forwarded_count: UInt,

    /// Whether the device backing up the key verified the device that the key is from.
    pub is_verified: bool,

    /// Data about the session.
    pub session_data: SessionData,
}

/// The algorithm used for storing backups.
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct SessionData {
    /// Unpadded base64-encoded public half of the ephemeral key.
    pub ephemeral: String,

    /// Ciphertext, encrypted using AES-CBC-256 with PKCS#7 padding, encoded in base64.
    pub ciphertext: String,

    /// First 8 bytes of MAC key, encoded in base64.
    pub mac: String,
}
<commit_msg>Feature-gate backup endpoints on unstable-pre-spec<commit_after>//! Endpoints for server-side key backups.
#![cfg(feature = "unstable-pre-spec")]

pub mod add_backup_key_session;
pub mod add_backup_key_sessions;
pub mod add_backup_keys;
pub mod create_backup;
pub mod delete_backup;
pub mod delete_backup_key_session;
pub mod delete_backup_key_sessions;
pub mod delete_backup_keys;
pub mod get_backup;
pub mod get_backup_key_session;
pub mod get_backup_key_sessions;
pub mod get_backup_keys;
pub mod get_latest_backup;
pub mod update_backup;

use js_int::UInt;
use ruma_identifiers::{DeviceKeyId, RoomId, UserId};
use serde::{Deserialize, Serialize};
use std::collections::BTreeMap;

/// A map from room IDs to session IDs to key data.
///
/// Note: synapse has the `sessions: {}` wrapper, the Matrix spec does not.
#[cfg(not(feature = "unstable-synapse-quirks"))]
pub type Rooms = BTreeMap<RoomId, BTreeMap<String, KeyData>>;

/// A map from room IDs to session IDs to key data.
#[cfg(feature = "unstable-synapse-quirks")]
pub type Rooms = BTreeMap<RoomId, Sessions>;

// TODO: remove
/// A wrapper around a mapping of session IDs to key data.
#[cfg(feature = "unstable-synapse-quirks")]
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Sessions {
    /// A map of session IDs to key data.
    pub sessions: BTreeMap<String, KeyData>,
}

/// The algorithm used for storing backups.
#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(tag = "algorithm", content = "auth_data")]
pub enum BackupAlgorithm {
    /// `m.megolm_backup.v1.curve25519-aes-sha2` backup algorithm.
    #[serde(rename = "m.megolm_backup.v1.curve25519-aes-sha2")]
    MegolmBackupV1Curve25519AesSha2 {
        /// The curve25519 public key used to encrypt the backups, encoded in unpadded base64.
        public_key: String,

        /// Signatures of the auth_data as Signed JSON.
        signatures: BTreeMap<UserId, BTreeMap<DeviceKeyId, String>>,
    },
}

/// Information about the backup key.
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct KeyData {
    /// The index of the first message in the session that the key can decrypt.
    pub first_message_index: UInt,

    /// The number of times this key has been forwarded via key-sharing between devices.
    pub forwarded_count: UInt,

    /// Whether the device backing up the key verified the device that the key is from.
    pub is_verified: bool,

    /// Data about the session.
    pub session_data: SessionData,
}

/// The algorithm used for storing backups.
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct SessionData {
    /// Unpadded base64-encoded public half of the ephemeral key.
    pub ephemeral: String,

    /// Ciphertext, encrypted using AES-CBC-256 with PKCS#7 padding, encoded in base64.
    pub ciphertext: String,

    /// First 8 bytes of MAC key, encoded in base64.
    pub mac: String,
}
<|endoftext|>


<commit_before>//! Endpoints for event filters.

pub mod create_filter;
pub mod get_filter;

mod lazy_load;
mod url;

pub use lazy_load::LazyLoadOptions;
pub use url::UrlFilter;

use js_int::UInt;
use ruma_identifiers::{RoomId, UserId};
use ruma_serde::{Outgoing, StringEnum};
use serde::Serialize;

/// Format to use for returned events.
#[derive(Clone, Debug, PartialEq, Eq, StringEnum)]
#[ruma_enum(rename_all = "snake_case")]
pub enum EventFormat {
    /// Client format, as described in the Client API.
    Client,

    /// Raw events from federation.
    Federation,

    #[doc(hidden)]
    _Custom(String),
}

impl Default for EventFormat {
    fn default() -> Self {
        Self::Client
    }
}

/// Filters to be applied to room events.
#[derive(Clone, Copy, Debug, Default, Outgoing, Serialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[incoming_derive(Clone, Default, Serialize)]
pub struct RoomEventFilter<'a> {
    /// A list of event types to exclude.
    ///
    /// If this list is absent then no event types are excluded. A matching type will be excluded
    /// even if it is listed in the 'types' filter. A '*' can be used as a wildcard to match any
    /// sequence of characters.
    #[serde(default, skip_serializing_if = "<[_]>::is_empty")]
    pub not_types: &'a [String],

    /// A list of room IDs to exclude.
    ///
    /// If this list is absent then no rooms are excluded. A matching room will be excluded even if
    /// it is listed in the 'rooms' filter.
    #[serde(default, skip_serializing_if = "<[_]>::is_empty")]
    pub not_rooms: &'a [String],

    /// The maximum number of events to return.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub limit: Option<UInt>,

    /// A list of room IDs to include.
    ///
    /// If this list is absent then all rooms are included.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub rooms: Option<&'a [RoomId]>,

    /// A list of sender IDs to exclude.
    ///
    /// If this list is absent then no senders are excluded. A matching sender will be excluded
    /// even if it is listed in the 'senders' filter.
    #[serde(default, skip_serializing_if = "<[_]>::is_empty")]
    pub not_senders: &'a [UserId],

    /// A list of senders IDs to include.
    ///
    /// If this list is absent then all senders are included.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub senders: Option<&'a [UserId]>,

    /// A list of event types to include.
    ///
    /// If this list is absent then all event types are included. A '*' can be used as a wildcard
    /// to match any sequence of characters.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub types: Option<&'a [String]>,

    /// Controls whether to include events with a URL key in their content.
    ///
    /// * `None`: No filtering
    /// * `Some(EventsWithUrl)`: Only events with a URL
    /// * `Some(EventsWithoutUrl)`: Only events without a URL
    #[serde(rename = "contains_url", skip_serializing_if = "Option::is_none")]
    pub url_filter: Option<UrlFilter>,

    /// Options to control lazy-loading of membership events.
    ///
    /// Defaults to `LazyLoadOptions::Disabled`.
    #[serde(flatten)]
    pub lazy_load_options: LazyLoadOptions,
}

impl<'a> RoomEventFilter<'a> {
    /// Creates an empty `RoomEventFilter`.
    ///
    /// You can also use the [`Default`] implementation.
    pub fn empty() -> Self {
        Self::default()
    }

    /// Creates a `RoomEventFilter` that can be used to ignore all room events.
    pub fn ignore_all() -> Self {
        Self { types: Some(&[]), ..Default::default() }
    }

    /// Returns `true` if all fields are empty.
    pub fn is_empty(&self) -> bool {
        self.not_types.is_empty()
            && self.not_rooms.is_empty()
            && self.limit.is_none()
            && self.rooms.is_none()
            && self.not_senders.is_empty()
            && self.senders.is_none()
            && self.types.is_none()
            && self.url_filter.is_none()
            && self.lazy_load_options.is_disabled()
    }
}

impl IncomingRoomEventFilter {
    /// Returns `true` if all fields are empty.
    pub fn is_empty(&self) -> bool {
        self.not_types.is_empty()
            && self.not_rooms.is_empty()
            && self.limit.is_none()
            && self.rooms.is_none()
            && self.not_senders.is_empty()
            && self.senders.is_none()
            && self.types.is_none()
            && self.url_filter.is_none()
            && self.lazy_load_options.is_disabled()
    }
}

/// Filters to be applied to room data.
#[derive(Clone, Copy, Debug, Default, Outgoing, Serialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[incoming_derive(Clone, Default, Serialize)]
pub struct RoomFilter<'a> {
    /// Include rooms that the user has left in the sync.
    ///
    /// Defaults to `false`.
    #[serde(default, skip_serializing_if = "ruma_serde::is_default")]
    pub include_leave: bool,

    /// The per user account data to include for rooms.
    #[serde(default, skip_serializing_if = "ruma_serde::is_empty")]
    pub account_data: RoomEventFilter<'a>,

    /// The message and state update events to include for rooms.
    #[serde(default, skip_serializing_if = "ruma_serde::is_empty")]
    pub timeline: RoomEventFilter<'a>,

    /// The events that aren't recorded in the room history, e.g. typing and receipts, to include
    /// for rooms.
    #[serde(default, skip_serializing_if = "ruma_serde::is_empty")]
    pub ephemeral: RoomEventFilter<'a>,

    /// The state events to include for rooms.
    #[serde(default, skip_serializing_if = "ruma_serde::is_empty")]
    pub state: RoomEventFilter<'a>,

    /// A list of room IDs to exclude.
    ///
    /// If this list is absent then no rooms are excluded. A matching room will be excluded even if
    /// it is listed in the 'rooms' filter. This filter is applied before the filters in
    /// `ephemeral`, `state`, `timeline` or `account_data`.
    #[serde(default, skip_serializing_if = "<[_]>::is_empty")]
    pub not_rooms: &'a [RoomId],

    /// A list of room IDs to include.
    ///
    /// If this list is absent then all rooms are included. This filter is applied before the
    /// filters in `ephemeral`, `state`, `timeline` or `account_data`.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub rooms: Option<&'a [RoomId]>,
}

impl<'a> RoomFilter<'a> {
    /// Creates an empty `RoomFilter`.
    ///
    /// You can also use the [`Default`] implementation.
    pub fn empty() -> Self {
        Self::default()
    }

    /// Creates a `RoomFilter` that can be used to ignore all room events (of any type).
    pub fn ignore_all() -> Self {
        Self { rooms: Some(&[]), ..Default::default() }
    }

    /// Returns `true` if all fields are empty.
    pub fn is_empty(&self) -> bool {
        !self.include_leave
            && self.account_data.is_empty()
            && self.timeline.is_empty()
            && self.ephemeral.is_empty()
            && self.state.is_empty()
            && self.not_rooms.is_empty()
            && self.rooms.is_none()
    }
}

impl IncomingRoomFilter {
    /// Returns `true` if all fields are empty.
    pub fn is_empty(&self) -> bool {
        !self.include_leave
            && self.account_data.is_empty()
            && self.timeline.is_empty()
            && self.ephemeral.is_empty()
            && self.state.is_empty()
            && self.not_rooms.is_empty()
            && self.rooms.is_none()
    }
}

/// Filter for non-room data.
#[derive(Clone, Copy, Debug, Default, Outgoing, Serialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[incoming_derive(Clone, Default, Serialize)]
pub struct Filter<'a> {
    /// A list of event types to exclude.
    ///
    /// If this list is absent then no event types are excluded. A matching type will be excluded
    /// even if it is listed in the 'types' filter. A '*' can be used as a wildcard to match any
    /// sequence of characters.
    #[serde(default, skip_serializing_if = "<[_]>::is_empty")]
    pub not_types: &'a [String],

    /// The maximum number of events to return.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub limit: Option<UInt>,

    /// A list of senders IDs to include.
    ///
    /// If this list is absent then all senders are included.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub senders: Option<&'a [UserId]>,

    /// A list of event types to include.
    ///
    /// If this list is absent then all event types are included. A '*' can be used as a wildcard
    /// to match any sequence of characters.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub types: Option<&'a [String]>,

    /// A list of sender IDs to exclude.
    ///
    /// If this list is absent then no senders are excluded. A matching sender will be excluded
    /// even if it is listed in the 'senders' filter.
    #[serde(default, skip_serializing_if = "<[_]>::is_empty")]
    pub not_senders: &'a [UserId],
}

impl<'a> Filter<'a> {
    /// Creates an empty `Filter`.
    ///
    /// You can also use the [`Default`] implementation.
    pub fn empty() -> Self {
        Self::default()
    }

    /// Creates a `Filter` that can be used to ignore all events.
    pub fn ignore_all() -> Self {
        Self { types: Some(&[]), ..Default::default() }
    }

    /// Returns `true` if all fields are empty.
    pub fn is_empty(&self) -> bool {
        self.not_types.is_empty()
            && self.limit.is_none()
            && self.senders.is_none()
            && self.types.is_none()
            && self.not_senders.is_empty()
    }
}

impl IncomingFilter {
    /// Returns `true` if all fields are empty.
    pub fn is_empty(&self) -> bool {
        self.not_types.is_empty()
            && self.limit.is_none()
            && self.senders.is_none()
            && self.types.is_none()
            && self.not_senders.is_empty()
    }
}

/// A filter definition
#[derive(Clone, Debug, Default, Outgoing, Serialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[incoming_derive(Clone, Default, Serialize)]
pub struct FilterDefinition<'a> {
    /// List of event fields to include.
    ///
    /// If this list is absent then all fields are included. The entries may include '.' characters
    /// to indicate sub-fields. So ['content.body'] will include the 'body' field of the 'content'
    /// object. A literal '.' character in a field name may be escaped using a '\'. A server may
    /// include more fields than were requested.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub event_fields: Option<&'a [String]>,

    /// The format to use for events.
    ///
    /// 'client' will return the events in a format suitable for clients. 'federation' will return
    /// the raw event as received over federation. The default is 'client'.
    #[serde(default, skip_serializing_if = "ruma_serde::is_default")]
    pub event_format: EventFormat,

    /// The presence updates to include.
    #[serde(default, skip_serializing_if = "ruma_serde::is_empty")]
    pub presence: Filter<'a>,

    /// The user account data that isn't associated with rooms to include.
    #[serde(default, skip_serializing_if = "ruma_serde::is_empty")]
    pub account_data: Filter<'a>,

    /// Filters to be applied to room data.
    #[serde(default, skip_serializing_if = "ruma_serde::is_empty")]
    pub room: RoomFilter<'a>,
}

impl<'a> FilterDefinition<'a> {
    /// Creates an empty `FilterDefinition`.
    ///
    /// You can also use the [`Default`] implementation.
    pub fn empty() -> Self {
        Self::default()
    }

    /// Creates a `FilterDefinition` that can be used to ignore all events.
    pub fn ignore_all() -> Self {
        Self {
            account_data: Filter::ignore_all(),
            room: RoomFilter::ignore_all(),
            presence: Filter::ignore_all(),
            ..Default::default()
        }
    }

    /// Returns `true` if all fields are empty.
    pub fn is_empty(&self) -> bool {
        self.event_fields.is_none()
            && self.event_format == EventFormat::Client
            && self.presence.is_empty()
            && self.account_data.is_empty()
            && self.room.is_empty()
    }
}

impl IncomingFilterDefinition {
    /// Returns `true` if all fields are empty.
    pub fn is_empty(&self) -> bool {
        self.event_fields.is_none()
            && self.event_format == EventFormat::Client
            && self.presence.is_empty()
            && self.account_data.is_empty()
            && self.room.is_empty()
    }
}

macro_rules! can_be_empty {
    ($ty:ident $(<$gen:tt>)?) => {
        impl $(<$gen>)? ruma_serde::CanBeEmpty for $ty $(<$gen>)? {
            fn is_empty(&self) -> bool {
                self.is_empty()
            }
        }
    };
}

can_be_empty!(Filter<'a>);
can_be_empty!(FilterDefinition<'a>);
can_be_empty!(RoomEventFilter<'a>);
can_be_empty!(RoomFilter<'a>);

can_be_empty!(IncomingFilter);
can_be_empty!(IncomingFilterDefinition);
can_be_empty!(IncomingRoomEventFilter);
can_be_empty!(IncomingRoomFilter);

#[cfg(test)]
mod tests {
    use serde_json::{json, to_value as to_json_value};

    use super::{
        Filter, FilterDefinition, IncomingFilterDefinition, IncomingRoomFilter, RoomEventFilter,
        RoomFilter,
    };

    #[test]
    fn default_filters_are_empty() -> Result<(), serde_json::Error> {
        assert_eq!(to_json_value(Filter::default())?, json!({}));
        assert_eq!(to_json_value(FilterDefinition::default())?, json!({}));
        assert_eq!(to_json_value(RoomEventFilter::default())?, json!({}));
        assert_eq!(to_json_value(RoomFilter::default())?, json!({}));

        Ok(())
    }

    #[test]
    fn filter_definition_roundtrip() -> Result<(), serde_json::Error> {
        let filter = FilterDefinition::default();
        let filter_str = serde_json::to_value(&filter)?;

        let incoming_filter = serde_json::from_value::<IncomingFilterDefinition>(filter_str)?;
        assert!(incoming_filter.is_empty());

        Ok(())
    }

    #[test]
    fn room_filter_definition_roundtrip() -> Result<(), serde_json::Error> {
        let filter = RoomFilter::default();
        let room_filter = serde_json::to_value(&filter)?;

        let incoming_room_filter = serde_json::from_value::<IncomingRoomFilter>(room_filter)?;
        assert!(incoming_room_filter.is_empty());

        Ok(())
    }
}
<commit_msg>filter: Import serde_json functions for tests<commit_after>//! Endpoints for event filters.

pub mod create_filter;
pub mod get_filter;

mod lazy_load;
mod url;

pub use lazy_load::LazyLoadOptions;
pub use url::UrlFilter;

use js_int::UInt;
use ruma_identifiers::{RoomId, UserId};
use ruma_serde::{Outgoing, StringEnum};
use serde::Serialize;

/// Format to use for returned events.
#[derive(Clone, Debug, PartialEq, Eq, StringEnum)]
#[ruma_enum(rename_all = "snake_case")]
pub enum EventFormat {
    /// Client format, as described in the Client API.
    Client,

    /// Raw events from federation.
    Federation,

    #[doc(hidden)]
    _Custom(String),
}

impl Default for EventFormat {
    fn default() -> Self {
        Self::Client
    }
}

/// Filters to be applied to room events.
#[derive(Clone, Copy, Debug, Default, Outgoing, Serialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[incoming_derive(Clone, Default, Serialize)]
pub struct RoomEventFilter<'a> {
    /// A list of event types to exclude.
    ///
    /// If this list is absent then no event types are excluded. A matching type will be excluded
    /// even if it is listed in the 'types' filter. A '*' can be used as a wildcard to match any
    /// sequence of characters.
    #[serde(default, skip_serializing_if = "<[_]>::is_empty")]
    pub not_types: &'a [String],

    /// A list of room IDs to exclude.
    ///
    /// If this list is absent then no rooms are excluded. A matching room will be excluded even if
    /// it is listed in the 'rooms' filter.
    #[serde(default, skip_serializing_if = "<[_]>::is_empty")]
    pub not_rooms: &'a [String],

    /// The maximum number of events to return.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub limit: Option<UInt>,

    /// A list of room IDs to include.
    ///
    /// If this list is absent then all rooms are included.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub rooms: Option<&'a [RoomId]>,

    /// A list of sender IDs to exclude.
    ///
    /// If this list is absent then no senders are excluded. A matching sender will be excluded
    /// even if it is listed in the 'senders' filter.
    #[serde(default, skip_serializing_if = "<[_]>::is_empty")]
    pub not_senders: &'a [UserId],

    /// A list of senders IDs to include.
    ///
    /// If this list is absent then all senders are included.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub senders: Option<&'a [UserId]>,

    /// A list of event types to include.
    ///
    /// If this list is absent then all event types are included. A '*' can be used as a wildcard
    /// to match any sequence of characters.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub types: Option<&'a [String]>,

    /// Controls whether to include events with a URL key in their content.
    ///
    /// * `None`: No filtering
    /// * `Some(EventsWithUrl)`: Only events with a URL
    /// * `Some(EventsWithoutUrl)`: Only events without a URL
    #[serde(rename = "contains_url", skip_serializing_if = "Option::is_none")]
    pub url_filter: Option<UrlFilter>,

    /// Options to control lazy-loading of membership events.
    ///
    /// Defaults to `LazyLoadOptions::Disabled`.
    #[serde(flatten)]
    pub lazy_load_options: LazyLoadOptions,
}

impl<'a> RoomEventFilter<'a> {
    /// Creates an empty `RoomEventFilter`.
    ///
    /// You can also use the [`Default`] implementation.
    pub fn empty() -> Self {
        Self::default()
    }

    /// Creates a `RoomEventFilter` that can be used to ignore all room events.
    pub fn ignore_all() -> Self {
        Self { types: Some(&[]), ..Default::default() }
    }

    /// Returns `true` if all fields are empty.
    pub fn is_empty(&self) -> bool {
        self.not_types.is_empty()
            && self.not_rooms.is_empty()
            && self.limit.is_none()
            && self.rooms.is_none()
            && self.not_senders.is_empty()
            && self.senders.is_none()
            && self.types.is_none()
            && self.url_filter.is_none()
            && self.lazy_load_options.is_disabled()
    }
}

impl IncomingRoomEventFilter {
    /// Returns `true` if all fields are empty.
    pub fn is_empty(&self) -> bool {
        self.not_types.is_empty()
            && self.not_rooms.is_empty()
            && self.limit.is_none()
            && self.rooms.is_none()
            && self.not_senders.is_empty()
            && self.senders.is_none()
            && self.types.is_none()
            && self.url_filter.is_none()
            && self.lazy_load_options.is_disabled()
    }
}

/// Filters to be applied to room data.
#[derive(Clone, Copy, Debug, Default, Outgoing, Serialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[incoming_derive(Clone, Default, Serialize)]
pub struct RoomFilter<'a> {
    /// Include rooms that the user has left in the sync.
    ///
    /// Defaults to `false`.
    #[serde(default, skip_serializing_if = "ruma_serde::is_default")]
    pub include_leave: bool,

    /// The per user account data to include for rooms.
    #[serde(default, skip_serializing_if = "ruma_serde::is_empty")]
    pub account_data: RoomEventFilter<'a>,

    /// The message and state update events to include for rooms.
    #[serde(default, skip_serializing_if = "ruma_serde::is_empty")]
    pub timeline: RoomEventFilter<'a>,

    /// The events that aren't recorded in the room history, e.g. typing and receipts, to include
    /// for rooms.
    #[serde(default, skip_serializing_if = "ruma_serde::is_empty")]
    pub ephemeral: RoomEventFilter<'a>,

    /// The state events to include for rooms.
    #[serde(default, skip_serializing_if = "ruma_serde::is_empty")]
    pub state: RoomEventFilter<'a>,

    /// A list of room IDs to exclude.
    ///
    /// If this list is absent then no rooms are excluded. A matching room will be excluded even if
    /// it is listed in the 'rooms' filter. This filter is applied before the filters in
    /// `ephemeral`, `state`, `timeline` or `account_data`.
    #[serde(default, skip_serializing_if = "<[_]>::is_empty")]
    pub not_rooms: &'a [RoomId],

    /// A list of room IDs to include.
    ///
    /// If this list is absent then all rooms are included. This filter is applied before the
    /// filters in `ephemeral`, `state`, `timeline` or `account_data`.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub rooms: Option<&'a [RoomId]>,
}

impl<'a> RoomFilter<'a> {
    /// Creates an empty `RoomFilter`.
    ///
    /// You can also use the [`Default`] implementation.
    pub fn empty() -> Self {
        Self::default()
    }

    /// Creates a `RoomFilter` that can be used to ignore all room events (of any type).
    pub fn ignore_all() -> Self {
        Self { rooms: Some(&[]), ..Default::default() }
    }

    /// Returns `true` if all fields are empty.
    pub fn is_empty(&self) -> bool {
        !self.include_leave
            && self.account_data.is_empty()
            && self.timeline.is_empty()
            && self.ephemeral.is_empty()
            && self.state.is_empty()
            && self.not_rooms.is_empty()
            && self.rooms.is_none()
    }
}

impl IncomingRoomFilter {
    /// Returns `true` if all fields are empty.
    pub fn is_empty(&self) -> bool {
        !self.include_leave
            && self.account_data.is_empty()
            && self.timeline.is_empty()
            && self.ephemeral.is_empty()
            && self.state.is_empty()
            && self.not_rooms.is_empty()
            && self.rooms.is_none()
    }
}

/// Filter for non-room data.
#[derive(Clone, Copy, Debug, Default, Outgoing, Serialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[incoming_derive(Clone, Default, Serialize)]
pub struct Filter<'a> {
    /// A list of event types to exclude.
    ///
    /// If this list is absent then no event types are excluded. A matching type will be excluded
    /// even if it is listed in the 'types' filter. A '*' can be used as a wildcard to match any
    /// sequence of characters.
    #[serde(default, skip_serializing_if = "<[_]>::is_empty")]
    pub not_types: &'a [String],

    /// The maximum number of events to return.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub limit: Option<UInt>,

    /// A list of senders IDs to include.
    ///
    /// If this list is absent then all senders are included.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub senders: Option<&'a [UserId]>,

    /// A list of event types to include.
    ///
    /// If this list is absent then all event types are included. A '*' can be used as a wildcard
    /// to match any sequence of characters.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub types: Option<&'a [String]>,

    /// A list of sender IDs to exclude.
    ///
    /// If this list is absent then no senders are excluded. A matching sender will be excluded
    /// even if it is listed in the 'senders' filter.
    #[serde(default, skip_serializing_if = "<[_]>::is_empty")]
    pub not_senders: &'a [UserId],
}

impl<'a> Filter<'a> {
    /// Creates an empty `Filter`.
    ///
    /// You can also use the [`Default`] implementation.
    pub fn empty() -> Self {
        Self::default()
    }

    /// Creates a `Filter` that can be used to ignore all events.
    pub fn ignore_all() -> Self {
        Self { types: Some(&[]), ..Default::default() }
    }

    /// Returns `true` if all fields are empty.
    pub fn is_empty(&self) -> bool {
        self.not_types.is_empty()
            && self.limit.is_none()
            && self.senders.is_none()
            && self.types.is_none()
            && self.not_senders.is_empty()
    }
}

impl IncomingFilter {
    /// Returns `true` if all fields are empty.
    pub fn is_empty(&self) -> bool {
        self.not_types.is_empty()
            && self.limit.is_none()
            && self.senders.is_none()
            && self.types.is_none()
            && self.not_senders.is_empty()
    }
}

/// A filter definition
#[derive(Clone, Debug, Default, Outgoing, Serialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[incoming_derive(Clone, Default, Serialize)]
pub struct FilterDefinition<'a> {
    /// List of event fields to include.
    ///
    /// If this list is absent then all fields are included. The entries may include '.' characters
    /// to indicate sub-fields. So ['content.body'] will include the 'body' field of the 'content'
    /// object. A literal '.' character in a field name may be escaped using a '\'. A server may
    /// include more fields than were requested.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub event_fields: Option<&'a [String]>,

    /// The format to use for events.
    ///
    /// 'client' will return the events in a format suitable for clients. 'federation' will return
    /// the raw event as received over federation. The default is 'client'.
    #[serde(default, skip_serializing_if = "ruma_serde::is_default")]
    pub event_format: EventFormat,

    /// The presence updates to include.
    #[serde(default, skip_serializing_if = "ruma_serde::is_empty")]
    pub presence: Filter<'a>,

    /// The user account data that isn't associated with rooms to include.
    #[serde(default, skip_serializing_if = "ruma_serde::is_empty")]
    pub account_data: Filter<'a>,

    /// Filters to be applied to room data.
    #[serde(default, skip_serializing_if = "ruma_serde::is_empty")]
    pub room: RoomFilter<'a>,
}

impl<'a> FilterDefinition<'a> {
    /// Creates an empty `FilterDefinition`.
    ///
    /// You can also use the [`Default`] implementation.
    pub fn empty() -> Self {
        Self::default()
    }

    /// Creates a `FilterDefinition` that can be used to ignore all events.
    pub fn ignore_all() -> Self {
        Self {
            account_data: Filter::ignore_all(),
            room: RoomFilter::ignore_all(),
            presence: Filter::ignore_all(),
            ..Default::default()
        }
    }

    /// Returns `true` if all fields are empty.
    pub fn is_empty(&self) -> bool {
        self.event_fields.is_none()
            && self.event_format == EventFormat::Client
            && self.presence.is_empty()
            && self.account_data.is_empty()
            && self.room.is_empty()
    }
}

impl IncomingFilterDefinition {
    /// Returns `true` if all fields are empty.
    pub fn is_empty(&self) -> bool {
        self.event_fields.is_none()
            && self.event_format == EventFormat::Client
            && self.presence.is_empty()
            && self.account_data.is_empty()
            && self.room.is_empty()
    }
}

macro_rules! can_be_empty {
    ($ty:ident $(<$gen:tt>)?) => {
        impl $(<$gen>)? ruma_serde::CanBeEmpty for $ty $(<$gen>)? {
            fn is_empty(&self) -> bool {
                self.is_empty()
            }
        }
    };
}

can_be_empty!(Filter<'a>);
can_be_empty!(FilterDefinition<'a>);
can_be_empty!(RoomEventFilter<'a>);
can_be_empty!(RoomFilter<'a>);

can_be_empty!(IncomingFilter);
can_be_empty!(IncomingFilterDefinition);
can_be_empty!(IncomingRoomEventFilter);
can_be_empty!(IncomingRoomFilter);

#[cfg(test)]
mod tests {
    use serde_json::{from_value as from_json_value, json, to_value as to_json_value};

    use super::{
        Filter, FilterDefinition, IncomingFilterDefinition, IncomingRoomFilter, RoomEventFilter,
        RoomFilter,
    };

    #[test]
    fn default_filters_are_empty() -> Result<(), serde_json::Error> {
        assert_eq!(to_json_value(Filter::default())?, json!({}));
        assert_eq!(to_json_value(FilterDefinition::default())?, json!({}));
        assert_eq!(to_json_value(RoomEventFilter::default())?, json!({}));
        assert_eq!(to_json_value(RoomFilter::default())?, json!({}));

        Ok(())
    }

    #[test]
    fn filter_definition_roundtrip() -> Result<(), serde_json::Error> {
        let filter = FilterDefinition::default();
        let filter_str = to_json_value(&filter)?;

        let incoming_filter = from_json_value::<IncomingFilterDefinition>(filter_str)?;
        assert!(incoming_filter.is_empty());

        Ok(())
    }

    #[test]
    fn room_filter_definition_roundtrip() -> Result<(), serde_json::Error> {
        let filter = RoomFilter::default();
        let room_filter = to_json_value(&filter)?;

        let incoming_room_filter = from_json_value::<IncomingRoomFilter>(room_filter)?;
        assert!(incoming_room_filter.is_empty());

        Ok(())
    }
}
<|endoftext|>


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

//use std::sync::Arc;
//use super::MeasuredStr;

/// A [str] that can be marked up with a single value of type `M`.
#[derive(Debug)]
pub struct MarkedStr<S, M>(S, M);

impl<S, M> MarkedStr<S, M> {
    pub fn text(&self) -> &S {
        &self.0
    }
    pub fn as_str(&self) -> &str
    where
        S: AsRef<str>,
    {
        self.0.as_ref()
    }
    pub fn mark(&self) -> &M {
        &self.1
    }
    pub fn mark_mut(&mut self) -> &mut M {
        &mut self.1
    }
    /*
    pub fn split<O: Offset>(&self, split_at: O) -> (Self, Self)
    where
        M: Clone,
    {
        //use super::offsets::StrExt;
        //let split_at_byte = split_at.
        //self.0.split(
    }
    */
}

impl<S, M> Default for MarkedStr<S, M>
where
    S: From<&'static str>,
    M: Default,
{
    fn default() -> Self {
        "".into()
    }
}

impl<S, M> Clone for MarkedStr<S, M>
where
    S: Clone,
    M: Clone,
{
    fn clone(&self) -> Self {
        Self(self.0.clone(), self.1.clone())
    }
}

impl<'a, S, M> From<&'a str> for MarkedStr<S, M>
where
    S: From<&'a str>,
    M: Default,
{
    fn from(src: &'a str) -> Self {
        Self(src.into(), Default::default())
    }
}

impl<S, M> AsRef<str> for MarkedStr<S, M>
where
    S: AsRef<str>,
{
    fn as_ref(&self) -> &str {
        self.0.as_ref()
    }
}

//pub trait MarkedSlice<M>: AsRef<[MarkedStr<M>]> {}

//pub type MarkupSlice<M> = [Arc<MarkedStr<M>>];
//pub type MarkupVec = Vec<Arc<MarkedStr<M>>>;

//use std::iter;
//use std::slice;
pub trait Markup<S, M = ()>: AsRef<[MarkedStr<S, M>]> {
    //fn bytes(&self) -> Bytes<'_> { self.as_ref() .iter() .map(MarkedStr::as_str) .flat_map(str::as_bytes) }
    //fn chars(&self) -> Chars<'_> { todo!(""); }
    //fn graphemes(&self) -> Graphemes<'_> { todo!(""); }
    //fn words(&self) -> Words<'_> { todo!(""); }
    //fn lines(&self) -> Lines<'_> { todo!(""); }
    fn len(&self) -> usize
    where
        S: AsRef<str>,
    {
        self.as_ref()
            .iter()
            .fold(0, |acc, seg| acc + seg.as_str().len())
    }
}

impl<T, S, M> Markup<S, M> for T where T: AsRef<[MarkedStr<S, M>]> {}

pub type Segments<'a, S, M> = std::slice::Iter<'a, MarkedStr<S, M>>;

//pub type Bytes<'a, M> (iter::Peekable<Segments<'a, M>>); impl<'a,M> Iterator for Bytes<'a,M>{ }

//iter::FlatMap<iter::Map<slice::Iter<'a, MarkedStr<M>>, for<'r> fn(&'r MarkedStr<M >) -> &'r str {MarkedStr::<M>::as_str}>, &[u8], for<'r> fn(&'r str) -> &'r [u8] {core::str::<impl str>::as_bytes}>;
//pub struct Chars<'a> {}
//pub struct Graphemes<'a> {}
//pub struct Words<'a> {}
//pub struct Lines<'a> {}

#[cfg(test)]
mod a_char_vec {
    #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
    enum Font {
        Serif,
        SansSerif,
    }
    impl Default for Font {
        fn default() -> Self {
            Font::Serif
        }
    }

    #[test]
    fn is_empty_by_default() {
        //use super::Markup;
        use super::MarkedStr;
        let mut text: Vec<MarkedStr<String, Font>> = vec!["hello".into()];
        assert_eq!(text[0].as_str(), "hello");
        assert_eq!(*text[0].mark(), Font::Serif);
        *text[0].mark_mut() = Font::SansSerif;
        assert_eq!(*text[0].mark(), Font::SansSerif);
    }
}
<commit_msg>rust/notemaps_core: experimental ideas<commit_after>// Copyright 2021-2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software distributed under the
// License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
// express or implied. See the License for the specific language governing permissions and
// limitations under the License.

use super::offsets;
use super::offsets::Grapheme;
use super::Note;
use core::ops::Range;
use std::rc::Rc;

/// Any type implementing [Mark] can be used to mark up text in a [MarkStr].
///
/// # Examples
///
/// ```rust
/// use notemaps_core::Mark;
///
/// #[derive(Clone)]
/// enum FontFamily { Serif, SansSerif }
///
/// impl Mark for FontFamily {}
///
/// use FontFamily::*;
///
/// let formatted_text = vec![
///     Serif.mark("Hello, "),
///     SansSerif.mark("World!"),
/// ];
/// ```
pub trait Mark {
    /// Creates a [MarkStr] that applies self to s.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use notemaps_core::Mark;
    ///
    /// #[derive(Clone)]
    /// struct PointSize (u8);
    ///
    /// impl Mark for PointSize {}
    ///
    /// PointSize(12).mark("Hello, World!");
    /// ```
    fn mark<S: AsRef<str>>(&self, s: S) -> MarkStr<Self, S>
    where
        Self: Clone,
    {
        MarkStr::new(self.clone(), s)
    }
}

/// A contiguous piece of marked up text that has the same mark from beginning to end.
///
/// With a sufficiently expressive implementation of [Mark], any rich text document can be
/// represented as a sequence of [MarkStr] values.
///
/// # Examples
///
/// ```rust
/// use notemaps_core::Mark;
/// use notemaps_core::MarkStr;
///
/// #[derive(Clone)]
/// enum Style { Regular, Italic }
///
/// impl Mark for Style {}
///
/// use Style::*;
///
/// let document: Vec<MarkStr<Style, &'static str>> = [
///     Regular.mark("Hello, "),
///     Italic.mark("World!"),
/// ].to_vec();
/// ```
#[derive(Debug)]
pub struct MarkStr<M: Mark, S: AsRef<str> = Rc<str>> {
    mark: M,
    string: S,
}

impl<M: Mark, S: AsRef<str>> MarkStr<M, S> {
    fn new(mark: M, string: S) -> Self {
        Self { mark, string }
    }
    pub fn as_str(&self) -> &str {
        self.string.as_ref()
    }
    pub fn mark(&self) -> &M {
        &self.mark
    }
    pub fn mark_mut(&mut self) -> &mut M {
        &mut self.mark
    }
    pub fn map_str<T: AsRef<str>, F: FnOnce(S) -> T>(self, f: F) -> MarkStr<M, T> {
        MarkStr {
            mark: self.mark,
            string: f(self.string),
        }
    }
    pub fn map_mark<N: Mark, F: FnOnce(M) -> N>(self, f: F) -> MarkStr<N, S> {
        MarkStr {
            mark: f(self.mark),
            string: self.string,
        }
    }
}

impl<M: Mark, S: AsRef<str>> Default for MarkStr<M, S>
where
    S: Default,
    M: Default,
{
    fn default() -> Self {
        Self::new(Default::default(), Default::default())
    }
}

impl<M: Mark, S: AsRef<str>> Clone for MarkStr<M, S>
where
    S: Clone,
    M: Clone,
{
    fn clone(&self) -> Self {
        Self::new(self.mark.clone(), self.string.clone())
    }
}

impl<'a, M: Mark, S: AsRef<str>> From<&'a str> for MarkStr<M, S>
where
    S: From<&'a str>,
    M: Default,
{
    fn from(src: &'a str) -> Self {
        Self::new(Default::default(), src.into())
    }
}

impl<'a, M: Mark, S: AsRef<str>> From<(M, S)> for MarkStr<M, S> {
    fn from(src: (M, S)) -> Self {
        Self::new(src.0, src.1)
    }
}

impl<M: Mark, S: AsRef<str>> AsRef<str> for MarkStr<M, S>
where
    S: AsRef<str>,
{
    fn as_ref(&self) -> &str {
        self.string.as_ref()
    }
}

/// Extensions for [Iterator] types.
pub trait IteratorExt: Iterator {
    fn count_bytes(&mut self) -> offsets::Byte
    where
        <Self as Iterator>::Item: AsRef<str>,
    {
        offsets::Byte(self.map(|s| s.as_ref().len()).sum())
    }

    fn count_chars(&mut self) -> offsets::Char
    where
        <Self as Iterator>::Item: AsRef<str>,
    {
        offsets::Char(self.map(|s| s.as_ref().char_indices().count()).sum())
    }

    fn count_graphemes(&mut self) -> offsets::Grapheme
    where
        <Self as Iterator>::Item: AsRef<str>,
    {
        use unicode_segmentation::UnicodeSegmentation;
        offsets::Grapheme(
            self.map(|s| s.as_ref().grapheme_indices(/*extended=*/ true).count())
                .sum(),
        )
    }

    fn into_input<M: Mark, S: AsRef<str>>(
        self,
        range: Range<Grapheme>,
        r: Replacement<M, S>,
    ) -> MarkStrInput<M, S>
    where
        Self: Sized,
        <Self as Iterator>::Item: std::borrow::Borrow<MarkStr<M, S>>,
        M: Clone,
        S: Clone,
    {
        MarkStrInput::new(self, range, r)
    }
}

impl<T: Iterator> IteratorExt for T {}

#[cfg(test)]
mod a_collection_of_mark_strs {
    use super::offsets::{Byte, Char, Grapheme};
    use super::IteratorExt;
    use super::Mark;
    use super::MarkStr;

    #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
    enum Font {
        Serif,
        SansSerif,
    }

    impl Mark for Font {}
    impl Mark for std::rc::Rc<Font> {}

    impl Default for Font {
        fn default() -> Self {
            Font::Serif
        }
    }

    #[test]
    fn can_be_cheaply_converted_to_a_str_reference() {
        let mut text: Vec<MarkStr<Font>> = vec!["hello".into()];
        assert_eq!(text[0].as_str(), "hello");
        assert_eq!(text[0].as_ref(), "hello");
        assert_eq!(*text[0].mark(), Font::Serif);
        *text[0].mark_mut() = Font::SansSerif;
        assert_eq!(*text[0].mark(), Font::SansSerif);
        assert_eq!(
            vec![Font::Serif.mark("a̐éö̲"), Font::SansSerif.mark("\r\n")]
                .iter()
                .count_bytes(),
            Byte(13)
        );
        assert_eq!(
            vec![Font::Serif.mark("a̐éö̲"), Font::SansSerif.mark("\r\n")]
                .iter()
                .count_chars(),
            Char(9)
        );
        assert_eq!(
            vec![Font::Serif.mark("a̐éö̲"), Font::SansSerif.mark("\r\n")]
                .iter()
                .count_graphemes(),
            Grapheme(4)
        );
    }
}

#[derive(Clone)]
pub enum Replacement<M: Mark, S: AsRef<str>> {
    Mark(M),
    Str(S),
}

#[derive(Clone)]
pub struct MarkStrInput<M: Mark, S: AsRef<str>> {
    context: Vec<MarkStr<M, S>>,
    range: Range<Grapheme>,
    replacement: Replacement<M, S>,
}

impl<M: Mark, S: AsRef<str>> MarkStrInput<M, S> {
    fn new<I: Iterator>(
        context: I,
        range_graphemes: Range<Grapheme>,
        replacement: Replacement<M, S>,
    ) -> Self
    where
        <I as Iterator>::Item: std::borrow::Borrow<MarkStr<M, S>>,
        M: Clone,
        S: Clone,
    {
        use std::borrow::Borrow;
        Self {
            context: context.map(|m| m.borrow().clone()).collect(),
            range: range_graphemes,
            replacement,
        }
    }

    pub fn context(&self) -> &[MarkStr<M, S>] {
        self.context.as_ref()
    }

    pub fn range_graphemes(&self) -> Range<Grapheme> {
        self.range.clone()
    }

    pub fn text(&self) -> Option<S>
    where
        S: Clone,
    {
        match &self.replacement {
            Replacement::Str(text) => Some(text.clone()),
            _ => None,
        }
    }

    pub fn mark(&self) -> Option<M>
    where
        M: Clone,
    {
        match &self.replacement {
            Replacement::Mark(mark) => Some(mark.clone()),
            _ => None,
        }
    }
}

pub struct Command<'a, E> {
    commit_fn: Box<dyn 'a+FnOnce() -> Result<(), E>>,
}

impl<'a,E> Command<'a,E> {
    pub fn new<F:'a+FnOnce()->Result<(),E>>(commit_fn:F)->Self{Self{commit_fn:Box::new(commit_fn)}}
    pub fn into_result(self) -> Result<(), E> {
        let commit = self.commit_fn;
        commit()
    }
}

pub trait Interpreter<M: Mark> {
    type InterpreterError;
    type CommandError;
    fn interpret<S: AsRef<str>>(
        &mut self,
        input: MarkStrInput<M, S>,
    ) -> Result<Command<Self::CommandError>, Self::InterpreterError>;
}

#[derive(Clone)]
pub struct TopicMark {
    pub topic: Note,
}

#[derive(Clone, Default)]
pub struct OccurrenceMark {
    pub occurrence_offset: usize,
    pub occurrence_types: Vec<Note>,
}

impl OccurrenceMark {
    pub fn is_name(&self) -> bool {
        self.occurrence_types.contains(&Note::NAME)
    }
}

#[derive(Clone)]
pub enum StrType {
    /// Delimiter text should:
    /// - typically not be editable in the UI.
    /// - be edtitable in the UI only to _delete_ the delimiter text, and only if there is a
    ///   command that can be expressed by doing so.
    Delimiter,
    /// Value text should:
    /// - contain the value of the note identified in the associated [OccurrenceMark].
    Value,
    /// Hyper text should:
    /// - afford navigation to an associated note through optional user interaction.
    /// - contain the value of an occurrence of type Note::NAME, or else another readable
    ///   identifier.
    Hyper,
}

//#[derive(Clone)] struct Actionable { editable: bool, splittable: bool, }

#[derive(Clone)]
pub struct NoteMark {
    pub topic: Rc<TopicMark>,
    pub occurrence: Rc<OccurrenceMark>,
    pub str_type: StrType,
}

impl Mark for NoteMark {}

impl NoteMark {
    pub fn new(topic: Rc<TopicMark>) -> Self {
        Self {
            topic,
            occurrence: Rc::default(),
            str_type: StrType::Delimiter,
        }
    }
    pub fn with_occurrence(mut self, occurrence: Rc<OccurrenceMark>) -> Self {
        self.occurrence = occurrence;
        self
    }
    pub fn with_strtype(mut self, str_type: StrType) -> Self {
        self.str_type = str_type;
        self
    }
}

trait ExtendExt<S: AsRef<str>>: Extend<MarkStr<NoteMark, S>> {
    fn extend_name(&mut self, mut m: NoteMark, value: S)
    where
        S: From<&'static str>,
    {
        Rc::make_mut(&mut m.occurrence)
            .occurrence_types
            .push(Note::NAME);
        self.extend([
            (m.clone().with_strtype(StrType::Value), value).into(),
            (m.clone().with_strtype(StrType::Delimiter), "\n".into()).into(),
        ]);
    }
}

impl<C: Extend<MarkStr<NoteMark, S>>, S: AsRef<str>> ExtendExt<S> for C {}

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

    #[derive(Debug)]
    struct MyModel {
        name: String,
    }

    #[derive(Clone,Debug)]
    enum MyMark {
        Name,
        Delimiter,
    }

    impl Mark for MyMark {}

    struct View {}

    impl View {
        fn render(&self, model: &MyModel) -> Vec<MarkStr<MyMark>> {
            vec![
                MyMark::Delimiter.mark("Hello, ".into()),
                MyMark::Name.mark(model.name.as_str().into()),
                MyMark::Delimiter.mark("!".into()),
                MyMark::Delimiter.mark("\n".into()),
            ]
        }
    }

    use std::sync::{Arc, Mutex};
    struct MyInterpreter {
        _model: Arc<Mutex<MyModel>>,
    }

    impl Interpreter<MyMark> for MyInterpreter {
        type InterpreterError = &'static str;
        type CommandError = &'static str;
        fn interpret<S: AsRef<str>>(
            &mut self,
            input: MarkStrInput<MyMark, S>,
        ) -> Result<Command<Self::CommandError>, Self::InterpreterError> {
            if input.context().len()!=1{
                Err("can only act on one segment at a time for now")
            }else {
                let segment = &input.context()[0];
                match segment.mark(){
                    MyMark::Name=>{
                        Ok(Command::new(||{
                            Ok(())
                        }))
                    }
                    _=>Err("cannot interpret command from attempt to edit this segment"),
                }
            }
        }
    }

    #[test]
    fn documents_made_of_marked_strings() {
        let internet = Note::random();
        let mark_internet = NoteMark::new(Rc::new(TopicMark { topic: internet }));
        let mark_name0 = mark_internet
            .clone()
            .with_occurrence(Rc::new(OccurrenceMark {
                occurrence_offset: 0,
                occurrence_types: [Note::NAME].into(),
            }));
        let document: Vec<MarkStr<NoteMark>> = vec![
            mark_name0
                .clone()
                .with_strtype(StrType::Value)
                .mark("internet".into()),
            mark_name0
                .clone()
                .with_strtype(StrType::Delimiter)
                .mark("\n".into()),
        ];
        assert_eq!(
            document
                .iter()
                .map(|m| m.as_str().to_string())
                .fold(String::new(), |a, b| a + &b),
            "internet\n"
        );
    }

    #[test]
    fn interpret_input_to_command() {
        let model = Arc::new(Mutex::new(MyModel {
            name: "World".into(),
        }));
        let interpreter = MyInterpreter {
            _model: model.clone(),
        };
        let document = {
            let model = model.lock().unwrap();
            View {}.render(&*model)
        };
        let input = document
            .iter()
            .into_input(Grapheme(7)..Grapheme(12), Replacement::Str("Test".into()));
        println!("{:?}",input.context());
        println!("{:?}",interpreter._model  );
        //interpreter.interpret(input).expect("input should be interpretable");
    }
}
<|endoftext|>


<commit_before>use learning::toolkit::kernel::{Kernel, SquaredExp};
use learning::SupModel;
use linalg::matrix::Matrix;

trait MeanFunc {
    fn func(&self, x: f64) -> f64;
}

struct ConstMean {
    a: f64,
}

impl Default for ConstMean {
    fn default() -> ConstMean {
        ConstMean { a: 0f64 }
    }
}

impl MeanFunc for ConstMean {
    fn func(&self, _: f64) -> f64 {
        self.a
    }
}

struct GaussianProcess<T: Kernel, U: MeanFunc> {
    ker: T,
    mean: U,
    noise: f64,
    train_data: Option<Matrix<f64>>,
    train_output: Option<Matrix<f64>>,
    train_mat: Option<Matrix<f64>>,
}

impl Default for GaussianProcess<SquaredExp, ConstMean> {
    fn default() -> GaussianProcess<SquaredExp, ConstMean> {
        GaussianProcess {
            ker: SquaredExp::default(),
            mean: ConstMean::default(),
            noise: 1f64,
            train_data: None,
            train_output: None,
            train_mat: None,
        }
    }
}

impl<T: Kernel, U: MeanFunc> GaussianProcess<T, U> {
    fn ker_mat(&self, m1: &Matrix<f64>, m2: &Matrix<f64>) -> Matrix<f64> {
        assert_eq!(m1.cols(), m2.cols());
        let dim1 = m1.rows();
        let dim2 = m2.rows();

        let mut ker_data = Vec::with_capacity(dim1 * dim2);

        for i in 0..dim1 {
            for j in 0..dim2 {
                ker_data.push(self.ker.kernel(&m1.data[i * m1.cols()..(i + 1) * m1.cols()],
                                              &m2.data[j * m2.cols()..(j + 1) * m2.cols()]));
            }
        }

        Matrix::new(dim1, dim2, ker_data)
    }
}

impl<T: Kernel, U: MeanFunc> SupModel<Matrix<f64>, Matrix<f64>> for GaussianProcess<T, U> {

	/// Predict output from data.
        fn predict(&self, data: &Matrix<f64>) -> Matrix<f64> {
        	Matrix::new(1,1,vec![1f64])
        }

        /// Train the model using data and outputs.
        fn train(&mut self, data: &Matrix<f64>, value: &Matrix<f64>) {
        	let noise_mat = Matrix::identity(data.rows()) * self.noise;

        	let ker_mat = self.ker_mat(data, data);

        	let train_mat = (ker_mat + noise_mat).inverse();

        	self.train_mat = Some(train_mat);
        	self.train_data = Some(data.clone());
        	self.train_output = Some(value.clone());
        }
}
<commit_msg>First pass at GP regression.<commit_after>use learning::toolkit::kernel::{Kernel, SquaredExp};
use learning::SupModel;
use linalg::matrix::Matrix;

trait MeanFunc {
    fn func(&self, x: Matrix<f64>) -> Matrix<f64>;
}

struct ConstMean {
    a: f64,
}

impl Default for ConstMean {
    fn default() -> ConstMean {
        ConstMean { a: 0f64 }
    }
}

impl MeanFunc for ConstMean {
    fn func(&self, x: Matrix<f64>) -> Matrix<f64> {
        Matrix::ones(x.rows(), x.cols()) * self.a
    }
}

struct GaussianProcess<T: Kernel, U: MeanFunc> {
    ker: T,
    mean: U,
    noise: f64,
    train_data: Option<Matrix<f64>>,
    train_output: Option<Matrix<f64>>,
    train_mat: Option<Matrix<f64>>,
}

impl Default for GaussianProcess<SquaredExp, ConstMean> {
    fn default() -> GaussianProcess<SquaredExp, ConstMean> {
        GaussianProcess {
            ker: SquaredExp::default(),
            mean: ConstMean::default(),
            noise: 1f64,
            train_data: None,
            train_output: None,
            train_mat: None,
        }
    }
}

impl<T: Kernel, U: MeanFunc> GaussianProcess<T, U> {
    fn ker_mat(&self, m1: &Matrix<f64>, m2: &Matrix<f64>) -> Matrix<f64> {
        assert_eq!(m1.cols(), m2.cols());
        let dim1 = m1.rows();
        let dim2 = m2.rows();

        let mut ker_data = Vec::with_capacity(dim1 * dim2);

        for i in 0..dim1 {
            for j in 0..dim2 {
                ker_data.push(self.ker.kernel(&m1.data[i * m1.cols()..(i + 1) * m1.cols()],
                                              &m2.data[j * m2.cols()..(j + 1) * m2.cols()]));
            }
        }

        Matrix::new(dim1, dim2, ker_data)
    }
}

impl<T: Kernel, U: MeanFunc> SupModel<Matrix<f64>, Matrix<f64>> for GaussianProcess<T, U> {
    /// Predict output from data.
    fn predict(&self, data: &Matrix<f64>) -> Matrix<f64> {
        let mean = self.mean.func(data.clone());

        // Messy referencing for succint syntax
        if let (&Some(ref t_data), &Some(ref t_mat), &Some(ref t_out)) = (&self.train_data, &self.train_mat, &self.train_output) {
        	let test_mat = self.ker_mat(data, t_data) * t_mat *
                       (t_out - self.mean.func(t_data.clone()));
        	return mean + test_mat;
        }

        panic!("The model has not been trained.");

    }

    /// Train the model using data and outputs.
    fn train(&mut self, data: &Matrix<f64>, value: &Matrix<f64>) {
        let noise_mat = Matrix::identity(data.rows()) * self.noise;

        let ker_mat = self.ker_mat(data, data);

        let train_mat = (ker_mat + noise_mat).inverse();

        self.train_mat = Some(train_mat);
        self.train_data = Some(data.clone());
        self.train_output = Some(value.clone());
    }
}
<|endoftext|>