use std::collections::HashMap;
use serde::{Deserialize, Serialize, Serializer};
use ocapn_syrup::Value;
#[derive(Deserialize, Debug)]
pub struct Peer {
pub designator: String,
pub transport: String,
pub hints: HashMap<String, String>,
}
pub trait Uri {
fn scheme() -> &'static str {
"ocapn"
}
fn authority(&self) -> String;
fn path(&self) -> String;
fn query(&self) -> String;
fn uri_string(&self) -> String {
let mut u = Self::scheme().to_string();
u.push_str("://");
u.push_str(self.authority().as_str());
let (path, query) = (self.path(), self.query());
if !path.is_empty() {
if let Some('/') = path.chars().nth(0) {
u.push_str(&path);
} else {
u.push('/');
u.push_str(&path);
}
}
if !query.is_empty() {
u.push('?');
u.push_str(&query);
}
u
}
}
impl Uri for Peer {
fn authority(&self) -> String {
format!("{}.{}", self.designator, self.transport)
}
fn path(&self) -> String {
"".to_string()
}
fn query(&self) -> String {
let mut qs = "".to_string();
for (k, v) in &self.hints {
qs.push_str(urlencoding::encode(k).into_owned().as_str());
qs.push('=');
qs.push_str(urlencoding::encode(v).into_owned().as_str());
}
qs
}
}
impl From<&Peer> for Value {
fn from(value: &Peer) -> Self {
Value::Record {
label: Box::new(Value::Symbol("ocapn-peer".to_owned())),
fields: vec![
Value::Symbol(value.designator.to_owned()),
Value::Symbol(value.transport.to_owned()),
if value.hints.is_empty() {
Value::Boolean(false)
} else {
Value::Dictionary(
value
.hints
.iter()
.map(|(k, v)| {
(Value::Symbol(k.to_owned()), Value::String(v.to_owned()))
})
.collect(),
)
},
],
}
}
}
impl Serialize for Peer {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_bytes(Value::from(self).to_vec().as_slice())
}
}
pub struct SturdyRef {
pub peer: Peer,
pub swiss_num: String,
}
impl Uri for SturdyRef {
fn authority(&self) -> String {
self.peer.authority()
}
fn path(&self) -> String {
format!("/s/{}", self.swiss_num)
}
fn query(&self) -> String {
self.peer.query()
}
}
impl From<&SturdyRef> for Value {
fn from(value: &SturdyRef) -> Self {
Value::Record {
label: Box::new(Value::Symbol("ocapn-sturdyref".to_owned())),
fields: vec![
Value::from(&value.peer),
Value::String(value.swiss_num.to_owned()),
],
}
}
}
impl Serialize for SturdyRef {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_bytes(Value::from(self).to_vec().as_slice())
}
}