aldrin-core 0.13.0

Shared core components of Aldrin, a message bus for service-oriented RPC and interprocess communication.
Documentation
use super::{ir, resolve_ir, LexicalId};
use crate::tags::{self, PrimaryTag, Tag};
use crate::{
    Deserialize, DeserializeError, Deserializer, Serialize, SerializeError, Serializer, TypeId,
};
use num_enum::{IntoPrimitive, TryFromPrimitive};
use std::collections::BTreeMap;

#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(
    feature = "serde",
    derive(serde::Serialize, serde::Deserialize),
    serde(rename_all = "kebab-case")
)]
pub struct Function {
    id: u32,
    name: String,

    #[cfg_attr(
        feature = "serde",
        serde(default, skip_serializing_if = "Option::is_none")
    )]
    doc: Option<String>,

    #[cfg_attr(
        feature = "serde",
        serde(default, skip_serializing_if = "Option::is_none")
    )]
    args: Option<TypeId>,

    #[cfg_attr(
        feature = "serde",
        serde(default, skip_serializing_if = "Option::is_none")
    )]
    ok: Option<TypeId>,

    #[cfg_attr(
        feature = "serde",
        serde(default, skip_serializing_if = "Option::is_none")
    )]
    err: Option<TypeId>,
}

impl Function {
    pub fn from_ir(func: ir::FunctionIr, references: &BTreeMap<LexicalId, TypeId>) -> Self {
        Self {
            id: func.id,
            name: func.name,
            doc: func.doc,
            args: func.args.map(|ty| resolve_ir(ty, references)),
            ok: func.ok.map(|ty| resolve_ir(ty, references)),
            err: func.err.map(|ty| resolve_ir(ty, references)),
        }
    }

    pub fn id(&self) -> u32 {
        self.id
    }

    pub fn name(&self) -> &str {
        &self.name
    }

    pub fn doc(&self) -> Option<&str> {
        self.doc.as_deref()
    }

    pub fn args(&self) -> Option<TypeId> {
        self.args
    }

    pub fn ok(&self) -> Option<TypeId> {
        self.ok
    }

    pub fn err(&self) -> Option<TypeId> {
        self.err
    }
}

#[derive(IntoPrimitive, TryFromPrimitive)]
#[repr(u32)]
enum FunctionField {
    Id = 0,
    Name = 1,
    Doc = 2,
    Args = 3,
    Ok = 4,
    Err = 5,
}

impl Tag for Function {}

impl PrimaryTag for Function {
    type Tag = Self;
}

impl Serialize<Self> for Function {
    fn serialize(self, serializer: Serializer) -> Result<(), SerializeError> {
        serializer.serialize(&self)
    }
}

impl Serialize<Function> for &Function {
    fn serialize(self, serializer: Serializer) -> Result<(), SerializeError> {
        let mut serializer = serializer.serialize_struct2()?;

        serializer.serialize::<tags::U32>(FunctionField::Id, &self.id)?;
        serializer.serialize::<tags::String>(FunctionField::Name, &self.name)?;

        serializer
            .serialize_if_some::<tags::Option<tags::String>>(FunctionField::Doc, &self.doc)?;

        serializer.serialize_if_some::<tags::Option<TypeId>>(FunctionField::Args, &self.args)?;
        serializer.serialize_if_some::<tags::Option<TypeId>>(FunctionField::Ok, &self.ok)?;
        serializer.serialize_if_some::<tags::Option<TypeId>>(FunctionField::Err, &self.err)?;

        serializer.finish()
    }
}

impl Deserialize<Self> for Function {
    fn deserialize(deserializer: Deserializer) -> Result<Self, DeserializeError> {
        let mut deserializer = deserializer.deserialize_struct()?;

        let mut id = None;
        let mut name = None;
        let mut doc = None;
        let mut args = None;
        let mut ok = None;
        let mut err = None;

        while let Some(deserializer) = deserializer.deserialize()? {
            match deserializer.try_id() {
                Ok(FunctionField::Id) => {
                    id = deserializer.deserialize::<tags::U32, _>().map(Some)?;
                }

                Ok(FunctionField::Name) => {
                    name = deserializer.deserialize::<tags::String, _>().map(Some)?;
                }

                Ok(FunctionField::Doc) => {
                    doc = deserializer.deserialize::<tags::Option<tags::String>, _>()?;
                }

                Ok(FunctionField::Args) => {
                    args = deserializer.deserialize::<tags::Option<TypeId>, _>()?;
                }

                Ok(FunctionField::Ok) => {
                    ok = deserializer.deserialize::<tags::Option<TypeId>, _>()?;
                }

                Ok(FunctionField::Err) => {
                    err = deserializer.deserialize::<tags::Option<TypeId>, _>()?;
                }

                Err(_) => deserializer.skip()?,
            }
        }

        deserializer.finish(Self {
            id: id.ok_or(DeserializeError::InvalidSerialization)?,
            name: name.ok_or(DeserializeError::InvalidSerialization)?,
            doc,
            args,
            ok,
            err,
        })
    }
}