use std::io::Result;
use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt};
pub trait ReadFrom: Sized {
fn read_from<T: AsyncRead + Unpin>(
source: &mut T,
) -> impl std::future::Future<Output = Result<Self>>;
}
pub trait WriteTo {
fn write_to<T: AsyncWrite + Unpin>(
&self,
sink: &mut T,
) -> impl std::future::Future<Output = Result<()>>;
}
impl WriteTo for bool {
async fn write_to<T: AsyncWrite + Unpin>(&self, sink: &mut T) -> Result<()> {
let byte: u8 = match self {
false => 0xc2,
true => 0xc3,
};
sink.write_u8(byte).await
}
}
#[derive(Clone, Debug, PartialEq)]
pub enum Int {
U8(u8),
U16(u16),
U32(u32),
U64(u64),
I8(i8),
I16(i16),
I32(i32),
I64(i64),
}
impl Int {
pub fn as_u64(&self) -> Option<u64> {
use Int::*;
match self {
U8(i) => Some((*i).into()),
U16(i) => Some((*i).into()),
U32(i) => Some((*i).into()),
U64(i) => Some(*i),
I8(i) => (*i >= 0).then(|| (*i).try_into().unwrap()),
I16(i) => (*i >= 0).then(|| (*i).try_into().unwrap()),
I32(i) => (*i >= 0).then(|| (*i).try_into().unwrap()),
I64(i) => (*i >= 0).then(|| (*i).try_into().unwrap()),
}
}
}
impl WriteTo for Int {
async fn write_to<T: AsyncWrite + Unpin>(&self, sink: &mut T) -> Result<()> {
match self {
Int::U8(i) => {
if *i >= 0b10000000 {
sink.write_u8(0xcc).await?;
}
sink.write_u8(*i).await
}
Int::U16(i) => {
sink.write_u8(0xcd).await?;
sink.write_u16(*i).await
}
Int::U32(i) => {
sink.write_u8(0xce).await?;
sink.write_u32(*i).await
}
Int::U64(i) => {
sink.write_u8(0xcf).await?;
sink.write_u64(*i).await
}
Int::I8(i) => {
if *i > 0 || *i < -0b00100000 {
sink.write_u8(0xd0).await?;
sink.write_i8(*i).await
} else {
let i: u8 = -*i as u8;
sink.write_u8(0b11100000 | i).await
}
}
Int::I16(i) => {
sink.write_u8(0xd1).await?;
sink.write_i16(*i).await
}
Int::I32(i) => {
sink.write_u8(0xd2).await?;
sink.write_i32(*i).await
}
Int::I64(i) => {
sink.write_u8(0xd3).await?;
sink.write_i64(*i).await
}
}
}
}
#[derive(Clone, Debug, PartialEq)]
pub enum Float {
F32(f32),
F64(f64),
}
impl WriteTo for Float {
async fn write_to<T: AsyncWrite + Unpin>(&self, sink: &mut T) -> Result<()> {
match self {
Float::F32(f) => {
sink.write_u8(0xca).await?;
sink.write_f32(*f).await?;
}
Float::F64(f) => {
sink.write_u8(0xcb).await?;
sink.write_f64(*f).await?;
}
}
Ok(())
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct Ext {
pub r#type: u8,
pub data: Vec<u8>,
}
impl WriteTo for Ext {
async fn write_to<T: AsyncWrite + Unpin>(&self, sink: &mut T) -> Result<()> {
let len = self.data.len();
match len {
1 => sink.write_u8(0xd4).await?,
2 => sink.write_u8(0xd5).await?,
4 => sink.write_u8(0xd6).await?,
8 => sink.write_u8(0xd7).await?,
16 => sink.write_u8(0xd8).await?,
i if i <= u8::MAX as usize => {
sink.write_u8(0xc7).await?;
sink.write_u8(i.try_into().unwrap()).await?;
}
i if i <= u16::MAX as usize => {
sink.write_u8(0xc8).await?;
sink.write_u16(i.try_into().unwrap()).await?;
}
i if i <= u32::MAX as usize => {
sink.write_u8(0xc9).await?;
sink.write_u32(i.try_into().unwrap()).await?;
}
_ => panic!(),
}
sink.write_u8(self.r#type).await?;
sink.write_all(self.data.as_slice()).await
}
}
#[derive(Clone, Debug, PartialEq)]
pub enum Value {
Nil,
Bool(bool),
Int(Int),
Float(Float),
Str(String),
Bin(Vec<u8>),
Arr(Vec<Value>),
Map(Vec<(Value, Value)>),
Ext(Ext),
}
impl From<()> for Value {
fn from(_: ()) -> Self {
Value::Nil
}
}
impl From<bool> for Value {
fn from(value: bool) -> Self {
Value::Bool(value)
}
}
impl From<&str> for Value {
fn from(value: &str) -> Self {
Self::Str(value.into())
}
}
impl From<String> for Value {
fn from(value: String) -> Self {
Self::Str(value.into())
}
}
impl From<Vec<(Value, Value)>> for Value {
fn from(value: Vec<(Value, Value)>) -> Self {
Self::Map(value)
}
}
impl<A: Into<Int>> From<A> for Value {
fn from(value: A) -> Self {
Value::Int(value.into())
}
}
impl From<u8> for Int {
fn from(value: u8) -> Self {
Int::U8(value)
}
}
impl From<i8> for Int {
fn from(value: i8) -> Self {
if value >= 0 {
return u8::try_from(value).unwrap().into();
}
Int::I8(value)
}
}
impl From<u16> for Int {
fn from(value: u16) -> Self {
if let Ok(value) = u8::try_from(value) {
return Int::U8(value);
}
Int::U16(value)
}
}
impl From<i16> for Int {
fn from(value: i16) -> Self {
if value >= 0 {
return u16::try_from(value).unwrap().into();
}
if let Ok(value) = i8::try_from(value) {
return Int::I8(value);
}
Int::I16(value)
}
}
impl From<u32> for Int {
fn from(value: u32) -> Self {
if let Ok(value) = u8::try_from(value) {
return Int::U8(value);
}
if let Ok(value) = u16::try_from(value) {
return Int::U16(value);
}
Int::U32(value)
}
}
impl From<i32> for Int {
fn from(value: i32) -> Self {
if value >= 0 {
return u32::try_from(value).unwrap().into();
}
if let Ok(value) = i8::try_from(value) {
return Int::I8(value);
}
if let Ok(value) = i16::try_from(value) {
return Int::I16(value);
}
Int::I32(value)
}
}
impl From<u64> for Int {
fn from(value: u64) -> Self {
if let Ok(value) = u8::try_from(value) {
return Int::U8(value);
}
if let Ok(value) = u16::try_from(value) {
return Int::U16(value);
}
if let Ok(value) = u32::try_from(value) {
return Int::U32(value);
}
Int::U64(value)
}
}
impl From<i64> for Int {
fn from(value: i64) -> Self {
if value >= 0 {
return u64::try_from(value).unwrap().into();
}
if let Ok(value) = i8::try_from(value) {
return Int::I8(value);
}
if let Ok(value) = i16::try_from(value) {
return Int::I16(value);
}
if let Ok(value) = i32::try_from(value) {
return Int::I32(value);
}
Int::I64(value)
}
}
impl ReadFrom for Value {
async fn read_from<T: AsyncRead + Unpin>(source: &mut T) -> Result<Self> {
let leading = source.read_u8().await?;
Ok(match leading {
0xc0 => Value::Nil,
0xc2 => Value::Bool(false),
0xc3 => Value::Bool(true),
i if i < 0b1000000 => Value::Int(Int::U8(i)),
i if i >= 0b11100000 => Value::Int(Int::I8(-((i - 0b11100000) as i8))),
0xcc => Value::Int(Int::U8(source.read_u8().await?)),
0xcd => Value::Int(Int::U16(source.read_u16().await?)),
0xce => Value::Int(Int::U32(source.read_u32().await?)),
0xcf => Value::Int(Int::U64(source.read_u64().await?)),
0xd0 => Value::Int(Int::I8(source.read_i8().await?)),
0xd1 => Value::Int(Int::I16(source.read_i16().await?)),
0xd2 => Value::Int(Int::I32(source.read_i32().await?)),
0xd3 => Value::Int(Int::I64(source.read_i64().await?)),
0xca => Value::Float(Float::F32(source.read_f32().await?)),
0xcb => Value::Float(Float::F64(source.read_f64().await?)),
i if i & 0b11100000 == 0b10100000 => {
let len: usize = (i & 0b00011111).into();
let mut bytes: Vec<u8> = vec![0u8; len];
source.read_exact(&mut bytes).await?;
Value::Str(String::from_utf8(bytes).unwrap())
}
i @ (0xd9 | 0xda | 0xdb) => {
let len: usize = match i {
0xd9 => source.read_u8().await?.into(),
0xda => source.read_u16().await?.into(),
0xdb => source.read_u32().await?.try_into().unwrap(),
_ => panic!(),
};
let mut bytes: Vec<u8> = vec![0u8; len];
source.read_exact(&mut bytes).await?;
Value::Str(String::from_utf8(bytes).unwrap())
}
i @ (0xc4 | 0xc5 | 0xc6) => {
let len: usize = match i {
0xc4 => source.read_u8().await?.into(),
0xc5 => source.read_u16().await?.into(),
0xc6 => source.read_u32().await?.try_into().unwrap(),
_ => panic!(),
};
let mut bytes: Vec<u8> = vec![0u8; len];
source.read_exact(&mut bytes).await?;
Value::Bin(bytes)
}
i if i & 0b11110000 == 0b10010000 => {
let len: usize = (i & 0b00001111).into();
let mut arr: Vec<Value> = vec![];
for _ in 0..len {
arr.push(Box::pin(Value::read_from(&mut *source)).await?);
}
Value::Arr(arr)
}
i @ (0xdc | 0xdd) => {
let len: usize = match i {
0xdc => source.read_u16().await?.into(),
0xdd => source.read_u32().await?.try_into().unwrap(),
_ => panic!(),
};
let mut arr: Vec<Value> = vec![];
for _ in 0..len {
arr.push(Box::pin(Value::read_from(&mut *source)).await?);
}
Value::Arr(arr)
}
i if (i & 0b11110000) == 0b10000000 => {
let len: usize = (i & 0b00001111).into();
let mut map = vec![];
for _ in 0..len {
let key: Value = Box::pin(Value::read_from(&mut *source)).await?;
let value: Value = Box::pin(Value::read_from(&mut *source)).await?;
map.push((key, value));
}
Value::Map(map)
}
i @ (0xde | 0xdf) => {
let len: usize = match i {
0xde => source.read_u16().await?.into(),
0xdf => source.read_u32().await?.try_into().unwrap(),
_ => panic!(),
};
let mut map = vec![];
for _ in 0..len {
let key: Value = Box::pin(Value::read_from(&mut *source)).await?;
let value: Value = Box::pin(Value::read_from(&mut *source)).await?;
map.push((key, value));
}
Value::Map(map)
}
i @ (0xd4 | 0xd5 | 0xd6 | 0xd7 | 0xd8 | 0xc7 | 0xc8 | 0xc9) => {
let len: usize = match i {
0xd4 => 1,
0xd5 => 2,
0xd6 => 4,
0xd7 => 8,
0xd8 => 16,
0xc7 => source.read_u8().await?.into(),
0xc8 => source.read_u16().await?.into(),
0xc9 => source.read_u32().await?.try_into().unwrap(),
_ => panic!(),
};
let r#type = source.read_u8().await?;
let mut data = vec![0u8; len];
source.read_exact(&mut data).await?;
Value::Ext(Ext { r#type, data })
}
_ => panic!(),
})
}
}
impl WriteTo for Value {
async fn write_to<T: AsyncWrite + Unpin>(&self, sink: &mut T) -> Result<()> {
match self {
Value::Nil => sink.write_u8(0xc0).await,
Value::Bool(b) => b.write_to(sink).await,
Value::Int(i) => i.write_to(sink).await,
Value::Float(f) => f.write_to(sink).await,
Value::Str(bytes) => {
let len = bytes.len();
if len < 0b100000 {
let len: u8 = len.try_into().unwrap();
sink.write_u8(0b10100000 | len).await?;
} else if let Ok(len) = TryInto::<u8>::try_into(len) {
sink.write_u8(0xd9).await?;
sink.write_u8(len).await?;
} else if let Ok(len) = TryInto::<u16>::try_into(len) {
sink.write_u8(0xda).await?;
sink.write_u16(len).await?;
} else if let Ok(len) = TryInto::<u32>::try_into(len) {
sink.write_u8(0xdb).await?;
sink.write_u32(len).await?;
} else {
panic!()
}
sink.write_all(bytes.as_bytes()).await
}
Value::Bin(bytes) => {
let len = bytes.len();
if let Ok(len) = TryInto::<u8>::try_into(len) {
sink.write_u8(0xc4).await?;
sink.write_u8(len).await?;
} else if let Ok(len) = TryInto::<u16>::try_into(len) {
sink.write_u8(0xc5).await?;
sink.write_u16(len).await?;
} else if let Ok(len) = TryInto::<u32>::try_into(len) {
sink.write_u8(0xc6).await?;
sink.write_u32(len).await?;
}
sink.write_all(bytes).await
}
Value::Arr(arr) => {
let len = arr.len();
if len < 0b10000 {
let len: u8 = len.try_into().unwrap();
sink.write_u8(0b10010000 | len).await?;
} else if let Ok(len) = TryInto::<u16>::try_into(len) {
sink.write_u8(0xdc).await?;
sink.write_u16(len).await?;
} else if let Ok(len) = TryInto::<u32>::try_into(len) {
sink.write_u8(0xdd).await?;
sink.write_u32(len).await?;
} else {
panic!();
}
for v in arr {
Box::pin(v.write_to(&mut *sink)).await?;
}
Ok(())
}
Value::Map(map) => {
let len = map.len();
if len < 0b10000 {
let len: u8 = len.try_into().unwrap();
sink.write_u8(0b10000000 | len).await?;
} else if let Ok(len) = TryInto::<u16>::try_into(len) {
sink.write_u8(0xde).await?;
sink.write_u16(len).await?;
} else if let Ok(len) = TryInto::<u32>::try_into(len) {
sink.write_u8(0xdf).await?;
sink.write_u32(len).await?;
} else {
panic!();
}
for (k, v) in map {
Box::pin(k.write_to(&mut *sink)).await?;
Box::pin(v.write_to(&mut *sink)).await?;
}
Ok(())
}
Value::Ext(e) => e.write_to(sink).await,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
async fn assert_read_write(value: Value, bytes: &[u8]) {
let mut candidate_bytes: Vec<u8> = vec![];
value.write_to(&mut candidate_bytes).await.unwrap();
assert_eq!(bytes, candidate_bytes);
let mut cursor = bytes;
let candidate_value = Value::read_from(&mut cursor).await.unwrap();
assert_eq!(value, candidate_value)
}
#[tokio::test]
async fn nil_read_write() {
assert_read_write(Value::Nil, &[0xc0]).await;
}
#[tokio::test]
async fn bool_read_write() {
assert_read_write(Value::Bool(false), &[0xc2]).await;
assert_read_write(Value::Bool(true), &[0xc3]).await;
}
#[tokio::test]
async fn int_read_write() {
assert_read_write(Value::Int(Int::U8(0)), &[0]).await;
assert_read_write(Value::Int(Int::U8(5)), &[5]).await;
assert_read_write(Value::Int(Int::U8(230)), &[0xcc, 230]).await;
assert_read_write(Value::Int(Int::U16(256)), &[0xcd, 1, 0]).await;
assert_read_write(Value::Int(Int::U32(65_536)), &[0xce, 0, 1, 0, 0]).await;
assert_read_write(
Value::Int(Int::U64(4_294_967_296)),
&[0xcf, 0, 0, 0, 1, 0, 0, 0, 0],
)
.await;
assert_read_write(Value::Int(Int::I8(-6)), &[0b11100000 + 6]).await;
assert_read_write(Value::Int(Int::I8(-100)), &[0xd0, u8::MAX - 100 + 1]).await;
assert_read_write(
Value::Int(Int::I16(-100)),
&[0xd1, u8::MAX, u8::MAX - 100 + 1],
)
.await;
assert_read_write(
Value::Int(Int::I32(-100)),
&[0xd2, u8::MAX, u8::MAX, u8::MAX, u8::MAX - 100 + 1],
)
.await;
assert_read_write(
Value::Int(Int::I64(-100)),
&[
0xd3,
u8::MAX,
u8::MAX,
u8::MAX,
u8::MAX,
u8::MAX,
u8::MAX,
u8::MAX,
u8::MAX - 100 + 1,
],
)
.await;
}
#[tokio::test]
async fn float_read_write() {
assert_read_write(
Value::Float(Float::F32(0.3)),
&[0xca, 0x3e, 0x99, 0x99, 0x9a],
)
.await;
assert_read_write(
Value::Float(Float::F64(0.3)),
&[0xcb, 0x3f, 0xd3, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33],
)
.await;
}
#[tokio::test]
async fn str_bin_read_write() {
let bytes: Vec<u8> = b"Oh hello there, isn't this an interesting test".into();
let len: u8 = bytes.len().try_into().unwrap();
assert_read_write(
Value::Str(String::from_utf8(bytes.clone()).unwrap()),
&[[0xd9, len].as_slice(), bytes.as_slice()].concat(),
)
.await;
assert_read_write(
Value::Bin(bytes.clone()),
&[[0xc4, len].as_slice(), bytes.as_slice()].concat(),
)
.await;
}
#[tokio::test]
async fn arr_read_write() {
assert_read_write(
Value::Arr(vec![Value::Int(Int::U8(1)), Value::Int(Int::U8(2))]),
&[0b10010000 | 2, 1, 2],
)
.await;
}
#[tokio::test]
async fn map_read_write() {
assert_read_write(
Value::Map(vec![
(Value::Int(Int::U8(1)), Value::Int(Int::U8(10))),
(Value::Int(Int::U8(2)), Value::Int(Int::U8(20))),
]),
&[0b10000000 | 2, 1, 10, 2, 20],
)
.await;
assert_read_write(Value::Map(vec![]), &[128]).await;
}
#[tokio::test]
async fn ext_read_write() {
assert_read_write(
Value::Ext(Ext {
r#type: 0xa8,
data: b"Hi there".into(),
}),
&[[0xd7, 0xa8].as_slice(), b"Hi there".as_slice()].concat(),
)
.await;
}
#[tokio::test]
async fn compound_read_write() {
assert_read_write(
Value::Arr(
[
Value::Int(Int::U8(0)),
Value::Int(Int::U32(0xf264e4f)),
Value::Str("nvim_subscribe".into()),
Value::Arr([Value::Str("rsnote_open_window".into())].into()),
]
.into(),
),
&[
148, 0, 206, 15, 38, 78, 79, 174, 110, 118, 105, 109, 95, 115, 117, 98, 115, 99,
114, 105, 98, 101, 145, 178, 114, 115, 110, 111, 116, 101, 95, 111, 112, 101, 110,
95, 119, 105, 110, 100, 111, 119,
],
)
.await;
assert_read_write(
Value::Arr(
[
Value::Int(Int::I8(0)),
Value::Int(Int::U32(0x3f0c4a25)),
Value::Str("nvim_buf_set_keymap".into()),
Value::Arr(
[
Value::Ext(Ext {
r#type: 0,
data: [0xcd, 1, 0x2f].into(),
}),
Value::Str("n".into()),
Value::Str("<ESC>".into()),
Value::Str("<Cmd>w! .tasks<CR><Cmd>q<CR>".into()),
Value::Map([].into()),
]
.into(),
),
]
.into(),
),
&[
148, 224, 206, 63, 12, 74, 37, 179, 110, 118, 105, 109, 95, 98, 117, 102, 95, 115,
101, 116, 95, 107, 101, 121, 109, 97, 112, 149, 199, 3, 0, 205, 1, 47, 161, 110,
165, 60, 69, 83, 67, 62, 188, 60, 67, 109, 100, 62, 119, 33, 32, 46, 116, 97, 115,
107, 115, 60, 67, 82, 62, 60, 67, 109, 100, 62, 113, 60, 67, 82, 62, 128,
],
)
.await;
assert_read_write(
Value::Arr(
[
Value::Int(Int::U8(0)),
Value::Int(Int::U32(0xc032e486)),
Value::Str("nvim_exec_lua".into()),
Value::Arr(
[
Value::Str("return vim.o.columns".into()),
Value::Arr([].into()),
]
.into(),
),
]
.into(),
),
&[
148, 0, 206, 192, 50, 228, 134, 173, 110, 118, 105, 109, 95, 101, 120, 101, 99, 95,
108, 117, 97, 146, 180, 114, 101, 116, 117, 114, 110, 32, 118, 105, 109, 46, 111,
46, 99, 111, 108, 117, 109, 110, 115, 144,
],
)
.await;
assert_read_write(
Value::Arr(
[
Value::Int(Int::U8(0)),
Value::Int(Int::U32(0x49d10de0)),
Value::Str("nvim_buf_set_lines".into()),
Value::Arr(
[
Value::Ext(Ext {
r#type: 0,
data: [25].into(),
}),
Value::Int(Int::U8(0)),
Value::Int(Int::U8(1)),
Value::Bool(false),
Value::Arr(
[
Value::Str("Add the messagepack-rs module".into()),
Value::Str(
"Delete the
local code"
.into(),
),
Value::Str("Refactor to use the messagepack library".into()),
Value::Str("".into()),
]
.into(),
),
]
.into(),
),
]
.into(),
),
&[
148, 0, 206, 73, 209, 13, 224, 178, 110, 118, 105, 109, 95, 98, 117, 102, 95, 115,
101, 116, 95, 108, 105, 110, 101, 115, 149, 212, 0, 25, 0, 1, 194, 148, 189, 65,
100, 100, 32, 116, 104, 101, 32, 109, 101, 115, 115, 97, 103, 101, 112, 97, 99,
107, 45, 114, 115, 32, 109, 111, 100, 117, 108, 101, 182, 68, 101, 108, 101, 116,
101, 32, 116, 104, 101, 10, 32, 108, 111, 99, 97, 108, 32, 99, 111, 100, 101, 217,
39, 82, 101, 102, 97, 99, 116, 111, 114, 32, 116, 111, 32, 117, 115, 101, 32, 116,
104, 101, 32, 109, 101, 115, 115, 97, 103, 101, 112, 97, 99, 107, 32, 108, 105, 98,
114, 97, 114, 121, 160,
],
)
.await;
}
}