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", "async-trait",
"axum", "axum",
"base-62", "base-62",
"flabk-derive",
"handlebars", "handlebars",
"jsonwebtoken", "jsonwebtoken",
"mime_guess", "mime_guess",
@ -335,6 +336,16 @@ dependencies = [
"tower-cookies", "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]] [[package]]
name = "fnv" name = "fnv"
version = "1.0.7" version = "1.0.7"

View File

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

View File

@ -1,13 +1,21 @@
use super::serde_ext::IriPartial;
use serde::Deserialize; use serde::Deserialize;
pub const CONTEXT_ID: &str = "https://www.w3.org/ns/activitystreams"; pub const CONTEXT_ID: &str = "https://www.w3.org/ns/activitystreams";
#[derive(Default, Debug, Clone, Deserialize)] #[derive(Default, Debug, Clone, Deserialize)]
pub struct Context { pub struct Context {
pub id: Option<String>,
#[serde(rename = "@context")] #[serde(rename = "@context")]
pub ctx: ContextMap, 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)] #[derive(Default, Debug, Clone, Deserialize)]
#[serde(rename_all = "PascalCase")] #[serde(rename_all = "PascalCase")]
pub struct ContextMap { pub struct ContextMap {

View File

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

View File

@ -1,24 +1,25 @@
use super::resolve::Resolver;
use std::{fmt, marker::PhantomData}; use std::{fmt, marker::PhantomData};
use serde::{de::Visitor, Deserialize, Deserializer}; 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 pub trait IriPartial: Default {
// TODO: deserializing the actual object isnt supported atm LOL fn set_id(&mut self, new_id: &str);
pub(super) fn expand<'de, D, Out>(deserializer: D) -> Result<Out, D::Error> }
// 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 where
D: Deserializer<'de>, D: Deserializer<'de>,
Out: for<'dt> serde::Deserialize<'dt>, Out: for<'dt> serde::Deserialize<'dt> + IriPartial,
{ {
let resolver = Resolver::new();
struct ResolveVisitor<Out> { struct ResolveVisitor<Out> {
resolver: Resolver,
_type: PhantomData<Out>, _type: PhantomData<Out>,
} }
impl<'de, Out> Visitor<'de> for ResolveVisitor<Out> impl<'de, Out> Visitor<'de> for ResolveVisitor<Out>
where where
Out: for<'dt> serde::Deserialize<'dt>, Out: for<'dt> serde::Deserialize<'dt> + IriPartial,
{ {
type Value = Out; type Value = Out;
@ -30,18 +31,9 @@ where
where where
E: serde::de::Error, E: serde::de::Error,
{ {
tokio::runtime::Runtime::new() let mut out = Out::default();
.unwrap() out.set_id(value);
.block_on(self.resolver.resolve_into::<Out>(value.to_string())) Ok(out)
.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,
)
})
} }
fn visit_seq<S>(self, visitor: S) -> Result<Self::Value, S::Error> fn visit_seq<S>(self, visitor: S) -> Result<Self::Value, S::Error>
@ -52,10 +44,7 @@ where
} }
} }
let resolve_visitor = ResolveVisitor { let resolve_visitor = ResolveVisitor { _type: PhantomData };
resolver: resolver,
_type: PhantomData,
};
deserializer.deserialize_map_string(resolve_visitor, |des| Out::deserialize(des)) deserializer.deserialize_map_string(resolve_visitor, |des| Out::deserialize(des))
} }
@ -99,28 +88,38 @@ where
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use flabk_derive::IRI;
use serde::Deserialize; use serde::Deserialize;
use super::expand; use crate::astreams::serde_ext::IriPartial;
use super::expand_partial;
#[test] #[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)] #[derive(Deserialize)]
struct WithContext { struct WithContext {
#[serde(deserialize_with = "expand")] #[serde(deserialize_with = "expand_partial")]
pub context: super::super::context::Context, pub context: Context,
} }
const JSONLD_INPUT: &str = r#"{"context": "https://www.w3.org/ns/activitystreams"}"#; const JSONLD_INPUT: &str = r#"{"context": "https://www.w3.org/ns/activitystreams"}"#;
let result = let result =
serde_json::from_str::<WithContext>(JSONLD_INPUT).expect("deserializing with expand"); 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] #[test]
fn expand_when_json_isnt_iri_but_the_object_itself() { fn expand_partial_expands_into_object_fully() {
#[derive(Deserialize)] #[derive(Deserialize, IRI, Default)]
struct Expanded { struct Expanded {
pub id: String, pub id: String,
pub truth: bool, pub truth: bool,
@ -128,7 +127,7 @@ mod tests {
#[derive(Deserialize)] #[derive(Deserialize)]
struct Expandable { struct Expandable {
#[serde(deserialize_with = "expand")] #[serde(deserialize_with = "expand_partial")]
pub expansive: Expanded, pub expansive: Expanded,
} }