irk 0.1.1

A lil (wip) IRC protocol library
Documentation
use serde::{ser, Serialize};

use crate::{Error, Message, Result};

#[derive(Debug, Default)]
pub struct Serializer {
    pub args: Vec<Box<str>>,
}

#[derive(Debug)]
pub struct Sequence<'a>(&'a mut Serializer, Vec<Box<str>>);

impl Serializer {
    pub fn new<T: Serialize>(value: T) -> Result<Self> {
        let mut ser = Self::default();
        value.serialize(&mut ser)?;
        Ok(ser)
    }

    pub fn argument<T: Serialize>(mut self, value: T) -> Result<Self> {
        value.serialize(&mut self)?;
        Ok(self)
    }

    pub fn to_message(&self) -> Result<Message> {
        let (command, param) = self.args.split_first().ok_or(Error::Eof)?;
        Ok(Message {
            source: None,
            command,
            parameters: param.iter().map(|c| c.as_ref()).collect(),
        })
    }
}

macro_rules! pushes {
    ($($fun:ident($($param:ident: $type:ty),*) { $val:expr })*) => {
        $(fn $fun(self, $($param: $type),*) -> Result<()> {
            self.args.push($val.into());
            Ok(())
        })*
    };
}

macro_rules! pushes_string {
    ($($fun:ident($type:ty))*) => {
        pushes! { $($fun(v: $type) { v.to_string() })* }
    };
}

macro_rules! noop {
    ($($fun:ident($($type:ty),*))*) => {
        $(fn $fun(self, $(_: $type),*) -> Result<()> {
            Ok(())
        })*
    };
}

macro_rules! serializes_self {
    ($($fun:ident($($type:ty),*))*) => {
        $(fn $fun(self, $(_: $type),*) -> Result<Self> {
            Ok(self)
        })*
    };
}

macro_rules! forwards_self {
    ($($fun:ident($($type:ty),*))*) => {
        $(fn $fun<T: Serialize + ?Sized>(self, $(_: $type,)* value: &T) -> Result<()> {
            value.serialize(self)
        })*
    };
}

impl<'a> ser::Serializer for &'a mut Serializer {
    type Ok = ();
    type Error = Error;

    type SerializeSeq = Sequence<'a>;
    type SerializeTuple = Self;
    type SerializeTupleStruct = Self;
    type SerializeTupleVariant = Self;
    type SerializeMap = ser::Impossible<(), Error>;
    type SerializeStruct = Self;
    type SerializeStructVariant = Self;

    pushes! {
        serialize_str(v: &str) { v }
        serialize_bytes(v: &[u8]) { std::str::from_utf8(v).unwrap() }
        serialize_unit_variant(_name: &'static str, _index: u32, variant: &'static str) {
            variant
        }
    }

    pushes_string! {
        serialize_i8(i8) serialize_i16(i16) serialize_i32(i32) serialize_i64(i64)
        serialize_u8(u8) serialize_u16(u16) serialize_u32(u32) serialize_u64(u64)
        serialize_f32(f32) serialize_f64(f64) serialize_char(char) serialize_bool(bool)
    }

    noop! {
        serialize_unit() serialize_none() serialize_unit_struct(&'static str)
    }

    forwards_self! {
        serialize_some() serialize_newtype_struct(&'static str)
    }

    serializes_self! {
        serialize_tuple(usize) serialize_tuple_struct(&'static str, usize)
        serialize_struct(&'static str, usize)
    }

    fn serialize_seq(self, _len: Option<usize>) -> Result<Sequence<'a>> {
        Ok(Sequence(self, Vec::new()))
    }

    fn serialize_map(self, _len: Option<usize>) -> Result<ser::Impossible<(), Error>> {
        Err(Error::UnsupportedType)
    }

    fn serialize_newtype_variant<T>(
        self,
        _name: &'static str,
        _variant_index: u32,
        variant: &'static str,
        value: &T,
    ) -> Result<()>
    where
        T: Serialize + ?Sized,
    {
        self.args.push(variant.into());
        value.serialize(self)
    }

    fn serialize_tuple_variant(
        self,
        _name: &'static str,
        _variant_index: u32,
        variant: &'static str,
        _len: usize,
    ) -> Result<Self> {
        self.args.push(variant.into());
        Ok(self)
    }

    fn serialize_struct_variant(
        self,
        _name: &'static str,
        _variant_index: u32,
        variant: &'static str,
        _len: usize,
    ) -> Result<Self> {
        self.args.push(variant.into());
        Ok(self)
    }
}

impl<'a> ser::SerializeSeq for Sequence<'a> {
    type Ok = ();
    type Error = Error;

    fn serialize_element<T: Serialize + ?Sized>(&mut self, value: &T) -> Result<()> {
        let mut ser = Serializer::default();
        value.serialize(&mut ser)?;
        self.1.extend(ser.args);

        Ok(())
    }

    fn end(self) -> Result<()> {
        self.0.args.push(self.1.join(",").into());
        Ok(())
    }
}

macro_rules! serialize_fields {
    ($($trait:ident::$fun:ident($($type:ty),*))*) => {
        $(impl<'a> ser::$trait for &'a mut Serializer {
            type Ok = ();
            type Error = Error;

            fn $fun<T>(&mut self, $(_: $type,)* value: &T) -> Result<()>
            where
                T: Serialize + ?Sized,
            {
                value.serialize(&mut **self)
            }

            fn end(self) -> Result<()> {
                Ok(())
            }
        })*
    };
}

serialize_fields! {
    SerializeTuple::serialize_element()
    SerializeTupleStruct::serialize_field()
    SerializeTupleVariant::serialize_field()
    SerializeStruct::serialize_field(&'static str)
    SerializeStructVariant::serialize_field(&'static str)
}