feat(apb): allow upcasting from object

basically now object.as_actor() or object.as_collection() returns an
option which is full with a self ref only if the type is correct, so
that we can assume flexible json behavior from anything implementing our
apb traits, and we don't need to rely anymore on knowing the underlying
type
also little import refactor
This commit is contained in:
əlemi 2024-04-29 20:01:39 +02:00
parent f6ba30a43f
commit a3cf7a17e8
Signed by: alemi
GPG key ID: A4895B84D311642C
3 changed files with 52 additions and 19 deletions

View file

@ -3,7 +3,7 @@
pub enum Node<T : super::Base> { pub enum Node<T : super::Base> {
Array(std::collections::VecDeque<T>), // TODO would be cool to make it Box<[T]> so that Node is just a ptr Array(std::collections::VecDeque<T>), // TODO would be cool to make it Box<[T]> so that Node is just a ptr
Object(Box<T>), Object(Box<T>),
Link(Box<dyn super::Link + Sync + Send>), // TODO feature flag to toggle these maybe? Link(Box<dyn crate::Link + Sync + Send>), // TODO feature flag to toggle these maybe?
Empty, Empty,
} }

View file

@ -1,6 +1,4 @@
use crate::Node; use crate::{Node, Object, ObjectMut};
use crate::{Object, ObjectMut, PublicKey};
crate::strenum! { crate::strenum! {
pub enum ActorType { pub enum ActorType {
@ -13,7 +11,7 @@ crate::strenum! {
} }
pub trait Actor : Object { pub trait Actor : Object {
type PublicKey : PublicKey; type PublicKey : crate::PublicKey;
fn actor_type(&self) -> Option<ActorType> { None } fn actor_type(&self) -> Option<ActorType> { None }
fn preferred_username(&self) -> Option<&str> { None } fn preferred_username(&self) -> Option<&str> { None }
@ -30,7 +28,7 @@ pub trait Actor : Object {
} }
pub trait ActorMut : ObjectMut { pub trait ActorMut : ObjectMut {
type PublicKey : PublicKey; type PublicKey : crate::PublicKey;
fn set_actor_type(self, val: Option<ActorType>) -> Self; fn set_actor_type(self, val: Option<ActorType>) -> Self;
fn set_preferred_username(self, val: Option<&str>) -> Self; fn set_preferred_username(self, val: Option<&str>) -> Self;

View file

@ -7,12 +7,12 @@ pub mod place;
pub mod profile; pub mod profile;
pub mod relationship; pub mod relationship;
use crate::{Base, BaseMut, Link, Node}; use crate::{Base, BaseMut, Node};
use actor::{Actor, ActorType}; use actor::ActorType;
use document::{Document, DocumentType}; use document::DocumentType;
use activity::ActivityType; use activity::ActivityType;
use collection::{Collection, CollectionType}; use collection::CollectionType;
crate::strenum! { crate::strenum! {
pub enum ObjectType { pub enum ObjectType {
@ -33,11 +33,12 @@ crate::strenum! {
} }
pub trait Object : Base { pub trait Object : Base {
type Link : Link; type Link : crate::Link;
type Actor : Actor; type Actor : crate::Actor;
type Object : Object; type Object : Object;
type Collection : Collection; type Collection : crate::Collection;
type Document : Document; type Document : crate::Document;
type Activity : crate::Activity;
fn object_type(&self) -> Option<ObjectType> { None } fn object_type(&self) -> Option<ObjectType> { None }
fn attachment(&self) -> Node<Self::Object> { Node::Empty } fn attachment(&self) -> Node<Self::Object> { Node::Empty }
@ -69,14 +70,19 @@ pub trait Object : Base {
// TODO i really need this but it isn't part of AP! // TODO i really need this but it isn't part of AP!
fn sensitive(&self) -> Option<bool> { None } fn sensitive(&self) -> Option<bool> { None }
fn as_activity(&self) -> Option<&Self::Activity> { None }
fn as_actor(&self) -> Option<&Self::Actor> { None }
fn as_collection(&self) -> Option<&Self::Collection> { None }
fn as_document(&self) -> Option<&Self::Document> { None }
} }
pub trait ObjectMut : BaseMut { pub trait ObjectMut : BaseMut {
type Link : Link; type Link : crate::Link;
type Actor : Actor; type Actor : crate::Actor;
type Object : Object; type Object : Object;
type Collection : Collection; type Collection : crate::Collection;
type Document : Document; type Document : crate::Document;
fn set_object_type(self, val: Option<ObjectType>) -> Self; fn set_object_type(self, val: Option<ObjectType>) -> Self;
fn set_attachment(self, val: Node<Self::Object>) -> Self; fn set_attachment(self, val: Node<Self::Object>) -> Self;
@ -116,6 +122,7 @@ impl Object for serde_json::Value {
type Object = serde_json::Value; type Object = serde_json::Value;
type Document = serde_json::Value; type Document = serde_json::Value;
type Collection = serde_json::Value; type Collection = serde_json::Value;
type Activity = serde_json::Value;
crate::getter! { object_type -> type ObjectType } crate::getter! { object_type -> type ObjectType }
crate::getter! { attachment -> node <Self as Object>::Object } crate::getter! { attachment -> node <Self as Object>::Object }
@ -156,6 +163,34 @@ impl Object for serde_json::Value {
} }
} }
} }
fn as_activity(&self) -> Option<&Self::Activity> {
match self.object_type() {
Some(ObjectType::Activity(_)) => Some(self),
_ => None,
}
}
fn as_actor(&self) -> Option<&Self::Actor> {
match self.object_type() {
Some(ObjectType::Actor(_)) => Some(self),
_ => None,
}
}
fn as_collection(&self) -> Option<&Self::Collection> {
match self.object_type() {
Some(ObjectType::Collection(_)) => Some(self),
_ => None,
}
}
fn as_document(&self) -> Option<&Self::Document> {
match self.object_type() {
Some(ObjectType::Document(_)) => Some(self),
_ => None,
}
}
} }
#[cfg(feature = "unstructured")] #[cfg(feature = "unstructured")]