cord-nvim 2.0.0-beta.28

🚀 The most extensible Discord Rich Presence plugin for Neovim, powered by Rust.
#![allow(dead_code)]

use super::value::ValueRef;
use super::{
    MsgPack, ARRAY16, ARRAY32, FALSE, FIXARRAY_VALUE, FIXMAP_SIZE_MASK,
    FIXMAP_VALUE, FIXSTR_VALUE, FLOAT64, INT64, MAP16, MAP32, NIL, STR16,
    STR32, TRUE, UINT16, UINT32, UINT64, UINT8,
};
use crate::protocol::error::ProtocolError;

pub type SerializeFn<'a> =
    fn(&'a str, ValueRef<'a>, &mut SerializeState) -> crate::Result<()>;

/// Trait for serializing Rust types into MsgPack data.
///
/// This trait defines a method for converting a Rust data structure into
/// a MsgPack representation. It requires implementing the `serialize` method
/// that uses a `SerializeFn` and `SerializeState` to produce the MsgPack output.
pub trait Serialize {
    /// Serializes a Rust type into MsgPack data.
    ///
    /// # Arguments
    ///
    /// * `f` - A function for serializing key-value pairs.
    /// * `state` - A mutable reference to the serialization state.
    ///
    /// # Returns
    ///
    /// A result indicating success or failure of the serialization process.
    fn serialize<'a>(
        &'a self,
        f: SerializeFn<'a>,
        state: &mut SerializeState,
    ) -> crate::Result<()>;
}

pub trait SerializeObj: Serialize + std::fmt::Debug {}
impl<T: Serialize + std::fmt::Debug> SerializeObj for T {}

pub struct SerializeState {
    buf: Vec<u8>,
    stack: Vec<usize>,
}

impl SerializeState {
    fn new() -> Self {
        Self {
            buf: Vec::with_capacity(512),
            stack: Vec::with_capacity(8),
        }
    }

    fn push_scope(&mut self) {
        self.stack.push(self.buf.len());
    }

    fn write_u8(&mut self, v: u8) {
        self.buf.push(v);
    }

    fn write_u16(&mut self, v: u16) {
        self.buf.extend_from_slice(&v.to_be_bytes());
    }

    fn write_u32(&mut self, v: u32) {
        self.buf.extend_from_slice(&v.to_be_bytes());
    }

    fn write_i64(&mut self, v: i64) {
        self.buf.extend_from_slice(&v.to_be_bytes());
    }

    fn write_f64(&mut self, v: f64) {
        self.buf.extend_from_slice(&v.to_be_bytes());
    }

    fn write_u64(&mut self, v: u64) {
        self.buf.extend_from_slice(&v.to_be_bytes());
    }

    fn write_bytes(&mut self, bytes: &[u8]) {
        self.buf.extend_from_slice(bytes);
    }
}

impl std::fmt::Debug for ValueRef<'_> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            ValueRef::Str(s) => write!(f, "Str({:?})", s),
            ValueRef::String(s) => write!(f, "String({:?})", s),
            ValueRef::Float(n) => write!(f, "Number({:?})", n),
            ValueRef::Integer(i) => write!(f, "Integer({:?})", i),
            ValueRef::UInteger(u) => write!(f, "UInteger({:?})", u),
            ValueRef::Boolean(b) => write!(f, "Boolean({:?})", b),
            ValueRef::Array(arr) => f.debug_tuple("Array").field(arr).finish(),
            ValueRef::Object(_) => write!(f, "Object(function)"),
            ValueRef::Map(map) => f.debug_tuple("Map").field(map).finish(),
            ValueRef::Nil => write!(f, "Nil"),
        }
    }
}

impl MsgPack {
    pub fn serialize(value: &dyn Serialize) -> crate::Result<Vec<u8>> {
        let mut state = SerializeState::new();
        state.write_u8(FIXMAP_VALUE | 2);

        fn serialize_adapter(
            key: &str,
            value: ValueRef,
            state: &mut SerializeState,
        ) -> crate::Result<()> {
            MsgPack::write_kv(key, &value, state)
        }

        value.serialize(serialize_adapter, &mut state)?;
        Ok(state.buf)
    }

    fn write_str(s: &str, state: &mut SerializeState) -> crate::Result<()> {
        let bytes = s.as_bytes();
        let len = bytes.len();
        match len {
            0..=31 => {
                state.write_u8(FIXSTR_VALUE | (len as u8));
            }
            32..=65535 => {
                state.write_u8(STR16);
                state.write_u16(len as u16);
            }
            _ => {
                if len > u32::MAX as usize {
                    return Err(ProtocolError::InvalidLength.into());
                }
                state.write_u8(STR32);
                state.write_u32(len as u32);
            }
        }
        state.write_bytes(bytes);
        Ok(())
    }

    fn write_value(
        value: &ValueRef,
        state: &mut SerializeState,
    ) -> crate::Result<()> {
        match value {
            ValueRef::Nil => {
                state.write_u8(NIL);
                Ok(())
            }
            ValueRef::Str(s) => Self::write_str(s, state),
            ValueRef::String(s) => Self::write_str(s, state),
            ValueRef::Float(n) => {
                state.write_u8(FLOAT64);
                state.write_f64(*n);
                Ok(())
            }
            ValueRef::Integer(n) => {
                if *n >= -(1 << 5) && *n < (1 << 7) {
                    state.write_u8(*n as u8);
                } else {
                    state.write_u8(INT64);
                    state.write_i64(*n);
                }
                Ok(())
            }
            ValueRef::UInteger(n) => {
                if *n < (1 << 8) {
                    state.write_u8(UINT8);
                    state.write_u8(*n as u8);
                } else if *n < (1 << 16) {
                    state.write_u8(UINT16);
                    state.write_u16(*n as u16);
                } else if *n < (1 << 32) {
                    state.write_u8(UINT32);
                    state.write_u32(*n as u32);
                } else {
                    state.write_u8(UINT64);
                    state.write_u64(*n);
                }
                Ok(())
            }
            ValueRef::Boolean(b) => {
                state.write_u8(if *b { TRUE } else { FALSE });
                Ok(())
            }
            ValueRef::Array(arr) => {
                let len = arr.len();
                match len {
                    0..=15 => {
                        state.write_u8(FIXARRAY_VALUE | (len as u8));
                    }
                    16..=65535 => {
                        state.write_u8(ARRAY16);
                        state.write_u16(len as u16);
                    }
                    _ => {
                        if len > u32::MAX as usize {
                            return Err(ProtocolError::InvalidLength.into());
                        }
                        state.write_u8(ARRAY32);
                        state.write_u32(len as u32);
                    }
                }
                for item in arr {
                    Self::write_value(item, state)?;
                }
                Ok(())
            }
            ValueRef::Object(obj) => {
                state.push_scope();
                obj.serialize(|k, v, s| Self::write_kv(k, &v, s), state)?;
                Ok(())
            }
            ValueRef::Map(map) => {
                let len = map.len();
                match len {
                    0..=15 => {
                        state.write_u8(FIXMAP_VALUE | (len as u8));
                    }
                    16..=65535 => {
                        state.write_u8(MAP16);
                        state.write_u16(len as u16);
                    }
                    _ => {
                        if len > u32::MAX as usize {
                            return Err(ProtocolError::InvalidLength.into());
                        }
                        state.write_u8(MAP32);
                        state.write_u32(len as u32);
                    }
                }
                for (k, v) in map {
                    Self::write_str(k, state)?;
                    Self::write_value(v, state)?;
                }
                Ok(())
            }
        }
    }

    fn write_kv(
        key: &str,
        value: &ValueRef,
        state: &mut SerializeState,
    ) -> crate::Result<()> {
        Self::write_str(key, state)?;
        Self::write_value(value, state)
    }
}