change expand into a partial expand to remove resolver dependency

This commit is contained in:
emilis 2022-11-08 20:23:27 +00:00
parent 271eba8d7b
commit 1e7c59c5a4
5 changed files with 62 additions and 41 deletions

11
Cargo.lock generated
View File

@ -321,6 +321,7 @@ dependencies = [
"async-trait",
"axum",
"base-62",
"flabk-derive",
"handlebars",
"jsonwebtoken",
"mime_guess",
@ -335,6 +336,16 @@ dependencies = [
"tower-cookies",
]
[[package]]
name = "flabk-derive"
version = "0.1.0"
source = "git+https://sectorinf.com/emilis/flabk-derive#d5647801bb9fe24edcb1165c900ce5f3d7f24cee"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "fnv"
version = "1.0.7"

View File

@ -31,6 +31,7 @@ serde_json = "1.0.85"
tokio = { version = "1", features = ["full"] }
tokio-postgres = { version = "0.7.7", features = ["with-serde_json-1"] }
tower-cookies = "0.7.0"
flabk-derive = { git = "https://sectorinf.com/emilis/flabk-derive" }
[patch.crates-io]
serde = { git = "https://sectorinf.com/emilis/serde" }

View File

@ -1,13 +1,21 @@
use super::serde_ext::IriPartial;
use serde::Deserialize;
pub const CONTEXT_ID: &str = "https://www.w3.org/ns/activitystreams";
#[derive(Default, Debug, Clone, Deserialize)]
pub struct Context {
pub id: Option<String>,
#[serde(rename = "@context")]
pub ctx: ContextMap,
}
impl IriPartial for Context {
fn set_id(&mut self, new_id: &str) {
self.id = Some(new_id.into());
}
}
#[derive(Default, Debug, Clone, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct ContextMap {

View File

@ -1,11 +1,13 @@
use async_trait::async_trait;
use flabk_derive::IRI;
use serde::{Deserialize, Serialize};
use serde_ext::IriPartial;
use self::{
context::Context,
note::Note,
resolve::ResolveError,
serde_ext::{expand, pull_single_into_vec},
serde_ext::{expand_partial, pull_single_into_vec},
};
pub mod context;
@ -54,17 +56,18 @@ pub struct ActivityLD {
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Activity {
#[serde(rename = "@context")]
#[serde(deserialize_with = "expand")]
pub ap_context: Context,
// #[serde(rename = "@context")]
// #[serde(deserialize_with = "expand_partial")]
// pub ap_context: Context,
pub id: String,
#[serde(rename = "type")]
pub kind: ActivityKind,
#[serde(deserialize_with = "expand_partial")]
pub attributed_to: Actor,
pub content: Option<String>,
// pub context: Option<String>,
#[serde(deserialize_with = "expand")]
pub to: Context,
pub context: Option<String>,
#[serde(deserialize_with = "pull_single_into_vec")]
pub to: Vec<String>,
pub url: Option<String>,
}
@ -89,7 +92,7 @@ pub struct ObjectLD {
pub enum ActorType {}
#[derive(Debug, Clone, Deserialize)]
#[derive(Debug, Clone, Deserialize, IRI, Default)]
pub struct Actor {
id: String,
}
@ -110,7 +113,6 @@ pub async fn test() {
}"#;
let obj = serde_json::from_str::<Activity>(obj).unwrap();
println!("to: {:#?}", &obj.to);
println!();
println!("{:#?}", obj);
}

View File

@ -1,24 +1,25 @@
use super::resolve::Resolver;
use std::{fmt, marker::PhantomData};
use serde::{de::Visitor, Deserialize, Deserializer};
// Allows a value that's a string to be expanded into an object AND the serialization of that object itself
// TODO: deserializing the actual object isnt supported atm LOL
pub(super) fn expand<'de, D, Out>(deserializer: D) -> Result<Out, D::Error>
pub trait IriPartial: Default {
fn set_id(&mut self, new_id: &str);
}
// Allows a value that's a string to be expanded into an object (move string into id property via From<IRI>)
// AND the serialization of that object itself
pub(super) fn expand_partial<'de, D, Out>(deserializer: D) -> Result<Out, D::Error>
where
D: Deserializer<'de>,
Out: for<'dt> serde::Deserialize<'dt>,
Out: for<'dt> serde::Deserialize<'dt> + IriPartial,
{
let resolver = Resolver::new();
struct ResolveVisitor<Out> {
resolver: Resolver,
_type: PhantomData<Out>,
}
impl<'de, Out> Visitor<'de> for ResolveVisitor<Out>
where
Out: for<'dt> serde::Deserialize<'dt>,
Out: for<'dt> serde::Deserialize<'dt> + IriPartial,
{
type Value = Out;
@ -30,18 +31,9 @@ where
where
E: serde::de::Error,
{
tokio::runtime::Runtime::new()
.unwrap()
.block_on(self.resolver.resolve_into::<Out>(value.to_string()))
.map_err(|e| {
let name = std::any::type_name::<Out>();
serde::de::Error::invalid_value(
serde::de::Unexpected::Other(
format!("failed resolving iri [{}]: {}", value, e.0).as_str(),
),
&name,
)
})
let mut out = Out::default();
out.set_id(value);
Ok(out)
}
fn visit_seq<S>(self, visitor: S) -> Result<Self::Value, S::Error>
@ -52,10 +44,7 @@ where
}
}
let resolve_visitor = ResolveVisitor {
resolver: resolver,
_type: PhantomData,
};
let resolve_visitor = ResolveVisitor { _type: PhantomData };
deserializer.deserialize_map_string(resolve_visitor, |des| Out::deserialize(des))
}
@ -99,28 +88,38 @@ where
#[cfg(test)]
mod tests {
use flabk_derive::IRI;
use serde::Deserialize;
use super::expand;
use crate::astreams::serde_ext::IriPartial;
use super::expand_partial;
#[test]
fn expand_context_from_iri() {
fn expand_partial_populates_iri_from_string() {
#[derive(Deserialize, IRI, Default)]
struct Context {
pub id: String,
pub context: bool,
}
#[derive(Deserialize)]
struct WithContext {
#[serde(deserialize_with = "expand")]
pub context: super::super::context::Context,
#[serde(deserialize_with = "expand_partial")]
pub context: Context,
}
const JSONLD_INPUT: &str = r#"{"context": "https://www.w3.org/ns/activitystreams"}"#;
let result =
serde_json::from_str::<WithContext>(JSONLD_INPUT).expect("deserializing with expand");
assert!(result.context.ctx.xsd == "http://www.w3.org/2001/XMLSchema#")
assert!(result.context.id == "https://www.w3.org/ns/activitystreams");
assert!(result.context.context == false);
}
#[test]
fn expand_when_json_isnt_iri_but_the_object_itself() {
#[derive(Deserialize)]
fn expand_partial_expands_into_object_fully() {
#[derive(Deserialize, IRI, Default)]
struct Expanded {
pub id: String,
pub truth: bool,
@ -128,7 +127,7 @@ mod tests {
#[derive(Deserialize)]
struct Expandable {
#[serde(deserialize_with = "expand")]
#[serde(deserialize_with = "expand_partial")]
pub expansive: Expanded,
}