three_em_cli 0.2.0

A blazingly fast, secure, reliable, multi-language execution machine for Smart Contracts.
use crate::utils::{parse_node_ip, usize_to_u8_array};
use serde::{Deserialize, Serialize};
use std::io::{Read, Write};
use std::net::TcpStream;

#[derive(Serialize, Deserialize)]
pub struct Node {
  pub ip: String,
  pub port: i32,
}

impl Node {
  pub fn new(host: &str, port: i32) -> Node {
    Node {
      ip: String::from(host),
      port,
    }
  }

  pub fn is_not(&self, node: &Node) -> bool {
    let current_node = parse_node_ip(self);
    let diff_node = parse_node_ip(node);
    current_node != diff_node
  }

  #[allow(clippy::inherent_to_string)]
  pub fn to_string(&self) -> String {
    parse_node_ip(self)
  }
}

// TODO: Implement length approach
pub async fn send_message(
  message: String,
  node: &Node,
) -> Result<Vec<u8>, &str> {
  let result = match TcpStream::connect(node.to_string()) {
    Ok(mut stream) => {
      let future = tokio::task::spawn(async move {
        let message_as_bytes = message.as_bytes();
        let message_len = message_as_bytes.len();
        let message_length = &usize_to_u8_array(message_len.to_owned() as u32);
        let magic_number = 0x69_u8;

        let mut final_message: Vec<u8> = Vec::new();
        final_message.extend_from_slice(message_length);
        final_message.extend_from_slice(message_as_bytes);
        final_message.extend_from_slice(&[magic_number]);

        let as_bytes = &final_message[..];
        stream.write_all(as_bytes).unwrap();
        let mut result: Vec<u8> = Vec::new();

        loop {
          let mut buf = [0; 1024];
          let n = stream.read(&mut buf[..]).unwrap();

          if n == 0 {
            break;
          }

          result.extend_from_slice(&buf);
        }

        result
      });

      let result = future.await;
      Ok(result.unwrap())
    }
    Err(_) => Err("Could not send message"),
  };

  result
}

#[cfg(test)]
mod tests {
  use crate::node::Node;

  #[tokio::test]
  async fn test_is_not() {
    let node1 = Node::new("127.0.0.1", 9999);
    let node2 = Node::new("127.0.0.1", 9898);
    assert!(node1.is_not(&node2));

    let node1 = Node::new("127.0.0.1", 9999);
    let node2 = Node::new("127.0.0.1", 9999);
    assert!(!(node1.is_not(&node2)));
  }

  #[tokio::test]
  async fn test_to_string() {
    let node1 = Node::new("127.0.0.1", 9999);
    assert_eq!(node1.to_string(), "127.0.0.1:9999");
  }
}