new-home-proxy 0.1.2

This is a part of the New Home IoT System. It is used to make the core available in the www.
use std::sync::atomic::{AtomicUsize, Ordering};

use actix::Message;
use serde::de::DeserializeOwned;
use serde::{Deserialize, Serialize};
use serde_json::Value;

use crate::proxy_error::ProxyResult;

static COUNT: AtomicUsize = AtomicUsize::new(1);

/// A serde (serializable/deserializable) message which contains a message id for resolving the
/// correct message pair
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct WrappedMessage<M>
where
    M: Clone,
{
    pub id: usize,
    pub message: M,
}

impl<M> WrappedMessage<M>
where
    M: Clone + Serialize + DeserializeOwned,
{
    /// Creates a new WrappedMessage from the given message and a newly generated message id
    pub fn new(message: M) -> Self {
        Self {
            message,
            id: COUNT.fetch_add(1, Ordering::Relaxed),
        }
    }

    /// Creates a new WrappedMessage with the given message and the message id of the already existing
    /// message
    pub fn answer<A>(&self, message: A) -> WrappedMessage<A>
    where
        A: Clone + Serialize + DeserializeOwned,
    {
        WrappedMessage {
            message,
            id: self.id,
        }
    }

    /// Converts the inner message into a more general `serde_json::Value`
    pub fn into_value(self) -> WrappedMessage<Value> {
        WrappedMessage::<Value>::identified(serde_json::to_value(self.message).unwrap(), self.id)
    }

    /// Converts the inner message into the specified message type
    pub fn into_specific<S>(self) -> ProxyResult<WrappedMessage<S>>
    where
        S: Clone + Serialize + DeserializeOwned,
    {
        let id = self.id;
        let message: S = serde_json::from_value::<S>(self.into_value().message)?;

        Ok(WrappedMessage::<S>::identified(message, id))
    }

    /// Returns the inner message object
    pub fn into_inner(self) -> M {
        self.message
    }

    /// Creates a new WrappedMessage with a given message and message id
    fn identified(message: M, id: usize) -> WrappedMessage<M> {
        Self { message, id }
    }
}

impl Message for WrappedMessage<ProxyRequest> {
    type Result = ();
}

impl Message for WrappedMessage<ProxyResponse> {
    type Result = ();
}

#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct ProxyRequest {
    pub method: String,
    pub url: String,
    pub origin: String,
    pub request_body: Value,
    pub username: String,
    pub password: String,
}

/// This struct contains the fields required from the client
#[derive(Serialize, Deserialize, Debug, Clone, Default)]
pub struct ProxyResponse {
    /// Contains a json value
    /// This value might be a `Value::String` if the content_type is not "application/json"
    pub response: Value,

    /// Contains the content for the `Content-Type` header
    /// if "application/json" the response is send as a true JSON object
    pub content_type: String,
}

pub struct WebsocketCommand(pub WebsocketSignal);

impl Message for WebsocketCommand {
    type Result = ();
}

pub enum WebsocketSignal {
    Close,
    CheckPing,
    Ping,
}