nui 0.0.1

Experimental neovim RPC for UI clients
Documentation
use rmpv::Value;

#[non_exhaustive]
struct MessageType;

impl MessageType {
    pub const REQUEST: u64 = 0;
    pub const RESPONSE: u64 = 1;
    pub const NOTIFICATION: u64 = 2;
}

#[derive(Debug, PartialEq)]
pub enum Message {
    Request {
        id: u64,
        method: String,
        params: Value,
    },
    Response {
        id: u64,
        error: Value,
        result: Value,
    },
    Notification {
        method: String,
        params: Value,
    },
}

impl<'de> serde::Deserialize<'de> for Message {
    fn deserialize<D>(d: D) -> Result<Self, D::Error>
    where
        D: serde::Deserializer<'de>,
    {
        let value = Value::deserialize(d)?;

        match value.as_array() {
            Some(arr) => match arr[0].as_u64().unwrap() {
                MessageType::REQUEST => Ok(Self::Request {
                    id: arr[1].as_u64().unwrap(),
                    method: arr[2].as_str().unwrap().to_string(),
                    params: arr[3].to_owned(),
                }),
                MessageType::RESPONSE => Ok(Self::Response {
                    id: arr[1].as_u64().unwrap(),
                    error: arr[2].to_owned(),
                    result: arr[3].to_owned(),
                }),
                MessageType::NOTIFICATION => Ok(Self::Notification {
                    method: arr[1].as_str().unwrap().to_string(),
                    params: arr[2].to_owned(),
                }),
                msg_type => Err(serde::de::Error::custom(format!(
                    "Invalid message type: {}",
                    msg_type
                ))),
            },
            None => Err(serde::de::Error::custom("Value is not array")),
        }
    }
}

impl serde::Serialize for Message {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: serde::Serializer,
    {
        match self {
            Message::Request { id, method, params } => Value::from(vec![
                Value::from(MessageType::REQUEST),
                Value::from(*id),
                Value::from(method.to_owned()),
                Value::from(params.to_owned()),
            ]),
            Message::Response { id, error, result } => Value::from(vec![
                Value::from(MessageType::RESPONSE),
                Value::from(id.to_owned()),
                error.to_owned(),
                result.to_owned(),
            ]),
            Message::Notification { method, params } => Value::from(vec![
                Value::from(MessageType::NOTIFICATION),
                Value::from(method.to_owned()),
                Value::from(params.to_owned()),
            ]),
        }
        .serialize(serializer)
    }
}