pub mod blob;
pub mod core;
pub mod object;
pub mod session;
use std::{borrow::Cow, collections::HashMap, fmt::Formatter};
use serde::{
de::{Error, MapAccess, SeqAccess},
ser::{SerializeMap, SerializeSeq},
Deserialize, Deserializer, Serialize, Serializer,
};
use serde_json::Value;
use serde_with::serde_as;
use crate::{
common::{Id, SessionState},
util::strip_prefix_from_cow,
};
const REFERENCE_OCTOTHORPE: &str = "#";
#[derive(Debug, Clone, Default)]
pub struct Arguments<'a>(HashMap<Cow<'a, str>, Argument<'a>>);
impl<'a> Serialize for Arguments<'a> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut ser = serializer.serialize_map(Some(self.0.len()))?;
for (key, value) in &self.0 {
match value {
Argument::Reference(v) => {
ser.serialize_entry(&format!("{REFERENCE_OCTOTHORPE}{key}"), v)?
}
Argument::Absolute(v) => ser.serialize_entry(key, v)?,
}
}
ser.end()
}
}
impl<'de> Deserialize<'de> for Arguments<'de> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
pub struct Visitor {}
impl<'de> serde::de::Visitor<'de> for Visitor {
type Value = Arguments<'de>;
fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result {
formatter.write_str("a list of arguments as defined by RFC8620")
}
fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
where
A: MapAccess<'de>,
{
let mut arguments = Arguments::default();
while let Some(key) = map.next_key::<Cow<'de, str>>()? {
if let Some(key) = strip_prefix_from_cow(key.clone(), REFERENCE_OCTOTHORPE) {
arguments
.0
.insert(key, Argument::Reference(map.next_value()?));
} else {
arguments
.0
.insert(key, Argument::Absolute(map.next_value()?));
}
}
Ok(arguments)
}
}
deserializer.deserialize_seq(Visitor {})
}
}
#[derive(Debug, Clone)]
pub enum Argument<'a> {
Reference(ResultReference<'a>),
Absolute(Value),
}
#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(rename_all = "camelCase")]
pub struct ResultReference<'a> {
#[serde(borrow)]
result_of: Cow<'a, str>,
#[serde(borrow)]
name: Cow<'a, str>,
#[serde(borrow)]
path: Cow<'a, str>,
}
#[derive(Clone, Debug)]
pub struct Invocation<'a> {
name: Cow<'a, str>,
arguments: Arguments<'a>,
request_id: Cow<'a, str>,
}
impl<'a> Serialize for Invocation<'a> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut ser = serializer.serialize_seq(Some(3))?;
ser.serialize_element(&self.name)?;
ser.serialize_element(&self.arguments)?;
ser.serialize_element(&self.request_id)?;
ser.end()
}
}
impl<'de: 'a, 'a> Deserialize<'de> for Invocation<'a> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
pub struct Visitor {}
impl<'de> serde::de::Visitor<'de> for Visitor {
type Value = Invocation<'de>;
fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result {
formatter.write_str(
"an Invocation data type containing 3 elements; name, arguments & id",
)
}
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: SeqAccess<'de>,
{
let name = seq.next_element()?.ok_or(A::Error::missing_field("name"))?;
let arguments = seq
.next_element()?
.ok_or(A::Error::missing_field("arguments"))?;
let request_id = seq.next_element()?.ok_or(A::Error::missing_field("id"))?;
if seq.next_element::<Value>()?.is_some() {
return Err(A::Error::invalid_length(4, &self));
}
Ok(Invocation {
name,
arguments,
request_id,
})
}
}
deserializer.deserialize_seq(Visitor {})
}
}
#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde_as]
#[serde(rename_all = "camelCase")]
pub struct Request<'a> {
#[serde_as(as = "Vec<BorrowedCow>")]
using: Vec<Cow<'a, str>>,
#[serde(borrow)]
method_calls: Vec<Invocation<'a>>,
#[serde(borrow)]
created_ids: Option<HashMap<Id<'a>, Id<'a>>>,
}
#[serde_as]
#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(rename_all = "camelCase")]
pub struct Response<'a> {
#[serde(borrow)]
method_responses: Invocation<'a>,
#[serde(borrow)]
created_ids: Option<HashMap<Id<'a>, Id<'a>>>,
session_state: SessionState<'a>,
}