<commit_before>extern crate serde_json;

pub mod learning;

use input::util;
use na::{DMatrix, DVector, IterableMut};
use rand;
use rand::distributions::normal::StandardNormal;
use rand::Rng;
use std::fs::File;
use std::io::{self, BufReader, BufWriter};
use std::str;
use structs::serialnet::SerializableNet;

/// Artificial Neural Network
///
/// This struct represents a simple Artificial Neural Network (ANN) using
/// feedforward and backpropagation. It uses Stochastic Gradient Descent(SGD)
/// and a sigmoid activation function.
///
/// [Source](http://neuralnetworksanddeeplearning.com/chap1.html)
///
/// # Example
///
/// ```rust
/// // This will create a new ANN with the following topology:
/// // 3 "neurons" in the input layer
/// // 5 "neurons" in the first hidden layer
/// // 3 "neurons" in the second hidden layer
/// // 2 "neurons" in the output layer
/// let nnet = Network::new(vec![3, 5, 2]);
/// ```
#[derive(Debug, Clone)]
pub struct Network {
    /// a Vec outlining the topology of the ANN
    /// the first entry corresponds to the inputlayer,
    /// the intermediate entries correspond to the hidden layers
    /// and the last entry corresponds to the outputlayer.
    layers: Vec<u8>,
    /// a Vec that contains the weights of the respective layer
    weights: Vec<DMatrix<f32>>,
    /// a Vec cointaining the biases of the respective layer
    biases: Vec<DVector<f32>>,
}

impl Network {
    /// build a new Network with a topology Vector
    pub fn new(sizes: Vec<u8>) -> Result<Network, &'static str> {
        assert!(sizes.len() >= 3, "at least three layers required");

        // Store the weights and biases in lists
        // We will not need weights or biases for input layer, so ignore that (hence -1)
        let mut weights = Vec::with_capacity(sizes.len() - 1);
        let mut biases = Vec::with_capacity(sizes.len() - 1);

        let mut rng = rand::thread_rng();

        // we use the standard normal distribution to initialize weights and biases - why?
        for (i, layer) in sizes.iter().enumerate().skip(1) {
            // initialize weight matrices
            weights.push(DMatrix::from_fn(*layer as usize, sizes[i - 1] as usize, |_, _| {
                let StandardNormal(x) = rng.gen();
                x as f32
            }));

            // initialize biases
            biases.push(DVector::from_fn(*layer as usize, |_| {
                let StandardNormal(x) = rng.gen();
                x as f32
            }));
        }

        Ok(Network {
            layers: sizes,
            weights: weights,
            biases: biases,
        })
    }

    /// Feed input through network, return output layer activation level
    pub fn feedforward(&self, a: &DVector<f32>) -> DVector<f32> {
        let mut act = a.clone();
        for (weight, bias) in self.weights.iter().zip(self.biases.clone().into_iter()) {
            act = sigmoid(&(weight * act + bias));
        }
        act
    }

    /// return the layers used to initialize the ANN
    pub fn get_layers(&self) -> &[u8] {
        &self.layers
    }

    /// return a vector of the weight matrices of the ANN
    pub fn get_weights(&self) -> &[DMatrix<f32>] {
        &self.weights
    }

    /// return a mutable vector of the weight matrices of the ANN
    pub fn get_weights_mut(&mut self) -> &mut Vec<DMatrix<f32>> {
        &mut self.weights
    }

    /// return a vector of the bias matrices of the ANN
    pub fn get_biases(&self) -> &[DVector<f32>] {
        &self.biases
    }

    /// Saves a network state to the given filename and returns a result
    pub fn save_to_file(self, filename: &str) -> Result<(), serde_json::Error> {
        // wrap it in a SerializableNet
        let serializable_net: SerializableNet = self.into();
        // create the file
        let f = File::create(util::get_root_dir().join("data/").join(filename)).unwrap();
        // create a writer
        let mut writer = BufWriter::new(f);
        // serialize the network and return the result
        serde_json::to_writer(&mut writer, &serializable_net)
    }

    /// Loads a network state from the given file
    ///
    /// Returns a result with the file or an io::Error if the specified file could
    /// not be opened
    pub fn from_file(filename: &str) -> Result<Self, io::Error> {
        // attempt to open the file
        let f = File::open(util::get_root_dir().join("data/").join(filename))?;
        let reader = BufReader::new(f);
        // read the SerializableNet from the file
        // we use unwrap here b/c if the file exists then we want the program to panic
        // if we cannot read from it
        let my_net: SerializableNet = serde_json::from_reader(reader)
            .expect("Could not parse Network from File");
        // convert into a Network and return it
        Ok(my_net.into())
    }

    /// return a vector of the bias matrices of the ANN
    pub fn get_biases_mut(&mut self) -> &mut Vec<DVector<f32>> {
        &mut self.biases
    }
}

// calculate elementwise sigmoid function
pub fn sigmoid(arr: &DVector<f32>) -> DVector<f32> {
    let mut sig = arr.clone();
    for elem in sig.iter_mut() {
        *elem = 1.0 / (1.0 + (-1.0f32 * elem.clone()).exp());
    }
    sig
}

impl From<SerializableNet> for Network {
    fn from(ser_net: SerializableNet) -> Self {

        let mut weights: Vec<DMatrix<f32>> = Vec::new();
        for v in ser_net.weights {
            let (nrows, ncols) = (v.0, v.1);
            weights.push(DMatrix::from_column_vector(nrows, ncols, &v.2))
        }

        let mut biases: Vec<DVector<f32>> = Vec::new();
        for v in ser_net.biases {
            biases.push(DVector::from_slice(v.len(), &v))
        }

        Network {
            layers: ser_net.layers,
            weights: weights,
            biases: biases,
        }
    }
}

#[test]
fn test_sigmoid() {
    let mut arr_orig = DVector::from_element(3, 1.0f32);
    arr_orig[2] = 2.4137;
    let arr = sigmoid(&arr_orig);
    assert_eq!(arr[0], arr[1]);
    assert_eq!(arr[0], 0.26894142137f32);
    assert_eq!(0.082133951f32, arr[2]);
}
<commit_msg>Fixed unit test and one copy call<commit_after>extern crate serde_json;

pub mod learning;

use input::util;
use na::{DMatrix, DVector, IterableMut};
use rand;
use rand::distributions::normal::StandardNormal;
use rand::Rng;
use std::fs::File;
use std::io::{self, BufReader, BufWriter};
use std::str;
use structs::serialnet::SerializableNet;

/// Artificial Neural Network
///
/// This struct represents a simple Artificial Neural Network (ANN) using
/// feedforward and backpropagation. It uses Stochastic Gradient Descent(SGD)
/// and a sigmoid activation function.
///
/// [Source](http://neuralnetworksanddeeplearning.com/chap1.html)
///
/// # Example
///
/// ```rust
/// // This will create a new ANN with the following topology:
/// // 3 "neurons" in the input layer
/// // 5 "neurons" in the first hidden layer
/// // 3 "neurons" in the second hidden layer
/// // 2 "neurons" in the output layer
/// let nnet = Network::new(vec![3, 5, 2]);
/// ```
#[derive(Debug, Clone)]
pub struct Network {
    /// a Vec outlining the topology of the ANN
    /// the first entry corresponds to the inputlayer,
    /// the intermediate entries correspond to the hidden layers
    /// and the last entry corresponds to the outputlayer.
    layers: Vec<u8>,
    /// a Vec that contains the weights of the respective layer
    weights: Vec<DMatrix<f32>>,
    /// a Vec cointaining the biases of the respective layer
    biases: Vec<DVector<f32>>,
}

impl Network {
    /// build a new Network with a topology Vector
    pub fn new(sizes: Vec<u8>) -> Result<Network, &'static str> {
        assert!(sizes.len() >= 3, "at least three layers required");

        // Store the weights and biases in lists
        // We will not need weights or biases for input layer, so ignore that (hence -1)
        let mut weights = Vec::with_capacity(sizes.len() - 1);
        let mut biases = Vec::with_capacity(sizes.len() - 1);

        let mut rng = rand::thread_rng();

        // we use the standard normal distribution to initialize weights and biases - why?
        for (i, layer) in sizes.iter().enumerate().skip(1) {
            // initialize weight matrices
            weights.push(DMatrix::from_fn(*layer as usize, sizes[i - 1] as usize, |_, _| {
                let StandardNormal(x) = rng.gen();
                x as f32
            }));

            // initialize biases
            biases.push(DVector::from_fn(*layer as usize, |_| {
                let StandardNormal(x) = rng.gen();
                x as f32
            }));
        }

        Ok(Network {
            layers: sizes,
            weights: weights,
            biases: biases,
        })
    }

    /// Feed input through network, return output layer activation level
    pub fn feedforward(&self, a: &DVector<f32>) -> DVector<f32> {
        let mut act = a.clone();
        for (weight, bias) in self.weights.iter().zip(self.biases.clone().into_iter()) {
            act = sigmoid(&(weight * act + bias));
        }
        act
    }

    /// return the layers used to initialize the ANN
    pub fn get_layers(&self) -> &[u8] {
        &self.layers
    }

    /// return a vector of the weight matrices of the ANN
    pub fn get_weights(&self) -> &[DMatrix<f32>] {
        &self.weights
    }

    /// return a mutable vector of the weight matrices of the ANN
    pub fn get_weights_mut(&mut self) -> &mut Vec<DMatrix<f32>> {
        &mut self.weights
    }

    /// return a vector of the bias matrices of the ANN
    pub fn get_biases(&self) -> &[DVector<f32>] {
        &self.biases
    }

    /// Saves a network state to the given filename and returns a result
    pub fn save_to_file(self, filename: &str) -> Result<(), serde_json::Error> {
        // wrap it in a SerializableNet
        let serializable_net: SerializableNet = self.into();
        // create the file
        let f = File::create(util::get_root_dir().join("data/").join(filename)).unwrap();
        // create a writer
        let mut writer = BufWriter::new(f);
        // serialize the network and return the result
        serde_json::to_writer(&mut writer, &serializable_net)
    }

    /// Loads a network state from the given file
    ///
    /// Returns a result with the file or an io::Error if the specified file could
    /// not be opened
    pub fn from_file(filename: &str) -> Result<Self, io::Error> {
        // attempt to open the file
        let f = File::open(util::get_root_dir().join("data/").join(filename))?;
        let reader = BufReader::new(f);
        // read the SerializableNet from the file
        // we use unwrap here b/c if the file exists then we want the program to panic
        // if we cannot read from it
        let my_net: SerializableNet = serde_json::from_reader(reader)
            .expect("Could not parse Network from File");
        // convert into a Network and return it
        Ok(my_net.into())
    }

    /// return a vector of the bias matrices of the ANN
    pub fn get_biases_mut(&mut self) -> &mut Vec<DVector<f32>> {
        &mut self.biases
    }
}

/// calculate elementwise sigmoid function of the `input` vector.
pub fn sigmoid(input: &DVector<f32>) -> DVector<f32> {
    let mut sig = input.clone();
    for elem in sig.iter_mut() {
        *elem = 1.0 / (1.0 + (-1.0f32 * *elem).exp());
    }
    sig
}

impl From<SerializableNet> for Network {
    fn from(ser_net: SerializableNet) -> Self {

        let mut weights: Vec<DMatrix<f32>> = Vec::new();
        for v in ser_net.weights {
            let (nrows, ncols) = (v.0, v.1);
            weights.push(DMatrix::from_column_vector(nrows, ncols, &v.2))
        }

        let mut biases: Vec<DVector<f32>> = Vec::new();
        for v in ser_net.biases {
            biases.push(DVector::from_slice(v.len(), &v))
        }

        Network {
            layers: ser_net.layers,
            weights: weights,
            biases: biases,
        }
    }
}

#[test]
fn test_sigmoid() {
    let mut arr_orig = DVector::from_element(3, 1.0f32);
    arr_orig[2] = 2.4137;
    let arr = sigmoid(&arr_orig);
    assert_eq!(arr[0], arr[1]);
    assert_eq!(arr[0], 0.73105857863f32);
    assert_eq!(arr[2], 0.91786604895f32);
}
<|endoftext|>


<commit_before>/*
Tristen Horton
tristen@tristenhorton.com
2017-04-03 23:37
*/
<commit_msg>Added a new line lmao<commit_after>/*
Tristen Horton
tristen@tristenhorton.com
2017-04-03 23:37
*/

// TODO: similar to rfc.rs, create kraken web request wrapper
<|endoftext|>


<commit_before>use super::{Array1dView, Array1dViewMut, Array2dView, Array2dViewMut};

use openblas::ffi::*;

#[derive(Clone, Copy)]
pub enum Transpose {
  N,
  T,
}

impl<'a> Array1dView<'a, f32> {
  pub fn l2_norm(&'a self) -> f32 {
    let n = self.dim();
    let incx = self.stride();
    unsafe { openblas_sequential_cblas_snrm2(
        n as _,
        self.buf.as_ptr(),
        incx as _,
    ) }
  }

  pub fn elem_sum(&'a self) -> f32 {
    let x_n = self.dim();
    let incx = self.stride();
    let mut p = 0;
    let mut x_sum = 0.0;
    for _ in 0 .. x_n {
      let x_i = self.buf[p];
      x_sum += x_i;
      p += incx;
    }
    x_sum
  }

  pub fn inner_prod(&'a self, alpha: f32, y: Array1dView<'a, f32>) -> f32 {
    let x_n = self.dim();
    let y_n = y.dim();
    assert_eq!(x_n, y_n);
    let incx = self.stride();
    let incy = y.stride();
    unsafe { openblas_sequential_cblas_sdot(
        x_n as _,
        alpha,
        self.buf.as_ptr(),
        incx as _,
        y.as_ptr(),
        incy as _,
    ) }
  }
}

impl<'a> Array1dViewMut<'a, f32> {
  pub fn add_scalar(&'a mut self, c: f32) {
    let n = self.dim();
    let incx = self.stride();
    let mut p = 0;
    for _ in 0 .. n {
      self.buf[p] += c;
      p += incx;
    }
  }

  pub fn vector_add_scalar(&'a mut self, c: f32) {
    self.add_scalar(c);
  }

  pub fn square(&'a mut self) {
    let n = self.dim();
    let incx = self.stride();
    let mut p = 0;
    for _ in 0 .. n {
      let x_i = self.buf[p];
      self.buf[p] = x_i * x_i;
      p += incx;
    }
  }

  pub fn vector_square(&'a mut self) {
    self.square();
  }

  pub fn sqrt(&'a mut self) {
    let n = self.dim();
    let incx = self.stride();
    let mut p = 0;
    for _ in 0 .. n {
      let x_i = self.buf[p];
      self.buf[p] = x_i.sqrt();
      p += incx;
    }
  }

  pub fn vector_sqrt(&'a mut self) {
    self.sqrt();
  }

  pub fn reciprocal(&'a mut self) {
    let n = self.dim();
    let incx = self.stride();
    let mut p = 0;
    for _ in 0 .. n {
      let x_i = self.buf[p];
      self.buf[p] = 1.0 / x_i;
      p += incx;
    }
  }

  pub fn vector_recip(&'a mut self) {
    self.reciprocal();
  }

  pub fn scale(&'a mut self, alpha: f32) {
    let n = self.dim();
    let incx = self.stride();
    unsafe { openblas_sequential_cblas_sscal(
        n as _,
        alpha,
        self.buf.as_mut_ptr(),
        incx as _,
    ) }
  }

  pub fn vector_scale(&'a mut self, alpha: f32) {
    self.scale(alpha);
  }

  pub fn add(&'a mut self, alpha: f32, x: Array1dView<'a, f32>) {
    let x_n = x.dim();
    let y_n = self.dim();
    assert_eq!(x_n, y_n);
    let incx = x.stride();
    let incy = self.stride();
    unsafe { openblas_sequential_cblas_saxpy(
        x_n as _,
        alpha,
        x.buf.as_ptr(),
        incx as _,
        self.buf.as_mut_ptr(),
        incy as _,
    ) };
  }

  pub fn vector_add(&'a mut self, alpha: f32, x: Array1dView<'a, f32>) {
    self.add(alpha, x);
  }

  pub fn average(&'a mut self, alpha: f32, x: Array1dView<'a, f32>) {
    let x_n = x.dim();
    let y_n = self.dim();
    assert_eq!(x_n, y_n);
    let incx = x.stride();
    let incy = self.stride();
    let mut p = 0;
    let mut q = 0;
    for _ in 0 .. x_n {
      let x_i = x.buf[p];
      let y_i = self.buf[q];
      self.buf[q] = alpha * (x_i - y_i);
      p += incx;
      q += incy;
    }
  }

  pub fn elem_mult(&'a mut self, alpha: f32, x: Array1dView<'a, f32>) {
    let x_n = x.dim();
    let y_n = self.dim();
    assert_eq!(x_n, y_n);
    let incx = x.stride();
    let incy = self.stride();
    let mut p = 0;
    let mut q = 0;
    for _ in 0 .. x_n {
      let x_i = x.buf[p];
      let y_i = self.buf[q];
      self.buf[q] = alpha * x_i * y_i;
      p += incx;
      q += incy;
    }
  }

  pub fn vector_elem_mult(&'a mut self, alpha: f32, x: Array1dView<'a, f32>) {
    self.elem_mult(alpha, x);
  }

  pub fn elem_div(&'a mut self, alpha: f32, x: Array1dView<'a, f32>) {
    let x_n = x.dim();
    let y_n = self.dim();
    assert_eq!(x_n, y_n);
    let incx = x.stride();
    let incy = self.stride();
    let mut p = 0;
    let mut q = 0;
    for _ in 0 .. x_n {
      let x_i = x.buf[p];
      let y_i = self.buf[q];
      self.buf[q] = alpha * y_i / x_i;
      p += incx;
      q += incy;
    }
  }
}

impl<'a> Array2dView<'a, f32> {
  pub fn matrix_diag(&'a self, y: Array1dViewMut<'a, f32>) {
    let (a_m, a_n) = self.dim();
    let y_m = y.dim();
    assert_eq!(a_m, a_n);
    assert_eq!(a_m, y_m);
    let (a_inc, lda) = self.stride();
    let incy = y.stride();
    assert_eq!(1, a_inc);
    let mut p = 0;
    let mut q = 0;
    for _ in 0 .. y_m {
      y.buf[q] = self.buf[p];
      p += a_inc + lda;
      q += incy;
    }
  }
}

impl<'a> Array2dViewMut<'a, f32> {
  pub fn matrix_add(&'a mut self, alpha: f32, x: Array2dView<'a, f32>) {
    let (x_m, x_n) = x.dim();
    let (y_m, y_n) = self.dim();
    assert_eq!(x_m, y_m);
    assert_eq!(x_n, y_n);
    let (incx, ldx) = x.stride();
    let (incy, ldy) = self.stride();
    if x_n == 1 {
      unsafe { openblas_sequential_cblas_saxpy(
          x_m as _,
          alpha,
          x.buf.as_ptr(),
          incx as _,
          self.buf.as_mut_ptr(),
          incy as _,
      ) };
    } else if x_m == 1 {
      unimplemented!();
    } else {
      unimplemented!();
    }
  }

  pub fn matrix_prod(&'a mut self, alpha: f32, a: Array2dView<'a, f32>, a_trans: Transpose, b: Array2dView<'a, f32>, b_trans: Transpose, beta: f32) {
    let (a_m, a_n) = a.dim();
    let (b_m, b_n) = b.dim();
    let (c_m, c_n) = self.dim();
    let (at_m, at_n) = match a_trans {
      Transpose::N => (a_m, a_n),
      Transpose::T => (a_n, a_m),
    };
    let (bt_m, bt_n) = match b_trans {
      Transpose::N => (b_m, b_n),
      Transpose::T => (b_n, b_m),
    };
    assert_eq!(c_m, at_m);
    assert_eq!(c_n, bt_n);
    assert_eq!(at_n, bt_m);
    let k = at_n;
    let (a_inc, lda) = a.stride();
    let (b_inc, ldb) = b.stride();
    let (c_inc, ldc) = self.stride();
    assert_eq!(1, a_inc);
    assert_eq!(1, b_inc);
    assert_eq!(1, c_inc);
    unsafe { openblas_sequential_cblas_sgemm(
        CblasOrder::ColMajor,
        match a_trans {
          Transpose::N => CblasTranspose::NoTrans,
          Transpose::T => CblasTranspose::Trans,
        },
        match b_trans {
          Transpose::N => CblasTranspose::NoTrans,
          Transpose::T => CblasTranspose::Trans,
        },
        c_m as _, c_n as _, k as _,
        alpha,
        a.buf.as_ptr(), lda as _,
        b.buf.as_ptr(), ldb as _,
        beta,
        self.buf.as_mut_ptr(), ldc as _,
    ) };
  }
}

impl<'a> Array2dViewMut<'a, f64> {
  pub fn matrix_prod(&'a mut self) {
    unimplemented!();
  }
}
<commit_msg>Add an `exp` method (the kernel was already implemented).<commit_after>use super::{Array1dView, Array1dViewMut, Array2dView, Array2dViewMut};

use openblas::ffi::*;

#[derive(Clone, Copy)]
pub enum Transpose {
  N,
  T,
}

impl<'a> Array1dView<'a, f32> {
  pub fn l2_norm(&'a self) -> f32 {
    let n = self.dim();
    let incx = self.stride();
    unsafe { openblas_sequential_cblas_snrm2(
        n as _,
        self.buf.as_ptr(),
        incx as _,
    ) }
  }

  pub fn elem_sum(&'a self) -> f32 {
    let x_n = self.dim();
    let incx = self.stride();
    let mut p = 0;
    let mut x_sum = 0.0;
    for _ in 0 .. x_n {
      let x_i = self.buf[p];
      x_sum += x_i;
      p += incx;
    }
    x_sum
  }

  pub fn inner_prod(&'a self, alpha: f32, y: Array1dView<'a, f32>) -> f32 {
    let x_n = self.dim();
    let y_n = y.dim();
    assert_eq!(x_n, y_n);
    let incx = self.stride();
    let incy = y.stride();
    unsafe { openblas_sequential_cblas_sdot(
        x_n as _,
        alpha,
        self.buf.as_ptr(),
        incx as _,
        y.as_ptr(),
        incy as _,
    ) }
  }
}

impl<'a> Array1dViewMut<'a, f32> {
  pub fn add_scalar(&'a mut self, c: f32) {
    let n = self.dim();
    let incx = self.stride();
    let mut p = 0;
    for _ in 0 .. n {
      self.buf[p] += c;
      p += incx;
    }
  }

  pub fn vector_add_scalar(&'a mut self, c: f32) {
    self.add_scalar(c);
  }

  pub fn square(&'a mut self) {
    let n = self.dim();
    let incx = self.stride();
    let mut p = 0;
    for _ in 0 .. n {
      let x_i = self.buf[p];
      self.buf[p] = x_i * x_i;
      p += incx;
    }
  }

  pub fn vector_square(&'a mut self) {
    self.square();
  }

  pub fn sqrt(&'a mut self) {
    let n = self.dim();
    let incx = self.stride();
    let mut p = 0;
    for _ in 0 .. n {
      let x_i = self.buf[p];
      self.buf[p] = x_i.sqrt();
      p += incx;
    }
  }

  pub fn vector_sqrt(&'a mut self) {
    self.sqrt();
  }

  pub fn reciprocal(&'a mut self) {
    let n = self.dim();
    let incx = self.stride();
    let mut p = 0;
    for _ in 0 .. n {
      let x_i = self.buf[p];
      self.buf[p] = 1.0 / x_i;
      p += incx;
    }
  }

  pub fn vector_recip(&'a mut self) {
    self.reciprocal();
  }

  pub fn exp(&mut self) {
    let n = self.dim();
    let incx = self.stride();
    let mut p = 0;
    for _ in 0 .. n {
      let x_i = self.buf[p];
      self.buf[p] = x_i.exp();
      p += incx;
    }
  }

  pub fn scale(&'a mut self, alpha: f32) {
    let n = self.dim();
    let incx = self.stride();
    unsafe { openblas_sequential_cblas_sscal(
        n as _,
        alpha,
        self.buf.as_mut_ptr(),
        incx as _,
    ) }
  }

  pub fn vector_scale(&'a mut self, alpha: f32) {
    self.scale(alpha);
  }

  pub fn add(&'a mut self, alpha: f32, x: Array1dView<'a, f32>) {
    let x_n = x.dim();
    let y_n = self.dim();
    assert_eq!(x_n, y_n);
    let incx = x.stride();
    let incy = self.stride();
    unsafe { openblas_sequential_cblas_saxpy(
        x_n as _,
        alpha,
        x.buf.as_ptr(),
        incx as _,
        self.buf.as_mut_ptr(),
        incy as _,
    ) };
  }

  pub fn vector_add(&'a mut self, alpha: f32, x: Array1dView<'a, f32>) {
    self.add(alpha, x);
  }

  pub fn average(&'a mut self, alpha: f32, x: Array1dView<'a, f32>) {
    let x_n = x.dim();
    let y_n = self.dim();
    assert_eq!(x_n, y_n);
    let incx = x.stride();
    let incy = self.stride();
    let mut p = 0;
    let mut q = 0;
    for _ in 0 .. x_n {
      let x_i = x.buf[p];
      let y_i = self.buf[q];
      self.buf[q] = alpha * (x_i - y_i);
      p += incx;
      q += incy;
    }
  }

  pub fn elem_mult(&'a mut self, alpha: f32, x: Array1dView<'a, f32>) {
    let x_n = x.dim();
    let y_n = self.dim();
    assert_eq!(x_n, y_n);
    let incx = x.stride();
    let incy = self.stride();
    let mut p = 0;
    let mut q = 0;
    for _ in 0 .. x_n {
      let x_i = x.buf[p];
      let y_i = self.buf[q];
      self.buf[q] = alpha * x_i * y_i;
      p += incx;
      q += incy;
    }
  }

  pub fn vector_elem_mult(&'a mut self, alpha: f32, x: Array1dView<'a, f32>) {
    self.elem_mult(alpha, x);
  }

  pub fn elem_div(&'a mut self, alpha: f32, x: Array1dView<'a, f32>) {
    let x_n = x.dim();
    let y_n = self.dim();
    assert_eq!(x_n, y_n);
    let incx = x.stride();
    let incy = self.stride();
    let mut p = 0;
    let mut q = 0;
    for _ in 0 .. x_n {
      let x_i = x.buf[p];
      let y_i = self.buf[q];
      self.buf[q] = alpha * y_i / x_i;
      p += incx;
      q += incy;
    }
  }
}

impl<'a> Array2dView<'a, f32> {
  pub fn matrix_diag(&'a self, y: Array1dViewMut<'a, f32>) {
    let (a_m, a_n) = self.dim();
    let y_m = y.dim();
    assert_eq!(a_m, a_n);
    assert_eq!(a_m, y_m);
    let (a_inc, lda) = self.stride();
    let incy = y.stride();
    assert_eq!(1, a_inc);
    let mut p = 0;
    let mut q = 0;
    for _ in 0 .. y_m {
      y.buf[q] = self.buf[p];
      p += a_inc + lda;
      q += incy;
    }
  }
}

impl<'a> Array2dViewMut<'a, f32> {
  pub fn matrix_add(&'a mut self, alpha: f32, x: Array2dView<'a, f32>) {
    let (x_m, x_n) = x.dim();
    let (y_m, y_n) = self.dim();
    assert_eq!(x_m, y_m);
    assert_eq!(x_n, y_n);
    let (incx, ldx) = x.stride();
    let (incy, ldy) = self.stride();
    if x_n == 1 {
      unsafe { openblas_sequential_cblas_saxpy(
          x_m as _,
          alpha,
          x.buf.as_ptr(),
          incx as _,
          self.buf.as_mut_ptr(),
          incy as _,
      ) };
    } else if x_m == 1 {
      unimplemented!();
    } else {
      unimplemented!();
    }
  }

  pub fn matrix_prod(&'a mut self, alpha: f32, a: Array2dView<'a, f32>, a_trans: Transpose, b: Array2dView<'a, f32>, b_trans: Transpose, beta: f32) {
    let (a_m, a_n) = a.dim();
    let (b_m, b_n) = b.dim();
    let (c_m, c_n) = self.dim();
    let (at_m, at_n) = match a_trans {
      Transpose::N => (a_m, a_n),
      Transpose::T => (a_n, a_m),
    };
    let (bt_m, bt_n) = match b_trans {
      Transpose::N => (b_m, b_n),
      Transpose::T => (b_n, b_m),
    };
    assert_eq!(c_m, at_m);
    assert_eq!(c_n, bt_n);
    assert_eq!(at_n, bt_m);
    let k = at_n;
    let (a_inc, lda) = a.stride();
    let (b_inc, ldb) = b.stride();
    let (c_inc, ldc) = self.stride();
    assert_eq!(1, a_inc);
    assert_eq!(1, b_inc);
    assert_eq!(1, c_inc);
    unsafe { openblas_sequential_cblas_sgemm(
        CblasOrder::ColMajor,
        match a_trans {
          Transpose::N => CblasTranspose::NoTrans,
          Transpose::T => CblasTranspose::Trans,
        },
        match b_trans {
          Transpose::N => CblasTranspose::NoTrans,
          Transpose::T => CblasTranspose::Trans,
        },
        c_m as _, c_n as _, k as _,
        alpha,
        a.buf.as_ptr(), lda as _,
        b.buf.as_ptr(), ldb as _,
        beta,
        self.buf.as_mut_ptr(), ldc as _,
    ) };
  }
}

impl<'a> Array2dViewMut<'a, f64> {
  pub fn matrix_prod(&'a mut self) {
    unimplemented!();
  }
}
<|endoftext|>


<commit_before>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

/*!
Message passing
*/

#[allow(missing_doc)];

use clone::Clone;
use kinds::Send;
use option::Option;
pub use rt::comm::SendDeferred;
use rtcomm = rt::comm;

/// A trait for things that can send multiple messages.
pub trait GenericChan<T> {
    /// Sends a message.
    fn send(&self, x: T);
}

/// Things that can send multiple messages and can detect when the receiver
/// is closed
pub trait GenericSmartChan<T> {
    /// Sends a message, or report if the receiver has closed the connection.
    fn try_send(&self, x: T) -> bool;
}

/// A trait for things that can receive multiple messages.
pub trait GenericPort<T> {
    /// Receives a message, or fails if the connection closes.
    fn recv(&self) -> T;

    /** Receives a message, or returns `none` if
    the connection is closed or closes.
    */
    fn try_recv(&self) -> Option<T>;
}

/// Ports that can `peek`
pub trait Peekable<T> {
    /// Returns true if a message is available
    fn peek(&self) -> bool;
}

pub struct PortOne<T> { x: rtcomm::PortOne<T> }
pub struct ChanOne<T> { x: rtcomm::ChanOne<T> }

pub fn oneshot<T: Send>() -> (PortOne<T>, ChanOne<T>) {
    let (p, c) = rtcomm::oneshot();
    (PortOne { x: p }, ChanOne { x: c })
}

pub struct Port<T> { x: rtcomm::Port<T> }
pub struct Chan<T> { x: rtcomm::Chan<T> }

pub fn stream<T: Send>() -> (Port<T>, Chan<T>) {
    let (p, c) = rtcomm::stream();
    (Port { x: p }, Chan { x: c })
}

impl<T: Send> ChanOne<T> {
    pub fn send(self, val: T) {
        let ChanOne { x: c } = self;
        c.send(val)
    }

    pub fn try_send(self, val: T) -> bool {
        let ChanOne { x: c } = self;
        c.try_send(val)
    }

    pub fn send_deferred(self, val: T) {
        let ChanOne { x: c } = self;
        c.send_deferred(val)
    }

    pub fn try_send_deferred(self, val: T) -> bool {
        let ChanOne{ x: c } = self;
        c.try_send_deferred(val)
    }
}

impl<T: Send> PortOne<T> {
    pub fn recv(self) -> T {
        let PortOne { x: p } = self;
        p.recv()
    }

    pub fn try_recv(self) -> Option<T> {
        let PortOne { x: p } = self;
        p.try_recv()
    }
}

impl<T: Send> Peekable<T>  for PortOne<T> {
    fn peek(&self) -> bool {
        let &PortOne { x: ref p } = self;
        p.peek()
    }
}

impl<T: Send> GenericChan<T> for Chan<T> {
    fn send(&self, val: T) {
        let &Chan { x: ref c } = self;
        c.send(val)
    }
}

impl<T: Send> GenericSmartChan<T> for Chan<T> {
    fn try_send(&self, val: T) -> bool {
        let &Chan { x: ref c } = self;
        c.try_send(val)
    }
}

impl<T: Send> SendDeferred<T> for Chan<T> {
    fn send_deferred(&self, val: T) {
        let &Chan { x: ref c } = self;
        c.send_deferred(val)
    }

    fn try_send_deferred(&self, val: T) -> bool {
        let &Chan { x: ref c } = self;
        c.try_send_deferred(val)
    }
}

impl<T: Send> GenericPort<T> for Port<T> {
    fn recv(&self) -> T {
        let &Port { x: ref p } = self;
        p.recv()
    }

    fn try_recv(&self) -> Option<T> {
        let &Port { x: ref p } = self;
        p.try_recv()
    }
}

impl<T: Send> Peekable<T> for Port<T> {
    fn peek(&self) -> bool {
        let &Port { x: ref p } = self;
        p.peek()
    }
}

pub struct SharedChan<T> { x: rtcomm::SharedChan<T> }

impl<T: Send> SharedChan<T> {
    pub fn new(c: Chan<T>) -> SharedChan<T> {
        let Chan { x: c } = c;
        SharedChan { x: rtcomm::SharedChan::new(c) }
    }
}

impl<T: Send> GenericChan<T> for SharedChan<T> {
    fn send(&self, val: T) {
        let &SharedChan { x: ref c } = self;
        c.send(val)
    }
}

impl<T: Send> GenericSmartChan<T> for SharedChan<T> {
    fn try_send(&self, val: T) -> bool {
        let &SharedChan { x: ref c } = self;
        c.try_send(val)
    }
}

impl<T: Send> SendDeferred<T> for SharedChan<T> {
    fn send_deferred(&self, val: T) {
        let &SharedChan { x: ref c } = self;
        c.send_deferred(val)
    }

    fn try_send_deferred(&self, val: T) -> bool {
        let &SharedChan { x: ref c } = self;
        c.try_send_deferred(val)
    }
}

impl<T> Clone for SharedChan<T> {
    fn clone(&self) -> SharedChan<T> {
        let &SharedChan { x: ref c } = self;
        SharedChan { x: c.clone() }
    }
}

pub struct SharedPort<T> { x: rtcomm::SharedPort<T> }

impl<T: Send> SharedPort<T> {
    pub fn new(p: Port<T>) -> SharedPort<T> {
        let Port { x: p } = p;
        SharedPort { x: rtcomm::SharedPort::new(p) }
    }
}

impl<T: Send> GenericPort<T> for SharedPort<T> {
    fn recv(&self) -> T {
        let &SharedPort { x: ref p } = self;
        p.recv()
    }

    fn try_recv(&self) -> Option<T> {
        let &SharedPort { x: ref p } = self;
        p.try_recv()
    }
}

impl<T> Clone for SharedPort<T> {
    fn clone(&self) -> SharedPort<T> {
        let &SharedPort { x: ref p } = self;
        SharedPort { x: p.clone() }
    }
}
<commit_msg>Make fields in std::comm private<commit_after>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

/*!
Message passing
*/

#[allow(missing_doc)];

use clone::Clone;
use kinds::Send;
use option::Option;
pub use rt::comm::SendDeferred;
use rtcomm = rt::comm;

/// A trait for things that can send multiple messages.
pub trait GenericChan<T> {
    /// Sends a message.
    fn send(&self, x: T);
}

/// Things that can send multiple messages and can detect when the receiver
/// is closed
pub trait GenericSmartChan<T> {
    /// Sends a message, or report if the receiver has closed the connection.
    fn try_send(&self, x: T) -> bool;
}

/// A trait for things that can receive multiple messages.
pub trait GenericPort<T> {
    /// Receives a message, or fails if the connection closes.
    fn recv(&self) -> T;

    /** Receives a message, or returns `none` if
    the connection is closed or closes.
    */
    fn try_recv(&self) -> Option<T>;
}

/// Ports that can `peek`
pub trait Peekable<T> {
    /// Returns true if a message is available
    fn peek(&self) -> bool;
}

pub struct PortOne<T> { priv x: rtcomm::PortOne<T> }
pub struct ChanOne<T> { priv x: rtcomm::ChanOne<T> }

pub fn oneshot<T: Send>() -> (PortOne<T>, ChanOne<T>) {
    let (p, c) = rtcomm::oneshot();
    (PortOne { x: p }, ChanOne { x: c })
}

pub struct Port<T> { priv x: rtcomm::Port<T> }
pub struct Chan<T> { priv x: rtcomm::Chan<T> }

pub fn stream<T: Send>() -> (Port<T>, Chan<T>) {
    let (p, c) = rtcomm::stream();
    (Port { x: p }, Chan { x: c })
}

impl<T: Send> ChanOne<T> {
    pub fn send(self, val: T) {
        let ChanOne { x: c } = self;
        c.send(val)
    }

    pub fn try_send(self, val: T) -> bool {
        let ChanOne { x: c } = self;
        c.try_send(val)
    }

    pub fn send_deferred(self, val: T) {
        let ChanOne { x: c } = self;
        c.send_deferred(val)
    }

    pub fn try_send_deferred(self, val: T) -> bool {
        let ChanOne{ x: c } = self;
        c.try_send_deferred(val)
    }
}

impl<T: Send> PortOne<T> {
    pub fn recv(self) -> T {
        let PortOne { x: p } = self;
        p.recv()
    }

    pub fn try_recv(self) -> Option<T> {
        let PortOne { x: p } = self;
        p.try_recv()
    }
}

impl<T: Send> Peekable<T>  for PortOne<T> {
    fn peek(&self) -> bool {
        let &PortOne { x: ref p } = self;
        p.peek()
    }
}

impl<T: Send> GenericChan<T> for Chan<T> {
    fn send(&self, val: T) {
        let &Chan { x: ref c } = self;
        c.send(val)
    }
}

impl<T: Send> GenericSmartChan<T> for Chan<T> {
    fn try_send(&self, val: T) -> bool {
        let &Chan { x: ref c } = self;
        c.try_send(val)
    }
}

impl<T: Send> SendDeferred<T> for Chan<T> {
    fn send_deferred(&self, val: T) {
        let &Chan { x: ref c } = self;
        c.send_deferred(val)
    }

    fn try_send_deferred(&self, val: T) -> bool {
        let &Chan { x: ref c } = self;
        c.try_send_deferred(val)
    }
}

impl<T: Send> GenericPort<T> for Port<T> {
    fn recv(&self) -> T {
        let &Port { x: ref p } = self;
        p.recv()
    }

    fn try_recv(&self) -> Option<T> {
        let &Port { x: ref p } = self;
        p.try_recv()
    }
}

impl<T: Send> Peekable<T> for Port<T> {
    fn peek(&self) -> bool {
        let &Port { x: ref p } = self;
        p.peek()
    }
}

pub struct SharedChan<T> { priv x: rtcomm::SharedChan<T> }

impl<T: Send> SharedChan<T> {
    pub fn new(c: Chan<T>) -> SharedChan<T> {
        let Chan { x: c } = c;
        SharedChan { x: rtcomm::SharedChan::new(c) }
    }
}

impl<T: Send> GenericChan<T> for SharedChan<T> {
    fn send(&self, val: T) {
        let &SharedChan { x: ref c } = self;
        c.send(val)
    }
}

impl<T: Send> GenericSmartChan<T> for SharedChan<T> {
    fn try_send(&self, val: T) -> bool {
        let &SharedChan { x: ref c } = self;
        c.try_send(val)
    }
}

impl<T: Send> SendDeferred<T> for SharedChan<T> {
    fn send_deferred(&self, val: T) {
        let &SharedChan { x: ref c } = self;
        c.send_deferred(val)
    }

    fn try_send_deferred(&self, val: T) -> bool {
        let &SharedChan { x: ref c } = self;
        c.try_send_deferred(val)
    }
}

impl<T> Clone for SharedChan<T> {
    fn clone(&self) -> SharedChan<T> {
        let &SharedChan { x: ref c } = self;
        SharedChan { x: c.clone() }
    }
}

pub struct SharedPort<T> { priv x: rtcomm::SharedPort<T> }

impl<T: Send> SharedPort<T> {
    pub fn new(p: Port<T>) -> SharedPort<T> {
        let Port { x: p } = p;
        SharedPort { x: rtcomm::SharedPort::new(p) }
    }
}

impl<T: Send> GenericPort<T> for SharedPort<T> {
    fn recv(&self) -> T {
        let &SharedPort { x: ref p } = self;
        p.recv()
    }

    fn try_recv(&self) -> Option<T> {
        let &SharedPort { x: ref p } = self;
        p.try_recv()
    }
}

impl<T> Clone for SharedPort<T> {
    fn clone(&self) -> SharedPort<T> {
        let &SharedPort { x: ref p } = self;
        SharedPort { x: p.clone() }
    }
}
<|endoftext|>


<commit_before>use anyhow::Result;
use bytes::Bytes;
use std::collections::HashMap;
use std::process;
use std::sync::atomic::AtomicBool;
use std::sync::Mutex;
use std::time::{Duration, Instant};
use tide::Request;

use async_std::sync::{channel, Arc, Receiver, Sender};
use futures::sink::SinkExt;
use futures::stream::StreamExt;
use tungstenite::Message;

use async_ctrlc::CtrlC;
use async_std::task;

#[derive(Clone, Copy)]
#[repr(u8)]
enum SystemCommand {
    WakeUp = 1,
    Disconnect = 2,
}

#[derive(Copy, Clone, Debug)]
enum ReceiverType {
    System,
    Hypercore,
    Client,
}

#[derive(Clone)]
struct State {
    system_commands: Receiver<Bytes>,
    writers: HashMap<Bytes, Sender<Bytes>>,
    readers: HashMap<Bytes, Receiver<Bytes>>,
}

#[derive(Clone)]
struct WrappedData {
    data: Bytes,
    receiver_type: ReceiverType,
    id: Option<Bytes>,
}

type WrappedBytesClosure = Box<dyn Fn(Bytes) -> WrappedData + Send + Sync>;
// type WrappedWebSocketClosure =
//     Box<dyn Fn(Result<tungstenite::Message, std::io::Error>) -> WrappedData + Send + Sync>;

async fn async_main(initial_state: State) -> Result<()> {
    let mut app = tide::with_state(initial_state);

    app.at("/ws").get(|req: Request<State>| async move {
        tide::websocket::upgrade(req, |_req, handle| async move {
            // https://docs.rs/async-tungstenite/0.10.0/async_tungstenite/struct.WebSocketStream.html
            let ws = handle.into_inner();
            let (mut ws_writer, mut ws_reader) = ws.split();
            let init_msg: Bytes = Bytes::from(ws_reader.next().await.unwrap().unwrap().into_data());
            dbg!(&init_msg);
            let hypercore_writer = _req.state().writers[&*init_msg].clone();
            ws_writer
                .send(Message::Text("reply-to-init".to_string()))
                .await
                .unwrap();
            let (client_sender, client_receiver): (Sender<Bytes>, Receiver<Bytes>) = channel(1000);
            let init_msg: Arc<Bytes> = Arc::new(init_msg.clone());
            task::spawn(async move {
                let receivers = collect_receivers(_req.state(), client_receiver.clone(), init_msg);
                let mut merged_receivers = futures::stream::select_all(receivers);
                let mut now = Instant::now();
                while let Some(wrapped_value) = merged_receivers.next().await {
                    match wrapped_value.receiver_type {
                        ReceiverType::System => {
                            if wrapped_value.data.as_ref().get(0)
                                == Some(&(SystemCommand::Disconnect as u8))
                            {
                                dbg!("got disconnect");
                                ws_writer.close().await.unwrap();
                                break;
                            }
                            // Send ping message if enough time has elapsed
                            if now.elapsed().as_secs() > 30 {
                                dbg!("sending ping");
                                ws_writer
                                    .send(tungstenite::Message::Ping(Vec::new()))
                                    .await
                                    .unwrap();
                                now = Instant::now();
                            }
                        }
                        ReceiverType::Client => {
                            dbg!("got client request");
                            ws_writer
                                .send(tungstenite::Message::Binary(
                                    wrapped_value.data.as_ref().to_vec(),
                                ))
                                .await
                                .unwrap();
                        }
                        _ => break,
                    }
                }
            });
            loop {
                let incoming_msg = ws_reader.next().await;
                let msg = incoming_msg.unwrap().unwrap();
                client_sender.send(Bytes::from(msg.into_data())).await;
            }
        })
    });

    app.listen("0.0.0.0:8080").await?;
    Ok(())
}

fn collect_receivers(
    state: &State,
    client_receiver: Receiver<Bytes>,
    init_msg: Arc<Bytes>,
) -> Vec<futures::stream::Map<Receiver<Bytes>, WrappedBytesClosure>> {
    let reader = state.readers[init_msg.as_ref()].clone();
    vec![
        state
            .system_commands
            .clone()
            .map(Box::new(|data| WrappedData {
                data,
                receiver_type: ReceiverType::System,
                id: None,
            }) as WrappedBytesClosure),
        reader.map(Box::new(move |data| WrappedData {
            data,
            receiver_type: ReceiverType::Hypercore,
            id: Some((*init_msg).clone()),
        }) as WrappedBytesClosure),
        client_receiver.map(Box::new(move |data| WrappedData {
            data,
            receiver_type: ReceiverType::Client,
            id: None,
        }) as WrappedBytesClosure),
    ]
}

fn main() -> Result<()> {
    fern::Dispatch::new()
        .format(|out, message, record| {
            out.finish(format_args!(
                "{}[{}][{}] {}",
                chrono::Local::now().format("[%Y-%m-%d %H:%M:%S]"),
                record.target(),
                record.level(),
                message
            ))
        })
        .level(log::LevelFilter::Debug)
        .chain(std::io::stdout())
        .apply()?;
    let (ping_sender, system_command_receiver) = channel(1000);
    let (demo_sender, demo_receiver) = channel(1000);
    let initial_state = State {
        system_commands: system_command_receiver,
        writers: [(Bytes::from_static("demo".as_bytes()), demo_sender)]
            .iter()
            .cloned()
            .collect(),
        readers: [(Bytes::from_static("demo".as_bytes()), demo_receiver)]
            .iter()
            .cloned()
            .collect(),
    };

    let ctrlc = CtrlC::new().expect("cannot create Ctrl+C handler?");
    let disconnect_sender = ping_sender.clone();
    let abort: Arc<Mutex<AtomicBool>> = Arc::new(Mutex::new(AtomicBool::new(false)));
    let abort_writer = abort.clone();
    task::spawn(async move {
        ctrlc.await;
        disconnect_sender
            .send(Bytes::from_static(&[SystemCommand::Disconnect as u8]))
            .await;
        *abort_writer.as_ref().lock().unwrap() = AtomicBool::new(true);
        // Wait 2s before killing
        task::sleep(Duration::from_millis(2000)).await;
        process::exit(0);
    });

    // Need to start a system executor to send the WakeUp command, we send it once per second so
    // that the listener will send a WS Ping when it wants to in a 1s delay.
    task::spawn(async move {
        loop {
            if *abort.as_ref().lock().unwrap().get_mut() {
                break;
            }
            task::sleep(Duration::from_millis(1000)).await;
            dbg!("Sending WakeUp");
            ping_sender
                .send(Bytes::from_static(&[SystemCommand::WakeUp as u8]))
                .await;
        }
    });

    futures::executor::block_on(async_main(initial_state))?;

    Ok(())
}
<commit_msg>Slightly prettier<commit_after>use anyhow::Result;
use bytes::Bytes;
use std::collections::HashMap;
use std::process;
use std::sync::atomic::AtomicBool;
use std::sync::Mutex;
use std::time::{Duration, Instant};
use tide::Request;

use async_std::sync::{channel, Arc, Receiver, Sender};
use futures::sink::SinkExt;
use futures::stream::StreamExt;
use tungstenite::Message;

use async_ctrlc::CtrlC;
use async_std::task;

#[derive(Clone, Copy)]
#[repr(u8)]
enum SystemCommand {
    WakeUp = 1,
    Disconnect = 2,
}

#[derive(Copy, Clone, Debug)]
enum ReceiverType {
    System,
    Hypercore,
    Client,
}

#[derive(Clone)]
struct State {
    system_commands: Receiver<Bytes>,
    writers: HashMap<Bytes, Sender<Bytes>>,
    readers: HashMap<Bytes, Receiver<Bytes>>,
}

#[derive(Clone)]
struct WrappedData {
    data: Bytes,
    receiver_type: ReceiverType,
    id: Option<Bytes>,
}

type WrappedBytesClosure = Box<dyn Fn(Bytes) -> WrappedData + Send + Sync>;

async fn async_main(initial_state: State) -> Result<()> {
    let mut app = tide::with_state(initial_state);

    app.at("/ws").get(|req: Request<State>| async move {
        tide::websocket::upgrade(req, |_req, handle| async move {
            // https://docs.rs/async-tungstenite/0.10.0/async_tungstenite/struct.WebSocketStream.html
            let ws = handle.into_inner();
            let (mut ws_writer, mut ws_reader) = ws.split();
            let init_msg: Bytes = Bytes::from(ws_reader.next().await.unwrap().unwrap().into_data());
            dbg!(&init_msg);
            let hypercore_writer = _req.state().writers[&*init_msg].clone();
            ws_writer
                .send(Message::Text("reply-to-init".to_string()))
                .await
                .unwrap();
            let (client_sender, client_receiver): (Sender<Bytes>, Receiver<Bytes>) = channel(1000);
            let init_msg: Arc<Bytes> = Arc::new(init_msg.clone());
            task::spawn(async move {
                let receivers = collect_receivers(_req.state(), client_receiver.clone(), init_msg);
                let mut merged_receivers = futures::stream::select_all(receivers);
                let mut now = Instant::now();
                while let Some(wrapped_value) = merged_receivers.next().await {
                    match wrapped_value.receiver_type {
                        ReceiverType::System => {
                            if wrapped_value.data.as_ref().get(0)
                                == Some(&(SystemCommand::Disconnect as u8))
                            {
                                dbg!("got disconnect");
                                ws_writer.close().await.unwrap();
                                break;
                            }
                            // Send ping message if enough time has elapsed
                            if now.elapsed().as_secs() > 30 {
                                dbg!("sending ping");
                                ws_writer
                                    .send(tungstenite::Message::Ping(Vec::new()))
                                    .await
                                    .unwrap();
                                now = Instant::now();
                            }
                        }
                        ReceiverType::Client => {
                            dbg!("got client request");
                            ws_writer
                                .send(tungstenite::Message::Binary(
                                    wrapped_value.data.as_ref().to_vec(),
                                ))
                                .await
                                .unwrap();
                        }
                        _ => break,
                    }
                }
            });
            loop {
                let incoming_msg = ws_reader.next().await;
                let msg = incoming_msg.unwrap().unwrap();
                client_sender.send(Bytes::from(msg.into_data())).await;
            }
        })
    });

    app.listen("0.0.0.0:8080").await?;
    Ok(())
}

fn collect_receivers(
    state: &State,
    client_receiver: Receiver<Bytes>,
    init_msg: Arc<Bytes>,
) -> Vec<futures::stream::Map<Receiver<Bytes>, WrappedBytesClosure>> {
    let reader = state.readers[init_msg.as_ref()].clone();
    vec![
        state
            .system_commands
            .clone()
            .map(Box::new(|data| WrappedData {
                data,
                receiver_type: ReceiverType::System,
                id: None,
            }) as WrappedBytesClosure),
        reader.map(Box::new(move |data| WrappedData {
            data,
            receiver_type: ReceiverType::Hypercore,
            id: Some((*init_msg).clone()),
        }) as WrappedBytesClosure),
        client_receiver.map(Box::new(move |data| WrappedData {
            data,
            receiver_type: ReceiverType::Client,
            id: None,
        }) as WrappedBytesClosure),
    ]
}

fn main() -> Result<()> {
    fern::Dispatch::new()
        .format(|out, message, record| {
            out.finish(format_args!(
                "{}[{}][{}] {}",
                chrono::Local::now().format("[%Y-%m-%d %H:%M:%S]"),
                record.target(),
                record.level(),
                message
            ))
        })
        .level(log::LevelFilter::Debug)
        .chain(std::io::stdout())
        .apply()?;
    let (ping_sender, system_command_receiver) = channel(1000);
    let (demo_sender, demo_receiver) = channel(1000);
    let initial_state = State {
        system_commands: system_command_receiver,
        writers: [(Bytes::from_static("demo".as_bytes()), demo_sender)]
            .iter()
            .cloned()
            .collect(),
        readers: [(Bytes::from_static("demo".as_bytes()), demo_receiver)]
            .iter()
            .cloned()
            .collect(),
    };

    // Listen to ctrlc in a separate task
    let ctrlc = CtrlC::new().expect("cannot create Ctrl+C handler?");
    let disconnect_sender = ping_sender.clone();
    let abort: Arc<Mutex<AtomicBool>> = Arc::new(Mutex::new(AtomicBool::new(false)));
    let abort_writer = abort.clone();
    task::spawn(async move {
        ctrlc.await;
        disconnect_sender
            .send(Bytes::from_static(&[SystemCommand::Disconnect as u8]))
            .await;
        *abort_writer.as_ref().lock().unwrap() = AtomicBool::new(true);
        // Wait 2s before killing, to allow time for file saving and closing sockets
        task::sleep(Duration::from_millis(2000)).await;
        process::exit(0);
    });

    // Need to start a system executor to send the WakeUp command, we send it once per second so
    // that the listener will send a WS Ping when it wants to in a 1s delay.
    task::spawn(async move {
        let mut interval = async_std::stream::interval(Duration::from_secs(1));
        while interval.next().await.is_some() && !*abort.as_ref().lock().unwrap().get_mut() {
            task::sleep(Duration::from_millis(1000)).await;
            dbg!("Sending WakeUp");
            ping_sender
                .send(Bytes::from_static(&[SystemCommand::WakeUp as u8]))
                .await;
        }
    });

    // Block server with initial state
    futures::executor::block_on(async_main(initial_state))?;

    Ok(())
}
<|endoftext|>


<commit_before>#[macro_export]
macro_rules! compile_prim(
    ($ty:ty, $type_name:ident, $make_constant:ident) => (
impl Compile for $ty {
    #[inline(always)]
    fn compile<'a>(&self, func:&UncompiledFunction<'a>) -> Value<'a> {
        unsafe {
            NativeRef::from_ptr($make_constant(func.as_ptr(), $type_name, *self) )
        }
    }
    #[inline(always)]
    fn jit_type(_:Option<$ty>) -> Type {
        unsafe {
            NativeRef::from_ptr($type_name)
        }
    }
});
    ($ty:ty, $type_name:ident, $make_constant:ident, $cast:ty) => (
impl Compile for $ty {
    #[inline(always)]
    fn compile<'a>(&self, func:&UncompiledFunction<'a>) -> Value<'a> {
        unsafe {
            NativeRef::from_ptr($make_constant(func.as_ptr(), $type_name, *self as $cast) )
        }
    }
    #[inline(always)]
    fn jit_type(_:Option<$ty>) -> Type {
        unsafe {
            NativeRef::from_ptr($type_name)
        }
    }
});
)

macro_rules! compile_func(
    (fn($($arg:ident),*) -> $ret:ty, $sig:ty) => (
    impl<$($arg:Compile,)* R:Compile> Compile for $sig {
        #[inline(always)]
        fn compile<'a>(&self, func:&'a UncompiledFunction<'a>) -> Value<'a> {
            let ptr = (self as *const $sig).to_uint().compile(func);
            func.insn_convert(&ptr, get_type::<$sig>(), false)
        }
        #[inline(always)]
        fn jit_type(_:Option<$sig>) -> Type {
            Type::create_signature(CDECL, jit!(R), [$(get_type::<$arg>()),*][mut])
        }
    })
)

macro_rules! compile_prims(
    ($(($ty:ty, $cast: ty) => ($type_name:ident, $make_constant:ident)),+) => (
        $(compile_prim!($ty, $type_name, $make_constant, $cast))+
    );
)

#[macro_export]
macro_rules! native_ref(
    ($name:ident, $field:ident, $pointer_ty:ty) => (
        #[deriving(PartialEq)]
        pub struct $name {
            $field: $pointer_ty
        }
        impl NativeRef for $name {
            #[inline(always)]
            /// Convert to a native pointer
            unsafe fn as_ptr(&self) -> $pointer_ty {
                self.$field
            }
            #[inline(always)]
            /// Convert from a native pointer
            unsafe fn from_ptr(ptr:$pointer_ty) -> $name {
                $name {
                    $field: ptr
                }
            }
        }
    );
    ($name:ident, $field:ident, $pointer_ty:ty, $lifetime:ident) => (
        #[deriving(PartialEq)]
        pub struct $name<'a> {
            $field: $pointer_ty,
            marker: $lifetime<'a>
        }
        impl<'a> NativeRef for $name<'a> {
            #[inline]
            /// Convert to a native pointer
            unsafe fn as_ptr(&self) -> $pointer_ty {
                self.$field
            }
            #[inline]
            /// Convert from a native pointer
            unsafe fn from_ptr<'a>(ptr:$pointer_ty) -> $name<'a> {
                $name {
                    $field: ptr,
                    marker: $lifetime::<'a>
                }
            }
        }
    )
)
#[macro_export]
macro_rules! jit(
    (struct {
        $($name:expr: $ty:ty),*
    }) => ({
        let structure = Type::create_struct([
            $(get_type::<$ty>()),*
        ].as_mut_slice());
        structure.set_names(&[$($name),*]);
        structure
    });
    (union {
        $($name:expr: $ty:ty),+
    }) => ({
        let structure = Type::create_union([
            $(get_type::<$ty>()),+
        ].as_mut_slice());
        structure.set_names(&[$($name),+]);
        structure
    });
    ($func:expr, return) => (
        $func.insn_default_return()
    );
    ($func:expr, return $($t:tt)+) => (
        $func.insn_return(jit!($($t)+))
    );
    ($func:expr, call($call:expr,
        $($arg:expr),+
    )) => (
        $func.insn_call(None::<String>, $call, None, [$($arg),+].as_mut_slice())
    );
    ($func:expr, jump_table($value:expr,
        $($label:ident),+
    )) => (
    let ($($label),+) = {
        $(let $label:Label = Label::new($func);)+
        $func.insn_jump_table($value, [
            $($label),+
        ].as_mut_slice());
        ($($label),+)
    });
    ($func:expr, $value:expr) => (
        $func.insn_of(&$value)
    );
    ($ty:ty) => (
        get_type::<$ty>()
    );
)<commit_msg>Add lots more macros<commit_after>#[macro_export]
macro_rules! compile_prim(
    ($ty:ty, $type_name:ident, $make_constant:ident) => (
impl Compile for $ty {
    #[inline(always)]
    fn compile<'a>(&self, func:&UncompiledFunction<'a>) -> Value<'a> {
        unsafe {
            NativeRef::from_ptr($make_constant(func.as_ptr(), $type_name, *self) )
        }
    }
    #[inline(always)]
    fn jit_type(_:Option<$ty>) -> Type {
        unsafe {
            NativeRef::from_ptr($type_name)
        }
    }
});
    ($ty:ty, $type_name:ident, $make_constant:ident, $cast:ty) => (
impl Compile for $ty {
    #[inline(always)]
    fn compile<'a>(&self, func:&UncompiledFunction<'a>) -> Value<'a> {
        unsafe {
            NativeRef::from_ptr($make_constant(func.as_ptr(), $type_name, *self as $cast) )
        }
    }
    #[inline(always)]
    fn jit_type(_:Option<$ty>) -> Type {
        unsafe {
            NativeRef::from_ptr($type_name)
        }
    }
});
)

macro_rules! compile_func(
    (fn($($arg:ident),*) -> $ret:ty, $sig:ty) => (
    impl<$($arg:Compile,)* R:Compile> Compile for $sig {
        #[inline(always)]
        fn compile<'a>(&self, func:&'a UncompiledFunction<'a>) -> Value<'a> {
            let ptr = (self as *const $sig).to_uint().compile(func);
            func.insn_convert(&ptr, get::<$sig>(), false)
        }
        #[inline(always)]
        fn jit_type(_:Option<$sig>) -> Type {
            Type::create_signature(CDECL, get::<R>(), [$(get::<$arg>()),*][mut])
        }
    })
)

macro_rules! compile_prims(
    ($(($ty:ty, $cast: ty) => ($type_name:ident, $make_constant:ident)),+) => (
        $(compile_prim!($ty, $type_name, $make_constant, $cast))+
    );
)

#[macro_export]
macro_rules! native_ref(
    ($name:ident, $field:ident, $pointer_ty:ty) => (
        #[deriving(PartialEq)]
        pub struct $name {
            $field: $pointer_ty
        }
        impl NativeRef for $name {
            #[inline(always)]
            /// Convert to a native pointer
            unsafe fn as_ptr(&self) -> $pointer_ty {
                self.$field
            }
            #[inline(always)]
            /// Convert from a native pointer
            unsafe fn from_ptr(ptr:$pointer_ty) -> $name {
                $name {
                    $field: ptr
                }
            }
        }
    );
    ($name:ident, $field:ident, $pointer_ty:ty, $lifetime:ident) => (
        #[deriving(PartialEq)]
        pub struct $name<'a> {
            $field: $pointer_ty,
            marker: $lifetime<'a>
        }
        impl<'a> NativeRef for $name<'a> {
            #[inline]
            /// Convert to a native pointer
            unsafe fn as_ptr(&self) -> $pointer_ty {
                self.$field
            }
            #[inline]
            /// Convert from a native pointer
            unsafe fn from_ptr<'a>(ptr:$pointer_ty) -> $name<'a> {
                $name {
                    $field: ptr,
                    marker: $lifetime::<'a>
                }
            }
        }
    )
)
#[macro_export]
macro_rules! jit(
    (struct {
        $($name:expr: $ty:ty),*
    }) => ({
        let structure = Type::create_struct([
            $(get::<$ty>()),*
        ].as_mut_slice());
        structure.set_names(&[$($name),*]);
        structure
    });
    (union {
        $($name:expr: $ty:ty),+
    }) => ({
        let structure = Type::create_union([
            $(get::<$ty>()),+
        ].as_mut_slice());
        structure.set_names(&[$($name),+]);
        structure
    });
    ($func:ident, return) => (
        $func.insn_default_return()
    );
    ($func:ident, return $($t:tt)+) => (
        $func.insn_return(jit!($($t)+))
    );
    ($func:ident, $var:ident += $num:expr) => (
        $func.insn_store($var, &$func.insn_add($var, $num));
    );
    ($func:ident, $var:ident -= $num:expr) => (
        $func.insn_store($var, &$func.insn_sub($var, $num));
    );
    ($func:ident, $var:ident *= $num:expr) => (
        $func.insn_store($var, &$func.insn_mul($var, $num));
    );
    ($func:ident, $var:ident /= $num:expr) => (
        $func.insn_store($var, &$func.insn_div($var, $num));
    );
    ($func:ident, $a:expr + $b:expr) => (
        $func.insn_add($a, $b)
    );
    ($func:ident, $a:expr - $b:expr) => (
        $func.insn_sub($a, $b)
    );
    ($func:ident, $a:expr * $b:expr) => (
        $func.insn_mul($a, $b)
    );
    ($func:ident, $a:expr / $b:expr) => (
        $func.insn_div($a, $b)
    );
    ($func:ident, $a:expr % $b:expr) => (
        $func.insn_rem($a, $b)
    );
    ($func:ident, $var:ident = $val:expr) => (
        $func.insn_store($var, $val);
    );
    ($func:ident, *$var:ident) => (
        $func.insn_load($var)
    );
    ($func:ident, call($call:expr,
        $($arg:expr),+
    )) => (
        $func.insn_call(None::<String>, $call, None, [$($arg),+].as_mut_slice())
    );
    ($func:ident, jump_table($value:expr,
        $($label:ident),+
    )) => (
    let ($($label),+) = {
        $(let $label:Label = Label::new($func);)+
        $func.insn_jump_table($value, [
            $($label),+
        ].as_mut_slice());
        ($($label),+)
    });
    ($func:expr, $value:expr) => (
        $func.insn_of(&$value)
    );
)<|endoftext|>


<commit_before>/// Macro that allows you to quickly define a handlebars helper by passing a
/// name and a closure. The closure arguments are mapped to helper parameters
/// one by one. Named argument with default value is also supported and mapped
/// to helper hash.
///
/// # Examples
///
/// ```rust
/// #[macro_use] extern crate handlebars;
/// #[macro_use] extern crate serde_json;
///
/// handlebars_helper!(is_above_10: |x: u64| x > 10);
/// handlebars_helper!(is_above: |x: u64, { compare: u64 = 10 }| x > compare);
///
/// # fn main() {
/// #
/// let mut handlebars = handlebars::Handlebars::new();
/// handlebars.register_helper("is-above-10", Box::new(is_above_10));
/// handlebars.register_helper("is-above", Box::new(is_above));
///
/// let result = handlebars
///     .render_template("{{#if (is-above-10 12)}}great!{{else}}okay{{/if}}", &json!({}))
///     .unwrap();
///  assert_eq!(&result, "great!");
/// let result2 = handlebars
///     .render_template("{{#if (is-above 12 compare=10)}}great!{{else}}okay{{/if}}", &json!({}))
///     .unwrap();
///  assert_eq!(&result2, "great!");
/// # }
/// ```

#[macro_export]
macro_rules! handlebars_helper {
    ($struct_name:ident: |$($name:ident: $tpe:tt),*
                          $($(,)?{$($hash_name:ident: $hash_tpe:tt=$dft_val:literal),*})?|
                            $body:expr ) => {
        #[allow(non_camel_case_types)]
        pub struct $struct_name;

        impl $crate::HelperDef for $struct_name {
            #[allow(unused_assignments)]
            fn call_inner<'reg: 'rc, 'rc>(
                &self,
                h: &$crate::Helper<'reg, 'rc>,
                _: &'reg $crate::Handlebars<'reg>,
                _: &'rc $crate::Context,
                _: &mut $crate::RenderContext<'reg, 'rc>,
            ) -> Result<Option<$crate::ScopedJson<'reg, 'rc>>, $crate::RenderError> {
                let mut param_idx = 0;

                $(
                    let $name = h.param(param_idx)
                        .map(|x| x.value())
                        .ok_or_else(|| $crate::RenderError::new(&format!(
                            "`{}` helper: Couldn't read parameter {}",
                            stringify!($struct_name), stringify!($name),
                        )))
                        .and_then(|x|
                                  handlebars_helper!(@as_json_value x, $tpe)
                                  .ok_or_else(|| $crate::RenderError::new(&format!(
                                      "`{}` helper: Couldn't convert parameter {} to type `{}`. \
                                       It's {:?} as JSON. Got these params: {:?}",
                                      stringify!($struct_name), stringify!($name), stringify!($tpe),
                                      x, h.params(),
                                  )))
                        )?;
                    param_idx += 1;
                )*

                    $(
                        $(
                            let $hash_name = h.hash_get(stringify!($hash_name))
                                .map(|x| x.value())
                                .map(|x|
                                     handlebars_helper!(@as_json_value x, $hash_tpe)
                                     .ok_or_else(|| $crate::RenderError::new(&format!(
                                         "`{}` helper: Couldn't convert hash {} to type `{}`. \
                                          It's {:?} as JSON. Got these hash: {:?}",
                                         stringify!($struct_name), stringify!($hash_name), stringify!($hash_tpe),
                                         x, h.hash(),
                                     )))
                                )
                                .unwrap_or_else(|| Ok($dft_val))?;
                        )*
                    )?

                let result = $body;
                Ok(Some($crate::ScopedJson::Derived($crate::JsonValue::from(result))))
            }
        }
    };

    (@as_json_value $x:ident, object) => { $x.as_object() };
    (@as_json_value $x:ident, array) => { $x.as_array() };
    (@as_json_value $x:ident, str) => { $x.as_str() };
    (@as_json_value $x:ident, i64) => { $x.as_i64() };
    (@as_json_value $x:ident, u64) => { $x.as_u64() };
    (@as_json_value $x:ident, f64) => { $x.as_f64() };
    (@as_json_value $x:ident, bool) => { $x.as_bool() };
    (@as_json_value $x:ident, null) => { $x.as_null() };
    (@as_json_value $x:ident, Json) => { Some($x) };
}

/// This macro is defined if the `logging` feature is set.
///
/// It ignores all logging calls inside the library.
#[cfg(feature = "no_logging")]
#[macro_export]
macro_rules! debug {
    (target: $target:expr, $($arg:tt)*) => {};
    ($($arg:tt)*) => {};
}

/// This macro is defined if the `logging` feature is not set.
///
/// It ignores all logging calls inside the library.
#[cfg(feature = "no_logging")]
#[macro_export]
macro_rules! error {
    (target: $target:expr, $($arg:tt)*) => {};
    ($($arg:tt)*) => {};
}

/// This macro is defined if the `logging` feature is not set.
///
/// It ignores all logging calls inside the library.
#[cfg(feature = "no_logging")]
#[macro_export]
macro_rules! info {
    (target: $target:expr, $($arg:tt)*) => {};
    ($($arg:tt)*) => {};
}

/// This macro is defined if the `logging` feature is not set.
///
/// It ignores all logging calls inside the library.
#[cfg(feature = "no_logging")]
#[macro_export]
macro_rules! log {
    (target: $target:expr, $($arg:tt)*) => {};
    ($($arg:tt)*) => {};
}

/// This macro is defined if the `logging` feature is not set.
///
/// It ignores all logging calls inside the library.
#[cfg(feature = "no_logging")]
#[macro_export]
macro_rules! trace {
    (target: $target:expr, $($arg:tt)*) => {};
    ($($arg:tt)*) => {};
}

/// This macro is defined if the `logging` feature is not set.
///
/// It ignores all logging calls inside the library.
#[cfg(feature = "no_logging")]
#[macro_export]
macro_rules! warn {
    (target: $target:expr, $($arg:tt)*) => {};
    ($($arg:tt)*) => {};
}
<commit_msg>(feat) added *args and **kwargs support for helper macro<commit_after>/// Macro that allows you to quickly define a handlebars helper by passing a
/// name and a closure. The closure arguments are mapped to helper parameters
/// one by one. Named argument with default value is also supported and mapped
/// to helper hash.
///
/// # Examples
///
/// ```rust
/// #[macro_use] extern crate handlebars;
/// #[macro_use] extern crate serde_json;
///
/// handlebars_helper!(is_above_10: |x: u64| x > 10);
/// handlebars_helper!(is_above: |x: u64, { compare: u64 = 10 }| x > compare);
///
/// # fn main() {
/// #
/// let mut handlebars = handlebars::Handlebars::new();
/// handlebars.register_helper("is-above-10", Box::new(is_above_10));
/// handlebars.register_helper("is-above", Box::new(is_above));
///
/// let result = handlebars
///     .render_template("{{#if (is-above-10 12)}}great!{{else}}okay{{/if}}", &json!({}))
///     .unwrap();
///  assert_eq!(&result, "great!");
/// let result2 = handlebars
///     .render_template("{{#if (is-above 12 compare=10)}}great!{{else}}okay{{/if}}", &json!({}))
///     .unwrap();
///  assert_eq!(&result2, "great!");
/// # }
/// ```

#[macro_export]
macro_rules! handlebars_helper {
    ($struct_name:ident: |$($name:ident: $tpe:tt),*
     $($(,)?{$($hash_name:ident: $hash_tpe:tt=$dft_val:literal),*})?
     $($(,)?*$args:ident)?
     $($(,)?**$kwargs:ident)?|
     $body:expr ) => {
        #[allow(non_camel_case_types)]
        pub struct $struct_name;

        impl $crate::HelperDef for $struct_name {
            #[allow(unused_assignments)]
            fn call_inner<'reg: 'rc, 'rc>(
                &self,
                h: &$crate::Helper<'reg, 'rc>,
                _: &'reg $crate::Handlebars<'reg>,
                _: &'rc $crate::Context,
                _: &mut $crate::RenderContext<'reg, 'rc>,
            ) -> Result<Option<$crate::ScopedJson<'reg, 'rc>>, $crate::RenderError> {
                let mut param_idx = 0;

                $(
                    let $name = h.param(param_idx)
                        .map(|x| x.value())
                        .ok_or_else(|| $crate::RenderError::new(&format!(
                            "`{}` helper: Couldn't read parameter {}",
                            stringify!($struct_name), stringify!($name),
                        )))
                        .and_then(|x|
                                  handlebars_helper!(@as_json_value x, $tpe)
                                  .ok_or_else(|| $crate::RenderError::new(&format!(
                                      "`{}` helper: Couldn't convert parameter {} to type `{}`. \
                                       It's {:?} as JSON. Got these params: {:?}",
                                      stringify!($struct_name), stringify!($name), stringify!($tpe),
                                      x, h.params(),
                                  )))
                        )?;
                    param_idx += 1;
                )*

                    $(
                        $(
                            let $hash_name = h.hash_get(stringify!($hash_name))
                                .map(|x| x.value())
                                .map(|x|
                                     handlebars_helper!(@as_json_value x, $hash_tpe)
                                     .ok_or_else(|| $crate::RenderError::new(&format!(
                                         "`{}` helper: Couldn't convert hash {} to type `{}`. \
                                          It's {:?} as JSON. Got these hash: {:?}",
                                         stringify!($struct_name), stringify!($hash_name), stringify!($hash_tpe),
                                         x, h.hash(),
                                     )))
                                )
                                .unwrap_or_else(|| Ok($dft_val))?;
                        )*
                    )?

                    $(let $args = h.params().iter().map(|x| x.value()).collect::<Vec<&serde_json::Value>>();)?
                    $(let $kwargs = h.hash().iter().map(|(k, v)| (k.to_owned(), v.value())).collect::<std::collections::BTreeMap<&str, &serde_json::Value>>();)?

                let result = $body;
                Ok(Some($crate::ScopedJson::Derived($crate::JsonValue::from(result))))
            }
        }
    };

    (@as_json_value $x:ident, object) => { $x.as_object() };
    (@as_json_value $x:ident, array) => { $x.as_array() };
    (@as_json_value $x:ident, str) => { $x.as_str() };
    (@as_json_value $x:ident, i64) => { $x.as_i64() };
    (@as_json_value $x:ident, u64) => { $x.as_u64() };
    (@as_json_value $x:ident, f64) => { $x.as_f64() };
    (@as_json_value $x:ident, bool) => { $x.as_bool() };
    (@as_json_value $x:ident, null) => { $x.as_null() };
    (@as_json_value $x:ident, Json) => { Some($x) };
}

/// This macro is defined if the `logging` feature is set.
///
/// It ignores all logging calls inside the library.
#[cfg(feature = "no_logging")]
#[macro_export]
macro_rules! debug {
    (target: $target:expr, $($arg:tt)*) => {};
    ($($arg:tt)*) => {};
}

/// This macro is defined if the `logging` feature is not set.
///
/// It ignores all logging calls inside the library.
#[cfg(feature = "no_logging")]
#[macro_export]
macro_rules! error {
    (target: $target:expr, $($arg:tt)*) => {};
    ($($arg:tt)*) => {};
}

/// This macro is defined if the `logging` feature is not set.
///
/// It ignores all logging calls inside the library.
#[cfg(feature = "no_logging")]
#[macro_export]
macro_rules! info {
    (target: $target:expr, $($arg:tt)*) => {};
    ($($arg:tt)*) => {};
}

/// This macro is defined if the `logging` feature is not set.
///
/// It ignores all logging calls inside the library.
#[cfg(feature = "no_logging")]
#[macro_export]
macro_rules! log {
    (target: $target:expr, $($arg:tt)*) => {};
    ($($arg:tt)*) => {};
}

/// This macro is defined if the `logging` feature is not set.
///
/// It ignores all logging calls inside the library.
#[cfg(feature = "no_logging")]
#[macro_export]
macro_rules! trace {
    (target: $target:expr, $($arg:tt)*) => {};
    ($($arg:tt)*) => {};
}

/// This macro is defined if the `logging` feature is not set.
///
/// It ignores all logging calls inside the library.
#[cfg(feature = "no_logging")]
#[macro_export]
macro_rules! warn {
    (target: $target:expr, $($arg:tt)*) => {};
    ($($arg:tt)*) => {};
}
<|endoftext|>


<commit_before>#[macro_export]
/// A convenience macro for `AttributeSet` construction. Attributes with hyphens
/// should be camel-cased.
///
/// # Example
///
/// ```rust
/// # #[macro_use] extern crate hamlet;
/// # fn main() {
/// let attrs = attr_set!(dataFoo = "bar");
/// assert_eq!(attrs.get_attr("data-foo"),
///            Some(&hamlet::Attribute::new("data-foo", "bar")));
/// # }
/// ```
macro_rules! attr_set {
    () => {
        $crate::AttributeSet(::std::borrow::Cow::Borrowed(&[]))
    };
    ($($name:ident = $value:expr),+) => {
        ($crate::AttributeSet(::std::borrow::Cow::Owned(vec![
            $($crate::Attribute::new($crate::util::identifier_to_tag_name(stringify!($name)), $value)),+
        ])))
    };
}
<commit_msg>Remove unnecessary paranthesis<commit_after>#[macro_export]
/// A convenience macro for `AttributeSet` construction. Attributes with hyphens
/// should be camel-cased.
///
/// # Example
///
/// ```rust
/// # #[macro_use] extern crate hamlet;
/// # fn main() {
/// let attrs = attr_set!(dataFoo = "bar");
/// assert_eq!(attrs.get_attr("data-foo"),
///            Some(&hamlet::Attribute::new("data-foo", "bar")));
/// # }
/// ```
macro_rules! attr_set {
    () => {
        $crate::AttributeSet(::std::borrow::Cow::Borrowed(&[]))
    };
    ($($name:ident = $value:expr),+) => {
        $crate::AttributeSet(::std::borrow::Cow::Owned(vec![
            $($crate::Attribute::new($crate::util::identifier_to_tag_name(stringify!($name)), $value)),+
        ]))
    };
}
<|endoftext|>