Compare commits

..

No commits in common. "8b15ae9f4f28795084c732d271a03277f048b27f" and "6411923a0d668d0d5401b42f7e1573d9e77dd27c" have entirely different histories.

4 changed files with 20 additions and 40 deletions

View file

@ -338,9 +338,9 @@ pub fn set_maybe_node(obj: &mut serde_json::Value, key: &str, node: crate::Node<
obj, key, Some(serde_json::Value::String(l.href().to_string())), obj, key, Some(serde_json::Value::String(l.href().to_string())),
); );
}, },
crate::Node::Array(_) => { crate::Node::Array(arr) => {
set_maybe_value( set_maybe_value(
obj, key, Some(serde_json::Value::Array(node.into_iter().collect())), obj, key, Some(serde_json::Value::Array(arr.into())),
); );
}, },
crate::Node::Empty => { crate::Node::Empty => {

View file

@ -1,13 +1,12 @@
/// ActivityPub object node, representing either nothing, something, a link to something or /// ActivityPub object node, representing either nothing, something, a link to something or
/// multiple things /// multiple things
pub enum Node<T : super::Base> { pub enum Node<T : super::Base> {
Array(std::collections::VecDeque<Node<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 crate::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,
} }
// TODO convert in a from_residual (iirc?) so that in rust nightly we can do ?
impl<T : super::Base> From<Option<T>> for Node<T> { impl<T : super::Base> From<Option<T>> for Node<T> {
fn from(value: Option<T>) -> Self { fn from(value: Option<T>) -> Self {
match value { match value {
@ -17,6 +16,9 @@ impl<T : super::Base> From<Option<T>> for Node<T> {
} }
} }
// TODO how do i move out of the box for a moment? i need to leave it uninitialized while i update
// the value and then put it back, i think it should be safe to do so! but i'm not sure how, so i'm
// using a clone (expensive but simple solution)
impl<T : super::Base> Iterator for Node<T> { impl<T : super::Base> Iterator for Node<T> {
type Item = T; type Item = T;
@ -29,36 +31,30 @@ impl<T : super::Base> Iterator for Node<T> {
None None
}, },
Self::Array(mut arr) => { Self::Array(mut arr) => {
let mut out = None; let res = arr.pop_front();
while let Some(res) = arr.pop_front() {
if let Some(inner) = res.extract() {
out = Some(inner);
break;
}
}
*self = Self::Array(arr); *self = Self::Array(arr);
out res
} }
} }
} }
} }
impl<T : super::Base> Node<T> { impl<T : super::Base> Node<T> {
/// return reference to embedded object (or first if many are present) /// return reference to embedded object (or last if many are present)
pub fn get(&self) -> Option<&T> { pub fn get(&self) -> Option<&T> {
match self { match self {
Node::Empty | Node::Link(_) => None, Node::Empty | Node::Link(_) => None,
Node::Object(x) => Some(x), Node::Object(x) => Some(x),
Node::Array(v) => v.iter().filter_map(|x| x.get()).next(), Node::Array(v) => v.front(),
} }
} }
/// return reference to embedded object (or first if many are present) /// consume node and extract embedded object (or last if many are present)
pub fn extract(self) -> Option<T> { pub fn extract(self) -> Option<T> {
match self { match self {
Node::Empty | Node::Link(_) => None, Node::Empty | Node::Link(_) => None,
Node::Object(x) => Some(*x), Node::Object(x) => Some(*x),
Node::Array(mut v) => v.pop_front()?.extract(), Node::Array(mut v) => v.pop_front(),
} }
} }
@ -107,15 +103,6 @@ impl<T : super::Base> Node<T> {
Node::Array(arr) => Some(arr.front()?.id()?.to_string()), Node::Array(arr) => Some(arr.front()?.id()?.to_string()),
} }
} }
pub fn ids(&self) -> Vec<String> {
match self {
Node::Empty => vec![],
Node::Link(uri) => vec![uri.href().to_string()],
Node::Object(x) => x.id().map_or(vec![], |x| vec![x.to_string()]),
Node::Array(x) => x.iter().filter_map(Self::id).collect()
}
}
} }
#[cfg(feature = "unstructured")] #[cfg(feature = "unstructured")]
@ -128,7 +115,7 @@ impl Node<serde_json::Value> {
Node::Array( Node::Array(
uris uris
.into_iter() .into_iter()
.map(Node::link) .map(serde_json::Value::String)
.collect() .collect()
) )
} }
@ -152,12 +139,7 @@ impl Node<serde_json::Value> {
} }
pub fn array(values: Vec<serde_json::Value>) -> Self { pub fn array(values: Vec<serde_json::Value>) -> Self {
Node::Array( Node::Array(values.into())
std::collections::VecDeque::from_iter(
values.into_iter()
.map(Node::object)
)
)
} }
#[cfg(feature = "fetch")] #[cfg(feature = "fetch")]
@ -198,12 +180,7 @@ impl From<serde_json::Value> for Node<serde_json::Value> {
fn from(value: serde_json::Value) -> Self { fn from(value: serde_json::Value) -> Self {
match value { match value {
serde_json::Value::String(uri) => Node::Link(Box::new(uri)), serde_json::Value::String(uri) => Node::Link(Box::new(uri)),
serde_json::Value::Array(arr) => Node::Array( serde_json::Value::Array(arr) => Node::Array(arr.into()),
std::collections::VecDeque::from_iter(
arr.into_iter()
.map(Node::from)
)
),
serde_json::Value::Object(_) => match value.get("href") { serde_json::Value::Object(_) => match value.get("href") {
None => Node::Object(Box::new(value)), None => Node::Object(Box::new(value)),
Some(_) => Node::Link(Box::new(value)), Some(_) => Node::Link(Box::new(value)),

View file

@ -6,7 +6,8 @@ pub trait Addressed {
fn addressed(&self) -> Vec<String>; fn addressed(&self) -> Vec<String>;
} }
impl<T: Object> Addressed for T { #[cfg(feature = "unstructured")]
impl Addressed for serde_json::Value {
fn addressed(&self) -> Vec<String> { fn addressed(&self) -> Vec<String> {
let mut to : Vec<String> = self.to().map(|x| x.href().to_string()).collect(); let mut to : Vec<String> = self.to().map(|x| x.href().to_string()).collect();
to.append(&mut self.bto().map(|x| x.href().to_string()).collect()); to.append(&mut self.bto().map(|x| x.href().to_string()).collect());

View file

@ -65,15 +65,17 @@ impl Link for serde_json::Value {
#[cfg(feature = "unstructured")] #[cfg(feature = "unstructured")]
impl LinkMut for serde_json::Value { impl LinkMut for serde_json::Value {
// TODO this can fail, but it should never do!
fn set_href(mut self, href: &str) -> Self { fn set_href(mut self, href: &str) -> Self {
match &mut self { match &mut self {
serde_json::Value::String(x) => *x = href.to_string(),
serde_json::Value::Object(map) => { serde_json::Value::Object(map) => {
map.insert( map.insert(
"href".to_string(), "href".to_string(),
serde_json::Value::String(href.to_string()) serde_json::Value::String(href.to_string())
); );
}, },
x => *x = serde_json::Value::String(href.to_string()), _ => tracing::error!("failed setting href on invalid json Link object"),
} }
self self
} }