mirror of
https://git.asonix.dog/asonix/activitystreams.git
synced 2024-11-22 03:40:59 +00:00
Copy in -new and -ext
This commit is contained in:
parent
310d29482b
commit
afafe24d51
65 changed files with 17686 additions and 7563 deletions
43
Cargo.toml
43
Cargo.toml
|
@ -1,39 +1,28 @@
|
|||
[package]
|
||||
name = "activitystreams"
|
||||
description = "Activity Streams in Rust"
|
||||
version = "0.6.2"
|
||||
version = "0.7.0-alpha.0"
|
||||
license = "GPL-3.0"
|
||||
authors = ["asonix <asonix@asonix.dog>"]
|
||||
repository = "https://git.asonix.dog/Aardwolf/activitystreams"
|
||||
repository = "https://git.asonix.dog/asonix/activitystreams-sketch"
|
||||
documentation = "https://activitystreams-new.asonix.dog"
|
||||
readme = "README.md"
|
||||
keywords = ["activitystreams", "activitypub"]
|
||||
edition = "2018"
|
||||
|
||||
[features]
|
||||
default = ["types"]
|
||||
derive = ["activitystreams-derive", "serde", "serde_json"]
|
||||
kinds = ["derive", "serde"]
|
||||
primitives = ["chrono", "mime", "serde", "thiserror", "url"]
|
||||
types = ["derive", "kinds", "primitives"]
|
||||
|
||||
[dependencies]
|
||||
activitystreams-derive = { version = "0.6.0", path = "activitystreams-derive", optional = true}
|
||||
chrono = { version = "0.4", optional = true }
|
||||
mime = { version = "0.3", optional = true }
|
||||
serde = { version = "1.0", features = ["derive"], optional = true }
|
||||
serde_json = { version = "1.0", optional = true }
|
||||
thiserror = { version = "1.0", optional = true }
|
||||
url = { version = "2.1", optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
anyhow = "1.0"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
|
||||
[profile.dev.package.activitystreams-derive]
|
||||
opt-level = 3
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[workspace]
|
||||
members = [
|
||||
"activitystreams-derive",
|
||||
"activitystreams-ext"
|
||||
]
|
||||
|
||||
[dependencies]
|
||||
chrono = "0.4"
|
||||
mime = "0.3"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
thiserror = "1.0"
|
||||
url = { version = "2.1", features = ["serde"] }
|
||||
|
||||
[dev-dependencies]
|
||||
anyhow = "1.0"
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
[package]
|
||||
name = "activitystreams-derive"
|
||||
description = "Derive macros for activitystreams"
|
||||
version = "0.6.1"
|
||||
license = "GPL-3.0"
|
||||
authors = ["asonix <asonix.dev@gmail.com>"]
|
||||
repository = "https://git.asonix.dog/Aardwolf/activitystreams"
|
||||
readme = "README.md"
|
||||
keywords = ["activitystreams", "activitypub"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
quote = "1.0"
|
||||
syn = { version = "1.0", features = ["full"] }
|
||||
proc-macro2 = "1.0"
|
||||
|
||||
[dev-dependencies]
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
|
||||
[lib]
|
||||
proc-macro = true
|
|
@ -1,121 +0,0 @@
|
|||
# ActivityStreams Derive
|
||||
__derive macros for ActivityStreams__
|
||||
|
||||
- [Read the documentation on docs.rs](https://docs.rs/activitystreams-derive)
|
||||
- [Find the crate on crates.io](https://crates.io/crates/activitystreams-derive)
|
||||
- [Hit me up on Mastodon](https://asonix.dog/@asonix)
|
||||
|
||||
## Usage
|
||||
Add the required crates to your `Cargo.toml`
|
||||
```toml
|
||||
# Cargo.toml
|
||||
|
||||
activitystreams = "0.6.0"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
```
|
||||
|
||||
And then in your project
|
||||
```rust
|
||||
// derive macros
|
||||
use activitystreams::{
|
||||
properties,
|
||||
PropRefs,
|
||||
UnitString
|
||||
};
|
||||
// traits
|
||||
use activitystreams::Object;
|
||||
// properties
|
||||
use activitystreams::object::properties::ObjectProperties;
|
||||
|
||||
/// Using the UnitString derive macro
|
||||
///
|
||||
/// This macro implements Serialize and Deserialize for the given type, making this type
|
||||
/// represent the string "SomeKind" in JSON.
|
||||
#[derive(Clone, Debug, Default, UnitString)]
|
||||
#[unit_string(SomeKind)]
|
||||
pub struct MyKind;
|
||||
|
||||
properties! {
|
||||
My {
|
||||
docs [
|
||||
"Using the properties macro",
|
||||
"",
|
||||
"This macro generates getters and setters for the associated fields.",
|
||||
],
|
||||
|
||||
kind {
|
||||
docs [
|
||||
"Use the UnitString MyKind to enforce the type of the object by \"SomeKind\"",
|
||||
"",
|
||||
"Rename to/from 'type' when serializing/deserializing",
|
||||
],
|
||||
|
||||
types [
|
||||
MyKind,
|
||||
],
|
||||
functional,
|
||||
required,
|
||||
rename("type"),
|
||||
},
|
||||
|
||||
required_key {
|
||||
docs [
|
||||
"Derive getters and setters for required_key with String type.",
|
||||
"",
|
||||
"In the Activity Streams spec, 'functional' means there can only be one item for",
|
||||
"this key. This means all fields not labeled 'functional' can also be",
|
||||
"serialized/deserialized as Vec<T>.",
|
||||
"",
|
||||
"'required' here means that the field must be present, otherwise, it's"
|
||||
"represented as an Option<T>",
|
||||
],
|
||||
types [
|
||||
String,
|
||||
],
|
||||
functional,
|
||||
required,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Default, PropRefs, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[prop_refs(Object)]
|
||||
pub struct My {
|
||||
/// Derive AsRef<MyProperties> and AsMut<MyProperties>
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
my_properties: MyProperties,
|
||||
|
||||
/// Derive AsRef<ObjectProperties> and AsMut<ObjectProperties>
|
||||
///
|
||||
/// as well as the Object trait
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
properties: ObjectProperties,
|
||||
}
|
||||
|
||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let mut my = My::default();
|
||||
|
||||
let mprops: &mut MyProperties = my.as_mut();
|
||||
mprops.set_required_key("Hello")?;
|
||||
|
||||
let mprops: &MyProperties = my.as_ref();
|
||||
assert_eq!(mprops.get_required_key(), "Hello");
|
||||
Ok(())
|
||||
}
|
||||
```
|
||||
|
||||
## Contributing
|
||||
Feel free to open issues for anything you find an issue with. Please note that any contributed code will be licensed under the GPLv3.
|
||||
|
||||
## License
|
||||
|
||||
Copyright © 2020 Riley Trautman
|
||||
|
||||
ActivityStreams Derive is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||
|
||||
ActivityStreams Derive is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. This file is part of ActivityStreams Derive.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with ActivityStreams Derive. If not, see [http://www.gnu.org/licenses/](http://www.gnu.org/licenses/).
|
File diff suppressed because it is too large
Load diff
|
@ -1,3 +1,3 @@
|
|||
/target
|
||||
**/*.rs.bk
|
||||
/artifacts
|
||||
Cargo.lock
|
20
activitystreams-ext/Cargo.toml
Normal file
20
activitystreams-ext/Cargo.toml
Normal file
|
@ -0,0 +1,20 @@
|
|||
[package]
|
||||
name = "activitystreams-ext"
|
||||
version = "0.1.0"
|
||||
license = "GPL-3.0"
|
||||
authors = ["asonix <asonix@asonix.dog>"]
|
||||
repository = "https://git.asonix.dog/asonix/activitystreams-ext"
|
||||
documentation = "https://activitystreams-ext.asonix.dog"
|
||||
readme = "README.md"
|
||||
keywords = ["activitystreams", "activitypub"]
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
activitystreams = { path = ".." }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
|
||||
[dev-dependencies]
|
||||
anyhow = "1.0"
|
6
activitystreams-ext/Dockerfile.arm64v8
Normal file
6
activitystreams-ext/Dockerfile.arm64v8
Normal file
|
@ -0,0 +1,6 @@
|
|||
FROM arm64v8/nginx:mainline-alpine
|
||||
|
||||
COPY html/ /usr/share/nginx/html/
|
||||
|
||||
RUN chown -R nginx:nginx /usr/share/nginx/html
|
||||
|
104
activitystreams-ext/README.md
Normal file
104
activitystreams-ext/README.md
Normal file
|
@ -0,0 +1,104 @@
|
|||
# ActivityStreams Ext
|
||||
_This crate provides Ext1, Ext2, Ext3, and Ext4 for adding extensions to ActivityStreams types_
|
||||
|
||||
- Find the code on [git.asonix.dog](https://git.asonix.dog/asonix/activitystreams-ext)
|
||||
- Read the docs on [activitystreams-ext.asonix.dog](https://activitystreams-ext.asonix.dog)
|
||||
- Join the matrix channel at [#activitypub:asonix.dog](https://matrix.to/#/!fAEcHyTUdAaKCzIKCt:asonix.dog?via=asonix.dog&via=matrix.org&via=t2bot.io)
|
||||
- Hit me up on [mastodon](https://asonix.dog/@asonix)
|
||||
|
||||
## Usage
|
||||
|
||||
First, add ActivityStreams to your dependencies
|
||||
```toml
|
||||
[dependencies]
|
||||
activitystreams-new = { git = "https://git.asonix.dog/asonix/activitystreams-sketch", branch = "main" }
|
||||
activitystreams-ext = { git = "https://git.asonix.dog/asonix/activitystreams-ext", branch = "main" }
|
||||
```
|
||||
|
||||
For an example, we'll implement a PublicKey extension and demonstrate usage with Ext1
|
||||
```rust
|
||||
use activitystreams_ext::{Ext1, UnparsedExtension};
|
||||
use activitystreams_new::{
|
||||
actor::{ApActor, Person},
|
||||
context,
|
||||
prelude::*,
|
||||
primitives::XsdAnyUri,
|
||||
security,
|
||||
unparsed::UnparsedMutExt,
|
||||
};
|
||||
|
||||
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct PublicKey {
|
||||
public_key: PublicKeyInner,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct PublicKeyInner {
|
||||
id: XsdAnyUri,
|
||||
owner: XsdAnyUri,
|
||||
public_key_pem: String,
|
||||
}
|
||||
|
||||
impl<U> UnparsedExtension<U> for PublicKey
|
||||
where
|
||||
U: UnparsedMutExt,
|
||||
{
|
||||
type Error = serde_json::Error;
|
||||
|
||||
fn try_from_unparsed(unparsed_mut: &mut U) -> Result<Self, Self::Error> {
|
||||
Ok(PublicKey {
|
||||
public_key: unparsed_mut.remove("publicKey")?,
|
||||
})
|
||||
}
|
||||
|
||||
fn try_into_unparsed(self, unparsed_mut: &mut U) -> Result<(), Self::Error> {
|
||||
unparsed_mut.insert("publicKey", self.public_key)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub type ExtendedPerson = Ext1<ApActor<Person>, PublicKey>;
|
||||
|
||||
fn main() -> Result<(), anyhow::Error> {
|
||||
let actor = ApActor::new(
|
||||
"http://in.box".parse()?,
|
||||
"http://out.box".parse()?,
|
||||
Person::new(),
|
||||
);
|
||||
|
||||
let mut person = Ext1::new(
|
||||
actor,
|
||||
PublicKey {
|
||||
public_key: PublicKeyInner {
|
||||
id: "http://key.id".parse()?,
|
||||
owner: "http://owner.id".parse()?,
|
||||
public_key_pem: "asdfasdfasdf".to_owned(),
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
person.set_context(context()).add_context(security());
|
||||
|
||||
let any_base = person.into_any_base()?;
|
||||
println!("any_base: {:#?}", any_base);
|
||||
let person = ExtendedPerson::from_any_base(any_base)?;
|
||||
|
||||
println!("person: {:#?}", person);
|
||||
Ok(())
|
||||
}
|
||||
```
|
||||
|
||||
## Contributing
|
||||
Feel free to open issues for anything you find an issue with. Please note that any contributed code will be licensed under the GPLv3.
|
||||
|
||||
## License
|
||||
|
||||
Copyright © 2020 Riley Trautman
|
||||
|
||||
ActivityStreams is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||
|
||||
ActivityStreams is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. This file is part of ActivityStreams.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with ActivityStreams. If not, see [http://www.gnu.org/licenses/](http://www.gnu.org/licenses/).
|
54
activitystreams-ext/build.sh
Executable file
54
activitystreams-ext/build.sh
Executable file
|
@ -0,0 +1,54 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
BUILD_DATE=$(date)
|
||||
VERSION=$1
|
||||
MIGRATIONS=$2
|
||||
|
||||
function require() {
|
||||
if [ "$1" = "" ]; then
|
||||
echo "input '$2' required"
|
||||
print_help
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
function print_help() {
|
||||
echo "build.sh"
|
||||
echo ""
|
||||
echo "Usage:"
|
||||
echo " build.sh [version]"
|
||||
echo ""
|
||||
echo "Args:"
|
||||
echo " version: The version of the current container"
|
||||
}
|
||||
|
||||
require "$VERSION" "version"
|
||||
|
||||
if ! docker run --rm -it arm64v8/ubuntu:19.10 /bin/bash -c 'echo "docker is configured correctly"'; then
|
||||
echo "docker is not configured to run on qemu-emulated architectures, fixing will require sudo"
|
||||
sudo docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
|
||||
fi
|
||||
|
||||
set -xe
|
||||
|
||||
cargo clean
|
||||
cargo doc --no-deps
|
||||
|
||||
mkdir -p artifacts
|
||||
rm -rf artifacts/html
|
||||
cp -r ./target/doc artifacts/html
|
||||
|
||||
docker build \
|
||||
--pull \
|
||||
--no-cache \
|
||||
--build-arg BUILD_DATE="${BUILD_DATE}" \
|
||||
--build-arg TAG="${TAG}" \
|
||||
-f Dockerfile.arm64v8 \
|
||||
-t "asonix/activitystreams-ext-docs:${VERSION}-arm64v8" \
|
||||
-t "asonix/activitystreams-ext-docs:latest-arm64v8" \
|
||||
-t "asonix/activitystreams-ext-docs:latest" \
|
||||
./artifacts
|
||||
|
||||
docker push "asonix/activitystreams-ext-docs:${VERSION}-arm64v8"
|
||||
docker push "asonix/activitystreams-ext-docs:latest-arm64v8"
|
||||
docker push "asonix/activitystreams-ext-docs:latest"
|
71
activitystreams-ext/examples/public_key.rs
Normal file
71
activitystreams-ext/examples/public_key.rs
Normal file
|
@ -0,0 +1,71 @@
|
|||
use activitystreams_ext::{Ext1, UnparsedExtension};
|
||||
use activitystreams::{
|
||||
actor::{ApActor, Person},
|
||||
context,
|
||||
prelude::*,
|
||||
primitives::XsdAnyUri,
|
||||
security,
|
||||
unparsed::UnparsedMutExt,
|
||||
};
|
||||
|
||||
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct PublicKey {
|
||||
public_key: PublicKeyInner,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct PublicKeyInner {
|
||||
id: XsdAnyUri,
|
||||
owner: XsdAnyUri,
|
||||
public_key_pem: String,
|
||||
}
|
||||
|
||||
impl<U> UnparsedExtension<U> for PublicKey
|
||||
where
|
||||
U: UnparsedMutExt,
|
||||
{
|
||||
type Error = serde_json::Error;
|
||||
|
||||
fn try_from_unparsed(unparsed_mut: &mut U) -> Result<Self, Self::Error> {
|
||||
Ok(PublicKey {
|
||||
public_key: unparsed_mut.remove("publicKey")?,
|
||||
})
|
||||
}
|
||||
|
||||
fn try_into_unparsed(self, unparsed_mut: &mut U) -> Result<(), Self::Error> {
|
||||
unparsed_mut.insert("publicKey", self.public_key)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub type ExtendedPerson = Ext1<ApActor<Person>, PublicKey>;
|
||||
|
||||
fn main() -> Result<(), anyhow::Error> {
|
||||
let actor = ApActor::new(
|
||||
"http://in.box".parse()?,
|
||||
"http://out.box".parse()?,
|
||||
Person::new(),
|
||||
);
|
||||
|
||||
let mut person = Ext1::new(
|
||||
actor,
|
||||
PublicKey {
|
||||
public_key: PublicKeyInner {
|
||||
id: "http://key.id".parse()?,
|
||||
owner: "http://owner.id".parse()?,
|
||||
public_key_pem: "asdfasdfasdf".to_owned(),
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
person.set_context(context()).add_context(security());
|
||||
|
||||
let any_base = person.into_any_base()?;
|
||||
println!("any_base: {:#?}", any_base);
|
||||
let person = ExtendedPerson::from_any_base(any_base)?;
|
||||
|
||||
println!("person: {:#?}", person);
|
||||
Ok(())
|
||||
}
|
201
activitystreams-ext/src/ext1.rs
Normal file
201
activitystreams-ext/src/ext1.rs
Normal file
|
@ -0,0 +1,201 @@
|
|||
use crate::Ext1;
|
||||
use activitystreams::{
|
||||
activity::{
|
||||
Activity, ActorAndObjectRef, AsActivity, AsQuestion, OptOriginRef, OptTargetRef, OriginRef,
|
||||
Question, TargetRef,
|
||||
},
|
||||
actor::{ApActor, AsApActor},
|
||||
base::{AnyBase, AsBase, Base},
|
||||
collection::{AsCollection, AsCollectionPage, Collection, CollectionPage},
|
||||
markers,
|
||||
object::{ApObject, AsApObject, AsObject, Object},
|
||||
primitives::OneOrMany,
|
||||
};
|
||||
|
||||
impl<Inner, A> markers::Base for Ext1<Inner, A> where Inner: markers::Base {}
|
||||
impl<Inner, A> markers::Object for Ext1<Inner, A> where Inner: markers::Object {}
|
||||
impl<Inner, A> markers::Collection for Ext1<Inner, A> where Inner: markers::Collection {}
|
||||
impl<Inner, A> markers::CollectionPage for Ext1<Inner, A> where Inner: markers::CollectionPage {}
|
||||
impl<Inner, A> markers::Actor for Ext1<Inner, A> where Inner: markers::Actor {}
|
||||
impl<Inner, A> markers::Activity for Ext1<Inner, A> where Inner: markers::Activity {}
|
||||
impl<Inner, A> markers::IntransitiveActivity for Ext1<Inner, A> where
|
||||
Inner: markers::IntransitiveActivity
|
||||
{
|
||||
}
|
||||
|
||||
impl<Inner, A, Kind> AsBase<Kind> for Ext1<Inner, A>
|
||||
where
|
||||
Inner: AsBase<Kind>,
|
||||
{
|
||||
fn base_ref(&self) -> &Base<Kind> {
|
||||
self.inner.base_ref()
|
||||
}
|
||||
|
||||
fn base_mut(&mut self) -> &mut Base<Kind> {
|
||||
self.inner.base_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Inner, A, Kind> AsObject<Kind> for Ext1<Inner, A>
|
||||
where
|
||||
Inner: AsObject<Kind>,
|
||||
{
|
||||
fn object_ref(&self) -> &Object<Kind> {
|
||||
self.inner.object_ref()
|
||||
}
|
||||
|
||||
fn object_mut(&mut self) -> &mut Object<Kind> {
|
||||
self.inner.object_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Inner, A, ApInner> AsApObject<ApInner> for Ext1<Inner, A>
|
||||
where
|
||||
Inner: AsApObject<ApInner>,
|
||||
{
|
||||
fn ap_object_ref(&self) -> &ApObject<ApInner> {
|
||||
self.inner.ap_object_ref()
|
||||
}
|
||||
|
||||
fn ap_object_mut(&mut self) -> &mut ApObject<ApInner> {
|
||||
self.inner.ap_object_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Inner, A, Kind> AsCollection<Kind> for Ext1<Inner, A>
|
||||
where
|
||||
Inner: AsCollection<Kind>,
|
||||
{
|
||||
fn collection_ref(&self) -> &Collection<Kind> {
|
||||
self.inner.collection_ref()
|
||||
}
|
||||
|
||||
fn collection_mut(&mut self) -> &mut Collection<Kind> {
|
||||
self.inner.collection_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Inner, A, Kind> AsCollectionPage<Kind> for Ext1<Inner, A>
|
||||
where
|
||||
Inner: AsCollectionPage<Kind>,
|
||||
{
|
||||
fn collection_page_ref(&self) -> &CollectionPage<Kind> {
|
||||
self.inner.collection_page_ref()
|
||||
}
|
||||
|
||||
fn collection_page_mut(&mut self) -> &mut CollectionPage<Kind> {
|
||||
self.inner.collection_page_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Inner, A, ApInner> AsApActor<ApInner> for Ext1<Inner, A>
|
||||
where
|
||||
Inner: AsApActor<ApInner>,
|
||||
{
|
||||
fn ap_actor_ref(&self) -> &ApActor<ApInner> {
|
||||
self.inner.ap_actor_ref()
|
||||
}
|
||||
|
||||
fn ap_actor_mut(&mut self) -> &mut ApActor<ApInner> {
|
||||
self.inner.ap_actor_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Inner, A, Kind> AsActivity<Kind> for Ext1<Inner, A>
|
||||
where
|
||||
Inner: AsActivity<Kind>,
|
||||
{
|
||||
fn activity_ref(&self) -> &Activity<Kind> {
|
||||
self.inner.activity_ref()
|
||||
}
|
||||
|
||||
fn activity_mut(&mut self) -> &mut Activity<Kind> {
|
||||
self.inner.activity_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Inner, A> ActorAndObjectRef for Ext1<Inner, A>
|
||||
where
|
||||
Inner: ActorAndObjectRef,
|
||||
{
|
||||
fn actor_field_ref(&self) -> &OneOrMany<AnyBase> {
|
||||
self.inner.actor_field_ref()
|
||||
}
|
||||
|
||||
fn actor_field_mut(&mut self) -> &mut OneOrMany<AnyBase> {
|
||||
self.inner.actor_field_mut()
|
||||
}
|
||||
|
||||
fn object_field_ref(&self) -> &OneOrMany<AnyBase> {
|
||||
self.inner.object_field_ref()
|
||||
}
|
||||
|
||||
fn object_field_mut(&mut self) -> &mut OneOrMany<AnyBase> {
|
||||
self.inner.object_field_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Inner, A> TargetRef for Ext1<Inner, A>
|
||||
where
|
||||
Inner: TargetRef,
|
||||
{
|
||||
fn target_field_ref(&self) -> &OneOrMany<AnyBase> {
|
||||
self.inner.target_field_ref()
|
||||
}
|
||||
|
||||
fn target_field_mut(&mut self) -> &mut OneOrMany<AnyBase> {
|
||||
self.inner.target_field_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Inner, A> OriginRef for Ext1<Inner, A>
|
||||
where
|
||||
Inner: OriginRef,
|
||||
{
|
||||
fn origin_field_ref(&self) -> &OneOrMany<AnyBase> {
|
||||
self.inner.origin_field_ref()
|
||||
}
|
||||
|
||||
fn origin_field_mut(&mut self) -> &mut OneOrMany<AnyBase> {
|
||||
self.inner.origin_field_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Inner, A> OptTargetRef for Ext1<Inner, A>
|
||||
where
|
||||
Inner: OptTargetRef,
|
||||
{
|
||||
fn target_field_ref(&self) -> &Option<OneOrMany<AnyBase>> {
|
||||
self.inner.target_field_ref()
|
||||
}
|
||||
|
||||
fn target_field_mut(&mut self) -> &mut Option<OneOrMany<AnyBase>> {
|
||||
self.inner.target_field_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Inner, A> OptOriginRef for Ext1<Inner, A>
|
||||
where
|
||||
Inner: OptOriginRef,
|
||||
{
|
||||
fn origin_field_ref(&self) -> &Option<OneOrMany<AnyBase>> {
|
||||
self.inner.origin_field_ref()
|
||||
}
|
||||
|
||||
fn origin_field_mut(&mut self) -> &mut Option<OneOrMany<AnyBase>> {
|
||||
self.inner.origin_field_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Inner, A> AsQuestion for Ext1<Inner, A>
|
||||
where
|
||||
Inner: AsQuestion,
|
||||
{
|
||||
fn question_ref(&self) -> &Question {
|
||||
self.inner.question_ref()
|
||||
}
|
||||
|
||||
fn question_mut(&mut self) -> &mut Question {
|
||||
self.inner.question_mut()
|
||||
}
|
||||
}
|
201
activitystreams-ext/src/ext2.rs
Normal file
201
activitystreams-ext/src/ext2.rs
Normal file
|
@ -0,0 +1,201 @@
|
|||
use crate::Ext2;
|
||||
use activitystreams::{
|
||||
activity::{
|
||||
Activity, ActorAndObjectRef, AsActivity, AsQuestion, OptOriginRef, OptTargetRef, OriginRef,
|
||||
Question, TargetRef,
|
||||
},
|
||||
actor::{ApActor, AsApActor},
|
||||
base::{AnyBase, AsBase, Base},
|
||||
collection::{AsCollection, AsCollectionPage, Collection, CollectionPage},
|
||||
markers,
|
||||
object::{ApObject, AsApObject, AsObject, Object},
|
||||
primitives::OneOrMany,
|
||||
};
|
||||
|
||||
impl<Inner, A, B> markers::Base for Ext2<Inner, A, B> where Inner: markers::Base {}
|
||||
impl<Inner, A, B> markers::Object for Ext2<Inner, A, B> where Inner: markers::Object {}
|
||||
impl<Inner, A, B> markers::Collection for Ext2<Inner, A, B> where Inner: markers::Collection {}
|
||||
impl<Inner, A, B> markers::CollectionPage for Ext2<Inner, A, B> where Inner: markers::CollectionPage {}
|
||||
impl<Inner, A, B> markers::Actor for Ext2<Inner, A, B> where Inner: markers::Actor {}
|
||||
impl<Inner, A, B> markers::Activity for Ext2<Inner, A, B> where Inner: markers::Activity {}
|
||||
impl<Inner, A, B> markers::IntransitiveActivity for Ext2<Inner, A, B> where
|
||||
Inner: markers::IntransitiveActivity
|
||||
{
|
||||
}
|
||||
|
||||
impl<Inner, A, B, Kind> AsBase<Kind> for Ext2<Inner, A, B>
|
||||
where
|
||||
Inner: AsBase<Kind>,
|
||||
{
|
||||
fn base_ref(&self) -> &Base<Kind> {
|
||||
self.inner.base_ref()
|
||||
}
|
||||
|
||||
fn base_mut(&mut self) -> &mut Base<Kind> {
|
||||
self.inner.base_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Inner, A, B, Kind> AsObject<Kind> for Ext2<Inner, A, B>
|
||||
where
|
||||
Inner: AsObject<Kind>,
|
||||
{
|
||||
fn object_ref(&self) -> &Object<Kind> {
|
||||
self.inner.object_ref()
|
||||
}
|
||||
|
||||
fn object_mut(&mut self) -> &mut Object<Kind> {
|
||||
self.inner.object_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Inner, A, B, ApInner> AsApObject<ApInner> for Ext2<Inner, A, B>
|
||||
where
|
||||
Inner: AsApObject<ApInner>,
|
||||
{
|
||||
fn ap_object_ref(&self) -> &ApObject<ApInner> {
|
||||
self.inner.ap_object_ref()
|
||||
}
|
||||
|
||||
fn ap_object_mut(&mut self) -> &mut ApObject<ApInner> {
|
||||
self.inner.ap_object_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Inner, A, B, Kind> AsCollection<Kind> for Ext2<Inner, A, B>
|
||||
where
|
||||
Inner: AsCollection<Kind>,
|
||||
{
|
||||
fn collection_ref(&self) -> &Collection<Kind> {
|
||||
self.inner.collection_ref()
|
||||
}
|
||||
|
||||
fn collection_mut(&mut self) -> &mut Collection<Kind> {
|
||||
self.inner.collection_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Inner, A, B, Kind> AsCollectionPage<Kind> for Ext2<Inner, A, B>
|
||||
where
|
||||
Inner: AsCollectionPage<Kind>,
|
||||
{
|
||||
fn collection_page_ref(&self) -> &CollectionPage<Kind> {
|
||||
self.inner.collection_page_ref()
|
||||
}
|
||||
|
||||
fn collection_page_mut(&mut self) -> &mut CollectionPage<Kind> {
|
||||
self.inner.collection_page_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Inner, A, B, ApInner> AsApActor<ApInner> for Ext2<Inner, A, B>
|
||||
where
|
||||
Inner: AsApActor<ApInner>,
|
||||
{
|
||||
fn ap_actor_ref(&self) -> &ApActor<ApInner> {
|
||||
self.inner.ap_actor_ref()
|
||||
}
|
||||
|
||||
fn ap_actor_mut(&mut self) -> &mut ApActor<ApInner> {
|
||||
self.inner.ap_actor_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Inner, A, B, Kind> AsActivity<Kind> for Ext2<Inner, A, B>
|
||||
where
|
||||
Inner: AsActivity<Kind>,
|
||||
{
|
||||
fn activity_ref(&self) -> &Activity<Kind> {
|
||||
self.inner.activity_ref()
|
||||
}
|
||||
|
||||
fn activity_mut(&mut self) -> &mut Activity<Kind> {
|
||||
self.inner.activity_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Inner, A, B> ActorAndObjectRef for Ext2<Inner, A, B>
|
||||
where
|
||||
Inner: ActorAndObjectRef,
|
||||
{
|
||||
fn actor_field_ref(&self) -> &OneOrMany<AnyBase> {
|
||||
self.inner.actor_field_ref()
|
||||
}
|
||||
|
||||
fn actor_field_mut(&mut self) -> &mut OneOrMany<AnyBase> {
|
||||
self.inner.actor_field_mut()
|
||||
}
|
||||
|
||||
fn object_field_ref(&self) -> &OneOrMany<AnyBase> {
|
||||
self.inner.object_field_ref()
|
||||
}
|
||||
|
||||
fn object_field_mut(&mut self) -> &mut OneOrMany<AnyBase> {
|
||||
self.inner.object_field_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Inner, A, B> TargetRef for Ext2<Inner, A, B>
|
||||
where
|
||||
Inner: TargetRef,
|
||||
{
|
||||
fn target_field_ref(&self) -> &OneOrMany<AnyBase> {
|
||||
self.inner.target_field_ref()
|
||||
}
|
||||
|
||||
fn target_field_mut(&mut self) -> &mut OneOrMany<AnyBase> {
|
||||
self.inner.target_field_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Inner, A, B> OriginRef for Ext2<Inner, A, B>
|
||||
where
|
||||
Inner: OriginRef,
|
||||
{
|
||||
fn origin_field_ref(&self) -> &OneOrMany<AnyBase> {
|
||||
self.inner.origin_field_ref()
|
||||
}
|
||||
|
||||
fn origin_field_mut(&mut self) -> &mut OneOrMany<AnyBase> {
|
||||
self.inner.origin_field_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Inner, A, B> OptTargetRef for Ext2<Inner, A, B>
|
||||
where
|
||||
Inner: OptTargetRef,
|
||||
{
|
||||
fn target_field_ref(&self) -> &Option<OneOrMany<AnyBase>> {
|
||||
self.inner.target_field_ref()
|
||||
}
|
||||
|
||||
fn target_field_mut(&mut self) -> &mut Option<OneOrMany<AnyBase>> {
|
||||
self.inner.target_field_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Inner, A, B> OptOriginRef for Ext2<Inner, A, B>
|
||||
where
|
||||
Inner: OptOriginRef,
|
||||
{
|
||||
fn origin_field_ref(&self) -> &Option<OneOrMany<AnyBase>> {
|
||||
self.inner.origin_field_ref()
|
||||
}
|
||||
|
||||
fn origin_field_mut(&mut self) -> &mut Option<OneOrMany<AnyBase>> {
|
||||
self.inner.origin_field_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Inner, A, B> AsQuestion for Ext2<Inner, A, B>
|
||||
where
|
||||
Inner: AsQuestion,
|
||||
{
|
||||
fn question_ref(&self) -> &Question {
|
||||
self.inner.question_ref()
|
||||
}
|
||||
|
||||
fn question_mut(&mut self) -> &mut Question {
|
||||
self.inner.question_mut()
|
||||
}
|
||||
}
|
204
activitystreams-ext/src/ext3.rs
Normal file
204
activitystreams-ext/src/ext3.rs
Normal file
|
@ -0,0 +1,204 @@
|
|||
use crate::Ext3;
|
||||
use activitystreams::{
|
||||
activity::{
|
||||
Activity, ActorAndObjectRef, AsActivity, AsQuestion, OptOriginRef, OptTargetRef, OriginRef,
|
||||
Question, TargetRef,
|
||||
},
|
||||
actor::{ApActor, AsApActor},
|
||||
base::{AnyBase, AsBase, Base},
|
||||
collection::{AsCollection, AsCollectionPage, Collection, CollectionPage},
|
||||
markers,
|
||||
object::{ApObject, AsApObject, AsObject, Object},
|
||||
primitives::OneOrMany,
|
||||
};
|
||||
|
||||
impl<Inner, A, B, C> markers::Base for Ext3<Inner, A, B, C> where Inner: markers::Base {}
|
||||
impl<Inner, A, B, C> markers::Object for Ext3<Inner, A, B, C> where Inner: markers::Object {}
|
||||
impl<Inner, A, B, C> markers::Collection for Ext3<Inner, A, B, C> where Inner: markers::Collection {}
|
||||
impl<Inner, A, B, C> markers::CollectionPage for Ext3<Inner, A, B, C> where
|
||||
Inner: markers::CollectionPage
|
||||
{
|
||||
}
|
||||
impl<Inner, A, B, C> markers::Actor for Ext3<Inner, A, B, C> where Inner: markers::Actor {}
|
||||
impl<Inner, A, B, C> markers::Activity for Ext3<Inner, A, B, C> where Inner: markers::Activity {}
|
||||
impl<Inner, A, B, C> markers::IntransitiveActivity for Ext3<Inner, A, B, C> where
|
||||
Inner: markers::IntransitiveActivity
|
||||
{
|
||||
}
|
||||
|
||||
impl<Inner, A, B, C, Kind> AsBase<Kind> for Ext3<Inner, A, B, C>
|
||||
where
|
||||
Inner: AsBase<Kind>,
|
||||
{
|
||||
fn base_ref(&self) -> &Base<Kind> {
|
||||
self.inner.base_ref()
|
||||
}
|
||||
|
||||
fn base_mut(&mut self) -> &mut Base<Kind> {
|
||||
self.inner.base_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Inner, A, B, C, Kind> AsObject<Kind> for Ext3<Inner, A, B, C>
|
||||
where
|
||||
Inner: AsObject<Kind>,
|
||||
{
|
||||
fn object_ref(&self) -> &Object<Kind> {
|
||||
self.inner.object_ref()
|
||||
}
|
||||
|
||||
fn object_mut(&mut self) -> &mut Object<Kind> {
|
||||
self.inner.object_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Inner, A, B, C, ApInner> AsApObject<ApInner> for Ext3<Inner, A, B, C>
|
||||
where
|
||||
Inner: AsApObject<ApInner>,
|
||||
{
|
||||
fn ap_object_ref(&self) -> &ApObject<ApInner> {
|
||||
self.inner.ap_object_ref()
|
||||
}
|
||||
|
||||
fn ap_object_mut(&mut self) -> &mut ApObject<ApInner> {
|
||||
self.inner.ap_object_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Inner, A, B, C, Kind> AsCollection<Kind> for Ext3<Inner, A, B, C>
|
||||
where
|
||||
Inner: AsCollection<Kind>,
|
||||
{
|
||||
fn collection_ref(&self) -> &Collection<Kind> {
|
||||
self.inner.collection_ref()
|
||||
}
|
||||
|
||||
fn collection_mut(&mut self) -> &mut Collection<Kind> {
|
||||
self.inner.collection_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Inner, A, B, C, Kind> AsCollectionPage<Kind> for Ext3<Inner, A, B, C>
|
||||
where
|
||||
Inner: AsCollectionPage<Kind>,
|
||||
{
|
||||
fn collection_page_ref(&self) -> &CollectionPage<Kind> {
|
||||
self.inner.collection_page_ref()
|
||||
}
|
||||
|
||||
fn collection_page_mut(&mut self) -> &mut CollectionPage<Kind> {
|
||||
self.inner.collection_page_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Inner, A, B, C, ApInner> AsApActor<ApInner> for Ext3<Inner, A, B, C>
|
||||
where
|
||||
Inner: AsApActor<ApInner>,
|
||||
{
|
||||
fn ap_actor_ref(&self) -> &ApActor<ApInner> {
|
||||
self.inner.ap_actor_ref()
|
||||
}
|
||||
|
||||
fn ap_actor_mut(&mut self) -> &mut ApActor<ApInner> {
|
||||
self.inner.ap_actor_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Inner, A, B, C, Kind> AsActivity<Kind> for Ext3<Inner, A, B, C>
|
||||
where
|
||||
Inner: AsActivity<Kind>,
|
||||
{
|
||||
fn activity_ref(&self) -> &Activity<Kind> {
|
||||
self.inner.activity_ref()
|
||||
}
|
||||
|
||||
fn activity_mut(&mut self) -> &mut Activity<Kind> {
|
||||
self.inner.activity_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Inner, A, B, C> ActorAndObjectRef for Ext3<Inner, A, B, C>
|
||||
where
|
||||
Inner: ActorAndObjectRef,
|
||||
{
|
||||
fn actor_field_ref(&self) -> &OneOrMany<AnyBase> {
|
||||
self.inner.actor_field_ref()
|
||||
}
|
||||
|
||||
fn actor_field_mut(&mut self) -> &mut OneOrMany<AnyBase> {
|
||||
self.inner.actor_field_mut()
|
||||
}
|
||||
|
||||
fn object_field_ref(&self) -> &OneOrMany<AnyBase> {
|
||||
self.inner.object_field_ref()
|
||||
}
|
||||
|
||||
fn object_field_mut(&mut self) -> &mut OneOrMany<AnyBase> {
|
||||
self.inner.object_field_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Inner, A, B, C> TargetRef for Ext3<Inner, A, B, C>
|
||||
where
|
||||
Inner: TargetRef,
|
||||
{
|
||||
fn target_field_ref(&self) -> &OneOrMany<AnyBase> {
|
||||
self.inner.target_field_ref()
|
||||
}
|
||||
|
||||
fn target_field_mut(&mut self) -> &mut OneOrMany<AnyBase> {
|
||||
self.inner.target_field_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Inner, A, B, C> OriginRef for Ext3<Inner, A, B, C>
|
||||
where
|
||||
Inner: OriginRef,
|
||||
{
|
||||
fn origin_field_ref(&self) -> &OneOrMany<AnyBase> {
|
||||
self.inner.origin_field_ref()
|
||||
}
|
||||
|
||||
fn origin_field_mut(&mut self) -> &mut OneOrMany<AnyBase> {
|
||||
self.inner.origin_field_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Inner, A, B, C> OptTargetRef for Ext3<Inner, A, B, C>
|
||||
where
|
||||
Inner: OptTargetRef,
|
||||
{
|
||||
fn target_field_ref(&self) -> &Option<OneOrMany<AnyBase>> {
|
||||
self.inner.target_field_ref()
|
||||
}
|
||||
|
||||
fn target_field_mut(&mut self) -> &mut Option<OneOrMany<AnyBase>> {
|
||||
self.inner.target_field_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Inner, A, B, C> OptOriginRef for Ext3<Inner, A, B, C>
|
||||
where
|
||||
Inner: OptOriginRef,
|
||||
{
|
||||
fn origin_field_ref(&self) -> &Option<OneOrMany<AnyBase>> {
|
||||
self.inner.origin_field_ref()
|
||||
}
|
||||
|
||||
fn origin_field_mut(&mut self) -> &mut Option<OneOrMany<AnyBase>> {
|
||||
self.inner.origin_field_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Inner, A, B, C> AsQuestion for Ext3<Inner, A, B, C>
|
||||
where
|
||||
Inner: AsQuestion,
|
||||
{
|
||||
fn question_ref(&self) -> &Question {
|
||||
self.inner.question_ref()
|
||||
}
|
||||
|
||||
fn question_mut(&mut self) -> &mut Question {
|
||||
self.inner.question_mut()
|
||||
}
|
||||
}
|
207
activitystreams-ext/src/ext4.rs
Normal file
207
activitystreams-ext/src/ext4.rs
Normal file
|
@ -0,0 +1,207 @@
|
|||
use crate::Ext4;
|
||||
use activitystreams::{
|
||||
activity::{
|
||||
Activity, ActorAndObjectRef, AsActivity, AsQuestion, OptOriginRef, OptTargetRef, OriginRef,
|
||||
Question, TargetRef,
|
||||
},
|
||||
actor::{ApActor, AsApActor},
|
||||
base::{AnyBase, AsBase, Base},
|
||||
collection::{AsCollection, AsCollectionPage, Collection, CollectionPage},
|
||||
markers,
|
||||
object::{ApObject, AsApObject, AsObject, Object},
|
||||
primitives::OneOrMany,
|
||||
};
|
||||
|
||||
impl<Inner, A, B, C, D> markers::Base for Ext4<Inner, A, B, C, D> where Inner: markers::Base {}
|
||||
impl<Inner, A, B, C, D> markers::Object for Ext4<Inner, A, B, C, D> where Inner: markers::Object {}
|
||||
impl<Inner, A, B, C, D> markers::Collection for Ext4<Inner, A, B, C, D> where
|
||||
Inner: markers::Collection
|
||||
{
|
||||
}
|
||||
impl<Inner, A, B, C, D> markers::CollectionPage for Ext4<Inner, A, B, C, D> where
|
||||
Inner: markers::CollectionPage
|
||||
{
|
||||
}
|
||||
impl<Inner, A, B, C, D> markers::Actor for Ext4<Inner, A, B, C, D> where Inner: markers::Actor {}
|
||||
impl<Inner, A, B, C, D> markers::Activity for Ext4<Inner, A, B, C, D> where Inner: markers::Activity {}
|
||||
impl<Inner, A, B, C, D> markers::IntransitiveActivity for Ext4<Inner, A, B, C, D> where
|
||||
Inner: markers::IntransitiveActivity
|
||||
{
|
||||
}
|
||||
|
||||
impl<Inner, A, B, C, D, Kind> AsBase<Kind> for Ext4<Inner, A, B, C, D>
|
||||
where
|
||||
Inner: AsBase<Kind>,
|
||||
{
|
||||
fn base_ref(&self) -> &Base<Kind> {
|
||||
self.inner.base_ref()
|
||||
}
|
||||
|
||||
fn base_mut(&mut self) -> &mut Base<Kind> {
|
||||
self.inner.base_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Inner, A, B, C, D, Kind> AsObject<Kind> for Ext4<Inner, A, B, C, D>
|
||||
where
|
||||
Inner: AsObject<Kind>,
|
||||
{
|
||||
fn object_ref(&self) -> &Object<Kind> {
|
||||
self.inner.object_ref()
|
||||
}
|
||||
|
||||
fn object_mut(&mut self) -> &mut Object<Kind> {
|
||||
self.inner.object_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Inner, A, B, C, D, ApInner> AsApObject<ApInner> for Ext4<Inner, A, B, C, D>
|
||||
where
|
||||
Inner: AsApObject<ApInner>,
|
||||
{
|
||||
fn ap_object_ref(&self) -> &ApObject<ApInner> {
|
||||
self.inner.ap_object_ref()
|
||||
}
|
||||
|
||||
fn ap_object_mut(&mut self) -> &mut ApObject<ApInner> {
|
||||
self.inner.ap_object_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Inner, A, B, C, D, Kind> AsCollection<Kind> for Ext4<Inner, A, B, C, D>
|
||||
where
|
||||
Inner: AsCollection<Kind>,
|
||||
{
|
||||
fn collection_ref(&self) -> &Collection<Kind> {
|
||||
self.inner.collection_ref()
|
||||
}
|
||||
|
||||
fn collection_mut(&mut self) -> &mut Collection<Kind> {
|
||||
self.inner.collection_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Inner, A, B, C, D, Kind> AsCollectionPage<Kind> for Ext4<Inner, A, B, C, D>
|
||||
where
|
||||
Inner: AsCollectionPage<Kind>,
|
||||
{
|
||||
fn collection_page_ref(&self) -> &CollectionPage<Kind> {
|
||||
self.inner.collection_page_ref()
|
||||
}
|
||||
|
||||
fn collection_page_mut(&mut self) -> &mut CollectionPage<Kind> {
|
||||
self.inner.collection_page_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Inner, A, B, C, D, ApInner> AsApActor<ApInner> for Ext4<Inner, A, B, C, D>
|
||||
where
|
||||
Inner: AsApActor<ApInner>,
|
||||
{
|
||||
fn ap_actor_ref(&self) -> &ApActor<ApInner> {
|
||||
self.inner.ap_actor_ref()
|
||||
}
|
||||
|
||||
fn ap_actor_mut(&mut self) -> &mut ApActor<ApInner> {
|
||||
self.inner.ap_actor_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Inner, A, B, C, D, Kind> AsActivity<Kind> for Ext4<Inner, A, B, C, D>
|
||||
where
|
||||
Inner: AsActivity<Kind>,
|
||||
{
|
||||
fn activity_ref(&self) -> &Activity<Kind> {
|
||||
self.inner.activity_ref()
|
||||
}
|
||||
|
||||
fn activity_mut(&mut self) -> &mut Activity<Kind> {
|
||||
self.inner.activity_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Inner, A, B, C, D> ActorAndObjectRef for Ext4<Inner, A, B, C, D>
|
||||
where
|
||||
Inner: ActorAndObjectRef,
|
||||
{
|
||||
fn actor_field_ref(&self) -> &OneOrMany<AnyBase> {
|
||||
self.inner.actor_field_ref()
|
||||
}
|
||||
|
||||
fn actor_field_mut(&mut self) -> &mut OneOrMany<AnyBase> {
|
||||
self.inner.actor_field_mut()
|
||||
}
|
||||
|
||||
fn object_field_ref(&self) -> &OneOrMany<AnyBase> {
|
||||
self.inner.object_field_ref()
|
||||
}
|
||||
|
||||
fn object_field_mut(&mut self) -> &mut OneOrMany<AnyBase> {
|
||||
self.inner.object_field_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Inner, A, B, C, D> TargetRef for Ext4<Inner, A, B, C, D>
|
||||
where
|
||||
Inner: TargetRef,
|
||||
{
|
||||
fn target_field_ref(&self) -> &OneOrMany<AnyBase> {
|
||||
self.inner.target_field_ref()
|
||||
}
|
||||
|
||||
fn target_field_mut(&mut self) -> &mut OneOrMany<AnyBase> {
|
||||
self.inner.target_field_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Inner, A, B, C, D> OriginRef for Ext4<Inner, A, B, C, D>
|
||||
where
|
||||
Inner: OriginRef,
|
||||
{
|
||||
fn origin_field_ref(&self) -> &OneOrMany<AnyBase> {
|
||||
self.inner.origin_field_ref()
|
||||
}
|
||||
|
||||
fn origin_field_mut(&mut self) -> &mut OneOrMany<AnyBase> {
|
||||
self.inner.origin_field_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Inner, A, B, C, D> OptTargetRef for Ext4<Inner, A, B, C, D>
|
||||
where
|
||||
Inner: OptTargetRef,
|
||||
{
|
||||
fn target_field_ref(&self) -> &Option<OneOrMany<AnyBase>> {
|
||||
self.inner.target_field_ref()
|
||||
}
|
||||
|
||||
fn target_field_mut(&mut self) -> &mut Option<OneOrMany<AnyBase>> {
|
||||
self.inner.target_field_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Inner, A, B, C, D> OptOriginRef for Ext4<Inner, A, B, C, D>
|
||||
where
|
||||
Inner: OptOriginRef,
|
||||
{
|
||||
fn origin_field_ref(&self) -> &Option<OneOrMany<AnyBase>> {
|
||||
self.inner.origin_field_ref()
|
||||
}
|
||||
|
||||
fn origin_field_mut(&mut self) -> &mut Option<OneOrMany<AnyBase>> {
|
||||
self.inner.origin_field_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Inner, A, B, C, D> AsQuestion for Ext4<Inner, A, B, C, D>
|
||||
where
|
||||
Inner: AsQuestion,
|
||||
{
|
||||
fn question_ref(&self) -> &Question {
|
||||
self.inner.question_ref()
|
||||
}
|
||||
|
||||
fn question_mut(&mut self) -> &mut Question {
|
||||
self.inner.question_mut()
|
||||
}
|
||||
}
|
375
activitystreams-ext/src/lib.rs
Normal file
375
activitystreams-ext/src/lib.rs
Normal file
|
@ -0,0 +1,375 @@
|
|||
//! # An extension API for activitystreams-new
|
||||
//! _This crate provides Ext1, Ext2, Ext3, and Ext4 for adding extensions to ActivityStreams types_
|
||||
//!
|
||||
//! - Find the code on [git.asonix.dog](https://git.asonix.dog/asonix/activitystreams-ext)
|
||||
//! - Read the docs on [activitystreams-ext.asonix.dog](https://activitystreams-ext.asonix.dog)
|
||||
//! - Join the matrix channel at [#activitypub:asonix.dog](https://matrix.to/#/!fAEcHyTUdAaKCzIKCt:asonix.dog?via=asonix.dog&via=matrix.org&via=t2bot.io)
|
||||
//! - Hit me up on [mastodon](https://asonix.dog/@asonix)
|
||||
//!
|
||||
//! ## Usage
|
||||
//!
|
||||
//! First, add ActivityStreams to your dependencies
|
||||
//! ```toml
|
||||
//! [dependencies]
|
||||
//! activitystreams-new = { git = "https://git.asonix.dog/asonix/activitystreams-sketch", branch = "main" }
|
||||
//! activitystreams-ext = { git = "https://git.asonix.dog/asonix/activitystreams-ext", branch = "main" }
|
||||
//! ```
|
||||
//!
|
||||
//! For an example, we'll implement a PublicKey extension and demonstrate usage with Ext1
|
||||
//! ```rust
|
||||
//! use activitystreams_ext::{Ext1, UnparsedExtension};
|
||||
//! use activitystreams::{
|
||||
//! actor::{ApActor, Person},
|
||||
//! context,
|
||||
//! prelude::*,
|
||||
//! primitives::XsdAnyUri,
|
||||
//! security,
|
||||
//! unparsed::UnparsedMutExt,
|
||||
//! };
|
||||
//!
|
||||
//! #[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
|
||||
//! #[serde(rename_all = "camelCase")]
|
||||
//! pub struct PublicKey {
|
||||
//! public_key: PublicKeyInner,
|
||||
//! }
|
||||
//!
|
||||
//! #[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
|
||||
//! #[serde(rename_all = "camelCase")]
|
||||
//! pub struct PublicKeyInner {
|
||||
//! id: XsdAnyUri,
|
||||
//! owner: XsdAnyUri,
|
||||
//! public_key_pem: String,
|
||||
//! }
|
||||
//!
|
||||
//! impl<U> UnparsedExtension<U> for PublicKey
|
||||
//! where
|
||||
//! U: UnparsedMutExt,
|
||||
//! {
|
||||
//! type Error = serde_json::Error;
|
||||
//!
|
||||
//! fn try_from_unparsed(unparsed_mut: &mut U) -> Result<Self, Self::Error> {
|
||||
//! Ok(PublicKey {
|
||||
//! public_key: unparsed_mut.remove("publicKey")?,
|
||||
//! })
|
||||
//! }
|
||||
//!
|
||||
//! fn try_into_unparsed(self, unparsed_mut: &mut U) -> Result<(), Self::Error> {
|
||||
//! unparsed_mut.insert("publicKey", self.public_key)?;
|
||||
//! Ok(())
|
||||
//! }
|
||||
//! }
|
||||
//!
|
||||
//! pub type ExtendedPerson = Ext1<ApActor<Person>, PublicKey>;
|
||||
//!
|
||||
//! fn main() -> Result<(), anyhow::Error> {
|
||||
//! let actor = ApActor::new(
|
||||
//! "http://in.box".parse()?,
|
||||
//! "http://out.box".parse()?,
|
||||
//! Person::new(),
|
||||
//! );
|
||||
//!
|
||||
//! let mut person = Ext1::new(
|
||||
//! actor,
|
||||
//! PublicKey {
|
||||
//! public_key: PublicKeyInner {
|
||||
//! id: "http://key.id".parse()?,
|
||||
//! owner: "http://owner.id".parse()?,
|
||||
//! public_key_pem: "asdfasdfasdf".to_owned(),
|
||||
//! },
|
||||
//! },
|
||||
//! );
|
||||
//!
|
||||
//! person.set_context(context()).add_context(security());
|
||||
//!
|
||||
//! let any_base = person.into_any_base()?;
|
||||
//! println!("any_base: {:#?}", any_base);
|
||||
//! let person = ExtendedPerson::from_any_base(any_base)?;
|
||||
//!
|
||||
//! println!("person: {:#?}", person);
|
||||
//! Ok(())
|
||||
//! }
|
||||
//! ```
|
||||
|
||||
#![doc(html_root_url = "https://activitystreams-ext.asonix.dog")]
|
||||
|
||||
use activitystreams::{
|
||||
base::{Base, Extends},
|
||||
unparsed::{UnparsedMut, UnparsedMutExt},
|
||||
};
|
||||
|
||||
mod ext1;
|
||||
mod ext2;
|
||||
mod ext3;
|
||||
mod ext4;
|
||||
|
||||
/// Transform types from and into the Unparsed structure
|
||||
pub trait UnparsedExtension<U>
|
||||
where
|
||||
U: UnparsedMutExt,
|
||||
{
|
||||
type Error: std::error::Error;
|
||||
|
||||
/// Generate Self from Unparsed
|
||||
fn try_from_unparsed(unparsed_mut: &mut U) -> Result<Self, Self::Error>
|
||||
where
|
||||
Self: Sized;
|
||||
|
||||
/// Insert Self into Unparsed
|
||||
fn try_into_unparsed(self, unparsed_mut: &mut U) -> Result<(), Self::Error>;
|
||||
}
|
||||
|
||||
/// Extend a type with a single value
|
||||
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
|
||||
pub struct Ext1<Inner, A> {
|
||||
#[serde(flatten)]
|
||||
pub ext_one: A,
|
||||
|
||||
/// The type being extended
|
||||
#[serde(flatten)]
|
||||
pub inner: Inner,
|
||||
}
|
||||
|
||||
/// Extend a type with two values
|
||||
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
|
||||
pub struct Ext2<Inner, A, B> {
|
||||
#[serde(flatten)]
|
||||
pub ext_one: A,
|
||||
|
||||
#[serde(flatten)]
|
||||
pub ext_two: B,
|
||||
|
||||
/// The type being extended
|
||||
#[serde(flatten)]
|
||||
pub inner: Inner,
|
||||
}
|
||||
|
||||
/// Extend a type with three values
|
||||
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
|
||||
pub struct Ext3<Inner, A, B, C> {
|
||||
#[serde(flatten)]
|
||||
pub ext_one: A,
|
||||
|
||||
#[serde(flatten)]
|
||||
pub ext_two: B,
|
||||
|
||||
#[serde(flatten)]
|
||||
pub ext_three: C,
|
||||
|
||||
/// The type being extended
|
||||
#[serde(flatten)]
|
||||
pub inner: Inner,
|
||||
}
|
||||
|
||||
/// Extend a type with four values
|
||||
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
|
||||
pub struct Ext4<Inner, A, B, C, D> {
|
||||
#[serde(flatten)]
|
||||
pub ext_one: A,
|
||||
|
||||
#[serde(flatten)]
|
||||
pub ext_two: B,
|
||||
|
||||
#[serde(flatten)]
|
||||
pub ext_three: C,
|
||||
|
||||
#[serde(flatten)]
|
||||
pub ext_four: D,
|
||||
|
||||
/// The type being extended
|
||||
#[serde(flatten)]
|
||||
pub inner: Inner,
|
||||
}
|
||||
|
||||
impl<Inner, A> Ext1<Inner, A> {
|
||||
pub fn new(inner: Inner, ext_one: A) -> Self {
|
||||
Ext1 { inner, ext_one }
|
||||
}
|
||||
|
||||
pub fn extend<B>(self, ext_two: B) -> Ext2<Inner, A, B> {
|
||||
Ext2 {
|
||||
inner: self.inner,
|
||||
ext_one: self.ext_one,
|
||||
ext_two,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<Inner, A, B> Ext2<Inner, A, B> {
|
||||
pub fn new(inner: Inner, ext_one: A, ext_two: B) -> Self {
|
||||
Ext2 {
|
||||
inner,
|
||||
ext_one,
|
||||
ext_two,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn extend<C>(self, ext_three: C) -> Ext3<Inner, A, B, C> {
|
||||
Ext3 {
|
||||
inner: self.inner,
|
||||
ext_one: self.ext_one,
|
||||
ext_two: self.ext_two,
|
||||
ext_three,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<Inner, A, B, C> Ext3<Inner, A, B, C> {
|
||||
pub fn new(inner: Inner, ext_one: A, ext_two: B, ext_three: C) -> Self {
|
||||
Ext3 {
|
||||
inner,
|
||||
ext_one,
|
||||
ext_two,
|
||||
ext_three,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn extend<D>(self, ext_four: D) -> Ext4<Inner, A, B, C, D> {
|
||||
Ext4 {
|
||||
inner: self.inner,
|
||||
ext_one: self.ext_one,
|
||||
ext_two: self.ext_two,
|
||||
ext_three: self.ext_three,
|
||||
ext_four,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<Inner, A, Kind, Error> Extends<Kind> for Ext1<Inner, A>
|
||||
where
|
||||
Inner: Extends<Kind, Error = Error> + UnparsedMut,
|
||||
A: UnparsedExtension<Inner, Error = Error>,
|
||||
Error: From<serde_json::Error> + std::error::Error,
|
||||
{
|
||||
type Error = Error;
|
||||
|
||||
fn extends(base: Base<Kind>) -> Result<Self, Self::Error> {
|
||||
let mut inner = Inner::extends(base)?;
|
||||
let ext_one = A::try_from_unparsed(&mut inner)?;
|
||||
|
||||
Ok(Ext1 { inner, ext_one })
|
||||
}
|
||||
|
||||
fn retracts(self) -> Result<Base<Kind>, Self::Error> {
|
||||
let Ext1 { mut inner, ext_one } = self;
|
||||
|
||||
ext_one.try_into_unparsed(&mut inner)?;
|
||||
inner.retracts()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Inner, A, B, Kind, Error> Extends<Kind> for Ext2<Inner, A, B>
|
||||
where
|
||||
Inner: Extends<Kind, Error = Error> + UnparsedMut,
|
||||
A: UnparsedExtension<Inner, Error = Error>,
|
||||
B: UnparsedExtension<Inner, Error = Error>,
|
||||
Error: From<serde_json::Error> + std::error::Error,
|
||||
{
|
||||
type Error = Error;
|
||||
|
||||
fn extends(base: Base<Kind>) -> Result<Self, Self::Error> {
|
||||
let mut inner = Inner::extends(base)?;
|
||||
let ext_one = A::try_from_unparsed(&mut inner)?;
|
||||
let ext_two = B::try_from_unparsed(&mut inner)?;
|
||||
|
||||
Ok(Ext2 {
|
||||
inner,
|
||||
ext_one,
|
||||
ext_two,
|
||||
})
|
||||
}
|
||||
|
||||
fn retracts(self) -> Result<Base<Kind>, Self::Error> {
|
||||
let Ext2 {
|
||||
mut inner,
|
||||
ext_one,
|
||||
ext_two,
|
||||
} = self;
|
||||
|
||||
ext_one.try_into_unparsed(&mut inner)?;
|
||||
ext_two.try_into_unparsed(&mut inner)?;
|
||||
inner.retracts()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Inner, A, B, C, Kind, Error> Extends<Kind> for Ext3<Inner, A, B, C>
|
||||
where
|
||||
Inner: Extends<Kind, Error = Error> + UnparsedMut,
|
||||
A: UnparsedExtension<Inner, Error = Error>,
|
||||
B: UnparsedExtension<Inner, Error = Error>,
|
||||
C: UnparsedExtension<Inner, Error = Error>,
|
||||
Error: From<serde_json::Error> + std::error::Error,
|
||||
{
|
||||
type Error = Error;
|
||||
|
||||
fn extends(base: Base<Kind>) -> Result<Self, Self::Error> {
|
||||
let mut inner = Inner::extends(base)?;
|
||||
let ext_one = A::try_from_unparsed(&mut inner)?;
|
||||
let ext_two = B::try_from_unparsed(&mut inner)?;
|
||||
let ext_three = C::try_from_unparsed(&mut inner)?;
|
||||
|
||||
Ok(Ext3 {
|
||||
inner,
|
||||
ext_one,
|
||||
ext_two,
|
||||
ext_three,
|
||||
})
|
||||
}
|
||||
|
||||
fn retracts(self) -> Result<Base<Kind>, Self::Error> {
|
||||
let Ext3 {
|
||||
mut inner,
|
||||
ext_one,
|
||||
ext_two,
|
||||
ext_three,
|
||||
} = self;
|
||||
|
||||
ext_one.try_into_unparsed(&mut inner)?;
|
||||
ext_two.try_into_unparsed(&mut inner)?;
|
||||
ext_three.try_into_unparsed(&mut inner)?;
|
||||
inner.retracts()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Inner, A, B, C, D, Kind, Error> Extends<Kind> for Ext4<Inner, A, B, C, D>
|
||||
where
|
||||
Inner: Extends<Kind, Error = Error> + UnparsedMut,
|
||||
A: UnparsedExtension<Inner, Error = Error>,
|
||||
B: UnparsedExtension<Inner, Error = Error>,
|
||||
C: UnparsedExtension<Inner, Error = Error>,
|
||||
D: UnparsedExtension<Inner, Error = Error>,
|
||||
Error: From<serde_json::Error> + std::error::Error,
|
||||
{
|
||||
type Error = Error;
|
||||
|
||||
fn extends(base: Base<Kind>) -> Result<Self, Self::Error> {
|
||||
let mut inner = Inner::extends(base)?;
|
||||
let ext_one = A::try_from_unparsed(&mut inner)?;
|
||||
let ext_two = B::try_from_unparsed(&mut inner)?;
|
||||
let ext_three = C::try_from_unparsed(&mut inner)?;
|
||||
let ext_four = D::try_from_unparsed(&mut inner)?;
|
||||
|
||||
Ok(Ext4 {
|
||||
inner,
|
||||
ext_one,
|
||||
ext_two,
|
||||
ext_three,
|
||||
ext_four,
|
||||
})
|
||||
}
|
||||
|
||||
fn retracts(self) -> Result<Base<Kind>, Self::Error> {
|
||||
let Ext4 {
|
||||
mut inner,
|
||||
ext_one,
|
||||
ext_two,
|
||||
ext_three,
|
||||
ext_four,
|
||||
} = self;
|
||||
|
||||
ext_one.try_into_unparsed(&mut inner)?;
|
||||
ext_two.try_into_unparsed(&mut inner)?;
|
||||
ext_three.try_into_unparsed(&mut inner)?;
|
||||
ext_four.try_into_unparsed(&mut inner)?;
|
||||
inner.retracts()
|
||||
}
|
||||
}
|
3343
src/activity.rs
Normal file
3343
src/activity.rs
Normal file
File diff suppressed because it is too large
Load diff
|
@ -1,134 +0,0 @@
|
|||
/*
|
||||
* This file is part of ActivityStreams.
|
||||
*
|
||||
* Copyright © 2020 Riley Trautman
|
||||
*
|
||||
* ActivityStreams is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ActivityStreams is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ActivityStreams. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//! Namespace for Unit Structs that serialize to strings
|
||||
|
||||
use crate::UnitString;
|
||||
|
||||
#[derive(Clone, Debug, Default, UnitString)]
|
||||
#[unit_string(Accept)]
|
||||
pub struct AcceptType;
|
||||
|
||||
#[derive(Clone, Debug, Default, UnitString)]
|
||||
#[unit_string(Add)]
|
||||
pub struct AddType;
|
||||
|
||||
#[derive(Clone, Debug, Default, UnitString)]
|
||||
#[unit_string(Move)]
|
||||
pub struct MoveType;
|
||||
|
||||
#[derive(Clone, Debug, Default, UnitString)]
|
||||
#[unit_string(Announce)]
|
||||
pub struct AnnounceType;
|
||||
|
||||
#[derive(Clone, Debug, Default, UnitString)]
|
||||
#[unit_string(Arrive)]
|
||||
pub struct ArriveType;
|
||||
|
||||
#[derive(Clone, Debug, Default, UnitString)]
|
||||
#[unit_string(Block)]
|
||||
pub struct BlockType;
|
||||
|
||||
#[derive(Clone, Debug, Default, UnitString)]
|
||||
#[unit_string(Create)]
|
||||
pub struct CreateType;
|
||||
|
||||
#[derive(Clone, Debug, Default, UnitString)]
|
||||
#[unit_string(Delete)]
|
||||
pub struct DeleteType;
|
||||
|
||||
#[derive(Clone, Debug, Default, UnitString)]
|
||||
#[unit_string(Dislike)]
|
||||
pub struct DislikeType;
|
||||
|
||||
#[derive(Clone, Debug, Default, UnitString)]
|
||||
#[unit_string(Flag)]
|
||||
pub struct FlagType;
|
||||
|
||||
#[derive(Clone, Debug, Default, UnitString)]
|
||||
#[unit_string(Follow)]
|
||||
pub struct FollowType;
|
||||
|
||||
#[derive(Clone, Debug, Default, UnitString)]
|
||||
#[unit_string(Ignore)]
|
||||
pub struct IgnoreType;
|
||||
|
||||
#[derive(Clone, Debug, Default, UnitString)]
|
||||
#[unit_string(Invite)]
|
||||
pub struct InviteType;
|
||||
|
||||
#[derive(Clone, Debug, Default, UnitString)]
|
||||
#[unit_string(Join)]
|
||||
pub struct JoinType;
|
||||
|
||||
#[derive(Clone, Debug, Default, UnitString)]
|
||||
#[unit_string(Leave)]
|
||||
pub struct LeaveType;
|
||||
|
||||
#[derive(Clone, Debug, Default, UnitString)]
|
||||
#[unit_string(Like)]
|
||||
pub struct LikeType;
|
||||
|
||||
#[derive(Clone, Debug, Default, UnitString)]
|
||||
#[unit_string(Listen)]
|
||||
pub struct ListenType;
|
||||
|
||||
#[derive(Clone, Debug, Default, UnitString)]
|
||||
#[unit_string(Offer)]
|
||||
pub struct OfferType;
|
||||
|
||||
#[derive(Clone, Debug, Default, UnitString)]
|
||||
#[unit_string(Question)]
|
||||
pub struct QuestionType;
|
||||
|
||||
#[derive(Clone, Debug, Default, UnitString)]
|
||||
#[unit_string(Real)]
|
||||
pub struct ReadType;
|
||||
|
||||
#[derive(Clone, Debug, Default, UnitString)]
|
||||
#[unit_string(Reject)]
|
||||
pub struct RejectType;
|
||||
|
||||
#[derive(Clone, Debug, Default, UnitString)]
|
||||
#[unit_string(Remove)]
|
||||
pub struct RemoveType;
|
||||
|
||||
#[derive(Clone, Debug, Default, UnitString)]
|
||||
#[unit_string(TentativeAccept)]
|
||||
pub struct TentativeAcceptType;
|
||||
|
||||
#[derive(Clone, Debug, Default, UnitString)]
|
||||
#[unit_string(TentativeReject)]
|
||||
pub struct TentativeRejectType;
|
||||
|
||||
#[derive(Clone, Debug, Default, UnitString)]
|
||||
#[unit_string(Travel)]
|
||||
pub struct TravelType;
|
||||
|
||||
#[derive(Clone, Debug, Default, UnitString)]
|
||||
#[unit_string(Undo)]
|
||||
pub struct UndoType;
|
||||
|
||||
#[derive(Clone, Debug, Default, UnitString)]
|
||||
#[unit_string(Update)]
|
||||
pub struct UpdateType;
|
||||
|
||||
#[derive(Clone, Debug, Default, UnitString)]
|
||||
#[unit_string(View)]
|
||||
pub struct ViewType;
|
|
@ -1,52 +0,0 @@
|
|||
/*
|
||||
* This file is part of ActivityStreams.
|
||||
*
|
||||
* Copyright © 2020 Riley Trautman
|
||||
*
|
||||
* ActivityStreams is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ActivityStreams is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ActivityStreams. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//! Namespace for Activity types
|
||||
|
||||
#[cfg(feature = "kinds")]
|
||||
pub mod kind;
|
||||
#[cfg(feature = "types")]
|
||||
pub mod properties;
|
||||
#[cfg(feature = "types")]
|
||||
mod types;
|
||||
|
||||
#[cfg(feature = "types")]
|
||||
pub use self::types::{
|
||||
AMove, Accept, Add, Announce, Arrive, Block, Create, Delete, Dislike, Flag, Follow, Ignore,
|
||||
Invite, Join, Leave, Like, Listen, Offer, Question, Read, Reject, Remove, TentativeAccept,
|
||||
TentativeReject, Travel, Undo, Update, View,
|
||||
};
|
||||
|
||||
use crate::object::Object;
|
||||
|
||||
/// An Activity is a subtype of `Object` that describes some form of action that may happen, is
|
||||
/// currently happening, or has already happened.
|
||||
///
|
||||
/// The `Activity` type itself serves as an abstract base type for all types of activities. It is
|
||||
/// important to note that the `Activity` type itself does not carry any specific semantics about
|
||||
/// the kind of action being taken.
|
||||
#[cfg_attr(feature = "derive", crate::wrapper_type)]
|
||||
pub trait Activity: Object {}
|
||||
|
||||
/// Instances of `IntransitiveActivity` are a subtype of `Activity` representing intransitive
|
||||
/// actions.
|
||||
///
|
||||
/// The `object` property is therefore inappropriate for these activities.
|
||||
#[cfg_attr(feature = "derive", crate::wrapper_type)]
|
||||
pub trait IntransitiveActivity: Activity {}
|
|
@ -1,624 +0,0 @@
|
|||
/* This file is part of ActivityStreams.
|
||||
*
|
||||
* Copyright © 2020 Riley Trautman
|
||||
*
|
||||
* ActivityStreams is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ActivityStreams is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ActivityStreams. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//! Namespace for properties of standard Activity types
|
||||
//!
|
||||
//! To use these properties in your own types, you can flatten them into your struct with serde:
|
||||
//!
|
||||
//! ```rust
|
||||
//! use activitystreams::{
|
||||
//! activity::{
|
||||
//! properties::ActivityProperties,
|
||||
//! Activity, ActivityBox,
|
||||
//! },
|
||||
//! ext::Ext,
|
||||
//! object::{
|
||||
//! properties::ObjectProperties,
|
||||
//! Object, ObjectBox,
|
||||
//! },
|
||||
//! Base, BaseBox, PropRefs,
|
||||
//! };
|
||||
//! use serde::{Deserialize, Serialize};
|
||||
//!
|
||||
//! #[derive(Clone, Debug, Default, serde::Serialize, serde::Deserialize)]
|
||||
//! #[serde(transparent)]
|
||||
//! pub struct ObjProps(pub ObjectProperties);
|
||||
//!
|
||||
//! #[derive(Clone, Debug, Default, serde::Serialize, serde::Deserialize)]
|
||||
//! #[serde(transparent)]
|
||||
//! pub struct ActivityProps(pub ActivityProperties);
|
||||
//!
|
||||
//! #[derive(Clone, Debug, Default, Serialize, Deserialize, PropRefs)]
|
||||
//! #[serde(rename_all = "camelCase")]
|
||||
//! #[prop_refs(Object)]
|
||||
//! #[prop_refs(Activity)]
|
||||
//! pub struct MyActivity {
|
||||
//! #[serde(rename = "type")]
|
||||
//! #[serde(alias = "objectType")]
|
||||
//! #[serde(alias = "verb")]
|
||||
//! pub kind: String,
|
||||
//!
|
||||
//! /// Define a require property for the MyActivity type
|
||||
//! pub my_property: String,
|
||||
//!
|
||||
//! #[serde(flatten)]
|
||||
//! #[prop_refs]
|
||||
//! pub object_properties: ObjProps,
|
||||
//!
|
||||
//! #[serde(flatten)]
|
||||
//! #[prop_refs]
|
||||
//! pub activity_properties: ActivityProps,
|
||||
//! }
|
||||
//! #
|
||||
//! # fn main() {}
|
||||
//! ```
|
||||
|
||||
use crate::{primitives::*, properties, BaseBox};
|
||||
|
||||
properties! {
|
||||
Activity {
|
||||
docs [
|
||||
"Activity objects are specializations of the base Object type that provide information about",
|
||||
"actions that have either already occurred, are in the process of occurring, or may occur in the",
|
||||
"future.",
|
||||
],
|
||||
|
||||
result {
|
||||
docs [
|
||||
"Describes the result of the activity.",
|
||||
"",
|
||||
"For instance, if a particular action results in the creation of a new resource, the result",
|
||||
"property can be used to describe that new resource.",
|
||||
"",
|
||||
"- Range: `Object` | `Link`",
|
||||
"- Funcitonal: false",
|
||||
],
|
||||
types [
|
||||
XsdAnyUri,
|
||||
BaseBox
|
||||
],
|
||||
},
|
||||
|
||||
instrument {
|
||||
docs [
|
||||
"Identifies one or more objects used (or to be used) in the completion of an `Activity`.",
|
||||
"",
|
||||
"- Range: `Object` | `Link`",
|
||||
"- Funcitonal: false",
|
||||
],
|
||||
types [
|
||||
XsdAnyUri,
|
||||
BaseBox,
|
||||
],
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
properties! {
|
||||
ActorOptOriginAndTarget {
|
||||
docs [ "Struct with `actor` and optional `origin` and `target` properties" ],
|
||||
|
||||
actor {
|
||||
docs [
|
||||
"Describes one or more entities that either performed or are expected to perform the",
|
||||
"activity.",
|
||||
"",
|
||||
"Any single activity can have multiple actors. The actor MAY be specified using an indirect",
|
||||
"Link.",
|
||||
"",
|
||||
"- Range: `Object` | `Link`",
|
||||
"- Functional: false",
|
||||
],
|
||||
types [
|
||||
XsdAnyUri,
|
||||
BaseBox,
|
||||
],
|
||||
required
|
||||
},
|
||||
|
||||
origin {
|
||||
docs [
|
||||
"Describes an indirect object of the activity from which the activity is directed.",
|
||||
"",
|
||||
"The precise meaning of the origin is the object of the English preposition \"from\". For",
|
||||
"instance, in the activity \"John moved an item to List B from List A\", the origin of the",
|
||||
"activity is \"List A\".",
|
||||
"",
|
||||
"- Range: `Object` | `Link`",
|
||||
"- Functional: false",
|
||||
],
|
||||
types [
|
||||
XsdAnyUri,
|
||||
BaseBox,
|
||||
],
|
||||
},
|
||||
|
||||
target {
|
||||
docs [
|
||||
"Describes the indirect object, or target, of the activity.",
|
||||
"",
|
||||
"The precise meaning of the target is largely dependent on the type of action being",
|
||||
"described but will often be the object of the English preposition \"to\". For instance, in",
|
||||
"the activity \"John added a movie to his wishlist\", the target of the activity is John's",
|
||||
"wishlist. An activity can have more than one target",
|
||||
"",
|
||||
"- Range: `Object` | `Link`",
|
||||
"- Functional: false",
|
||||
],
|
||||
types [
|
||||
XsdAnyUri,
|
||||
BaseBox,
|
||||
],
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
properties! {
|
||||
ActorAndObject {
|
||||
docs [ "Struct with `actor` and `object` properties" ],
|
||||
|
||||
actor {
|
||||
docs [
|
||||
"Describes one or more entities that either performed or are expected to perform the",
|
||||
"activity.",
|
||||
"",
|
||||
"Any single activity can have multiple actors. The actor MAY be specified using an indirect",
|
||||
"Link.",
|
||||
"",
|
||||
"- Range: `Object` | `Link`",
|
||||
"- Functional: false",
|
||||
],
|
||||
types [
|
||||
XsdAnyUri,
|
||||
BaseBox,
|
||||
],
|
||||
required,
|
||||
},
|
||||
|
||||
object {
|
||||
docs [
|
||||
"When used within an Activity, describes the direct object of the activity.",
|
||||
"",
|
||||
"For instance, in the activity \"John added a movie to his wishlist\", the object of the",
|
||||
"activity is the movie added.",
|
||||
"",
|
||||
"- Range: `Object` | `Link`",
|
||||
"- Functional: false",
|
||||
],
|
||||
types [
|
||||
XsdAnyUri,
|
||||
BaseBox,
|
||||
],
|
||||
required,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
properties! {
|
||||
ActorObjectAndTarget {
|
||||
docs [ "Struct with `actor`, `object`, and `target` properties" ],
|
||||
|
||||
actor {
|
||||
docs [
|
||||
"Describes one or more entities that either performed or are expected to perform the",
|
||||
"activity.",
|
||||
"",
|
||||
"Any single activity can have multiple actors. The actor MAY be specified using an indirect",
|
||||
"Link.",
|
||||
"",
|
||||
"- Range: `Object` | `Link`",
|
||||
"- Functional: false",
|
||||
],
|
||||
types [
|
||||
XsdAnyUri,
|
||||
BaseBox,
|
||||
],
|
||||
required,
|
||||
},
|
||||
|
||||
object {
|
||||
docs [
|
||||
"When used within an Activity, describes the direct object of the activity.",
|
||||
"",
|
||||
"For instance, in the activity \"John added a movie to his wishlist\", the object of the",
|
||||
"activity is the movie added.",
|
||||
"",
|
||||
"- Range: `Object` | `Link`",
|
||||
"- Functional: false",
|
||||
],
|
||||
types [
|
||||
XsdAnyUri,
|
||||
BaseBox,
|
||||
],
|
||||
required,
|
||||
},
|
||||
|
||||
target {
|
||||
docs [
|
||||
"Describes the indirect object, or target, of the activity.",
|
||||
"",
|
||||
"The precise meaning of the target is largely dependent on the type of action being",
|
||||
"described but will often be the object of the English preposition \"to\". For instance, in",
|
||||
"the activity \"John added a movie to his wishlist\", the target of the activity is John's",
|
||||
"wishlist. An activity can have more than one target",
|
||||
"",
|
||||
"- Range: `Object` | `Link`",
|
||||
"- Functional: false",
|
||||
],
|
||||
types [
|
||||
XsdAnyUri,
|
||||
BaseBox,
|
||||
],
|
||||
required,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
properties! {
|
||||
ActorAndObjectOptTarget {
|
||||
docs [ "Struct with `actor`, `object`, and optional `target` properties" ],
|
||||
|
||||
actor {
|
||||
docs [
|
||||
"Describes one or more entities that either performed or are expected to perform the",
|
||||
"activity.",
|
||||
"",
|
||||
"Any single activity can have multiple actors. The actor MAY be specified using an indirect",
|
||||
"Link.",
|
||||
"",
|
||||
"- Range: `Object` | `Link`",
|
||||
"- Functional: false",
|
||||
],
|
||||
types [
|
||||
XsdAnyUri,
|
||||
BaseBox,
|
||||
],
|
||||
required,
|
||||
},
|
||||
|
||||
object {
|
||||
docs [
|
||||
"When used within an Activity, describes the direct object of the activity.",
|
||||
"",
|
||||
"For instance, in the activity \"John added a movie to his wishlist\", the object of the",
|
||||
"activity is the movie added.",
|
||||
"",
|
||||
"- Range: `Object` | `Link`",
|
||||
"- Functional: false",
|
||||
],
|
||||
types [
|
||||
XsdAnyUri,
|
||||
BaseBox,
|
||||
],
|
||||
required,
|
||||
},
|
||||
|
||||
target {
|
||||
docs [
|
||||
"Describes the indirect object, or target, of the activity.",
|
||||
"",
|
||||
"The precise meaning of the target is largely dependent on the type of action being",
|
||||
"described but will often be the object of the English preposition \"to\". For instance, in",
|
||||
"the activity \"John added a movie to his wishlist\", the target of the activity is John's",
|
||||
"wishlist. An activity can have more than one target",
|
||||
"",
|
||||
"- Range: `Object` | `Link`",
|
||||
"- Functional: false",
|
||||
],
|
||||
types [
|
||||
XsdAnyUri,
|
||||
BaseBox,
|
||||
],
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
properties! {
|
||||
ActorAndObjectOptOrigin {
|
||||
docs [ "Struct with `actor`, `object`, and optional `origin` properties" ],
|
||||
|
||||
actor {
|
||||
docs [
|
||||
"Describes one or more entities that either performed or are expected to perform the",
|
||||
"activity.",
|
||||
"",
|
||||
"Any single activity can have multiple actors. The actor MAY be specified using an indirect",
|
||||
"Link.",
|
||||
"",
|
||||
"- Range: `Object` | `Link`",
|
||||
"- Functional: false",
|
||||
],
|
||||
types [
|
||||
XsdAnyUri,
|
||||
BaseBox,
|
||||
],
|
||||
required,
|
||||
},
|
||||
|
||||
object {
|
||||
docs [
|
||||
"When used within an Activity, describes the direct object of the activity.",
|
||||
"",
|
||||
"For instance, in the activity \"John added a movie to his wishlist\", the object of the",
|
||||
"activity is the movie added.",
|
||||
"",
|
||||
"- Range: `Object` | `Link`",
|
||||
"- Functional: false",
|
||||
],
|
||||
types [
|
||||
XsdAnyUri,
|
||||
BaseBox,
|
||||
],
|
||||
required,
|
||||
},
|
||||
|
||||
origin {
|
||||
docs [
|
||||
"Describes an indirect object of the activity from which the activity is directed.",
|
||||
"",
|
||||
"The precise meaning of the origin is the object of the English preposition \"from\". For",
|
||||
"instance, in the activity \"John moved an item to List B from List A\", the origin of the",
|
||||
"activity is \"List A\".",
|
||||
"",
|
||||
"- Range: `Object` | `Link`",
|
||||
"- Functional: false",
|
||||
],
|
||||
types [
|
||||
XsdAnyUri,
|
||||
BaseBox,
|
||||
],
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
properties! {
|
||||
ActorAndObjectOptOthers {
|
||||
docs [ "Struct with `actor`, `object`, and optional `origin` and `target` properties" ],
|
||||
|
||||
actor {
|
||||
docs [
|
||||
"Describes one or more entities that either performed or are expected to perform the",
|
||||
"activity.",
|
||||
"",
|
||||
"Any single activity can have multiple actors. The actor MAY be specified using an indirect",
|
||||
"Link.",
|
||||
"",
|
||||
"- Range: `Object` | `Link`",
|
||||
"- Functional: false",
|
||||
],
|
||||
types [
|
||||
XsdAnyUri,
|
||||
BaseBox,
|
||||
],
|
||||
required,
|
||||
},
|
||||
|
||||
object {
|
||||
docs [
|
||||
"When used within an Activity, describes the direct object of the activity.",
|
||||
"",
|
||||
"For instance, in the activity \"John added a movie to his wishlist\", the object of the",
|
||||
"activity is the movie added.",
|
||||
"",
|
||||
"- Range: `Object` | `Link`",
|
||||
"- Functional: false",
|
||||
],
|
||||
types [
|
||||
XsdAnyUri,
|
||||
BaseBox,
|
||||
],
|
||||
required,
|
||||
},
|
||||
|
||||
origin {
|
||||
docs [
|
||||
"Describes an indirect object of the activity from which the activity is directed.",
|
||||
"",
|
||||
"The precise meaning of the origin is the object of the English preposition \"from\". For",
|
||||
"instance, in the activity \"John moved an item to List B from List A\", the origin of the",
|
||||
"activity is \"List A\".",
|
||||
"",
|
||||
"- Range: `Object` | `Link`",
|
||||
"- Functional: false",
|
||||
],
|
||||
types [
|
||||
XsdAnyUri,
|
||||
BaseBox,
|
||||
],
|
||||
},
|
||||
|
||||
target {
|
||||
docs [
|
||||
"Describes the indirect object, or target, of the activity.",
|
||||
"",
|
||||
"The precise meaning of the target is largely dependent on the type of action being",
|
||||
"described but will often be the object of the English preposition \"to\". For instance, in",
|
||||
"the activity \"John added a movie to his wishlist\", the target of the activity is John's",
|
||||
"wishlist. An activity can have more than one target",
|
||||
"",
|
||||
"- Range: `Object` | `Link`",
|
||||
"- Functional: false",
|
||||
],
|
||||
types [
|
||||
XsdAnyUri,
|
||||
BaseBox,
|
||||
],
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
properties! {
|
||||
ActorAndOrigin {
|
||||
docs [ "Struct with `actor` and `origin` properties" ],
|
||||
|
||||
actor {
|
||||
docs [
|
||||
"Describes one or more entities that either performed or are expected to perform the",
|
||||
"activity.",
|
||||
"",
|
||||
"Any single activity can have multiple actors. The actor MAY be specified using an indirect",
|
||||
"Link.",
|
||||
"",
|
||||
"- Range: `Object` | `Link`",
|
||||
"- Functional: false",
|
||||
],
|
||||
types [
|
||||
XsdString,
|
||||
BaseBox,
|
||||
],
|
||||
required,
|
||||
},
|
||||
|
||||
origin {
|
||||
docs [
|
||||
"Describes an indirect object of the activity from which the activity is directed.",
|
||||
"",
|
||||
"The precise meaning of the origin is the object of the English preposition \"from\". For",
|
||||
"instance, in the activity \"John moved an item to List B from List A\", the origin of the",
|
||||
"activity is \"List A\".",
|
||||
"",
|
||||
"- Range: `Object` | `Link`",
|
||||
"- Functional: false",
|
||||
],
|
||||
types [
|
||||
XsdAnyUri,
|
||||
BaseBox,
|
||||
],
|
||||
required,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// Properties for the Accept activity
|
||||
pub type AcceptProperties = ActorAndObjectProperties;
|
||||
|
||||
/// Properties for the Add activity
|
||||
pub type AddProperties = ActorAndObjectProperties;
|
||||
|
||||
/// Properties for the Move activity
|
||||
pub type MoveProperties = ActorAndObjectOptOthersProperties;
|
||||
|
||||
/// Properties for the Announce activity
|
||||
pub type AnnounceProperties = ActorAndObjectOptTargetProperties;
|
||||
|
||||
/// Properties for the Arrive activity
|
||||
pub type ArriveProperties = ActorAndOriginProperties;
|
||||
|
||||
/// Properties for the Block activity
|
||||
pub type BlockProperties = ActorAndObjectProperties;
|
||||
|
||||
/// Properties for the Create activity
|
||||
pub type CreateProperties = ActorAndObjectProperties;
|
||||
|
||||
/// Properties for the Delete activity
|
||||
pub type DeleteProperties = ActorAndObjectOptOriginProperties;
|
||||
|
||||
/// Properties for the Dislike activity
|
||||
pub type DislikeProperties = ActorAndObjectProperties;
|
||||
|
||||
/// Properties for the Flag activity
|
||||
pub type FlagProperties = ActorAndObjectProperties;
|
||||
|
||||
/// Properties for the Follow activity
|
||||
pub type FollowProperties = ActorAndObjectProperties;
|
||||
|
||||
/// Properties for the Ignore activity
|
||||
pub type IgnoreProperties = ActorAndObjectProperties;
|
||||
|
||||
/// Properties for the Invite activity
|
||||
pub type InviteProperties = ActorObjectAndTargetProperties;
|
||||
|
||||
/// Properties for the Join activity
|
||||
pub type JoinProperties = ActorAndObjectProperties;
|
||||
|
||||
/// Properties for the Leave activity
|
||||
pub type LeaveProperties = ActorAndObjectProperties;
|
||||
|
||||
/// Properties for the Like activity
|
||||
pub type LikeProperties = ActorAndObjectProperties;
|
||||
|
||||
/// Properties for the Listen activity
|
||||
pub type ListenProperties = ActorAndObjectProperties;
|
||||
|
||||
/// Properties for the Offer activity
|
||||
pub type OfferProperties = ActorAndObjectOptTargetProperties;
|
||||
|
||||
properties! {
|
||||
Question {
|
||||
docs [ "Properties for the Question activity" ],
|
||||
|
||||
one_of {
|
||||
docs [
|
||||
"Identifies an exclusive option for a Question.",
|
||||
"",
|
||||
"Use of `one_of` implies that the Question can have only a single answer. To indicate that a",
|
||||
"`Question` can have multiple answers, use `any_of`.",
|
||||
"",
|
||||
"- Range: `Object` | `Link`",
|
||||
"- Functional: false",
|
||||
],
|
||||
types [
|
||||
XsdAnyUri,
|
||||
BaseBox,
|
||||
],
|
||||
},
|
||||
|
||||
any_of {
|
||||
docs [
|
||||
"Identifies an inclusive option for a Question.",
|
||||
"",
|
||||
"Use of `any_of` implies that the Question can have multiple answers. To indicate that a",
|
||||
"`Question` can have only one answer, use `one_of`.",
|
||||
"",
|
||||
"- Range: `Object` | `Link`",
|
||||
"- Functional: false",
|
||||
],
|
||||
types [
|
||||
XsdAnyUri,
|
||||
BaseBox,
|
||||
],
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// Properties for the Read activity
|
||||
pub type ReadProperties = ActorAndObjectProperties;
|
||||
|
||||
/// Properties for the Reject activity
|
||||
pub type RejectProperties = ActorAndObjectProperties;
|
||||
|
||||
/// Properties for the Remove activity
|
||||
pub type RemoveProperties = ActorAndObjectOptOthersProperties;
|
||||
|
||||
/// Properties for the TentativeAccept activity
|
||||
pub type TentativeAcceptProperties = ActorAndObjectProperties;
|
||||
|
||||
/// Properties for the TentativeReject activity
|
||||
pub type TentativeRejectProperties = ActorAndObjectProperties;
|
||||
|
||||
/// Properties for the Travel activity
|
||||
pub type TravelProperties = ActorOptOriginAndTargetProperties;
|
||||
|
||||
/// Properties for the Undo activity
|
||||
pub type UndoProperties = ActorAndObjectProperties;
|
||||
|
||||
/// Properties for the Update activity
|
||||
pub type UpdateProperties = ActorAndObjectProperties;
|
||||
|
||||
/// Properties for the View activity
|
||||
pub type ViewProperties = ActorAndObjectProperties;
|
|
@ -1,881 +0,0 @@
|
|||
/*
|
||||
* This file is part of ActivityStreams.
|
||||
*
|
||||
* Copyright © 2020 Riley Trautman
|
||||
*
|
||||
* ActivityStreams is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ActivityStreams is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ActivityStreams. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
use crate::{
|
||||
activity::{
|
||||
kind::*, properties::*, Activity, ActivityBox, IntransitiveActivity,
|
||||
IntransitiveActivityBox,
|
||||
},
|
||||
ext::Ext,
|
||||
object::{
|
||||
properties::{ApObjectProperties, ObjectProperties},
|
||||
Object, ObjectBox,
|
||||
},
|
||||
Base, BaseBox, Extensible, PropRefs,
|
||||
};
|
||||
|
||||
/// Indicates that the actor accepts the object.
|
||||
///
|
||||
/// The target property can be used in certain circumstances to indicate the context into which the
|
||||
/// object has been accepted.
|
||||
#[derive(Clone, Debug, Default, Extensible, PropRefs, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[prop_refs(Object)]
|
||||
#[prop_refs(Activity)]
|
||||
#[extension(ApObjectProperties)]
|
||||
pub struct Accept {
|
||||
#[serde(rename = "type")]
|
||||
#[serde(alias = "objectType")]
|
||||
#[serde(alias = "verb")]
|
||||
pub kind: AcceptType,
|
||||
|
||||
/// Adds all valid accept properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub accept_props: AcceptProperties,
|
||||
|
||||
/// Adds all valid object properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub object_props: ObjectProperties,
|
||||
|
||||
/// Adds all valid activity properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub activity_props: ActivityProperties,
|
||||
}
|
||||
|
||||
/// Indicates that the actor has added the object to the target.
|
||||
///
|
||||
/// If the target property is not explicitly specified, the target would need to be determined
|
||||
/// implicitly by context. The origin can be used to identify the context from which the object
|
||||
/// originated.
|
||||
#[derive(Clone, Debug, Default, Extensible, PropRefs, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[prop_refs(Object)]
|
||||
#[prop_refs(Activity)]
|
||||
#[extension(ApObjectProperties)]
|
||||
pub struct Add {
|
||||
#[serde(rename = "type")]
|
||||
#[serde(alias = "objectType")]
|
||||
#[serde(alias = "verb")]
|
||||
pub kind: AddType,
|
||||
|
||||
/// Adds all valid add properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub add_props: AddProperties,
|
||||
|
||||
/// Adds all valid object properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub object_props: ObjectProperties,
|
||||
|
||||
/// Adds all valid activity properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub activity_props: ActivityProperties,
|
||||
}
|
||||
|
||||
/// Indicates that the actor has moved object from origin to target.
|
||||
///
|
||||
/// If the origin or target are not specified, either can be determined by context.
|
||||
#[derive(Clone, Debug, Default, Extensible, PropRefs, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[prop_refs(Object)]
|
||||
#[prop_refs(Activity)]
|
||||
#[extension(ApObjectProperties)]
|
||||
pub struct AMove {
|
||||
#[serde(rename = "type")]
|
||||
#[serde(alias = "objectType")]
|
||||
#[serde(alias = "verb")]
|
||||
pub kind: MoveType,
|
||||
|
||||
/// Adds all valid move properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub move_props: MoveProperties,
|
||||
|
||||
/// Adds all valid object properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub object_props: ObjectProperties,
|
||||
|
||||
/// Adds all valid activity properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub activity_props: ActivityProperties,
|
||||
}
|
||||
|
||||
/// Indicates that the actor is calling the target's attention the object.
|
||||
///
|
||||
/// The origin typically has no defined meaning.
|
||||
#[derive(Clone, Debug, Default, Extensible, PropRefs, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[prop_refs(Object)]
|
||||
#[prop_refs(Activity)]
|
||||
#[extension(ApObjectProperties)]
|
||||
pub struct Announce {
|
||||
#[serde(rename = "type")]
|
||||
#[serde(alias = "objectType")]
|
||||
#[serde(alias = "verb")]
|
||||
pub kind: AnnounceType,
|
||||
|
||||
/// Adds all valid announce properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub announce_props: AnnounceProperties,
|
||||
|
||||
/// Adds all valid object properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub object_props: ObjectProperties,
|
||||
|
||||
/// Adds all valid activity properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub activity_props: ActivityProperties,
|
||||
}
|
||||
|
||||
/// An IntransitiveActivity that indicates that the actor has arrived at the location.
|
||||
///
|
||||
/// The origin can be used to identify the context from which the actor originated. The target
|
||||
/// typically has no defined meaning.
|
||||
#[derive(Clone, Debug, Default, Extensible, PropRefs, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[prop_refs(Object)]
|
||||
#[prop_refs(Activity)]
|
||||
#[extension(ApObjectProperties)]
|
||||
#[prop_refs(IntransitiveActivity)]
|
||||
pub struct Arrive {
|
||||
#[serde(rename = "type")]
|
||||
#[serde(alias = "objectType")]
|
||||
#[serde(alias = "verb")]
|
||||
pub kind: ArriveType,
|
||||
|
||||
/// Adds all valid arrive properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub arrive_props: ArriveProperties,
|
||||
|
||||
/// Adds all valid object properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub object_props: ObjectProperties,
|
||||
|
||||
/// Adds all valid activity properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub activity_props: ActivityProperties,
|
||||
}
|
||||
|
||||
/// Indicates that the actor is blocking the object.
|
||||
///
|
||||
/// Blocking is a stronger form of Ignore. The typical use is to support social systems that allow
|
||||
/// one user to block activities or content of other users. The target and origin typically have no
|
||||
/// defined meaning.
|
||||
#[derive(Clone, Debug, Default, Extensible, PropRefs, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[prop_refs(Object)]
|
||||
#[prop_refs(Activity)]
|
||||
#[extension(ApObjectProperties)]
|
||||
pub struct Block {
|
||||
#[serde(rename = "type")]
|
||||
#[serde(alias = "objectType")]
|
||||
#[serde(alias = "verb")]
|
||||
pub kind: BlockType,
|
||||
|
||||
/// Adds all valid block properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub block_props: BlockProperties,
|
||||
|
||||
/// Adds all valid object properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub object_props: ObjectProperties,
|
||||
|
||||
/// Adds all valid activity properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub activity_props: ActivityProperties,
|
||||
}
|
||||
|
||||
/// Indicates that the actor has created the object.
|
||||
#[derive(Clone, Debug, Default, Extensible, PropRefs, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[prop_refs(Object)]
|
||||
#[prop_refs(Activity)]
|
||||
#[extension(ApObjectProperties)]
|
||||
pub struct Create {
|
||||
#[serde(rename = "type")]
|
||||
#[serde(alias = "objectType")]
|
||||
#[serde(alias = "verb")]
|
||||
pub kind: CreateType,
|
||||
|
||||
/// Adds all valid create properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub create_props: CreateProperties,
|
||||
|
||||
/// Adds all valid object properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub object_props: ObjectProperties,
|
||||
|
||||
/// Adds all valid activity properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub activity_props: ActivityProperties,
|
||||
}
|
||||
|
||||
/// Indicates that the actor has deleted the object.
|
||||
///
|
||||
/// If specified, the origin indicates the context from which the object was deleted.
|
||||
#[derive(Clone, Debug, Default, Extensible, PropRefs, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[prop_refs(Object)]
|
||||
#[prop_refs(Activity)]
|
||||
#[extension(ApObjectProperties)]
|
||||
pub struct Delete {
|
||||
#[serde(rename = "type")]
|
||||
#[serde(alias = "objectType")]
|
||||
#[serde(alias = "verb")]
|
||||
pub kind: DeleteType,
|
||||
|
||||
/// Adds all valid delete properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub delete_props: DeleteProperties,
|
||||
|
||||
/// Adds all valid object properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub object_props: ObjectProperties,
|
||||
|
||||
/// Adds all valid activity properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub activity_props: ActivityProperties,
|
||||
}
|
||||
|
||||
/// Indicates that the actor dislikes the object.
|
||||
#[derive(Clone, Debug, Default, Extensible, PropRefs, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[prop_refs(Object)]
|
||||
#[prop_refs(Activity)]
|
||||
#[extension(ApObjectProperties)]
|
||||
pub struct Dislike {
|
||||
#[serde(rename = "type")]
|
||||
#[serde(alias = "objectType")]
|
||||
#[serde(alias = "verb")]
|
||||
pub kind: DislikeType,
|
||||
|
||||
/// Adds all valid dislike properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub dislike_props: DislikeProperties,
|
||||
|
||||
/// Adds all valid object properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub object_props: ObjectProperties,
|
||||
|
||||
/// Adds all valid activity properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub activity_props: ActivityProperties,
|
||||
}
|
||||
|
||||
/// Indicates that the actor is "flagging" the object.
|
||||
///
|
||||
/// Flagging is defined in the sense common to many social platforms as reporting content as being
|
||||
/// inappropriate for any number of reasons.
|
||||
#[derive(Clone, Debug, Default, Extensible, PropRefs, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[prop_refs(Object)]
|
||||
#[prop_refs(Activity)]
|
||||
#[extension(ApObjectProperties)]
|
||||
pub struct Flag {
|
||||
#[serde(rename = "type")]
|
||||
#[serde(alias = "objectType")]
|
||||
#[serde(alias = "verb")]
|
||||
pub kind: FlagType,
|
||||
|
||||
/// Adds all valid flag properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub flag_props: FlagProperties,
|
||||
|
||||
/// Adds all valid object properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub object_props: ObjectProperties,
|
||||
|
||||
/// Adds all valid activity properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub activity_props: ActivityProperties,
|
||||
}
|
||||
|
||||
/// Indicates that the actor is "following" the object.
|
||||
///
|
||||
/// Following is defined in the sense typically used within Social systems in which the actor is
|
||||
/// interested in any activity performed by or on the object. The target and origin typically have
|
||||
/// no defined meaning.
|
||||
#[derive(Clone, Debug, Default, Extensible, PropRefs, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[prop_refs(Object)]
|
||||
#[prop_refs(Activity)]
|
||||
#[extension(ApObjectProperties)]
|
||||
pub struct Follow {
|
||||
#[serde(rename = "type")]
|
||||
#[serde(alias = "objectType")]
|
||||
#[serde(alias = "verb")]
|
||||
pub kind: FollowType,
|
||||
|
||||
/// Adds all valid follow properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub follow_props: FollowProperties,
|
||||
|
||||
/// Adds all valid object properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub object_props: ObjectProperties,
|
||||
|
||||
/// Adds all valid activity properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub activity_props: ActivityProperties,
|
||||
}
|
||||
|
||||
/// Indicates that the actor is ignoring the object.
|
||||
///
|
||||
/// The target and origin typically have no defined meaning.
|
||||
#[derive(Clone, Debug, Default, Extensible, PropRefs, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[prop_refs(Object)]
|
||||
#[prop_refs(Activity)]
|
||||
#[extension(ApObjectProperties)]
|
||||
pub struct Ignore {
|
||||
#[serde(rename = "type")]
|
||||
#[serde(alias = "objectType")]
|
||||
#[serde(alias = "verb")]
|
||||
pub kind: IgnoreType,
|
||||
|
||||
/// Adds all valid ignore properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub ignore_props: IgnoreProperties,
|
||||
|
||||
/// Adds all valid object properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub object_props: ObjectProperties,
|
||||
|
||||
/// Adds all valid activity properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub activity_props: ActivityProperties,
|
||||
}
|
||||
|
||||
/// A specialization of Offer in which the actor is extending an invitation for the object to the
|
||||
/// target.
|
||||
#[derive(Clone, Debug, Default, Extensible, PropRefs, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[prop_refs(Object)]
|
||||
#[prop_refs(Activity)]
|
||||
#[extension(ApObjectProperties)]
|
||||
pub struct Invite {
|
||||
#[serde(rename = "type")]
|
||||
#[serde(alias = "objectType")]
|
||||
#[serde(alias = "verb")]
|
||||
pub kind: InviteType,
|
||||
|
||||
/// Adds all valid invite properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub invite_props: InviteProperties,
|
||||
|
||||
/// Adds all valid object properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub object_props: ObjectProperties,
|
||||
|
||||
/// Adds all valid activity properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub activity_props: ActivityProperties,
|
||||
}
|
||||
|
||||
/// Indicates that the actor has joined the object.
|
||||
///
|
||||
/// The target and origin typically have no defined meaning
|
||||
#[derive(Clone, Debug, Default, Extensible, PropRefs, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[prop_refs(Object)]
|
||||
#[prop_refs(Activity)]
|
||||
#[extension(ApObjectProperties)]
|
||||
pub struct Join {
|
||||
#[serde(rename = "type")]
|
||||
#[serde(alias = "objectType")]
|
||||
#[serde(alias = "verb")]
|
||||
pub kind: JoinType,
|
||||
|
||||
/// Adds all valid join properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub join_props: JoinProperties,
|
||||
|
||||
/// Adds all valid object properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub object_props: ObjectProperties,
|
||||
|
||||
/// Adds all valid activity properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub activity_props: ActivityProperties,
|
||||
}
|
||||
|
||||
/// Indicates that the actor has left the object.
|
||||
///
|
||||
/// The target and origin typically have no meaning.
|
||||
#[derive(Clone, Debug, Default, Extensible, PropRefs, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[prop_refs(Object)]
|
||||
#[prop_refs(Activity)]
|
||||
#[extension(ApObjectProperties)]
|
||||
pub struct Leave {
|
||||
#[serde(rename = "type")]
|
||||
#[serde(alias = "objectType")]
|
||||
#[serde(alias = "verb")]
|
||||
pub kind: LeaveType,
|
||||
|
||||
/// Adds all valid leave properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub leave_props: LeaveProperties,
|
||||
|
||||
/// Adds all valid object properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub object_props: ObjectProperties,
|
||||
|
||||
/// Adds all valid activity properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub activity_props: ActivityProperties,
|
||||
}
|
||||
|
||||
/// Indicates that the actor likes, recommends or endorses the object.
|
||||
///
|
||||
/// The target and origin typically have no defined meaning.
|
||||
#[derive(Clone, Debug, Default, Extensible, PropRefs, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[prop_refs(Object)]
|
||||
#[prop_refs(Activity)]
|
||||
#[extension(ApObjectProperties)]
|
||||
pub struct Like {
|
||||
#[serde(rename = "type")]
|
||||
#[serde(alias = "objectType")]
|
||||
#[serde(alias = "verb")]
|
||||
pub kind: LikeType,
|
||||
|
||||
/// Adds all valid like properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub like_props: LikeProperties,
|
||||
|
||||
/// Adds all valid object properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub object_props: ObjectProperties,
|
||||
|
||||
/// Adds all valid activity properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub activity_props: ActivityProperties,
|
||||
}
|
||||
|
||||
/// Indicates that the actor has listened to the object.
|
||||
#[derive(Clone, Debug, Default, Extensible, PropRefs, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[prop_refs(Object)]
|
||||
#[prop_refs(Activity)]
|
||||
#[extension(ApObjectProperties)]
|
||||
pub struct Listen {
|
||||
#[serde(rename = "type")]
|
||||
#[serde(alias = "objectType")]
|
||||
#[serde(alias = "verb")]
|
||||
kind: ListenType,
|
||||
|
||||
/// Adds all valid listen properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub listen_props: ListenProperties,
|
||||
|
||||
/// Adds all valid object properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub object_props: ObjectProperties,
|
||||
|
||||
/// Adds all valid activity properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub activity_props: ActivityProperties,
|
||||
}
|
||||
|
||||
/// Indicates that the actor is offering the object.
|
||||
///
|
||||
/// If specified, the target indicates the entity to which the object is being offered.
|
||||
#[derive(Clone, Debug, Default, Extensible, PropRefs, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[prop_refs(Object)]
|
||||
#[prop_refs(Activity)]
|
||||
#[extension(ApObjectProperties)]
|
||||
pub struct Offer {
|
||||
#[serde(rename = "type")]
|
||||
#[serde(alias = "objectType")]
|
||||
#[serde(alias = "verb")]
|
||||
pub kind: OfferType,
|
||||
|
||||
/// Adds all valid object properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub offer_props: OfferProperties,
|
||||
|
||||
/// Adds all valid object properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub object_props: ObjectProperties,
|
||||
|
||||
/// Adds all valid activity properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub activity_props: ActivityProperties,
|
||||
}
|
||||
|
||||
/// Represents a question being asked.
|
||||
///
|
||||
/// Question objects are an extension of IntransitiveActivity. That is, the Question object is an
|
||||
/// Activity, but the direct object is the question itself and therefore it would not contain an
|
||||
/// object property.
|
||||
///
|
||||
/// Either of the anyOf and oneOf properties MAY be used to express possible answers, but a
|
||||
/// Question object MUST NOT have both properties.
|
||||
#[derive(Clone, Debug, Default, Extensible, PropRefs, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[prop_refs(Object)]
|
||||
#[prop_refs(Activity)]
|
||||
#[extension(ApObjectProperties)]
|
||||
#[prop_refs(IntransitiveActivity)]
|
||||
pub struct Question {
|
||||
#[serde(rename = "type")]
|
||||
#[serde(alias = "objectType")]
|
||||
#[serde(alias = "verb")]
|
||||
pub kind: QuestionType,
|
||||
|
||||
/// Adds all valid question properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub question_props: QuestionProperties,
|
||||
|
||||
/// Adds all valid object properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub object_props: ObjectProperties,
|
||||
|
||||
/// Adds all valid activity properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub activity_props: ActivityProperties,
|
||||
}
|
||||
|
||||
/// Indicates that the actor has read the object.
|
||||
#[derive(Clone, Debug, Default, Extensible, PropRefs, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[prop_refs(Object)]
|
||||
#[prop_refs(Activity)]
|
||||
#[extension(ApObjectProperties)]
|
||||
pub struct Read {
|
||||
#[serde(rename = "type")]
|
||||
#[serde(alias = "objectType")]
|
||||
#[serde(alias = "verb")]
|
||||
pub kind: ReadType,
|
||||
|
||||
/// Adds all valid read properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub read_props: ReadProperties,
|
||||
|
||||
/// Adds all valid object properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub object_props: ObjectProperties,
|
||||
|
||||
/// Adds all valid activity properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub activity_props: ActivityProperties,
|
||||
}
|
||||
|
||||
/// Indicates that the actor is rejecting the object.
|
||||
///
|
||||
/// The target and origin typically have no defined meaning.
|
||||
#[derive(Clone, Debug, Default, Extensible, PropRefs, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[prop_refs(Object)]
|
||||
#[prop_refs(Activity)]
|
||||
#[extension(ApObjectProperties)]
|
||||
pub struct Reject {
|
||||
#[serde(rename = "type")]
|
||||
#[serde(alias = "objectType")]
|
||||
#[serde(alias = "verb")]
|
||||
pub kind: RejectType,
|
||||
|
||||
/// Adds all valid reject properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub reject_props: RejectProperties,
|
||||
|
||||
/// Adds all valid object properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub object_props: ObjectProperties,
|
||||
|
||||
/// Adds all valid activity properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub activity_props: ActivityProperties,
|
||||
}
|
||||
|
||||
/// Indicates that the actor is removing the object.
|
||||
///
|
||||
/// If specified, the origin indicates the context from which the object is being removed.
|
||||
#[derive(Clone, Debug, Default, Extensible, PropRefs, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[prop_refs(Object)]
|
||||
#[prop_refs(Activity)]
|
||||
#[extension(ApObjectProperties)]
|
||||
pub struct Remove {
|
||||
#[serde(rename = "type")]
|
||||
#[serde(alias = "objectType")]
|
||||
#[serde(alias = "verb")]
|
||||
pub kind: RemoveType,
|
||||
|
||||
/// Adds all valid remove properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub remove_props: RemoveProperties,
|
||||
|
||||
/// Adds all valid object properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub object_props: ObjectProperties,
|
||||
|
||||
/// Adds all valid activity properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub activity_props: ActivityProperties,
|
||||
}
|
||||
|
||||
/// A specialization of Accept indicating that the acceptance is tentative.
|
||||
#[derive(Clone, Debug, Default, Extensible, PropRefs, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[prop_refs(Object)]
|
||||
#[prop_refs(Activity)]
|
||||
#[extension(ApObjectProperties)]
|
||||
pub struct TentativeAccept {
|
||||
#[serde(rename = "type")]
|
||||
#[serde(alias = "objectType")]
|
||||
#[serde(alias = "verb")]
|
||||
pub kind: TentativeAcceptType,
|
||||
|
||||
/// Adds all valid tentative_accept properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub tentative_accept_props: TentativeAcceptProperties,
|
||||
|
||||
/// Adds all valid object properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub object_props: ObjectProperties,
|
||||
|
||||
/// Adds all valid activity properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub activity_props: ActivityProperties,
|
||||
}
|
||||
|
||||
/// A specialization of Reject in which the rejection is considered tentative.
|
||||
#[derive(Clone, Debug, Default, Extensible, PropRefs, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[prop_refs(Object)]
|
||||
#[prop_refs(Activity)]
|
||||
#[extension(ApObjectProperties)]
|
||||
pub struct TentativeReject {
|
||||
#[serde(rename = "type")]
|
||||
#[serde(alias = "objectType")]
|
||||
#[serde(alias = "verb")]
|
||||
pub kind: TentativeRejectType,
|
||||
|
||||
/// Adds all valid tentative_reject properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub tentative_reject_props: TentativeRejectProperties,
|
||||
|
||||
/// Adds all valid object properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub object_props: ObjectProperties,
|
||||
|
||||
/// Adds all valid activity properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub activity_props: ActivityProperties,
|
||||
}
|
||||
|
||||
/// Indicates that the actor is traveling to target from origin.
|
||||
///
|
||||
/// Travel is an IntransitiveObject whose actor specifies the direct object. If the target or
|
||||
/// origin are not specified, either can be determined by context.
|
||||
#[derive(Clone, Debug, Default, Extensible, PropRefs, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[prop_refs(Object)]
|
||||
#[prop_refs(Activity)]
|
||||
#[extension(ApObjectProperties)]
|
||||
#[prop_refs(IntransitiveActivity)]
|
||||
pub struct Travel {
|
||||
#[serde(rename = "type")]
|
||||
#[serde(alias = "objectType")]
|
||||
#[serde(alias = "verb")]
|
||||
pub kind: TravelType,
|
||||
|
||||
/// Adds all valid travel properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub travel_props: TravelProperties,
|
||||
|
||||
/// Adds all valid object properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub object_props: ObjectProperties,
|
||||
|
||||
/// Adds all valid activity properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub activity_props: ActivityProperties,
|
||||
}
|
||||
|
||||
/// Indicates that the actor is undoing the object.
|
||||
///
|
||||
/// In most cases, the object will be an Activity describing some previously performed action (for
|
||||
/// instance, a person may have previously "liked" an article but, for whatever reason, might
|
||||
/// choose to undo that like at some later point in time).
|
||||
///
|
||||
/// The target and origin typically have no defined meaning.
|
||||
#[derive(Clone, Debug, Default, Extensible, PropRefs, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[prop_refs(Object)]
|
||||
#[prop_refs(Activity)]
|
||||
#[extension(ApObjectProperties)]
|
||||
pub struct Undo {
|
||||
#[serde(rename = "type")]
|
||||
#[serde(alias = "objectType")]
|
||||
#[serde(alias = "verb")]
|
||||
pub kind: UndoType,
|
||||
|
||||
/// Adds all valid undo properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub undo_props: UndoProperties,
|
||||
|
||||
/// Adds all valid object properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub object_props: ObjectProperties,
|
||||
|
||||
/// Adds all valid activity properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub activity_props: ActivityProperties,
|
||||
}
|
||||
|
||||
/// Indicates that the actor has updated the object.
|
||||
///
|
||||
/// Note, however, that this vocabulary does not define a mechanism for describing the actual set
|
||||
/// of modifications made to object.
|
||||
///
|
||||
/// The target and origin typically have no defined meaning.
|
||||
#[derive(Clone, Debug, Default, Extensible, PropRefs, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[prop_refs(Object)]
|
||||
#[prop_refs(Activity)]
|
||||
#[extension(ApObjectProperties)]
|
||||
pub struct Update {
|
||||
#[serde(rename = "type")]
|
||||
#[serde(alias = "objectType")]
|
||||
#[serde(alias = "verb")]
|
||||
pub kind: UpdateType,
|
||||
|
||||
/// Adds all valid update properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub update_props: UpdateProperties,
|
||||
|
||||
/// Adds all valid object properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub object_props: ObjectProperties,
|
||||
|
||||
/// Adds all valid activity properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub activity_props: ActivityProperties,
|
||||
}
|
||||
|
||||
/// Indicates that the actor has viewed the object.
|
||||
#[derive(Clone, Debug, Default, Extensible, PropRefs, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[prop_refs(Object)]
|
||||
#[prop_refs(Activity)]
|
||||
#[extension(ApObjectProperties)]
|
||||
pub struct View {
|
||||
#[serde(rename = "type")]
|
||||
#[serde(alias = "objectType")]
|
||||
#[serde(alias = "verb")]
|
||||
pub kind: ViewType,
|
||||
|
||||
/// Adds all valid view properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub view_props: ViewProperties,
|
||||
|
||||
/// Adds all valid object properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub object_props: ObjectProperties,
|
||||
|
||||
/// Adds all valid activity properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub activity_props: ActivityProperties,
|
||||
}
|
1559
src/actor.rs
Normal file
1559
src/actor.rs
Normal file
File diff suppressed because it is too large
Load diff
|
@ -1,41 +0,0 @@
|
|||
/*
|
||||
* This file is part of ActivityStreams.
|
||||
*
|
||||
* Copyright © 2020 Riley Trautman
|
||||
*
|
||||
* ActivityStreams is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ActivityStreams is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ActivityStreams. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//! Namespace for Unit Structs that serialize to strings
|
||||
use crate::UnitString;
|
||||
|
||||
#[derive(Clone, Debug, Default, UnitString)]
|
||||
#[unit_string(Application)]
|
||||
pub struct ApplicationType;
|
||||
|
||||
#[derive(Clone, Debug, Default, UnitString)]
|
||||
#[unit_string(Group)]
|
||||
pub struct GroupType;
|
||||
|
||||
#[derive(Clone, Debug, Default, UnitString)]
|
||||
#[unit_string(Organization)]
|
||||
pub struct OrganizationType;
|
||||
|
||||
#[derive(Clone, Debug, Default, UnitString)]
|
||||
#[unit_string(Person)]
|
||||
pub struct PersonType;
|
||||
|
||||
#[derive(Clone, Debug, Default, UnitString)]
|
||||
#[unit_string(Service)]
|
||||
pub struct ServiceType;
|
|
@ -1,54 +0,0 @@
|
|||
/*
|
||||
* This file is part of ActivityStreams.
|
||||
*
|
||||
* Copyright © 2020 Riley Trautman
|
||||
*
|
||||
* ActivityStreams is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ActivityStreams is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ActivityStreams. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//! Namespace for Actor types
|
||||
|
||||
#[cfg(feature = "kinds")]
|
||||
pub mod kind;
|
||||
#[cfg(feature = "types")]
|
||||
pub mod properties;
|
||||
#[cfg(feature = "types")]
|
||||
mod types;
|
||||
|
||||
#[cfg(feature = "types")]
|
||||
pub use self::types::{Application, Group, Organization, Person, Service};
|
||||
|
||||
use crate::object::Object;
|
||||
|
||||
/// `Actor` types are `Object` types that are capable of performing activities.
|
||||
///
|
||||
/// This specification intentionally defines `Actors` in only the most generalized way, stopping
|
||||
/// short of defining semantically specific properties for each. All Actor objects are
|
||||
/// specializations of `Object` and inherit all of the core properties common to all Objects.
|
||||
/// External vocabularies can be used to express additional detail not covered by the Activity
|
||||
/// Vocabulary. VCard [[vcard-rdf](https://www.w3.org/TR/vcard-rdf/) SHOULD be used to provide
|
||||
/// additional metadata for `Person`, `Group`, and `Organization` instances.
|
||||
///
|
||||
/// While implementations are free to introduce new types of Actors beyond those defined by the
|
||||
/// Activity Vocabulary, interoperability issues can arise when applications rely too much on
|
||||
/// extension types that are not recognized by other implementations. Care should be taken to not
|
||||
/// unduly overlap with or duplicate the existing `Actor` types.
|
||||
///
|
||||
/// When an implementation uses an extension type that overlaps with a core vocabulary type, the
|
||||
/// implementation MUST also specify the core vocabulary type. For instance, some vocabularies
|
||||
/// (e.g. VCard) define their own types for describing people. An implementation that wishes, for
|
||||
/// example, to use a `vcard:Individual` as an `Actor` MUST also identify that `Actor` as a
|
||||
/// `Person`.
|
||||
#[cfg_attr(feature = "derive", crate::wrapper_type)]
|
||||
pub trait Actor: Object {}
|
|
@ -1,192 +0,0 @@
|
|||
/*
|
||||
* This file is part of ActivityStreams.
|
||||
*
|
||||
* Copyright © 2020 Riley Trautman
|
||||
*
|
||||
* ActivityStreams is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ActivityStreams is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ActivityStreams. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//! Namespace for properties of standard Actor types
|
||||
//!
|
||||
//! To use these properties in your own types, you can flatten them into your struct with serde:
|
||||
//!
|
||||
//! ```rust
|
||||
//! use activitystreams::{
|
||||
//! actor::{
|
||||
//! properties::ApActorProperties,
|
||||
//! Actor, ActorBox,
|
||||
//! },
|
||||
//! ext::Ext,
|
||||
//! object::{
|
||||
//! properties::{ApObjectProperties, ObjectProperties},
|
||||
//! Object, ObjectBox,
|
||||
//! },
|
||||
//! Base, BaseBox, PropRefs,
|
||||
//! };
|
||||
//! use serde::{Deserialize, Serialize};
|
||||
//!
|
||||
//! #[derive(Clone, Debug, Default, serde::Serialize, serde::Deserialize)]
|
||||
//! #[serde(transparent)]
|
||||
//! pub struct ObjProps(pub ObjectProperties);
|
||||
//!
|
||||
//! #[derive(Clone, Debug, Default, serde::Serialize, serde::Deserialize)]
|
||||
//! #[serde(transparent)]
|
||||
//! pub struct ApObjProps(pub ApObjectProperties);
|
||||
//!
|
||||
//! #[derive(Clone, Debug, Default, serde::Serialize, serde::Deserialize)]
|
||||
//! #[serde(transparent)]
|
||||
//! pub struct ApActorProps(pub ApActorProperties);
|
||||
//!
|
||||
//! #[derive(Clone, Debug, Default, Serialize, Deserialize, PropRefs)]
|
||||
//! #[serde(rename_all = "camelCase")]
|
||||
//! #[prop_refs(Object)]
|
||||
//! #[prop_refs(Actor)]
|
||||
//! pub struct MyActor {
|
||||
//! #[serde(rename = "type")]
|
||||
//! pub kind: String,
|
||||
//!
|
||||
//! /// Define a require property for the MyActor type
|
||||
//! pub my_property: String,
|
||||
//!
|
||||
//! #[serde(flatten)]
|
||||
//! #[prop_refs]
|
||||
//! pub object_props: ObjProps,
|
||||
//!
|
||||
//! #[serde(flatten)]
|
||||
//! #[prop_refs]
|
||||
//! pub ap_object_props: ApObjProps,
|
||||
//!
|
||||
//! #[serde(flatten)]
|
||||
//! #[prop_refs]
|
||||
//! pub actor_props: ApActorProps,
|
||||
//! }
|
||||
//! #
|
||||
//! # fn main() {}
|
||||
//! ```
|
||||
|
||||
use crate::{
|
||||
actor::Actor,
|
||||
endpoint::EndpointProperties,
|
||||
ext::Extension,
|
||||
primitives::{XsdAnyUri, XsdString},
|
||||
properties,
|
||||
};
|
||||
|
||||
impl<T> Extension<T> for ApActorProperties where T: Actor {}
|
||||
|
||||
properties! {
|
||||
ApActor {
|
||||
docs [
|
||||
"Define activitypub properties for the Actor type as described by the Activity Pub vocabulary."
|
||||
],
|
||||
|
||||
inbox {
|
||||
docs [
|
||||
"A reference to an [[ActivityStreams](https://www.w3.org/ns/activitystreams)]",
|
||||
"OrderedCollection comprised of all the messages received by the actor.",
|
||||
"",
|
||||
"- Range: `xsd:anyUri`",
|
||||
"- Functional: true",
|
||||
],
|
||||
types [ XsdAnyUri ],
|
||||
functional,
|
||||
required,
|
||||
},
|
||||
|
||||
outbox {
|
||||
docs [
|
||||
"An [ActivityStreams](https://www.w3.org/ns/activitystreams)] OrderedCollection comprised of",
|
||||
"all the messages produced by the actor.",
|
||||
"",
|
||||
"- Range: `xsd:anyUri`",
|
||||
"- Functional: true",
|
||||
],
|
||||
types [ XsdAnyUri ],
|
||||
functional,
|
||||
required,
|
||||
},
|
||||
|
||||
following {
|
||||
docs [
|
||||
"A link to an [[ActivityStreams](https://www.w3.org/ns/activitystreams)] collection of the",
|
||||
"actors that this actor is following.",
|
||||
"",
|
||||
"- Range: `xsd:anyUri`",
|
||||
"- Functional: true",
|
||||
],
|
||||
types [ XsdAnyUri ],
|
||||
functional,
|
||||
},
|
||||
|
||||
followers {
|
||||
docs [
|
||||
"A link to an [[ActivityStreams](https://www.w3.org/ns/activitystreams)] collection of the",
|
||||
"actors that follow this actor.",
|
||||
"",
|
||||
"- Range: `xsd:anyUri`",
|
||||
"- Functional: true",
|
||||
],
|
||||
types [ XsdAnyUri ],
|
||||
functional,
|
||||
},
|
||||
|
||||
liked {
|
||||
docs [
|
||||
"A link to an [[ActivityStreams](https://www.w3.org/ns/activitystreams)] collection of",
|
||||
"objects this actor has liked.",
|
||||
"",
|
||||
"- Range: `xsd:anyUri`",
|
||||
"- Functional: true",
|
||||
],
|
||||
types [ XsdAnyUri ],
|
||||
functional,
|
||||
},
|
||||
|
||||
streams {
|
||||
docs [
|
||||
"A list of supplementary Collections which may be of interest.",
|
||||
"",
|
||||
"- Range: `xsd:anyUri`",
|
||||
"- Functional: false",
|
||||
],
|
||||
types [ XsdAnyUri ],
|
||||
},
|
||||
|
||||
preferred_username {
|
||||
docs [
|
||||
"A short username which may be used to refer to the actor, with no uniqueness guarantees.",
|
||||
"",
|
||||
"- Range: `xsd:string`",
|
||||
"- Functional: true",
|
||||
],
|
||||
types [ XsdString ],
|
||||
functional,
|
||||
},
|
||||
|
||||
endpoints {
|
||||
docs [
|
||||
"A json object which maps additional (typically server/domain-wide) endpoints which may be",
|
||||
"useful either for this actor or someone referencing this actor.",
|
||||
"",
|
||||
"This mapping may be nested inside the actor document as the value or may be a link to a",
|
||||
"JSON-LD document with these properties.",
|
||||
"",
|
||||
"- Range: `Endpoint`",
|
||||
"- Functional: true",
|
||||
],
|
||||
types [ EndpointProperties ],
|
||||
functional,
|
||||
},
|
||||
}
|
||||
}
|
|
@ -1,119 +0,0 @@
|
|||
/*
|
||||
* This file is part of ActivityStreams.
|
||||
*
|
||||
* Copyright © 2020 Riley Trautman
|
||||
*
|
||||
* ActivityStreams is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ActivityStreams is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ActivityStreams. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
use crate::{
|
||||
actor::{kind::*, properties::ApActorProperties, Actor, ActorBox},
|
||||
ext::Ext,
|
||||
object::{
|
||||
properties::{ApObjectProperties, ObjectProperties},
|
||||
Object, ObjectBox,
|
||||
},
|
||||
Base, BaseBox, Extensible, PropRefs,
|
||||
};
|
||||
|
||||
/// Describes a software application.
|
||||
#[derive(Clone, Debug, Default, Extensible, PropRefs, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[prop_refs(Object)]
|
||||
#[prop_refs(Actor)]
|
||||
#[extension(ApObjectProperties)]
|
||||
#[extension(ApActorProperties)]
|
||||
pub struct Application {
|
||||
#[serde(rename = "type")]
|
||||
#[serde(alias = "objectType")]
|
||||
#[serde(alias = "verb")]
|
||||
kind: ApplicationType,
|
||||
|
||||
/// Adds all valid object properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub object_props: ObjectProperties,
|
||||
}
|
||||
|
||||
/// Represents a formal or informal collective of Actors.
|
||||
#[derive(Clone, Debug, Default, Extensible, PropRefs, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[prop_refs(Object)]
|
||||
#[prop_refs(Actor)]
|
||||
#[extension(ApObjectProperties)]
|
||||
#[extension(ApActorProperties)]
|
||||
pub struct Group {
|
||||
#[serde(rename = "type")]
|
||||
#[serde(alias = "objectType")]
|
||||
#[serde(alias = "verb")]
|
||||
kind: GroupType,
|
||||
|
||||
/// Adds all valid object properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub object_props: ObjectProperties,
|
||||
}
|
||||
|
||||
/// Represents an organization.
|
||||
#[derive(Clone, Debug, Default, Extensible, PropRefs, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Organization {
|
||||
#[serde(rename = "type")]
|
||||
#[serde(alias = "objectType")]
|
||||
#[serde(alias = "verb")]
|
||||
kind: OrganizationType,
|
||||
|
||||
/// Adds all valid object properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub object_props: ObjectProperties,
|
||||
}
|
||||
|
||||
/// Represents an individual person.
|
||||
#[derive(Clone, Debug, Default, Extensible, PropRefs, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[prop_refs(Object)]
|
||||
#[prop_refs(Actor)]
|
||||
#[extension(ApObjectProperties)]
|
||||
#[extension(ApActorProperties)]
|
||||
pub struct Person {
|
||||
#[serde(rename = "type")]
|
||||
#[serde(alias = "objectType")]
|
||||
#[serde(alias = "verb")]
|
||||
kind: PersonType,
|
||||
|
||||
/// Adds all valid object properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub object_props: ObjectProperties,
|
||||
}
|
||||
|
||||
/// Represents a service of any kind.
|
||||
#[derive(Clone, Debug, Default, Extensible, PropRefs, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[prop_refs(Object)]
|
||||
#[prop_refs(Actor)]
|
||||
#[extension(ApObjectProperties)]
|
||||
#[extension(ApActorProperties)]
|
||||
pub struct Service {
|
||||
#[serde(rename = "type")]
|
||||
#[serde(alias = "objectType")]
|
||||
#[serde(alias = "verb")]
|
||||
kind: ServiceType,
|
||||
|
||||
/// Adds all valid object properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub object_props: ObjectProperties,
|
||||
}
|
1873
src/base.rs
Normal file
1873
src/base.rs
Normal file
File diff suppressed because it is too large
Load diff
1338
src/collection.rs
Normal file
1338
src/collection.rs
Normal file
File diff suppressed because it is too large
Load diff
|
@ -1,37 +0,0 @@
|
|||
/*
|
||||
* This file is part of ActivityStreams.
|
||||
*
|
||||
* Copyright © 2020 Riley Trautman
|
||||
*
|
||||
* ActivityStreams is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ActivityStreams is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ActivityStreams. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//! Namespace for Unit Structs that serialize to strings
|
||||
use crate::UnitString;
|
||||
|
||||
#[derive(Clone, Debug, Default, UnitString)]
|
||||
#[unit_string(Collection)]
|
||||
pub struct CollectionType;
|
||||
|
||||
#[derive(Clone, Debug, Default, UnitString)]
|
||||
#[unit_string(CollectionPage)]
|
||||
pub struct CollectionPageType;
|
||||
|
||||
#[derive(Clone, Debug, Default, UnitString)]
|
||||
#[unit_string(OrderedCollection)]
|
||||
pub struct OrderedCollectionType;
|
||||
|
||||
#[derive(Clone, Debug, Default, UnitString)]
|
||||
#[unit_string(OrderedCollectionPage)]
|
||||
pub struct OrderedCollectionPageType;
|
|
@ -1,59 +0,0 @@
|
|||
/*
|
||||
* This file is part of ActivityStreams.
|
||||
*
|
||||
* Copyright © 2020 Riley Trautman
|
||||
*
|
||||
* ActivityStreams is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ActivityStreams is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ActivityStreams. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//! Namespace for Collection types
|
||||
|
||||
#[cfg(feature = "kinds")]
|
||||
pub mod kind;
|
||||
#[cfg(feature = "types")]
|
||||
pub mod properties;
|
||||
#[cfg(feature = "types")]
|
||||
mod types;
|
||||
|
||||
#[cfg(feature = "types")]
|
||||
pub use self::types::{
|
||||
OrderedCollection, OrderedCollectionPage, UnorderedCollection, UnorderedCollectionPage,
|
||||
};
|
||||
|
||||
use crate::object::Object;
|
||||
|
||||
/// A Collection is a subtype of `Object` that represents ordered or unordered sets of `Object` or
|
||||
/// `Link` instances.
|
||||
///
|
||||
/// The items within a Collection can be ordered or unordered. The OrderedCollection type MAY be
|
||||
/// used to identify a Collection whose items are always ordered. In the JSON serialization, the
|
||||
/// unordered items of a Collection are represented using the items property while ordered items
|
||||
/// are represented using the orderedItems property.
|
||||
///
|
||||
/// `UnorderedCollection` and `OrderedCollection` types are provided by the `activitystreams-types`
|
||||
/// crate.
|
||||
#[cfg_attr(feature = "derive", crate::wrapper_type)]
|
||||
pub trait Collection: Object {}
|
||||
|
||||
/// Used to represent distinct subsets of items from a Collection.
|
||||
///
|
||||
/// A `Collection` can contain a large number of items. Often, it becomes impractical for an
|
||||
/// implementation to serialize every item contained by a `Collection` using the items (or
|
||||
/// `ordered_items`) property alone. In such cases, the items within a `Collection` can be divided
|
||||
/// into distinct subsets or "pages". A page is identified using the `CollectionPage` type.
|
||||
///
|
||||
/// `UnorderedCollectionPage` and `OrderedCollectionPage` types are provied by the
|
||||
/// `activitystreams-types` crate.
|
||||
#[cfg_attr(feature = "derive", crate::wrapper_type)]
|
||||
pub trait CollectionPage: Collection {}
|
|
@ -1,226 +0,0 @@
|
|||
/*
|
||||
* This file is part of ActivityStreams.
|
||||
*
|
||||
* Copyright © 2020 Riley Trautman
|
||||
*
|
||||
* ActivityStreams is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ActivityStreams is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ActivityStreams. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//! Namespace for properties of standard collection types
|
||||
//!
|
||||
//! To use these properties in your own types, you can flatten them into your struct with serde:
|
||||
//!
|
||||
//! ```rust
|
||||
//! use activitystreams::{
|
||||
//! collection::{
|
||||
//! properties::CollectionProperties,
|
||||
//! Collection, CollectionBox,
|
||||
//! },
|
||||
//! ext::Ext,
|
||||
//! object::{
|
||||
//! properties::ObjectProperties,
|
||||
//! Object, ObjectBox,
|
||||
//! },
|
||||
//! Base, BaseBox, PropRefs,
|
||||
//! };
|
||||
//! use serde::{Deserialize, Serialize};
|
||||
//!
|
||||
//! #[derive(Clone, Debug, Default, serde::Serialize, serde::Deserialize)]
|
||||
//! #[serde(transparent)]
|
||||
//! pub struct ObjProps(pub ObjectProperties);
|
||||
//!
|
||||
//! #[derive(Clone, Debug, Default, serde::Serialize, serde::Deserialize)]
|
||||
//! #[serde(transparent)]
|
||||
//! pub struct CollectionProps(pub CollectionProperties);
|
||||
//!
|
||||
//! #[derive(Clone, Debug, Default, Serialize, Deserialize, PropRefs)]
|
||||
//! #[serde(rename_all = "camelCase")]
|
||||
//! #[prop_refs(Object)]
|
||||
//! #[prop_refs(Collection)]
|
||||
//! pub struct MyCollection {
|
||||
//! #[serde(rename = "type")]
|
||||
//! pub kind: String,
|
||||
//!
|
||||
//! /// Define a require property for the MyCollection type
|
||||
//! pub my_property: String,
|
||||
//!
|
||||
//! #[serde(flatten)]
|
||||
//! #[prop_refs]
|
||||
//! pub object_properties: ObjProps,
|
||||
//!
|
||||
//! #[serde(flatten)]
|
||||
//! #[prop_refs]
|
||||
//! pub collection_properties: CollectionProps,
|
||||
//! }
|
||||
//! #
|
||||
//! # fn main() {}
|
||||
//! ```
|
||||
|
||||
use crate::{primitives::*, properties, BaseBox};
|
||||
|
||||
properties! {
|
||||
Collection {
|
||||
docs [
|
||||
"`Collection` objects are a specialization of the base `Object` that serve as a container for",
|
||||
"other `Objects` or `Links`.",
|
||||
"",
|
||||
"The items within a `Collection` can be ordered or unordered. The `OrderedCollection` type MAY be",
|
||||
"used to identify a `Collection` whose items are always ordered. In the JSON serialization, the",
|
||||
"unordered items of a `Collection` are represented using the `items` property while ordered items",
|
||||
"are represented using the `ordered_items` property.",
|
||||
],
|
||||
|
||||
items {
|
||||
docs [
|
||||
"Identifies the items contained in a collection. The items might be ordered or unordered.",
|
||||
"",
|
||||
"- Range: `Object` | `Link` | Ordered List of [ `Object` | `Link` ]",
|
||||
"- Functional: false",
|
||||
],
|
||||
types [
|
||||
XsdString,
|
||||
BaseBox,
|
||||
],
|
||||
required,
|
||||
},
|
||||
|
||||
total_items {
|
||||
docs [
|
||||
"A non-negative integer specifying the total number of objects contained by the logical view",
|
||||
"of the collection.",
|
||||
"",
|
||||
"This number might not reflect the actual number of items serialized within the `Collection`",
|
||||
"object instance.",
|
||||
"",
|
||||
"- Range: `xsd:nonNegativeInteger`",
|
||||
"- Functional: true",
|
||||
],
|
||||
types [
|
||||
XsdNonNegativeInteger,
|
||||
],
|
||||
functional,
|
||||
},
|
||||
|
||||
current {
|
||||
docs [
|
||||
"In a paged `Collection`, indicates the page that contains the most recently updated member",
|
||||
"items.",
|
||||
"",
|
||||
"- Range: `CollectionPage` | `Link`",
|
||||
"- Functional: true",
|
||||
],
|
||||
types [
|
||||
XsdAnyUri,
|
||||
BaseBox,
|
||||
],
|
||||
functional,
|
||||
},
|
||||
|
||||
first {
|
||||
docs [
|
||||
"In a paged `Collection`, indicates the furthest preceeding page of items in the collection.",
|
||||
"",
|
||||
"- Range: `CollectionPage` | `Link`",
|
||||
"- Functional: true",
|
||||
],
|
||||
types [
|
||||
XsdAnyUri,
|
||||
BaseBox,
|
||||
],
|
||||
functional,
|
||||
},
|
||||
|
||||
last {
|
||||
docs [
|
||||
"In a paged `Collection`, indicates the furthest proceeding page of the collection.",
|
||||
"",
|
||||
"- Range: `CollectionPage` | `Link`",
|
||||
"- Functional: true",
|
||||
],
|
||||
types [
|
||||
XsdAnyUri,
|
||||
BaseBox,
|
||||
],
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
properties! {
|
||||
CollectionPage {
|
||||
docs [
|
||||
"The `CollectionPage` type extends from the base `Collection` type and inherits all of it's",
|
||||
"properties.",
|
||||
],
|
||||
|
||||
part_of {
|
||||
docs [
|
||||
"Identifies the `Collection` to which a `CollectionPage` objects items belong.",
|
||||
"",
|
||||
"Range: `Collection` | `Link`",
|
||||
"Functional: true",
|
||||
],
|
||||
types [
|
||||
XsdAnyUri,
|
||||
BaseBox,
|
||||
],
|
||||
functional,
|
||||
},
|
||||
|
||||
next {
|
||||
docs [
|
||||
"In a paged `Collection`, indicates the next page of items.",
|
||||
"",
|
||||
"- Range: `CollectionPage` | `Link`",
|
||||
"- Functional: true",
|
||||
],
|
||||
types [
|
||||
XsdAnyUri,
|
||||
BaseBox,
|
||||
],
|
||||
functional,
|
||||
},
|
||||
|
||||
prev {
|
||||
docs [
|
||||
"In a paged `Collection`, identifies the previous page of items.",
|
||||
"",
|
||||
"- Range: `CollectionPage` | `Link`",
|
||||
"- Functional: true",
|
||||
],
|
||||
types [
|
||||
XsdAnyUri,
|
||||
BaseBox,
|
||||
],
|
||||
functional,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
properties! {
|
||||
OrderedCollectionPage {
|
||||
docs ["The OrderedCollectionPage type MAY be used to identify a page whose items are strictly ordered." ],
|
||||
start_index {
|
||||
docs ["A non-negative integer value identifying the relative position within the logical view of a",
|
||||
"strictly ordered collection.",
|
||||
"",
|
||||
"- Range: `xsd:nonNegativeInteger`",
|
||||
"- Functional: true",
|
||||
],
|
||||
types [
|
||||
XsdNonNegativeInteger,
|
||||
],
|
||||
functional,
|
||||
},
|
||||
}
|
||||
}
|
|
@ -1,142 +0,0 @@
|
|||
/*
|
||||
* This file is part of ActivityStreams.
|
||||
*
|
||||
* Copyright © 2020 Riley Trautman
|
||||
*
|
||||
* ActivityStreams is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ActivityStreams is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ActivityStreams. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//! Namespace for Collection types
|
||||
|
||||
use crate::{
|
||||
collection::{
|
||||
kind::*, properties::*, Collection, CollectionBox, CollectionPage, CollectionPageBox,
|
||||
},
|
||||
ext::Ext,
|
||||
object::{
|
||||
properties::{ApObjectProperties, ObjectProperties},
|
||||
Object, ObjectBox,
|
||||
},
|
||||
Base, BaseBox, Extensible, PropRefs,
|
||||
};
|
||||
|
||||
/// The default `Collection` type.
|
||||
#[derive(Clone, Debug, Default, Extensible, PropRefs, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[prop_refs(Object)]
|
||||
#[prop_refs(Collection)]
|
||||
#[extension(ApObjectProperties)]
|
||||
pub struct UnorderedCollection {
|
||||
#[serde(rename = "type")]
|
||||
#[serde(alias = "objectType")]
|
||||
#[serde(alias = "verb")]
|
||||
kind: CollectionType,
|
||||
|
||||
/// Adds all valid object properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub object_props: ObjectProperties,
|
||||
|
||||
/// Adds all valid collection properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub collection_props: CollectionProperties,
|
||||
}
|
||||
|
||||
/// A subtype of `Collection` in which members of the logical collection are assumed to always be
|
||||
/// strictly ordered.
|
||||
#[derive(Clone, Debug, Default, Extensible, PropRefs, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[prop_refs(Object)]
|
||||
#[prop_refs(Collection)]
|
||||
#[extension(ApObjectProperties)]
|
||||
pub struct OrderedCollection {
|
||||
#[serde(rename = "type")]
|
||||
#[serde(alias = "objectType")]
|
||||
#[serde(alias = "verb")]
|
||||
kind: OrderedCollectionType,
|
||||
|
||||
/// Adds all valid object properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub object_props: ObjectProperties,
|
||||
|
||||
/// Adds all valid collection properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub collection_props: CollectionProperties,
|
||||
}
|
||||
|
||||
/// Used to represent distinct subsets of items from a `Collection`.
|
||||
#[derive(Clone, Debug, Default, Extensible, PropRefs, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[prop_refs(Object)]
|
||||
#[prop_refs(Collection)]
|
||||
#[prop_refs(CollectionPage)]
|
||||
#[extension(ApObjectProperties)]
|
||||
pub struct UnorderedCollectionPage {
|
||||
#[serde(rename = "type")]
|
||||
#[serde(alias = "objectType")]
|
||||
#[serde(alias = "verb")]
|
||||
kind: CollectionPageType,
|
||||
|
||||
/// Adds all valid object properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub object_props: ObjectProperties,
|
||||
|
||||
/// Adds all valid collection properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub collection_props: CollectionProperties,
|
||||
|
||||
/// Adds all valid collection page properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub collection_page_props: CollectionPageProperties,
|
||||
}
|
||||
|
||||
/// Used to represent ordered subsets of items from an `OrderedCollection`.
|
||||
#[derive(Clone, Debug, Default, Extensible, PropRefs, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[prop_refs(Object)]
|
||||
#[prop_refs(Collection)]
|
||||
#[prop_refs(CollectionPage)]
|
||||
#[extension(ApObjectProperties)]
|
||||
pub struct OrderedCollectionPage {
|
||||
#[serde(rename = "type")]
|
||||
#[serde(alias = "objectType")]
|
||||
#[serde(alias = "verb")]
|
||||
kind: OrderedCollectionPageType,
|
||||
|
||||
/// Adds all valid object properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub object_props: ObjectProperties,
|
||||
|
||||
/// Adds all valid collection properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub collection_props: CollectionProperties,
|
||||
|
||||
/// Adds all valid collection page properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub collection_page_props: CollectionPageProperties,
|
||||
|
||||
/// Adds all valid ordered collection page properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub ordered_collection_page_props: OrderedCollectionPageProperties,
|
||||
}
|
51
src/either.rs
Normal file
51
src/either.rs
Normal file
|
@ -0,0 +1,51 @@
|
|||
#[derive(
|
||||
Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, serde::Deserialize, serde::Serialize,
|
||||
)]
|
||||
#[serde(untagged)]
|
||||
pub enum Either<L, R> {
|
||||
Left(L),
|
||||
Right(R),
|
||||
}
|
||||
|
||||
impl<L, R> Either<L, R> {
|
||||
pub fn left(self) -> Option<L> {
|
||||
if let Either::Left(l) = self {
|
||||
Some(l)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn right(self) -> Option<R> {
|
||||
if let Either::Right(r) = self {
|
||||
Some(r)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_ref(&self) -> Either<&L, &R> {
|
||||
match self {
|
||||
Either::Left(ref l) => Either::Left(l),
|
||||
Either::Right(ref r) => Either::Right(r),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_mut(&mut self) -> Either<&mut L, &mut R> {
|
||||
match self {
|
||||
Either::Left(ref mut l) => Either::Left(l),
|
||||
Either::Right(ref mut r) => Either::Right(r),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn map<F1, F2, L2, R2>(self, f1: F1, f2: F2) -> Either<L2, R2>
|
||||
where
|
||||
F1: Fn(L) -> L2,
|
||||
F2: Fn(R) -> R2,
|
||||
{
|
||||
match self {
|
||||
Either::Left(l) => Either::Left((f1)(l)),
|
||||
Either::Right(r) => Either::Right((f2)(r)),
|
||||
}
|
||||
}
|
||||
}
|
121
src/endpoint.rs
121
src/endpoint.rs
|
@ -1,121 +0,0 @@
|
|||
/*
|
||||
* This file is part of ActivityStreams.
|
||||
*
|
||||
* Copyright © 2020 Riley Trautman
|
||||
*
|
||||
* ActivityStreams is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ActivityStreams is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ActivityStreams. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//! Endpoint traits and types
|
||||
|
||||
use crate::{primitives::XsdAnyUri, properties};
|
||||
|
||||
properties! {
|
||||
Endpoint {
|
||||
docs [
|
||||
"A json object which maps additional (typically server/domain-wide) endpoints which may be",
|
||||
"useful either for this actor or someone referencing this actor.",
|
||||
"",
|
||||
"This mapping may be nested inside the actor document as the value or may be a link to a JSON-LD",
|
||||
"document with these properties.",
|
||||
],
|
||||
|
||||
proxy_url {
|
||||
docs [
|
||||
"Endpoint URI so this actor's clients may access remote ActivityStreams objects which",
|
||||
"require authentication to access.",
|
||||
"",
|
||||
"To use this endpoint, the client posts an x-www-form-urlencoded id parameter with the value",
|
||||
"being the id of the requested ActivityStreams object.",
|
||||
"",
|
||||
"- Range: `anyUri`",
|
||||
"- Functional: true",
|
||||
],
|
||||
types [ XsdAnyUri ],
|
||||
functional,
|
||||
},
|
||||
|
||||
oauth_authorization_endpoint {
|
||||
docs [
|
||||
"If OAuth 2.0 bearer tokens [[RFC6749](https://tools.ietf.org/html/rfc6749)]",
|
||||
"[[RFC6750](https://tools.ietf.org/html/rfc6750)] are being used for authenticating client",
|
||||
"to server interactions, this endpoint specifies a URI at which a browser-authenticated user",
|
||||
"may obtain a new authorization grant.",
|
||||
"",
|
||||
"- Range: `anyUri`",
|
||||
"- Functional: true",
|
||||
],
|
||||
types [ XsdAnyUri ],
|
||||
functional,
|
||||
},
|
||||
|
||||
oauth_token_endpoint {
|
||||
docs [
|
||||
"If OAuth 2.0 bearer tokens [[RFC6749](https://tools.ietf.org/html/rfc6749)]",
|
||||
"[[RFC6750](https://tools.ietf.org/html/rfc6750)] are being used for authenticating client",
|
||||
"to server interactions, this endpoint specifies a URI at which a client may acquire an",
|
||||
"access token.",
|
||||
"",
|
||||
"- Range: `anyUri`",
|
||||
"- Functional: true",
|
||||
],
|
||||
types [ XsdAnyUri ],
|
||||
functional,
|
||||
},
|
||||
|
||||
provide_client_key {
|
||||
docs [
|
||||
"If Linked Data Signatures and HTTP Signatures are being used for authentication and",
|
||||
"authorization, this endpoint specifies a URI at which browser-authenticated users may",
|
||||
"authorize a client's public key for client to server interactions.",
|
||||
"",
|
||||
"- Range: `anyUri`",
|
||||
"- Functional: true",
|
||||
],
|
||||
types [ XsdAnyUri ],
|
||||
functional,
|
||||
},
|
||||
|
||||
sign_client_key {
|
||||
docs [
|
||||
"If Linked Data Signatures and HTTP Signatures are being used for authentication and",
|
||||
"authorization, this endpoint specifies a URI at which a client key may be signed by the",
|
||||
"actor's key for a time window to act on behalf of the actor in interacting with foreign",
|
||||
"servers.",
|
||||
"",
|
||||
"- Range: `anyUri`",
|
||||
"- Functional: true",
|
||||
],
|
||||
types [ XsdAnyUri ],
|
||||
functional,
|
||||
},
|
||||
|
||||
shared_inbox {
|
||||
docs [
|
||||
"An optional endpoint used for wide delivery of publicly addressed activities and activities",
|
||||
"sent to followers.",
|
||||
"",
|
||||
"`shared_inbox`endpoints SHOULD also be publicly readable `OrderedCollection` objects",
|
||||
"containing objects addressed to the Public special collection. Reading from the",
|
||||
"`shared_inbox` endpoint MUST NOT present objects which are not addressed to the Public",
|
||||
"endpoint.",
|
||||
"",
|
||||
"- Range: `anyUri`",
|
||||
"- Functional: true",
|
||||
],
|
||||
types [ XsdAnyUri ],
|
||||
functional,
|
||||
},
|
||||
}
|
||||
}
|
3
src/error.rs
Normal file
3
src/error.rs
Normal file
|
@ -0,0 +1,3 @@
|
|||
#[derive(Clone, Debug, thiserror::Error)]
|
||||
#[error("URL did not match expected domain")]
|
||||
pub struct DomainError;
|
384
src/ext.rs
384
src/ext.rs
|
@ -1,384 +0,0 @@
|
|||
/*
|
||||
* This file is part of ActivityStreams.
|
||||
*
|
||||
* Copyright © 2020 Riley Trautman
|
||||
*
|
||||
* ActivityStreams is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ActivityStreams is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ActivityStreams. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//! Defining extensibility in the ActivityStreams spec
|
||||
//!
|
||||
//! In ActivityStreams, there are many times you may want to use an extension. For example, to
|
||||
//! interact with Mastodon, you need to at least understand the `publicKey` field on their actor
|
||||
//! type. If not, you won't be able to use HTTP Signatures, and will have your messages rejected.
|
||||
//!
|
||||
//! But this library doesn't provide any of the security extensions to ActivityStreams. In order to
|
||||
//! support it, you could implment your own extensions to this library. Let's cover a basic
|
||||
//! example.
|
||||
//!
|
||||
//! ```rust
|
||||
//! // For this example, we'll use the Extensible trait, the Extension trait, the Actor trait, and
|
||||
//! // the Person type
|
||||
//! use activitystreams::{
|
||||
//! actor::{Actor, Person},
|
||||
//! ext::{Extensible, Extension},
|
||||
//! };
|
||||
//!
|
||||
//! /// Let's define the PublicKey type. The three fields in this PublicKey struct are how Mastodon
|
||||
//! /// represents Public Keys on actors. We'll need to derive Serialize and Deserialize for these
|
||||
//! /// in order for them to be useful.
|
||||
//! #[derive(Clone, Debug, Default, serde::Deserialize, serde::Serialize)]
|
||||
//! #[serde(rename_all = "camelCase")]
|
||||
//! pub struct PublicKey {
|
||||
//! /// The ID of the key.
|
||||
//! ///
|
||||
//! /// In mastodon, this is the same as the actor's URL with a #main-key on
|
||||
//! /// the end.
|
||||
//! pub id: String,
|
||||
//!
|
||||
//! /// The ID of the actor who owns this key.
|
||||
//! pub owner: String,
|
||||
//!
|
||||
//! /// This is a PEM file with PKCS#8 encoded data.
|
||||
//! pub public_key_pem: String,
|
||||
//! }
|
||||
//!
|
||||
//! /// Now, we'll need more than just a PublicKey struct to make this work. We'll need to define a
|
||||
//! /// second struct that declares the correct key to house this information inside of
|
||||
//! ///
|
||||
//! /// The information is represented as the following json:
|
||||
//! /// ```json
|
||||
//! /// {
|
||||
//! /// "publicKey": {
|
||||
//! /// "id": "key id",
|
||||
//! /// "owner": "actor id",
|
||||
//! /// "publicKeyPem": "pem string"
|
||||
//! /// }
|
||||
//! /// }
|
||||
//! /// ```
|
||||
//! ///
|
||||
//! /// This means we'll need to define the 'publicKey' key
|
||||
//! #[derive(Clone, Debug, Default, serde::Deserialize, serde::Serialize)]
|
||||
//! #[serde(rename_all = "camelCase")]
|
||||
//! pub struct PublicKeyExtension {
|
||||
//! /// The public key's information
|
||||
//! pub public_key: PublicKey
|
||||
//! }
|
||||
//!
|
||||
//! impl PublicKey {
|
||||
//! /// Let's add a convenience method to turn a PublicKey into a PublicKeyExtension
|
||||
//! pub fn to_ext(self) -> PublicKeyExtension {
|
||||
//! PublicKeyExtension { public_key: self }
|
||||
//! }
|
||||
//! }
|
||||
//!
|
||||
//! // And finally, we'll implement the Extension trait for PublicKeyExtension
|
||||
//! //
|
||||
//! // We'll bound this extension by the Actor trait, since we don't care about non-actors having
|
||||
//! // keys. This means that you can put a key on a `Person`, but not on a `Video`.
|
||||
//! impl<T> Extension<T> for PublicKeyExtension where T: Actor {}
|
||||
//!
|
||||
//! // Now that these types are defined, we can put them to use!
|
||||
//! let person = Person::new();
|
||||
//!
|
||||
//! // let's just create a dummy key for this example
|
||||
//! let public_key = PublicKey {
|
||||
//! id: "My ID".to_owned(),
|
||||
//! owner: "Owner ID".to_owned(),
|
||||
//! public_key_pem: "My Public Key".to_owned(),
|
||||
//! };
|
||||
//!
|
||||
//! // We're doing it! The person is being extended with a public key
|
||||
//! //
|
||||
//! // Note that calling `extend` on person here is possible because the Extensible trait is in
|
||||
//! // scope
|
||||
//! let person_with_key = person.extend(public_key.to_ext());
|
||||
//! ```
|
||||
|
||||
use crate::{
|
||||
activity::{Activity, ActivityBox, IntransitiveActivity, IntransitiveActivityBox},
|
||||
actor::{Actor, ActorBox},
|
||||
collection::{Collection, CollectionBox, CollectionPage, CollectionPageBox},
|
||||
link::{Link, LinkBox},
|
||||
object::{Object, ObjectBox},
|
||||
Base, BaseBox,
|
||||
};
|
||||
use std::{convert::TryFrom, fmt::Debug};
|
||||
|
||||
/// Defines an extension to an activitystreams object or link
|
||||
///
|
||||
/// This type provides two fields, the first field, `base`, should always the be base
|
||||
/// ActivityStreams type. As long as `base` implements an ActivityStreams trait, Ext will also.
|
||||
///
|
||||
/// For example, the type `Ext<Video, HashMap<String, String>>` will implement the `Object` trait,
|
||||
/// because `Video` implements that trait.
|
||||
///
|
||||
/// Additionally, AsRef and AsMut have been implemented for Ext. If type type
|
||||
/// `Ext<Ext<Follow, SomeTime>, AnotherType>` exists, that will implement
|
||||
/// `AsRef<ActivityProperties>` just like the innermost `Follow`.
|
||||
///
|
||||
/// Usage:
|
||||
/// ```rust
|
||||
/// use activitystreams::object::Video;
|
||||
///
|
||||
/// fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// let mut video = Video::full();
|
||||
///
|
||||
/// // AsMut works even though this is an Ext<Video, ApObjectProperties>
|
||||
/// video
|
||||
/// .as_mut()
|
||||
/// .set_id("https://example.com")?;
|
||||
///
|
||||
/// // set information on the extension
|
||||
/// video
|
||||
/// .extension
|
||||
/// .set_source_xsd_any_uri("https://example.com")?;
|
||||
///
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
#[derive(Clone, Debug, Default)]
|
||||
#[cfg_attr(feature = "derive", derive(serde::Deserialize, serde::Serialize))]
|
||||
pub struct Ext<T, U> {
|
||||
/// The ActivityStreams base type, or another extension containing one
|
||||
#[cfg_attr(feature = "derive", serde(flatten))]
|
||||
pub base: T,
|
||||
|
||||
/// The extension being applied to the type
|
||||
#[cfg_attr(feature = "derive", serde(flatten))]
|
||||
pub extension: U,
|
||||
}
|
||||
|
||||
/// A trait implemented by extensions to the ActivityStreams specification
|
||||
///
|
||||
/// This is implemented for a couple types by default, such as
|
||||
/// ApObjectProperties, and ApActorProperties.
|
||||
///
|
||||
/// Extensions are not intended to be used as trait objects
|
||||
pub trait Extension<T>
|
||||
where
|
||||
T: Base,
|
||||
{
|
||||
/// A default implementation that simply returns the Ext type with Self and the base type
|
||||
/// inside of it.
|
||||
fn extends(self, base: T) -> Ext<T, Self>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
Ext {
|
||||
base,
|
||||
extension: self,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A trait implemented (automatically) by objects and links in the ActivityStreams specification
|
||||
///
|
||||
/// This is used to easily extend objects.
|
||||
///
|
||||
/// ```rust
|
||||
/// # use activitystreams::object::{Video, properties::ApObjectProperties};
|
||||
/// use activitystreams::ext::Extensible;
|
||||
/// let vid = Video::new();
|
||||
/// let ap_props = ApObjectProperties::default();
|
||||
///
|
||||
/// let extended_vid = vid.extend(ap_props);
|
||||
/// ```
|
||||
pub trait Extensible<U> {
|
||||
fn extend(self, extension: U) -> Ext<Self, U>
|
||||
where
|
||||
Self: Sized;
|
||||
}
|
||||
|
||||
impl<T, U, V> AsRef<V> for Ext<T, U>
|
||||
where
|
||||
T: Base + AsRef<V>,
|
||||
U: Extension<T> + Debug,
|
||||
{
|
||||
fn as_ref(&self) -> &V {
|
||||
self.base.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U, V> AsMut<V> for Ext<T, U>
|
||||
where
|
||||
T: Base + AsMut<V>,
|
||||
U: Extension<T> + Debug,
|
||||
{
|
||||
fn as_mut(&mut self) -> &mut V {
|
||||
self.base.as_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TryFrom<Ext<T, U>> for BaseBox
|
||||
where
|
||||
T: Base + serde::ser::Serialize,
|
||||
U: Extension<T> + serde::ser::Serialize + Debug,
|
||||
{
|
||||
type Error = std::io::Error;
|
||||
|
||||
fn try_from(e: Ext<T, U>) -> Result<Self, Self::Error> {
|
||||
BaseBox::from_concrete(e)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TryFrom<Ext<T, U>> for ObjectBox
|
||||
where
|
||||
T: Object + serde::ser::Serialize,
|
||||
U: Extension<T> + serde::ser::Serialize + Debug,
|
||||
{
|
||||
type Error = std::io::Error;
|
||||
|
||||
fn try_from(e: Ext<T, U>) -> Result<Self, Self::Error> {
|
||||
ObjectBox::from_concrete(e)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TryFrom<Ext<T, U>> for LinkBox
|
||||
where
|
||||
T: Link + serde::ser::Serialize,
|
||||
U: Extension<T> + serde::ser::Serialize + Debug,
|
||||
{
|
||||
type Error = std::io::Error;
|
||||
|
||||
fn try_from(e: Ext<T, U>) -> Result<Self, Self::Error> {
|
||||
LinkBox::from_concrete(e)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TryFrom<Ext<T, U>> for CollectionBox
|
||||
where
|
||||
T: Collection + serde::ser::Serialize,
|
||||
U: Extension<T> + serde::ser::Serialize + Debug,
|
||||
{
|
||||
type Error = std::io::Error;
|
||||
|
||||
fn try_from(e: Ext<T, U>) -> Result<Self, Self::Error> {
|
||||
CollectionBox::from_concrete(e)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TryFrom<Ext<T, U>> for CollectionPageBox
|
||||
where
|
||||
T: CollectionPage + serde::ser::Serialize,
|
||||
U: Extension<T> + serde::ser::Serialize + Debug,
|
||||
{
|
||||
type Error = std::io::Error;
|
||||
|
||||
fn try_from(e: Ext<T, U>) -> Result<Self, Self::Error> {
|
||||
CollectionPageBox::from_concrete(e)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TryFrom<Ext<T, U>> for ActivityBox
|
||||
where
|
||||
T: Activity + serde::ser::Serialize,
|
||||
U: Extension<T> + serde::ser::Serialize + Debug,
|
||||
{
|
||||
type Error = std::io::Error;
|
||||
|
||||
fn try_from(e: Ext<T, U>) -> Result<Self, Self::Error> {
|
||||
ActivityBox::from_concrete(e)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TryFrom<Ext<T, U>> for IntransitiveActivityBox
|
||||
where
|
||||
T: IntransitiveActivity + serde::ser::Serialize,
|
||||
U: Extension<T> + serde::ser::Serialize + Debug,
|
||||
{
|
||||
type Error = std::io::Error;
|
||||
|
||||
fn try_from(e: Ext<T, U>) -> Result<Self, Self::Error> {
|
||||
IntransitiveActivityBox::from_concrete(e)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TryFrom<Ext<T, U>> for ActorBox
|
||||
where
|
||||
T: Actor + serde::ser::Serialize,
|
||||
U: Extension<T> + serde::ser::Serialize + Debug,
|
||||
{
|
||||
type Error = std::io::Error;
|
||||
|
||||
fn try_from(e: Ext<T, U>) -> Result<Self, Self::Error> {
|
||||
ActorBox::from_concrete(e)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> Extensible<U> for T
|
||||
where
|
||||
T: crate::Base,
|
||||
U: Extension<T>,
|
||||
{
|
||||
fn extend(self, item: U) -> Ext<Self, U> {
|
||||
item.extends(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> Base for Ext<T, U>
|
||||
where
|
||||
T: Base,
|
||||
U: Debug,
|
||||
{
|
||||
}
|
||||
|
||||
impl<T, U> Object for Ext<T, U>
|
||||
where
|
||||
T: Object,
|
||||
U: Debug,
|
||||
{
|
||||
}
|
||||
|
||||
impl<T, U> Link for Ext<T, U>
|
||||
where
|
||||
T: Link,
|
||||
U: Debug,
|
||||
{
|
||||
}
|
||||
|
||||
impl<T, U> Actor for Ext<T, U>
|
||||
where
|
||||
T: Actor,
|
||||
U: Debug,
|
||||
{
|
||||
}
|
||||
|
||||
impl<T, U> Collection for Ext<T, U>
|
||||
where
|
||||
T: Collection,
|
||||
U: Debug,
|
||||
{
|
||||
}
|
||||
|
||||
impl<T, U> CollectionPage for Ext<T, U>
|
||||
where
|
||||
T: CollectionPage,
|
||||
U: Debug,
|
||||
{
|
||||
}
|
||||
|
||||
impl<T, U> Activity for Ext<T, U>
|
||||
where
|
||||
T: Activity,
|
||||
U: Debug,
|
||||
{
|
||||
}
|
||||
|
||||
impl<T, U> IntransitiveActivity for Ext<T, U>
|
||||
where
|
||||
T: IntransitiveActivity,
|
||||
U: Debug,
|
||||
{
|
||||
}
|
522
src/lib.rs
522
src/lib.rs
|
@ -1,31 +1,17 @@
|
|||
/*
|
||||
* This file is part of ActivityStreams.
|
||||
*
|
||||
* Copyright © 2020 Riley Trautman
|
||||
*
|
||||
* ActivityStreams is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ActivityStreams is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ActivityStreams. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//! ActivityStreams
|
||||
//! # ActivityStreams New
|
||||
//! _A set of Traits and Types that make up the ActivityStreams and ActivityPub specifications_
|
||||
//!
|
||||
//! A set of Traits and Types that make up the ActivityStreams and ActivityPub specifications
|
||||
//! - Find the code on [git.asonix.dog](https://git.asonix.dog/asonix/activitystreams-sketch)
|
||||
//! - Read the docs on [activitystreams-new.asonix.dog](https://activitystreams-new.asonix.dog)
|
||||
//! - Join the matrix channel at [#activitypub:asonix.dog](https://matrix.to/#/!fAEcHyTUdAaKCzIKCt:asonix.dog?via=asonix.dog&via=matrix.org&via=t2bot.io)
|
||||
//! - Hit me up on [mastodon](https://asonix.dog/@asonix)
|
||||
//!
|
||||
//! ## Usage
|
||||
//!
|
||||
//! First, add ActivityStreams to your dependencies
|
||||
//! ```toml
|
||||
//! activitystreams = "0.6.2"
|
||||
//! [dependencies]
|
||||
//! activitystreams-new = { git = "https://git.asonix.dog/asonix/activitystreams-sketch", branch = "main" }
|
||||
//! ```
|
||||
//!
|
||||
//! ### Types
|
||||
|
@ -35,40 +21,31 @@
|
|||
//! So to use an ActivityStreams Video, you'd write
|
||||
//! ```rust
|
||||
//! use activitystreams::object::Video;
|
||||
//! let video = Video::new();
|
||||
//! ```
|
||||
//!
|
||||
//! And to use an ActivityStreams profile, you'd write
|
||||
//! And to use an ActivityPub profile, you'd write
|
||||
//! ```rust
|
||||
//! use activitystreams::object::Profile;
|
||||
//! use activitystreams::object::{ApObject, Profile};
|
||||
//! let inner = Profile::new();
|
||||
//! let profile = ApObject::new(inner);
|
||||
//! ```
|
||||
//!
|
||||
//! ### Properties
|
||||
//! There's only one kind of Link
|
||||
//! ```rust
|
||||
//! use activitystreams::link::Mention;
|
||||
//! let mention = Mention::new();
|
||||
//! ```
|
||||
//!
|
||||
//! Each concrete type implements `AsRef<>` for each of their properties fields. A basic
|
||||
//! ActivityStreams object will implement `AsRef<ObjectProperties>`.
|
||||
//! ### Fields
|
||||
//!
|
||||
//! The Properties types can be found near the kind they're associated with. `ObjectProperties` and
|
||||
//! `ApObjectProperties` are located in `activitystreams::object::properties`.
|
||||
//!
|
||||
//! The Properties types are generated by the `properties` macro, which attempts to create fields
|
||||
//! that represent exactly the bounds of the ActivityStreams and ActivityPub specifications.
|
||||
//! Many fields on the provided types are wrapped in `OneOrMany<>` or have a type of `AnyBase`. This
|
||||
//! is because the activitystreams spec is very open as to what is considered a valid structure.
|
||||
//!
|
||||
//! For example, the Object type in ActivityStreams has a `summary` field, which can either be
|
||||
//! represented as an `xsd:string` or an `rdf:langString`. It also states that the `summary` field
|
||||
//! is not `functional`, meaning that any number of `xsd:string` or `rdf:langString`, or a
|
||||
//! combination thereof, can be present. To represent this, the `properties` macro generates a
|
||||
//! couple `enum` types.
|
||||
//!
|
||||
//! First, it generates `ObjectPropertiesSummaryTermEnum`, which is a "terminating" enum.
|
||||
//! "terminating" in this context means it is the smallest unit of the type. This enum has two
|
||||
//! variants, named after the types they contain, `XsdString(...)` and `RdfLangString(...)`.
|
||||
//!
|
||||
//! Next, it generates `ObjectPropertiesSummaryEnum`, which contains two variants, `Term(...)` and
|
||||
//! `Array(...)`. The `Term` variant contains an `ObjectPropertiesSummaryTermEnum`, and the `Array`
|
||||
//! variant contains a `Vec<ObjectPropertiesSummaryTermEnum>`.
|
||||
//!
|
||||
//! Finally, when declaring the field, it generates `summary: Option<ObjectPropertiesSummaryEnum>`,
|
||||
//! since `summary` is not a required field.
|
||||
//! combination thereof, can be present. This library represents this as `Option<OneOrMany<AnyString>>`.
|
||||
//!
|
||||
//! This resulting type is exactly specific enough to match the following valid ActivityStreams
|
||||
//! json, without matching any invalid json.
|
||||
|
@ -78,7 +55,7 @@
|
|||
//! {}
|
||||
//! ```
|
||||
//!
|
||||
//! With a sring summary:
|
||||
//! With a string summary:
|
||||
//! ```json
|
||||
//! {
|
||||
//! "summary": "A string"
|
||||
|
@ -108,43 +85,75 @@
|
|||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! It may seem like interacting with these types might get unweildy, so the `properties` macro
|
||||
//! also generates methods for interacting with each field.
|
||||
//! It may seem like interacting with these types might get unweildy, there are some custom methods
|
||||
//! implemented on the `OneOrMany` type depending on what's inside of it.
|
||||
//!
|
||||
//! ```ignore
|
||||
//! fn set_summary_xsd_string<T>(&mut self, T) -> Result<...>;
|
||||
//! fn set_summary_rdf_lang_string<T>(&mut self, T) -> Result<...>;
|
||||
//! fn set_many_summary_xsd_strings<T>(&mut self, Vec<T>) -> Result<...>;
|
||||
//! fn set_many_summary_rdf_lang_strings<T>(&mut self, Vec<T>) -> Result<...>;
|
||||
//! ```rust,ignore
|
||||
//! fn from_xsd_string<T>(&mut self, T) -> Self;
|
||||
//! fn from_rdf_lang_string<T>(&mut self, T) -> Self;
|
||||
//!
|
||||
//! fn delete_summary(&mut self) -> &mut Self;
|
||||
//! fn as_single_xsd_string(&self) -> Option<&str>;
|
||||
//! fn as_single_rdf_langstring(&self) -> Option<&RdfLangString>;
|
||||
//!
|
||||
//! fn get_summary_xsd_string(&self) -> Option<XsdString>;
|
||||
//! fn get_summary_rdf_lang_string(&self) -> Option<RdfLangString>;
|
||||
//! fn get_many_summary_xsd_strings(&self) -> Option<Vec<&XsdString>>;
|
||||
//! fn get_many_summary_rdf_lang_strings(&self) -> Option<Vec<&RdfLangString>>;
|
||||
//! fn single_xsd_string(self) -> Option<String>;
|
||||
//! fn single_rdf_lang_string(self) -> Option<RdfLangString>;
|
||||
//!
|
||||
//! fn add_xsd_string<T>(&mut self, T) -> &mut Self;
|
||||
//! fn add_rdf_lang_string<T>(&mut self, T) -> &mut Self;
|
||||
//! ```
|
||||
//! These methods provide access to setting and fetching uniformly typed data, as well as deleting
|
||||
//! the data. In the setter methods, the type parameter T is bound by
|
||||
//! `TryInto<XsdString>` or `TryInto<RdfLangString>`. This allows passing values to the method that
|
||||
//! `Into<String>` or `Into<RdfLangString>`. This allows passing values to the method that
|
||||
//! can be converted into the types, rather than requiring the caller to perform the conversion.
|
||||
//!
|
||||
//! Types like `XsdString` and `RdfLangString` can be found in the `primitives` module. Unless
|
||||
//! Types like `RdfLangString` can be found in the `primitives` module. Unless
|
||||
//! you're building your own custom types, you shouldn't need to import them yourself. They each
|
||||
//! implement `FromStr` for parsing and `Display` to convert back to strings, as well as `From` and
|
||||
//! `Into` or `TryFrom` and `TryInto` for types you might expect them to (e.g.
|
||||
//! `XsdNonNegativeInteger` implements `From<u64>` and `Into<u64>`).
|
||||
//!
|
||||
//! For some fields, like `id`, there is only one valid type. methods generated for fields like
|
||||
//! these will leave out the type name from the function name.
|
||||
//! ### Traits
|
||||
//!
|
||||
//! ```ignore
|
||||
//! fn set_id<T>(&mut self, T) -> Result<...>;
|
||||
//! fn delete_id(&mut self) -> &mut Self;
|
||||
//! fn get_id(&self) -> Option<XsdAnyUri>;
|
||||
//! Since ActivityStreams is a heirarchical structure of data, it's represented as structs containing
|
||||
//! other structs. This means that the `context` field, which can be present on any ActivityStreams type,
|
||||
//! will be located in the innermost struct. In order to avoid writing code like
|
||||
//! `ap_object.collection.object.base.context = Some(context())`, this library provides traits that are
|
||||
//! automatically implmeneted for provided types.
|
||||
//!
|
||||
//! For example, the `BaseExt` trait provides the following methods for `context`,
|
||||
//! ```rust,ignore
|
||||
//! fn context(&self) -> Option<&OneOrMany<AnyBase>>;
|
||||
//!
|
||||
//! fn set_context<T>(&mut self, context: T) -> &mut Self
|
||||
//! where
|
||||
//! T: Into<AnyBase>;
|
||||
//!
|
||||
//! fn set_many_contexts<I, T>(&mut self, items: I) -> &mut Self
|
||||
//! where
|
||||
//! I: IntoIterator<Item = T>,
|
||||
//! T: Into<AnyBase>;
|
||||
//!
|
||||
//! fn add_context<T>(&mut self, context: T) -> &mut Self
|
||||
//! where
|
||||
//! T: Into<AnyBase>;
|
||||
//!
|
||||
//! fn take_context(&mut self) -> Option<OneOrMany<AnyBase>>;
|
||||
//! fn delete_context(&mut self) -> &mut Self;
|
||||
//! ```
|
||||
//!
|
||||
//! ### Traits
|
||||
//! For fields with more specific bounds, like `id`,
|
||||
//! ```rust,ignore
|
||||
//! fn id(&self) -> Option<&Url>;
|
||||
//! fn set_id(&mut self, Url) -> &mut Self;
|
||||
//! fn take_id(&self) -> Option<Url>;
|
||||
//! fn delete_id(&mut self) -> &mut Self;
|
||||
//! ```
|
||||
//!
|
||||
//! The full list of extension traits that implement methods like these on types can be found in the
|
||||
//! prelude module. By using `use activitystreams::prelude::*;` all of the methods will be
|
||||
//! implemented for types containing their fields.
|
||||
//!
|
||||
//! ### Markers
|
||||
//!
|
||||
//! This library provides a number of traits, such as `Object`, `Link`, `Actor`, `Activity`,
|
||||
//! `Collection`, and `CollectionPage`. The majority of these traits exist solely to "mark" types,
|
||||
|
@ -153,12 +162,18 @@
|
|||
//!
|
||||
//! If you want to make a function that manipulates an Activity, but not a normal object, you could
|
||||
//! bound the function like so:
|
||||
//! ```ignore
|
||||
//! fn my_manipulator<T>(some_activity: T) -> Result<&mut ObjectProperties, SomeErrorType>
|
||||
//!
|
||||
//! ```rust
|
||||
//! use activitystreams::{base::BaseExt, context, markers::Activity, uri};
|
||||
//!
|
||||
//! fn manipulator<T, Kind>(mut activity: T) -> Result<(), anyhow::Error>
|
||||
//! where
|
||||
//! T: Activity + AsMut<ObjectProperties>,
|
||||
//! T: Activity + BaseExt<Kind>,
|
||||
//! {
|
||||
//! some_activity.as_mut().set_whatever_tbh()
|
||||
//! activity
|
||||
//! .set_id(uri!("https://example.com"))
|
||||
//! .set_context(context());
|
||||
//! Ok(())
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
|
@ -169,7 +184,7 @@
|
|||
//! These can be found in `activitystreams::objects::kind`, and similar paths.
|
||||
//!
|
||||
//! To build your own Person struct, for example, you could write
|
||||
//! ```ignore
|
||||
//! ```rust
|
||||
//! use activitystreams::actor::kind::PersonType;
|
||||
//!
|
||||
//! #[derive(serde::Deserialize, serde::Serialize)]
|
||||
|
@ -181,80 +196,38 @@
|
|||
//! ```
|
||||
//! And this type would only deserialize for JSON where `"type":"Person"`
|
||||
//!
|
||||
//! ### Extensions
|
||||
//!
|
||||
//! In some cases, like when dealing with ActivityPub, it is neccessary to extend the
|
||||
//! ActivityStreams specification. For this purpose, two traits and a type have been introduced.
|
||||
//!
|
||||
//! ```ignore
|
||||
//! use activitystreams::ext::{Ext, Extensible, Extension};
|
||||
//! ```
|
||||
//!
|
||||
//! The `Ext` type is a simple record containing first, the ActivityStreams type, and second, the
|
||||
//! extension to that type.
|
||||
//!
|
||||
//! There are two provided extensions in the ActivityStreams library.
|
||||
//! - ApObjectProperties, extra properties for all ActivityStreams objects in the ActivityPub spec
|
||||
//! - ApActorProperties, extra properties specifically for Actors in the ActivityPub spec
|
||||
//!
|
||||
//! To use an object with its default extensions, the object's `full()` associated function may be
|
||||
//! invoked.
|
||||
//! ```rust
|
||||
//! # use activitystreams::object::Video;
|
||||
//! let video_with_extensions = Video::full();
|
||||
//! ```
|
||||
//!
|
||||
//! ### Features
|
||||
//! There are a number of features that can be disabled in this crate. By default, everything is
|
||||
//! enabled.
|
||||
//!
|
||||
//! ```toml
|
||||
//! activitystreams = { version = "0.6.2", default-features = "false", features = ["derive"] }
|
||||
//! ```
|
||||
//!
|
||||
//! | feature | what you get |
|
||||
//! | ---------- | --------------------------------------------------------- |
|
||||
//! | none | Just the Marker Traits |
|
||||
//! | derive | Marker Traits + derive macros from activitystreams-derive |
|
||||
//! | kinds | Marker Traits + derive macros + Kind UnitStructs |
|
||||
//! | primitives | Marker Traits + Primitive values |
|
||||
//! | types | Everything, this is the default |
|
||||
//!
|
||||
//! ## Examples
|
||||
//!
|
||||
//! ### Basic
|
||||
//! ### Create
|
||||
//!
|
||||
//! ```rust
|
||||
//! use activitystreams::object::{Video, properties::ObjectProperties};
|
||||
//! use anyhow::Error;
|
||||
//! use activitystreams::{
|
||||
//! context,
|
||||
//! object::{ApObject, Video},
|
||||
//! prelude::*,
|
||||
//! uri,
|
||||
//! };
|
||||
//! use chrono::Duration;
|
||||
//!
|
||||
//! // We perform configuration in a dedicated function to specify which Properties type we want to
|
||||
//! // perform the operations on.
|
||||
//! fn configure_video(mut v: impl AsMut<ObjectProperties>) -> Result<(), Error> {
|
||||
//! v.as_mut()
|
||||
//! .set_context_xsd_any_uri("https://www.w3.org/ns/activitystreams")?
|
||||
//! .set_id("https://example.com/@example/lions")?
|
||||
//! .set_url_xsd_any_uri("https://example.com/@example/lions/video.webm")?
|
||||
//! .set_name_xsd_string("My Cool Video")?
|
||||
//! .set_summary_xsd_string("A video about some cool lions")?
|
||||
//! .set_media_type("video/webm")?
|
||||
//! .set_duration("PT4M20S")?;
|
||||
//! fn main() -> Result<(), anyhow::Error> {
|
||||
//! let mut video = ApObject::new(Video::new());
|
||||
//!
|
||||
//! Ok(())
|
||||
//! }
|
||||
//! video
|
||||
//! .set_context(context())
|
||||
//! .set_id(uri!("https://example.com/@example/lions"))
|
||||
//! .set_media_type("video/webm".parse()?)
|
||||
//! .set_url(uri!("https://example.com/@example/lions/video.webm"))
|
||||
//! .set_summary("A cool video")
|
||||
//! .set_duration(Duration::minutes(4) + Duration::seconds(20))
|
||||
//! .set_shares(uri!("https://example.com/@example/lions/video.webm#shares"));
|
||||
//!
|
||||
//! fn main() -> Result<(), Error> {
|
||||
//! let mut v = Video::default();
|
||||
//! println!("Video, {:#?}", video);
|
||||
//!
|
||||
//! configure_video(&mut v)?;
|
||||
//!
|
||||
//! println!("Video, {:#?}", v);
|
||||
//!
|
||||
//! let s = serde_json::to_string(&v)?;
|
||||
//! let s = serde_json::to_string(&video)?;
|
||||
//!
|
||||
//! println!("json, {}", s);
|
||||
//!
|
||||
//! let v: Video = serde_json::from_str(&s)?;
|
||||
//! let v: ApObject<Video> = serde_json::from_str(&s)?;
|
||||
//!
|
||||
//! println!("Video again, {:#?}", v);
|
||||
//!
|
||||
|
@ -262,185 +235,164 @@
|
|||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! ### Intermediate
|
||||
//! ### Parse
|
||||
//!
|
||||
//! ```rust
|
||||
//! use activitystreams::{
|
||||
//! context,
|
||||
//! actor::{Actor, ActorBox},
|
||||
//! ext::Ext,
|
||||
//! object::{
|
||||
//! properties::{
|
||||
//! ObjectProperties,
|
||||
//! ProfileProperties
|
||||
//! },
|
||||
//! Profile,
|
||||
//! Object,
|
||||
//! ObjectBox,
|
||||
//! },
|
||||
//! primitives::XsdAnyUri,
|
||||
//! Base, BaseBox, PropRefs,
|
||||
//! };
|
||||
//! use serde::{Deserialize, Serialize};
|
||||
//! use activitystreams::{activity::ActorAndObject, prelude::*};
|
||||
//!
|
||||
//! #[derive(Clone, Debug, Default, Deserialize, Serialize, PropRefs)]
|
||||
//! #[serde(rename_all = "camelCase")]
|
||||
//! #[prop_refs(Object)]
|
||||
//! #[prop_refs(Actor)]
|
||||
//! pub struct Persona {
|
||||
//! #[serde(rename = "@context")]
|
||||
//! context: XsdAnyUri,
|
||||
//!
|
||||
//! #[serde(rename = "type")]
|
||||
//! kind: String,
|
||||
//! #[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
|
||||
//! pub enum AcceptedTypes {
|
||||
//! Accept,
|
||||
//! Announce,
|
||||
//! Create,
|
||||
//! Delete,
|
||||
//! Follow,
|
||||
//! Reject,
|
||||
//! Update,
|
||||
//! Undo,
|
||||
//! }
|
||||
//!
|
||||
//! fn main() -> Result<(), anyhow::Error> {
|
||||
//! let mut profile = Profile::full();
|
||||
//! pub type AcceptedActivity = ActorAndObject<AcceptedTypes>;
|
||||
//!
|
||||
//! let pprops: &mut ProfileProperties = profile.as_mut();
|
||||
//! pub fn handle_activity(activity: AcceptedActivity) -> Result<(), anyhow::Error> {
|
||||
//! println!("Actor: {:?}", activity.actor());
|
||||
//! println!("Object: {:?}", activity.object());
|
||||
//!
|
||||
//! pprops.set_describes_object_box(Persona {
|
||||
//! context: context(),
|
||||
//! kind: "Persona".to_owned(),
|
||||
//! })?;
|
||||
//!
|
||||
//! let oprops: &mut ObjectProperties = profile.as_mut();
|
||||
//! oprops.set_context_xsd_any_uri(context())?;
|
||||
//!
|
||||
//! let profile_string = serde_json::to_string(&profile)?;
|
||||
//!
|
||||
//! let profile: Profile = serde_json::from_str(&profile_string)?;
|
||||
//! match activity.kind() {
|
||||
//! Some(AcceptedTypes::Accept) => println!("Accept"),
|
||||
//! Some(AcceptedTypes::Announce) => println!("Announce"),
|
||||
//! Some(AcceptedTypes::Create) => println!("Create"),
|
||||
//! Some(AcceptedTypes::Delete) => println!("Delete"),
|
||||
//! Some(AcceptedTypes::Follow) => println!("Follow"),
|
||||
//! Some(AcceptedTypes::Reject) => println!("Reject"),
|
||||
//! Some(AcceptedTypes::Update) => println!("Update"),
|
||||
//! Some(AcceptedTypes::Undo) => println!("Undo"),
|
||||
//! None => return Err(anyhow::Error::msg("No activity type provided")),
|
||||
//! }
|
||||
//!
|
||||
//! Ok(())
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! ### Advanced
|
||||
//!
|
||||
//! ```rust
|
||||
//! use activitystreams::{
|
||||
//! properties,
|
||||
//! ext::Ext,
|
||||
//! link::{
|
||||
//! properties::LinkProperties,
|
||||
//! Link, LinkBox, Mention,
|
||||
//! },
|
||||
//! Base, BaseBox, PropRefs,
|
||||
//! UnitString,
|
||||
//! };
|
||||
//! use serde::{Deserialize, Serialize};
|
||||
//!
|
||||
//! /// Using the UnitString derive macro
|
||||
//! ///
|
||||
//! /// This macro implements Serialize and Deserialize for the given type, making this type
|
||||
//! /// represent the string "MyLink" in JSON.
|
||||
//! #[derive(Clone, Debug, Default, UnitString)]
|
||||
//! #[unit_string(MyLink)]
|
||||
//! pub struct MyKind;
|
||||
//!
|
||||
//! properties! {
|
||||
//! My {
|
||||
//! docs [ "Defining our own properties struct called MyProperties" ],
|
||||
//!
|
||||
//! required_key {
|
||||
//! docs [
|
||||
//! "Our own required key field",
|
||||
//! "",
|
||||
//! "'types' defines the range of values that can be stored in required_key",
|
||||
//! "",
|
||||
//! "'functional' means there is at most one value for required_key",
|
||||
//! "'required' means there is at least one value for required_key",
|
||||
//! ],
|
||||
//! types [ String ],
|
||||
//! functional,
|
||||
//! required,
|
||||
//! },
|
||||
//! }
|
||||
//! }
|
||||
//!
|
||||
//! #[derive(Clone, Debug, Default, serde::Serialize, serde::Deserialize)]
|
||||
//! #[serde(transparent)]
|
||||
//! pub struct MyLinkProps(pub LinkProperties);
|
||||
//!
|
||||
//! /// Using the Properties derive macro
|
||||
//! ///
|
||||
//! /// This macro generates getters and setters for the associated fields.
|
||||
//! #[derive(Clone, Debug, Default, Deserialize, Serialize, PropRefs)]
|
||||
//! #[serde(rename_all = "camelCase")]
|
||||
//! #[prop_refs(Link)]
|
||||
//! pub struct My {
|
||||
//! /// Use the UnitString MyKind to enforce the type of the object by "MyLink"
|
||||
//! pub kind: MyKind,
|
||||
//!
|
||||
//! /// Derive AsRef/AsMut for My -> MyProperties
|
||||
//! #[prop_refs]
|
||||
//! pub my_properties: MyProperties,
|
||||
//!
|
||||
//! /// Derive AsRef/AsMut/Link for My -> MyLinkProperties
|
||||
//! #[prop_refs]
|
||||
//! pub link_properties: MyLinkProps,
|
||||
//! }
|
||||
//! static EXAMPLE_JSON: &str = r#"{"actor":"https://asonix.dog/users/asonix","object":"https://asonix.dog/users/asonix/posts/1","type":"Announce"}"#;
|
||||
//!
|
||||
//! fn main() -> Result<(), anyhow::Error> {
|
||||
//! let mut my_link = My::default();
|
||||
//!
|
||||
//! let lprops: &mut MyProperties = my_link.as_mut();
|
||||
//! lprops.set_required_key("Hey")?;
|
||||
//!
|
||||
//! let my_link_string = serde_json::to_string(&my_link)?;
|
||||
//!
|
||||
//! let my_link: My = serde_json::from_str(&my_link_string)?;
|
||||
//!
|
||||
//! Ok(())
|
||||
//! handle_activity(serde_json::from_str(EXAMPLE_JSON)?)
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! ## Contributing
|
||||
//! Feel free to open issues for anything you find an issue with. Please note that any contributed code will be licensed under the GPLv3.
|
||||
//!
|
||||
//! ## License
|
||||
//!
|
||||
//! Copyright © 2020 Riley Trautman
|
||||
//!
|
||||
//! ActivityStreams is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||
//!
|
||||
//! ActivityStreams is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. This file is part of ActivityStreams.
|
||||
//!
|
||||
//! You should have received a copy of the GNU General Public License along with ActivityStreams. If not, see [http://www.gnu.org/licenses/](http://www.gnu.org/licenses/).
|
||||
|
||||
#![doc(html_root_url = "https://activitystreams-new.asonix.dog")]
|
||||
|
||||
pub mod activity;
|
||||
pub mod actor;
|
||||
pub mod base;
|
||||
pub mod collection;
|
||||
#[cfg(feature = "types")]
|
||||
pub mod endpoint;
|
||||
#[cfg(feature = "types")]
|
||||
pub mod ext;
|
||||
mod either;
|
||||
pub mod error;
|
||||
pub mod link;
|
||||
mod macros;
|
||||
pub mod markers;
|
||||
pub mod object;
|
||||
#[cfg(feature = "primitives")]
|
||||
pub mod primitives;
|
||||
pub mod unparsed;
|
||||
|
||||
pub use self::{
|
||||
activity::{Activity, IntransitiveActivity},
|
||||
actor::Actor,
|
||||
collection::{Collection, CollectionPage},
|
||||
link::Link,
|
||||
object::Object,
|
||||
};
|
||||
pub extern crate chrono;
|
||||
pub extern crate mime;
|
||||
pub extern crate url;
|
||||
|
||||
#[cfg_attr(feature = "types", wrapper_type)]
|
||||
/// The lowermost trait of the trait structure
|
||||
///
|
||||
/// Base exists solely so Object and Link can have impls that don't potentially conflict
|
||||
pub trait Base {}
|
||||
|
||||
#[cfg(feature = "primitives")]
|
||||
/// The context associated with all of the Activity Streams types defined in the crate.
|
||||
pub fn context() -> crate::primitives::XsdAnyUri {
|
||||
pub fn context() -> url::Url {
|
||||
"https://www.w3.org/ns/activitystreams".parse().unwrap()
|
||||
}
|
||||
|
||||
#[cfg(feature = "primitives")]
|
||||
/// The 'security' extension used by some implementations
|
||||
pub fn security() -> crate::primitives::XsdAnyUri {
|
||||
"https://w3id.org/security/v1".parse().unwrap()
|
||||
}
|
||||
|
||||
#[cfg(feature = "primitives")]
|
||||
/// The 'public' actor, doesn't denote a real actor but describes a publicly available object.
|
||||
pub fn public() -> crate::primitives::XsdAnyUri {
|
||||
pub fn public() -> url::Url {
|
||||
"https://www.w3.org/ns/activitystreams#Public"
|
||||
.parse()
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
#[cfg(feature = "derive")]
|
||||
pub use activitystreams_derive::{properties, wrapper_type, Extensible, PropRefs, UnitString};
|
||||
pub fn security() -> url::Url {
|
||||
"https://w3id.org/security/v1".parse().unwrap()
|
||||
}
|
||||
|
||||
pub mod prelude {
|
||||
//! Extension traits that provide the majority of the helper methods of the crate
|
||||
//!
|
||||
//! ```rust
|
||||
//! # fn main() -> Result<(), anyhow::Error> {
|
||||
//! use activitystreams::{
|
||||
//! activity::Create,
|
||||
//! actor::{ApActor, Person},
|
||||
//! context,
|
||||
//! prelude::*,
|
||||
//! public,
|
||||
//! object::{ApObject, Image, Video},
|
||||
//! security,
|
||||
//! uri,
|
||||
//! };
|
||||
//! use chrono::Duration;
|
||||
//!
|
||||
//! let mut person = ApActor::new(
|
||||
//! uri!("http://localhost:8080/inbox"),
|
||||
//! Person::new(),
|
||||
//! );
|
||||
//! person
|
||||
//! .set_outbox(uri!("http:/localhost:8080/outbox"))
|
||||
//! .set_name("Demo Account")
|
||||
//! .set_preferred_username("demo")
|
||||
//! .set_id(uri!("https://localhost:8080/actor"))
|
||||
//! .set_url(uri!("https://localhost:8080/actor"));
|
||||
//!
|
||||
//! let mut preview = Image::new();
|
||||
//!
|
||||
//! preview
|
||||
//! .set_url(uri!("https://localhost:8080/preview.png"))
|
||||
//! .set_media_type("image/png".parse()?)
|
||||
//! .set_id(uri!("https://localhostst:8080/preview.png"));
|
||||
//!
|
||||
//! let mut video = ApObject::new(Video::new());
|
||||
//!
|
||||
//! video
|
||||
//! .set_id(uri!("http://localhost:8080/video.webm"))
|
||||
//! .set_url(uri!("http://localhost:8080/video.webm"))
|
||||
//! .set_media_type("video/webm".parse()?)
|
||||
//! .set_summary("A cool video")
|
||||
//! .set_preview(preview.into_any_base()?)
|
||||
//! .set_duration(Duration::minutes(4) + Duration::seconds(20))
|
||||
//! .set_shares(uri!("http://localhost:8080/video.webm#shares"));
|
||||
//!
|
||||
//! let mut activity = Create::new(
|
||||
//! person.into_any_base()?,
|
||||
//! video.into_any_base()?
|
||||
//! );
|
||||
//!
|
||||
//! activity
|
||||
//! .set_many_tos(vec![public()]);
|
||||
//! #
|
||||
//! # Ok(())
|
||||
//! # }
|
||||
//! ```
|
||||
|
||||
pub use crate::{
|
||||
activity::{
|
||||
ActivityExt, ActorAndObjectRefExt, OptOriginRefExt, OptTargetRefExt, OriginRefExt,
|
||||
QuestionExt, TargetRefExt,
|
||||
},
|
||||
actor::ApActorExt,
|
||||
base::{BaseExt, ExtendsExt},
|
||||
collection::{CollectionExt, CollectionPageExt, OrderedCollectionPageExt},
|
||||
link::LinkExt,
|
||||
object::{ApObjectExt, ObjectExt, PlaceExt, ProfileExt, RelationshipExt, TombstoneExt},
|
||||
};
|
||||
}
|
||||
|
|
663
src/link.rs
Normal file
663
src/link.rs
Normal file
|
@ -0,0 +1,663 @@
|
|||
//! Types and traits for dealing with Link attributes
|
||||
//!
|
||||
//! ```rust
|
||||
//! # fn main() -> Result<(), anyhow::Error> {
|
||||
//! use activitystreams::{
|
||||
//! link::Mention,
|
||||
//! object::Image,
|
||||
//! prelude::*,
|
||||
//! uri,
|
||||
//! };
|
||||
//!
|
||||
//! let mut mention = Mention::new();
|
||||
//!
|
||||
//! mention
|
||||
//! .set_href(uri!("https://example.com"))
|
||||
//! .set_hreflang("en")
|
||||
//! .set_rel("link")
|
||||
//! .set_preview(Image::new().into_any_base()?);
|
||||
//! #
|
||||
//! # Ok(())
|
||||
//! # }
|
||||
//! ```
|
||||
use crate::{
|
||||
base::{AsBase, Base, Extends},
|
||||
markers,
|
||||
primitives::OneOrMany,
|
||||
unparsed::{Unparsed, UnparsedMut, UnparsedMutExt},
|
||||
};
|
||||
use std::convert::TryFrom;
|
||||
use url::Url;
|
||||
|
||||
pub mod kind {
|
||||
//! Kinds of links defined by the spec
|
||||
//!
|
||||
//! These types exist only to be statically-typed versions of the associated string. e.g.
|
||||
//! `MentionType` -> `"Mention"`
|
||||
|
||||
use crate::kind;
|
||||
|
||||
kind!(MentionType, Mention);
|
||||
}
|
||||
|
||||
use self::kind::MentionType;
|
||||
|
||||
/// Implementation trait for deriving Link methods for a type
|
||||
///
|
||||
/// Any type implementing AsLink will automatically gain methods provided by LinkExt
|
||||
pub trait AsLink<Kind>: markers::Link {
|
||||
/// Immutable borrow of `Link<Kind>`
|
||||
fn link_ref(&self) -> &Link<Kind>;
|
||||
|
||||
/// Mutable borrow of `Link<Kind>`
|
||||
fn link_mut(&mut self) -> &mut Link<Kind>;
|
||||
}
|
||||
|
||||
/// Helper methods for interacting with Link types
|
||||
///
|
||||
/// This trait represents methods valid for any ActivityStreams Link.
|
||||
///
|
||||
/// Documentation for the fields related to these methods can be found on the `Link` struct
|
||||
pub trait LinkExt<Kind>: AsLink<Kind> {
|
||||
/// Fetch the href for the current object
|
||||
///
|
||||
/// ```rust
|
||||
/// # use activitystreams::link::Mention;
|
||||
/// # let mention = Mention::new();
|
||||
/// #
|
||||
/// use activitystreams::prelude::*;
|
||||
///
|
||||
/// let mention_href = mention.href();
|
||||
/// ```
|
||||
fn href<'a>(&'a self) -> Option<&'a Url>
|
||||
where
|
||||
Kind: 'a,
|
||||
{
|
||||
self.link_ref().href.as_ref()
|
||||
}
|
||||
|
||||
/// Set the href for the current object
|
||||
///
|
||||
/// This overwrites the contents of href
|
||||
///
|
||||
/// ```rust
|
||||
/// # fn main() -> Result<(), anyhow::Error> {
|
||||
/// # use activitystreams::{link::Mention, uri};
|
||||
/// # let mut mention = Mention::new();
|
||||
/// #
|
||||
/// use activitystreams::prelude::*;
|
||||
///
|
||||
/// mention.set_href(uri!("https://example.com"));
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
fn set_href(&mut self, href: Url) -> &mut Self {
|
||||
self.link_mut().href = Some(href);
|
||||
self
|
||||
}
|
||||
|
||||
/// Take the href from the current object, leaving nothing
|
||||
///
|
||||
/// ```rust
|
||||
/// # use activitystreams::link::Mention;
|
||||
/// # let mut mention = Mention::new();
|
||||
/// #
|
||||
/// use activitystreams::prelude::*;
|
||||
///
|
||||
/// if let Some(href) = mention.take_href() {
|
||||
/// println!("{:?}", href);
|
||||
/// }
|
||||
/// ```
|
||||
fn take_href(&mut self) -> Option<Url> {
|
||||
self.link_mut().href.take()
|
||||
}
|
||||
|
||||
/// Delete the href from the current object
|
||||
///
|
||||
/// ```rust
|
||||
/// # fn main() -> Result<(), anyhow::Error> {
|
||||
/// # use activitystreams::{link::Mention, uri};
|
||||
/// # let mut mention = Mention::new();
|
||||
/// # mention.set_href(uri!("https://example.com"));
|
||||
/// #
|
||||
/// use activitystreams::prelude::*;
|
||||
///
|
||||
/// assert!(mention.href().is_some());
|
||||
/// mention.delete_href();
|
||||
/// assert!(mention.href().is_none());
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
fn delete_href(&mut self) -> &mut Self {
|
||||
self.link_mut().href = None;
|
||||
self
|
||||
}
|
||||
|
||||
/// Fetch the hreflang for the current object
|
||||
///
|
||||
/// ```rust
|
||||
/// # use activitystreams::link::Mention;
|
||||
/// # let mention = Mention::new();
|
||||
/// #
|
||||
/// use activitystreams::prelude::*;
|
||||
///
|
||||
/// let mention_hreflang = mention.hreflang();
|
||||
/// ```
|
||||
fn hreflang<'a>(&'a self) -> Option<&'a str>
|
||||
where
|
||||
Kind: 'a,
|
||||
{
|
||||
self.link_ref().hreflang.as_ref().map(|lr| lr.as_str())
|
||||
}
|
||||
|
||||
/// Set the hreflang for the current object
|
||||
///
|
||||
/// This overwrites the contents of hreflang
|
||||
///
|
||||
/// ```rust
|
||||
/// # use activitystreams::link::Mention;
|
||||
/// # let mut mention = Mention::new();
|
||||
/// #
|
||||
/// use activitystreams::prelude::*;
|
||||
///
|
||||
/// mention.set_hreflang("en");
|
||||
/// ```
|
||||
fn set_hreflang<T>(&mut self, hreflang: T) -> &mut Self
|
||||
where
|
||||
T: Into<String>,
|
||||
{
|
||||
self.link_mut().hreflang = Some(hreflang.into());
|
||||
self
|
||||
}
|
||||
|
||||
/// Take the hreflang from the current object, leaving nothing
|
||||
///
|
||||
/// ```rust
|
||||
/// # use activitystreams::link::Mention;
|
||||
/// # let mut mention = Mention::new();
|
||||
/// #
|
||||
/// use activitystreams::prelude::*;
|
||||
///
|
||||
/// if let Some(hreflang) = mention.take_hreflang() {
|
||||
/// println!("{:?}", hreflang);
|
||||
/// }
|
||||
/// ```
|
||||
fn take_hreflang(&mut self) -> Option<String> {
|
||||
self.link_mut().hreflang.take()
|
||||
}
|
||||
|
||||
/// Delete the hreflang from the current object
|
||||
///
|
||||
/// ```rust
|
||||
/// # fn main() -> Result<(), anyhow::Error> {
|
||||
/// # use activitystreams::link::Mention;
|
||||
/// # let mut mention = Mention::new();
|
||||
/// # mention.set_hreflang("en");
|
||||
/// #
|
||||
/// use activitystreams::prelude::*;
|
||||
///
|
||||
/// assert!(mention.hreflang().is_some());
|
||||
/// mention.delete_hreflang();
|
||||
/// assert!(mention.hreflang().is_none());
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
fn delete_hreflang(&mut self) -> &mut Self {
|
||||
self.link_mut().hreflang = None;
|
||||
self
|
||||
}
|
||||
|
||||
/// Fetch the rel for the current object
|
||||
///
|
||||
/// ```rust
|
||||
/// # use activitystreams::link::Mention;
|
||||
/// # let mention = Mention::new();
|
||||
/// #
|
||||
/// use activitystreams::prelude::*;
|
||||
///
|
||||
/// let mention_rel = mention.rel();
|
||||
/// ```
|
||||
fn rel<'a>(&'a self) -> Option<&'a OneOrMany<String>>
|
||||
where
|
||||
Kind: 'a,
|
||||
{
|
||||
self.link_ref().rel.as_ref()
|
||||
}
|
||||
|
||||
/// Set the rel for the current object
|
||||
///
|
||||
/// This overwrites the contents of rel
|
||||
///
|
||||
/// ```rust
|
||||
/// # use activitystreams::link::Mention;
|
||||
/// # let mut mention = Mention::new();
|
||||
/// #
|
||||
/// use activitystreams::prelude::*;
|
||||
///
|
||||
/// mention.set_rel("link");
|
||||
/// ```
|
||||
fn set_rel<T>(&mut self, rel: T) -> &mut Self
|
||||
where
|
||||
T: Into<String>,
|
||||
{
|
||||
self.link_mut().rel = Some(rel.into().into());
|
||||
self
|
||||
}
|
||||
|
||||
/// Set many rels for the current object
|
||||
///
|
||||
/// This overwrites the contents of rel
|
||||
///
|
||||
/// ```rust
|
||||
/// # use activitystreams::link::Mention;
|
||||
/// # let mut mention = Mention::new();
|
||||
/// #
|
||||
/// use activitystreams::prelude::*;
|
||||
///
|
||||
/// mention.set_many_rels(vec!["link".into(), "stylesheet".into()]);
|
||||
/// ```
|
||||
fn set_many_rels<I>(&mut self, items: I) -> &mut Self
|
||||
where
|
||||
I: IntoIterator<Item = String>,
|
||||
{
|
||||
let v: Vec<_> = items.into_iter().collect();
|
||||
self.link_mut().rel = Some(v.into());
|
||||
self
|
||||
}
|
||||
|
||||
/// Add a rel to the current object
|
||||
///
|
||||
/// This does not overwrite the contents of rel, only appends an item
|
||||
///
|
||||
/// ```rust
|
||||
/// # use activitystreams::link::Mention;
|
||||
/// # let mut mention = Mention::new();
|
||||
/// #
|
||||
/// use activitystreams::prelude::*;
|
||||
///
|
||||
/// mention
|
||||
/// .add_rel("link".into())
|
||||
/// .add_rel("stylesheet".into());
|
||||
/// ```
|
||||
fn add_rel(&mut self, rel: String) -> &mut Self {
|
||||
let v = match self.link_mut().rel.take() {
|
||||
Some(mut v) => {
|
||||
v.add(rel);
|
||||
v
|
||||
}
|
||||
None => vec![rel].into(),
|
||||
};
|
||||
self.link_mut().rel = Some(v);
|
||||
self
|
||||
}
|
||||
|
||||
/// Take the rel from the current object, leaving nothing
|
||||
///
|
||||
/// ```rust
|
||||
/// # use activitystreams::link::Mention;
|
||||
/// # let mut mention = Mention::new();
|
||||
/// #
|
||||
/// use activitystreams::prelude::*;
|
||||
///
|
||||
/// if let Some(rel) = mention.take_rel() {
|
||||
/// println!("{:?}", rel);
|
||||
/// }
|
||||
/// ```
|
||||
fn take_rel(&mut self) -> Option<OneOrMany<String>> {
|
||||
self.link_mut().rel.take()
|
||||
}
|
||||
|
||||
/// Delete the rel from the current object
|
||||
///
|
||||
/// ```rust
|
||||
/// # use activitystreams::link::Mention;
|
||||
/// # let mut mention = Mention::new();
|
||||
/// # mention.set_rel("link");
|
||||
/// #
|
||||
/// use activitystreams::prelude::*;
|
||||
///
|
||||
/// assert!(mention.rel().is_some());
|
||||
/// mention.delete_rel();
|
||||
/// assert!(mention.rel().is_none());
|
||||
/// ```
|
||||
fn delete_rel(&mut self) -> &mut Self {
|
||||
self.link_mut().rel = None;
|
||||
self
|
||||
}
|
||||
|
||||
/// Fetch the height of the current object
|
||||
///
|
||||
/// ```rust
|
||||
/// # use activitystreams::link::Mention;
|
||||
/// # let mut mention = Mention::new();
|
||||
/// #
|
||||
/// use activitystreams::prelude::*;
|
||||
///
|
||||
/// if let Some(height) = mention.height() {
|
||||
/// println!("{:?}", height);
|
||||
/// }
|
||||
/// ```
|
||||
fn height<'a>(&'a self) -> Option<u64>
|
||||
where
|
||||
Kind: 'a,
|
||||
{
|
||||
self.link_ref().height
|
||||
}
|
||||
|
||||
/// Set the height for the current object
|
||||
///
|
||||
/// This overwrites the contents of height
|
||||
///
|
||||
/// ```rust
|
||||
/// # use activitystreams::link::Mention;
|
||||
/// # let mut mention = Mention::new();
|
||||
/// #
|
||||
/// use activitystreams::prelude::*;
|
||||
///
|
||||
/// mention.set_height(5u64);
|
||||
/// ```
|
||||
fn set_height<T>(&mut self, height: T) -> &mut Self
|
||||
where
|
||||
T: Into<u64>,
|
||||
{
|
||||
self.link_mut().height = Some(height.into());
|
||||
self
|
||||
}
|
||||
|
||||
/// Take the height of the current object, leaving nothing
|
||||
///
|
||||
/// ```rust
|
||||
/// # use activitystreams::link::Mention;
|
||||
/// # let mut mention = Mention::new();
|
||||
/// #
|
||||
/// use activitystreams::prelude::*;
|
||||
///
|
||||
/// if let Some(height) = mention.height() {
|
||||
/// println!("{:?}", height);
|
||||
/// }
|
||||
/// ```
|
||||
fn take_height(&mut self) -> Option<u64> {
|
||||
self.link_mut().height.take()
|
||||
}
|
||||
|
||||
/// Delete the height from the current object
|
||||
///
|
||||
/// ```rust
|
||||
/// # use activitystreams::link::Mention;
|
||||
/// # let mut mention = Mention::new();
|
||||
/// # mention.set_height(5u64);
|
||||
/// #
|
||||
/// use activitystreams::prelude::*;
|
||||
///
|
||||
/// assert!(mention.height().is_some());
|
||||
/// mention.delete_height();
|
||||
/// assert!(mention.height().is_none());
|
||||
/// ```
|
||||
fn delete_height(&mut self) -> &mut Self {
|
||||
self.link_mut().height = None;
|
||||
self
|
||||
}
|
||||
|
||||
/// Fetch the width of the current object
|
||||
///
|
||||
/// ```rust
|
||||
/// # use activitystreams::link::Mention;
|
||||
/// # let mut mention = Mention::new();
|
||||
/// #
|
||||
/// use activitystreams::prelude::*;
|
||||
///
|
||||
/// if let Some(width) = mention.width() {
|
||||
/// println!("{:?}", width);
|
||||
/// }
|
||||
/// ```
|
||||
fn width<'a>(&'a self) -> Option<u64>
|
||||
where
|
||||
Kind: 'a,
|
||||
{
|
||||
self.link_ref().width
|
||||
}
|
||||
|
||||
/// Set the width for the current object
|
||||
///
|
||||
/// This overwrites the contents of width
|
||||
///
|
||||
/// ```rust
|
||||
/// # use activitystreams::link::Mention;
|
||||
/// # let mut mention = Mention::new();
|
||||
/// #
|
||||
/// use activitystreams::prelude::*;
|
||||
///
|
||||
/// mention.set_width(5u64);
|
||||
/// ```
|
||||
fn set_width<T>(&mut self, width: T) -> &mut Self
|
||||
where
|
||||
T: Into<u64>,
|
||||
{
|
||||
self.link_mut().width = Some(width.into());
|
||||
self
|
||||
}
|
||||
|
||||
/// Take the width of the current object, leaving nothing
|
||||
///
|
||||
/// ```rust
|
||||
/// # use activitystreams::link::Mention;
|
||||
/// # let mut mention = Mention::new();
|
||||
/// #
|
||||
/// use activitystreams::prelude::*;
|
||||
///
|
||||
/// if let Some(width) = mention.take_width() {
|
||||
/// println!("{:?}", width);
|
||||
/// }
|
||||
/// ```
|
||||
fn take_width(&mut self) -> Option<u64> {
|
||||
self.link_mut().width.take()
|
||||
}
|
||||
|
||||
/// Delete the width from the current object
|
||||
///
|
||||
/// ```rust
|
||||
/// # use activitystreams::link::Mention;
|
||||
/// # let mut mention = Mention::new();
|
||||
/// # mention.set_width(5u64);
|
||||
/// #
|
||||
/// use activitystreams::prelude::*;
|
||||
///
|
||||
/// assert!(mention.width().is_some());
|
||||
/// mention.delete_width();
|
||||
/// assert!(mention.width().is_none());
|
||||
/// ```
|
||||
fn delete_width(&mut self) -> &mut Self {
|
||||
self.link_mut().width = None;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
/// A specialized Link that represents an @mention.
|
||||
///
|
||||
/// This is just an alias for `Link<MentionType>` because there's no fields inherent to Mention
|
||||
/// that aren't already present on a Link.
|
||||
pub type Mention = Link<MentionType>;
|
||||
|
||||
/// Define all the properties of the Object base type as described by the Activity Streams
|
||||
/// vocabulary.
|
||||
///
|
||||
/// The properties of the Link object are not the properties of the referenced resource, but are
|
||||
/// provided as hints for rendering agents to understand how to make use of the resource. For
|
||||
/// example, height and width might represent the desired rendered size of a referenced image,
|
||||
/// rather than the actual pixel dimensions of the referenced image.
|
||||
///
|
||||
/// The target URI of the Link is expressed using the required href property.
|
||||
///
|
||||
/// For example, all Objects can contain an image property whose value describes a graphical
|
||||
/// representation of the containing object. This property will typically be used to provide the
|
||||
/// URL to an image (e.g. JPEG, GIF or PNG) resource that can be displayed to the user. Any given
|
||||
/// object might have multiple such visual representations -- multiple screenshots, for instance,
|
||||
/// or the same image at different resolutions. In Activity Streams 2.0, there are essentially
|
||||
/// three ways of describing such references.
|
||||
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Link<Kind> {
|
||||
/// The target resource pointed to by a Link.
|
||||
///
|
||||
/// - Range: xsd:anyUri
|
||||
/// - Functional: true
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
href: Option<Url>,
|
||||
|
||||
/// Hints as to the language used by the target resource.
|
||||
///
|
||||
/// Value MUST be a [BCP47] Language-Tag.
|
||||
///
|
||||
/// - Range: [BCP47] Language Tag
|
||||
/// - Functional: true
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
hreflang: Option<String>,
|
||||
|
||||
/// A link relation associated with a Link.
|
||||
///
|
||||
/// The value MUST conform to both the [HTML5] and [RFC5988] "link relation" definitions.
|
||||
///
|
||||
/// In the [HTML5], any string not containing the "space" U+0020, "tab" (U+0009), "LF" (U+000A), "FF" (U+000C), "CR" (U+000D) or "," (U+002C) characters can be used as a valid link relation.
|
||||
///
|
||||
/// - Range: [RFC5988] or [HTML5] Link Relation
|
||||
/// - Functional: false
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
rel: Option<OneOrMany<String>>,
|
||||
|
||||
/// On a Link, specifies a hint as to the rendering height in device-independent pixels of the linked resource.
|
||||
///
|
||||
/// - Range: xsd:nonNegativeInteger
|
||||
/// - Functional: true
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
height: Option<u64>,
|
||||
|
||||
/// On a Link, specifies a hint as to the rendering width in device-independent pixels of the linked resource.
|
||||
///
|
||||
/// Range: xsd:nonNegativeInteger
|
||||
/// Functional: true
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
width: Option<u64>,
|
||||
|
||||
/// Base fields and unparsed json ends up here
|
||||
#[serde(flatten)]
|
||||
inner: Base<Kind>,
|
||||
}
|
||||
|
||||
impl<Kind> Link<Kind> {
|
||||
/// Create a new Link
|
||||
///
|
||||
/// ```rust
|
||||
/// use activitystreams::link::Link;
|
||||
///
|
||||
/// let link = Link::<String>::new();
|
||||
/// ```
|
||||
pub fn new() -> Self
|
||||
where
|
||||
Kind: Default,
|
||||
{
|
||||
Link {
|
||||
href: None,
|
||||
hreflang: None,
|
||||
rel: None,
|
||||
height: None,
|
||||
width: None,
|
||||
inner: Base::new(),
|
||||
}
|
||||
}
|
||||
|
||||
fn extending(mut inner: Base<Kind>) -> Result<Self, serde_json::Error> {
|
||||
Ok(Link {
|
||||
href: inner.remove("href")?,
|
||||
hreflang: inner.remove("hreflang")?,
|
||||
rel: inner.remove("rel")?,
|
||||
height: inner.remove("height")?,
|
||||
width: inner.remove("width")?,
|
||||
inner,
|
||||
})
|
||||
}
|
||||
|
||||
fn retracting(self) -> Result<Base<Kind>, serde_json::Error> {
|
||||
let Link {
|
||||
href,
|
||||
hreflang,
|
||||
rel,
|
||||
height,
|
||||
width,
|
||||
mut inner,
|
||||
} = self;
|
||||
|
||||
inner
|
||||
.insert("href", href)?
|
||||
.insert("hreflang", hreflang)?
|
||||
.insert("rel", rel)?
|
||||
.insert("height", height)?
|
||||
.insert("width", width)?;
|
||||
|
||||
Ok(inner)
|
||||
}
|
||||
}
|
||||
|
||||
impl<Kind> markers::Base for Link<Kind> {}
|
||||
impl<Kind> markers::Link for Link<Kind> {}
|
||||
|
||||
impl<Kind> Extends<Kind> for Link<Kind> {
|
||||
type Error = serde_json::Error;
|
||||
|
||||
fn extends(base: Base<Kind>) -> Result<Self, Self::Error> {
|
||||
Self::extending(base)
|
||||
}
|
||||
|
||||
fn retracts(self) -> Result<Base<Kind>, Self::Error> {
|
||||
self.retracting()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Kind> TryFrom<Base<Kind>> for Link<Kind>
|
||||
where
|
||||
Kind: serde::de::DeserializeOwned,
|
||||
{
|
||||
type Error = serde_json::Error;
|
||||
|
||||
fn try_from(base: Base<Kind>) -> Result<Self, Self::Error> {
|
||||
Self::extending(base)
|
||||
}
|
||||
}
|
||||
|
||||
impl<Kind> TryFrom<Link<Kind>> for Base<Kind>
|
||||
where
|
||||
Kind: serde::ser::Serialize,
|
||||
{
|
||||
type Error = serde_json::Error;
|
||||
|
||||
fn try_from(link: Link<Kind>) -> Result<Self, Self::Error> {
|
||||
link.retracting()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Kind> UnparsedMut for Link<Kind> {
|
||||
fn unparsed_mut(&mut self) -> &mut Unparsed {
|
||||
self.inner.unparsed_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Kind> AsBase<Kind> for Link<Kind> {
|
||||
fn base_ref(&self) -> &Base<Kind> {
|
||||
&self.inner
|
||||
}
|
||||
|
||||
fn base_mut(&mut self) -> &mut Base<Kind> {
|
||||
&mut self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl<Kind> AsLink<Kind> for Link<Kind> {
|
||||
fn link_ref(&self) -> &Link<Kind> {
|
||||
self
|
||||
}
|
||||
|
||||
fn link_mut(&mut self) -> &mut Link<Kind> {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, Kind> LinkExt<Kind> for T where T: AsLink<Kind> {}
|
|
@ -1,26 +0,0 @@
|
|||
/*
|
||||
* This file is part of ActivityStreams.
|
||||
*
|
||||
* Copyright © 2020 Riley Trautman
|
||||
*
|
||||
* ActivityStreams is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ActivityStreams is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ActivityStreams. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//! Namespace for Unit Structs that serialize to strings
|
||||
use crate::UnitString;
|
||||
|
||||
/// A Unit Struct that represents the string "Mention"
|
||||
#[derive(Clone, Debug, Default, UnitString)]
|
||||
#[unit_string(Mention)]
|
||||
pub struct MentionType;
|
|
@ -1,41 +0,0 @@
|
|||
/*
|
||||
* This file is part of ActivityStreams.
|
||||
*
|
||||
* Copyright © 2020 Riley Trautman
|
||||
*
|
||||
* ActivityStreams is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ActivityStreams is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ActivityStreams. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//! Namespace for Link types
|
||||
|
||||
#[cfg(feature = "kinds")]
|
||||
pub mod kind;
|
||||
#[cfg(feature = "types")]
|
||||
pub mod properties;
|
||||
#[cfg(feature = "types")]
|
||||
mod types;
|
||||
|
||||
#[cfg(feature = "types")]
|
||||
pub use self::types::Mention;
|
||||
|
||||
/// A Link is an indirect, qualified reference to a resource identified by a URL.
|
||||
///
|
||||
/// The fundamental model for links is established by
|
||||
/// [[RFC5988](https://tools.ietf.org/html/rfc5988)]. Many of the properties defined by the
|
||||
/// Activity Vocabulary allow values that are either instances of Object or Link. When a Link is
|
||||
/// used, it establishes a qualified relation connecting the subject (the containing object) to the
|
||||
/// resource identified by the href. Properties of the Link are properties of the reference as
|
||||
/// opposed to properties of the resource.
|
||||
#[cfg_attr(feature = "derive", crate::wrapper_type)]
|
||||
pub trait Link: crate::Base {}
|
|
@ -1,236 +0,0 @@
|
|||
/*
|
||||
* This file is part of ActivityStreams.
|
||||
*
|
||||
* Copyright © 2020 Riley Trautman
|
||||
*
|
||||
* ActivityStreams is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ActivityStreams is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ActivityStreams. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//! Namespace for properties of standard link types
|
||||
//!
|
||||
//! To use these properties in your own types, you can flatten them into your struct with serde:
|
||||
//!
|
||||
//! ```rust
|
||||
//! use activitystreams::{
|
||||
//! ext::Ext,
|
||||
//! link::{
|
||||
//! properties::LinkProperties,
|
||||
//! Link, LinkBox,
|
||||
//! },
|
||||
//! Base, BaseBox, PropRefs,
|
||||
//! };
|
||||
//! use serde::{Deserialize, Serialize};
|
||||
//!
|
||||
//! #[derive(Clone, Debug, Default, serde::Serialize, serde::Deserialize)]
|
||||
//! #[serde(transparent)]
|
||||
//! pub struct MyProps(pub LinkProperties);
|
||||
//!
|
||||
//! #[derive(Clone, Debug, Default, Serialize, Deserialize, PropRefs)]
|
||||
//! #[serde(rename_all = "camelCase")]
|
||||
//! #[prop_refs(Link)]
|
||||
//! pub struct MyLink {
|
||||
//! #[serde(rename = "type")]
|
||||
//! pub kind: String,
|
||||
//!
|
||||
//! /// Define a require property for the MyLink type
|
||||
//! pub my_property: String,
|
||||
//!
|
||||
//! #[serde(flatten)]
|
||||
//! #[prop_refs]
|
||||
//! pub link_properties: MyProps,
|
||||
//! }
|
||||
//! #
|
||||
//! # fn main() {}
|
||||
//! ```
|
||||
|
||||
use crate::{link::LinkBox, object::ObjectBox, primitives::*, properties};
|
||||
|
||||
properties! {
|
||||
Link {
|
||||
docs [
|
||||
"Define all the properties of the Object base type as described by the Activity Streams vocabulary.",
|
||||
"",
|
||||
"The properties of the `Link` object are not the properties of the referenced resource, but are",
|
||||
"provided as hints for rendering agents to understand how to make use of the resource. For",
|
||||
"example, height and width might represent the desired rendered size of a referenced image,",
|
||||
"rather than the actual pixel dimensions of the referenced image.",
|
||||
"",
|
||||
"The target URI of the Link is expressed using the required href property.",
|
||||
"",
|
||||
"For example, all Objects can contain an image property whose value describes a graphical",
|
||||
"representation of the containing object. This property will typically be used to provide the URL",
|
||||
"to an image (e.g. JPEG, GIF or PNG) resource that can be displayed to the user. Any given object",
|
||||
"might have multiple such visual representations -- multiple screenshots, for instance, or the",
|
||||
"same image at different resolutions. In Activity Streams 2.0, there are essentially three ways",
|
||||
"of describing such references.",
|
||||
],
|
||||
id {
|
||||
docs [
|
||||
"Provides the globally unique identifier for an Object or Link.",
|
||||
"",
|
||||
"The `id` property is expressed as an absolute IRI in the spec, but for now is represented",
|
||||
"as a string.",
|
||||
"",
|
||||
"- Range: `anyUri`",
|
||||
"- Functional: true",
|
||||
],
|
||||
types [
|
||||
XsdAnyUri,
|
||||
],
|
||||
functional,
|
||||
},
|
||||
|
||||
context {
|
||||
docs [
|
||||
"Identifies the context within which the object exists or an activity was performed.",
|
||||
"",
|
||||
"The notion of \"context\" used is intentionally vague. The intended function is to serve as a",
|
||||
"means of grouping objects and activities that share a common originating context or purpose.",
|
||||
"An example could be all activities relating to a common project or event.",
|
||||
"",
|
||||
"- Range: `Object` | `Link`",
|
||||
"- Functional: false",
|
||||
],
|
||||
types [
|
||||
XsdAnyUri,
|
||||
ObjectBox,
|
||||
LinkBox,
|
||||
],
|
||||
rename("@context"),
|
||||
},
|
||||
|
||||
name {
|
||||
docs [
|
||||
"A simple, human-readable, plain-text name for the object.",
|
||||
"",
|
||||
"HTML markup MUST NOT be included. The name MAY be expressed using multiple language-tagged",
|
||||
"values.",
|
||||
"",
|
||||
"- Range: `xsd:string` | `rdf:langString`",
|
||||
"- Functional: false",
|
||||
],
|
||||
types [
|
||||
XsdString,
|
||||
RdfLangString,
|
||||
],
|
||||
},
|
||||
|
||||
href {
|
||||
docs [
|
||||
"The target resource pointed to by a Link.",
|
||||
"",
|
||||
"- Range: `xsd:anyUri`",
|
||||
"- Functional: true",
|
||||
],
|
||||
types [
|
||||
XsdAnyUri,
|
||||
],
|
||||
functional,
|
||||
},
|
||||
|
||||
hreflang {
|
||||
docs [
|
||||
"Hints as to the language used by the target resource.",
|
||||
"",
|
||||
"Value MUST be a [[BCP47](https://tools.ietf.org/html/bcp47)]",
|
||||
"Language-Tag.",
|
||||
"",
|
||||
"- Range: [[BCP47](https://tools.ietf.org/html/bcp47)] Language",
|
||||
"Tag",
|
||||
"- Functional: true",
|
||||
],
|
||||
types [
|
||||
XsdString,
|
||||
],
|
||||
functional,
|
||||
},
|
||||
|
||||
media_type {
|
||||
docs [
|
||||
"When used on a `Link`, identifies the MIME media type of the referenced resource.",
|
||||
"",
|
||||
"If not specified, the content property is assumed to contain text/html content.",
|
||||
"",
|
||||
"- Range: `Mime Media Type`",
|
||||
"- Functional: true",
|
||||
],
|
||||
types [
|
||||
MimeMediaType,
|
||||
],
|
||||
functional,
|
||||
},
|
||||
|
||||
rel {
|
||||
docs [
|
||||
"A link relation associated with a Link.",
|
||||
"",
|
||||
"The value MUST conform to both the",
|
||||
"[[HTML5](https://www.w3.org/TR/html5/)] and [[RFC5988](https://tools.ietf.org/html/rfc5988)]",
|
||||
"\"link relation\" definitions.",
|
||||
"",
|
||||
"In the [[HTML5](https://www.w3.org/TR/html5/)], any string",
|
||||
"not containing the \"space\" U+0020, \"tab\" (U+0009), \"LF\" (U+000A), \"FF\" (U+000C), \"CR\"",
|
||||
"(U+000D) or \",\" (U+002C) characters can be used as a valid link relation.",
|
||||
"",
|
||||
"- Range:",
|
||||
" [[RFC5988](https://tools.ietf.org/html/rfc5988)] or",
|
||||
" [[HTML5](https://www.w3.org/TR/html5/)] Link Relation",
|
||||
"- Functional: false",
|
||||
],
|
||||
types [
|
||||
XsdString,
|
||||
],
|
||||
},
|
||||
|
||||
height {
|
||||
docs ["On a `Link`, specifies a hint as to the rendering height in device-independent pixels of the",
|
||||
"linked resource.",
|
||||
"",
|
||||
"- Range: `xsd:nonNegativeInteger`",
|
||||
"- Functional: true",
|
||||
],
|
||||
types [
|
||||
XsdNonNegativeInteger,
|
||||
],
|
||||
functional,
|
||||
},
|
||||
|
||||
width {
|
||||
docs [
|
||||
"On a `Link`, specifies a hint as to the rendering width in device-independent pixels of the",
|
||||
"linked resource.",
|
||||
"",
|
||||
"- Range: `xsd:nonNegativeInteger`",
|
||||
"- Functional: true",
|
||||
],
|
||||
types [
|
||||
XsdNonNegativeInteger,
|
||||
],
|
||||
},
|
||||
|
||||
preview {
|
||||
docs [
|
||||
"Identifies an entity that provides a preview of this object.",
|
||||
"",
|
||||
"- Range: `Object` | `Link`",
|
||||
"- Functional: false",
|
||||
],
|
||||
types [
|
||||
XsdAnyUri,
|
||||
ObjectBox,
|
||||
LinkBox,
|
||||
],
|
||||
},
|
||||
}
|
||||
}
|
|
@ -1,40 +0,0 @@
|
|||
/*
|
||||
* This file is part of ActivityStreams.
|
||||
*
|
||||
* Copyright © 2020 Riley Trautman
|
||||
*
|
||||
* ActivityStreams is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ActivityStreams is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ActivityStreams. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
use crate::{
|
||||
link::{kind::*, properties::*, Link, LinkBox},
|
||||
Base, BaseBox, PropRefs,
|
||||
};
|
||||
|
||||
#[cfg(feature = "types")]
|
||||
/// A specialized Link that represents an @mention.
|
||||
#[derive(Clone, Debug, Default, PropRefs, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[prop_refs(Link)]
|
||||
pub struct Mention {
|
||||
#[serde(rename = "type")]
|
||||
#[serde(alias = "objectType")]
|
||||
#[serde(alias = "verb")]
|
||||
kind: MentionType,
|
||||
|
||||
/// Adds all valid link properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub link_props: LinkProperties,
|
||||
}
|
85
src/macros.rs
Normal file
85
src/macros.rs
Normal file
|
@ -0,0 +1,85 @@
|
|||
/// Generate an enum implementing serde's Serialize and Deserialize with a single variant
|
||||
///
|
||||
/// This is useful for describing constants
|
||||
///
|
||||
/// ```rust
|
||||
/// # fn main() -> Result<(), anyhow::Error> {
|
||||
/// use activitystreams::kind;
|
||||
///
|
||||
/// kind!(CustomType, Custom);
|
||||
///
|
||||
/// #[derive(serde::Deserialize)]
|
||||
/// struct MyStruct {
|
||||
/// #[serde(rename = "type")]
|
||||
/// kind: CustomType,
|
||||
/// }
|
||||
///
|
||||
/// let s: MyStruct = serde_json::from_str(r#"{"type":"Custom"}"#)?;
|
||||
///
|
||||
/// assert_eq!(s.kind, CustomType::Custom);
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[macro_export]
|
||||
macro_rules! kind {
|
||||
($x:ident, $y:ident) => {
|
||||
#[derive(
|
||||
Clone,
|
||||
Debug,
|
||||
Eq,
|
||||
Hash,
|
||||
Ord,
|
||||
PartialEq,
|
||||
PartialOrd,
|
||||
serde::Deserialize,
|
||||
serde::Serialize,
|
||||
)]
|
||||
/// A type stand-in for the constant $y, deriving serde traits
|
||||
pub enum $x {
|
||||
$y,
|
||||
}
|
||||
|
||||
impl std::fmt::Display for $x {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
write!(f, stringify!($y))
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for $x {
|
||||
fn default() -> Self {
|
||||
$x::$y
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// A macro to shorten the `string.parse::<Url>()?` calls inevitably made in downstream code
|
||||
///
|
||||
/// ```rust
|
||||
/// use activitystreams::uri;
|
||||
///
|
||||
/// fn fallible() -> Result<(), anyhow::Error> {
|
||||
/// let my_uri = uri!("https://example.com");
|
||||
/// Ok(())
|
||||
/// }
|
||||
///
|
||||
/// # fn main() -> Result<(), anyhow::Error> { fallible() }
|
||||
/// ```
|
||||
#[macro_export]
|
||||
macro_rules! uri {
|
||||
( $x:expr ) => {{
|
||||
use activitystreams::url::Url;
|
||||
|
||||
$x.parse::<Url>()?
|
||||
}};
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#[test]
|
||||
fn to_string_works() {
|
||||
kind!(MyType, My);
|
||||
|
||||
assert_eq!(MyType::My.to_string(), "My")
|
||||
}
|
||||
}
|
89
src/markers.rs
Normal file
89
src/markers.rs
Normal file
|
@ -0,0 +1,89 @@
|
|||
//! Marker traits for bounding methods
|
||||
//!
|
||||
//! ```rust
|
||||
//! use activitystreams::{base::BaseExt, markers::Activity};
|
||||
//!
|
||||
//! /// Applies the name "hi" to any given activity
|
||||
//! fn manipulator<T, Kind>(mut some_type: T) -> T
|
||||
//! where
|
||||
//! T: Activity + BaseExt<Kind>,
|
||||
//! {
|
||||
//! some_type.set_name("hi");
|
||||
//!
|
||||
//! some_type
|
||||
//! }
|
||||
//! ```
|
||||
|
||||
/// The lowermost trait of the trait structure
|
||||
///
|
||||
/// Base exists solely so Object and Link can have impls that don't potentially conflict
|
||||
pub trait Base {}
|
||||
|
||||
/// Describes an object of any kind.
|
||||
///
|
||||
/// The Object type serves as the base type for most of the other kinds of objects defined in the
|
||||
/// Activity Vocabulary, including other Core types such as `Activity`, `IntransitiveActivity`,
|
||||
/// `Collection` and `OrderedCollection`.
|
||||
pub trait Object: Base {}
|
||||
|
||||
/// A Link is an indirect, qualified reference to a resource identified by a URL.
|
||||
///
|
||||
/// The fundamental model for links is established by
|
||||
/// [[RFC5988](https://tools.ietf.org/html/rfc5988)]. Many of the properties defined by the
|
||||
/// Activity Vocabulary allow values that are either instances of Object or Link. When a Link is
|
||||
/// used, it establishes a qualified relation connecting the subject (the containing object) to the
|
||||
/// resource identified by the href. Properties of the Link are properties of the reference as
|
||||
/// opposed to properties of the resource.
|
||||
pub trait Link: Base {}
|
||||
|
||||
/// A Collection is a subtype of `Object` that represents ordered or unordered sets of `Object` or
|
||||
/// `Link` instances.
|
||||
///
|
||||
/// The items within a Collection can be ordered or unordered. The OrderedCollection type MAY be
|
||||
/// used to identify a Collection whose items are always ordered. In the JSON serialization, the
|
||||
/// unordered items of a Collection are represented using the items property while ordered items
|
||||
/// are represented using the orderedItems property.
|
||||
pub trait Collection: Object {}
|
||||
|
||||
/// Used to represent distinct subsets of items from a Collection.
|
||||
///
|
||||
/// A `Collection` can contain a large number of items. Often, it becomes impractical for an
|
||||
/// implementation to serialize every item contained by a `Collection` using the items (or
|
||||
/// `ordered_items`) property alone. In such cases, the items within a `Collection` can be divided
|
||||
/// into distinct subsets or "pages". A page is identified using the `CollectionPage` type.
|
||||
pub trait CollectionPage: Collection {}
|
||||
|
||||
/// `Actor` types are `Object` types that are capable of performing activities.
|
||||
///
|
||||
/// This specification intentionally defines `Actors` in only the most generalized way, stopping
|
||||
/// short of defining semantically specific properties for each. All Actor objects are
|
||||
/// specializations of `Object` and inherit all of the core properties common to all Objects.
|
||||
/// External vocabularies can be used to express additional detail not covered by the Activity
|
||||
/// Vocabulary. VCard [[vcard-rdf](https://www.w3.org/TR/vcard-rdf/) SHOULD be used to provide
|
||||
/// additional metadata for `Person`, `Group`, and `Organization` instances.
|
||||
///
|
||||
/// While implementations are free to introduce new types of Actors beyond those defined by the
|
||||
/// Activity Vocabulary, interoperability issues can arise when applications rely too much on
|
||||
/// extension types that are not recognized by other implementations. Care should be taken to not
|
||||
/// unduly overlap with or duplicate the existing `Actor` types.
|
||||
///
|
||||
/// When an implementation uses an extension type that overlaps with a core vocabulary type, the
|
||||
/// implementation MUST also specify the core vocabulary type. For instance, some vocabularies
|
||||
/// (e.g. VCard) define their own types for describing people. An implementation that wishes, for
|
||||
/// example, to use a `vcard:Individual` as an `Actor` MUST also identify that `Actor` as a
|
||||
/// `Person`.
|
||||
pub trait Actor: Object {}
|
||||
|
||||
/// An Activity is a subtype of `Object` that describes some form of action that may happen, is
|
||||
/// currently happening, or has already happened.
|
||||
///
|
||||
/// The `Activity` type itself serves as an abstract base type for all types of activities. It is
|
||||
/// important to note that the `Activity` type itself does not carry any specific semantics about
|
||||
/// the kind of action being taken.
|
||||
pub trait Activity: Object {}
|
||||
|
||||
/// Instances of `IntransitiveActivity` are a subtype of `Activity` representing intransitive
|
||||
/// actions.
|
||||
///
|
||||
/// The `object` property is therefore inappropriate for these activities.
|
||||
pub trait IntransitiveActivity: Activity {}
|
5540
src/object.rs
Normal file
5540
src/object.rs
Normal file
File diff suppressed because it is too large
Load diff
|
@ -1,81 +0,0 @@
|
|||
/*
|
||||
* This file is part of ActivityStreams.
|
||||
*
|
||||
* Copyright © 2020 Riley Trautman
|
||||
*
|
||||
* ActivityStreams is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ActivityStreams is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ActivityStreams. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//! Namespace for Unit Structs that serialize to strings
|
||||
use crate::UnitString;
|
||||
|
||||
/// A Unit Struct that represents the string "Article"
|
||||
#[derive(Clone, Debug, Default, UnitString)]
|
||||
#[unit_string(Article)]
|
||||
pub struct ArticleType;
|
||||
|
||||
/// A Unit Struct that represents the string "Audio"
|
||||
#[derive(Clone, Debug, Default, UnitString)]
|
||||
#[unit_string(Audio)]
|
||||
pub struct AudioType;
|
||||
|
||||
/// A Unit Struct that represents the string "Document"
|
||||
#[derive(Clone, Debug, Default, UnitString)]
|
||||
#[unit_string(Document)]
|
||||
pub struct DocumentType;
|
||||
|
||||
/// A Unit Struct that represents the string "Event"
|
||||
#[derive(Clone, Debug, Default, UnitString)]
|
||||
#[unit_string(Event)]
|
||||
pub struct EventType;
|
||||
|
||||
/// A Unit Struct that represents the string "Image"
|
||||
#[derive(Clone, Debug, Default, UnitString)]
|
||||
#[unit_string(Image)]
|
||||
pub struct ImageType;
|
||||
|
||||
/// A Unit Struct that represents the string "Note"
|
||||
#[derive(Clone, Debug, Default, UnitString)]
|
||||
#[unit_string(Note)]
|
||||
pub struct NoteType;
|
||||
|
||||
/// A Unit Struct that represents the string "Page"
|
||||
#[derive(Clone, Debug, Default, UnitString)]
|
||||
#[unit_string(Page)]
|
||||
pub struct PageType;
|
||||
|
||||
/// A Unit Struct that represents the string "Place"
|
||||
#[derive(Clone, Debug, Default, UnitString)]
|
||||
#[unit_string(Place)]
|
||||
pub struct PlaceType;
|
||||
|
||||
/// A Unit Struct that represents the string "Profile"
|
||||
#[derive(Clone, Debug, Default, UnitString)]
|
||||
#[unit_string(Profile)]
|
||||
pub struct ProfileType;
|
||||
|
||||
/// A Unit Struct that represents the string "Relationship"
|
||||
#[derive(Clone, Debug, Default, UnitString)]
|
||||
#[unit_string(Relationship)]
|
||||
pub struct RelationshipType;
|
||||
|
||||
/// A Unit Struct that represents the string "Tombstone"
|
||||
#[derive(Clone, Debug, Default, UnitString)]
|
||||
#[unit_string(Tombstone)]
|
||||
pub struct TombstoneType;
|
||||
|
||||
/// A Unit Struct that represents the string "Video"
|
||||
#[derive(Clone, Debug, Default, UnitString)]
|
||||
#[unit_string(Video)]
|
||||
pub struct VideoType;
|
|
@ -1,73 +0,0 @@
|
|||
/*
|
||||
* This file is part of ActivityStreams.
|
||||
*
|
||||
* Copyright © 2020 Riley Trautman
|
||||
*
|
||||
* ActivityStreams is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ActivityStreams is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ActivityStreams. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//! Namespace for Object types
|
||||
|
||||
#[cfg(feature = "kinds")]
|
||||
pub mod kind;
|
||||
#[cfg(feature = "types")]
|
||||
pub mod properties;
|
||||
#[cfg(feature = "types")]
|
||||
mod types;
|
||||
|
||||
#[cfg(feature = "types")]
|
||||
pub use self::types::{
|
||||
Article, Audio, Document, Event, Image, Note, Page, Place, Profile, Relationship, Tombstone,
|
||||
Video,
|
||||
};
|
||||
|
||||
/// Describes an object of any kind.
|
||||
///
|
||||
/// The Object type serves as the base type for most of the other kinds of objects defined in the
|
||||
/// Activity Vocabulary, including other Core types such as `Activity`, `IntransitiveActivity`,
|
||||
/// `Collection` and `OrderedCollection`.
|
||||
#[cfg_attr(feature = "derive", crate::wrapper_type)]
|
||||
pub trait Object: crate::Base {}
|
||||
|
||||
#[cfg(feature = "types")]
|
||||
/// Describes any kind of Image
|
||||
///
|
||||
/// Since Image is "concrete" in the ActivityStreams spec, but multiple fields in ObjectProperties
|
||||
/// require an "Image", this type acts as a filter to ensure only Images can be serialized or
|
||||
/// deserialized, but allows any adjacent fields through
|
||||
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
|
||||
pub struct AnyImage {
|
||||
#[serde(rename = "type")]
|
||||
kind: self::kind::ImageType,
|
||||
|
||||
#[serde(flatten)]
|
||||
rest: std::collections::HashMap<String, serde_json::Value>,
|
||||
}
|
||||
|
||||
#[cfg(feature = "types")]
|
||||
impl AnyImage {
|
||||
pub fn from_concrete<T>(t: T) -> Result<Self, serde_json::Error>
|
||||
where
|
||||
T: Object + serde::ser::Serialize,
|
||||
{
|
||||
serde_json::from_value(serde_json::to_value(t)?)
|
||||
}
|
||||
|
||||
pub fn into_concrete<T>(self) -> Result<T, serde_json::Error>
|
||||
where
|
||||
T: Object + serde::de::DeserializeOwned,
|
||||
{
|
||||
serde_json::from_value(serde_json::to_value(self)?)
|
||||
}
|
||||
}
|
|
@ -1,764 +0,0 @@
|
|||
/*
|
||||
* This file is part of ActivityStreams.
|
||||
*
|
||||
* Copyright © 2020 Riley Trautman
|
||||
*
|
||||
* ActivityStreams is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ActivityStreams is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ActivityStreams. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//! Namespace for properties of standard object types
|
||||
//!
|
||||
//! To use these properties in your own types, you can flatten them into your struct with serde:
|
||||
//!
|
||||
//! ```rust
|
||||
//! use activitystreams::{
|
||||
//! ext::Ext,
|
||||
//! object::{
|
||||
//! properties::ObjectProperties,
|
||||
//! Object, ObjectBox,
|
||||
//! },
|
||||
//! Base, BaseBox, PropRefs,
|
||||
//! };
|
||||
//! use std::collections::HashMap;
|
||||
//!
|
||||
//! #[derive(Clone, Debug, Default, serde::Serialize, serde::Deserialize)]
|
||||
//! #[serde(transparent)]
|
||||
//! pub struct MyProps(pub ObjectProperties);
|
||||
//!
|
||||
//! #[derive(Clone, Debug, Default, PropRefs, serde::Serialize, serde::Deserialize)]
|
||||
//! #[serde(rename_all = "camelCase")]
|
||||
//! #[prop_refs(Object)]
|
||||
//! pub struct MyObject {
|
||||
//! #[serde(rename = "type")]
|
||||
//! pub kind: String,
|
||||
//!
|
||||
//! /// Define a required property for the MyObject type
|
||||
//! pub my_property: String,
|
||||
//!
|
||||
//! #[serde(flatten)]
|
||||
//! #[prop_refs]
|
||||
//! pub extra: MyProps,
|
||||
//! }
|
||||
//! #
|
||||
//! # fn main() {}
|
||||
//! ```
|
||||
|
||||
use crate::{
|
||||
ext::Extension,
|
||||
link::LinkBox,
|
||||
object::{AnyImage, Object, ObjectBox},
|
||||
primitives::*,
|
||||
properties, BaseBox,
|
||||
};
|
||||
|
||||
impl<T> Extension<T> for ApObjectProperties where T: Object {}
|
||||
|
||||
properties! {
|
||||
Object {
|
||||
docs [
|
||||
"Define all the properties of the Object base type as described by the Activity Streams",
|
||||
"vocabulary.",
|
||||
"",
|
||||
"In addition to having a global identifier (expressed as an absolute IRI using the id property)",
|
||||
"and an \"object type\"(expressed using the type property), all instances of the Object type share",
|
||||
"a common set of properties normatively defined by the Activity Vocabulary.",
|
||||
"",
|
||||
"This struct does not provide an optional `type` property, if you are implementing your own",
|
||||
"object type, you must supply your own type. This crate's provided object types all supply their",
|
||||
"own `type` properties as Unit Structs with custom serde behaviour.",
|
||||
"",
|
||||
"All properties are optional (including the id and type).",
|
||||
],
|
||||
id {
|
||||
docs [
|
||||
"Provides the globally unique identifier for an Object or Link.",
|
||||
"",
|
||||
"The `id` property is expressed as an absolute IRI in the spec, but for now is represented",
|
||||
"as a string.",
|
||||
"",
|
||||
"- Range: `xsd:anyUri`",
|
||||
"- Functional: true",
|
||||
],
|
||||
types [
|
||||
XsdAnyUri,
|
||||
],
|
||||
functional,
|
||||
alias [ "@id" ],
|
||||
},
|
||||
|
||||
attachment {
|
||||
docs [
|
||||
"Identifies a resource attached or related to an object that potentially requires special",
|
||||
"handling.",
|
||||
"",
|
||||
"The intent is to provide a model that is at least semantically similar to attachments in",
|
||||
"email.",
|
||||
"",
|
||||
"- Range: `Object` | `Link`",
|
||||
"- Functional: false",
|
||||
],
|
||||
types [
|
||||
XsdAnyUri,
|
||||
BaseBox,
|
||||
],
|
||||
},
|
||||
|
||||
attributed_to {
|
||||
docs [
|
||||
"Identifies one or more entities to which this object is attributed.",
|
||||
"",
|
||||
"The attributed entities might not be Actors. For instance, an object might be attributed to",
|
||||
"the completion of another activity.",
|
||||
"",
|
||||
"- Range: `Object` | `Link`",
|
||||
"- Functional: false",
|
||||
],
|
||||
types [
|
||||
XsdAnyUri,
|
||||
BaseBox,
|
||||
],
|
||||
},
|
||||
|
||||
audience {
|
||||
docs [
|
||||
"Identifies one or more entities that represent the total population of entities for which",
|
||||
"the object can considered to be relevant.",
|
||||
"",
|
||||
"- Range: `Object` | `Link`",
|
||||
"- Functional: false",
|
||||
],
|
||||
types [
|
||||
XsdAnyUri,
|
||||
BaseBox,
|
||||
],
|
||||
},
|
||||
|
||||
content {
|
||||
docs [
|
||||
"The content or textual representation of the Object encoded as a JSON string.",
|
||||
"",
|
||||
"By default, the value of content is HTML. The mediaType property can be used in the object",
|
||||
"to indicate a different content type.",
|
||||
"",
|
||||
"The content MAY be expressed using multiple language-tagged values.",
|
||||
"",
|
||||
"- Range: `xsd:string` | `rdf:langString`",
|
||||
"- Functional: false",
|
||||
],
|
||||
types [
|
||||
XsdString,
|
||||
RdfLangString,
|
||||
],
|
||||
},
|
||||
|
||||
context {
|
||||
docs [
|
||||
"Identifies the context within which the object exists or an activity was performed.",
|
||||
"",
|
||||
"The notion of \"context\"used is intentionally vague. The intended function is to serve as a",
|
||||
"means of grouping objects and activities that share a common originating context or purpose.",
|
||||
"An example could be all activities relating to a common project or event.",
|
||||
"",
|
||||
"- Range: `Object` | `Link`",
|
||||
"- Functional: false",
|
||||
],
|
||||
types [
|
||||
XsdAnyUri,
|
||||
BaseBox,
|
||||
],
|
||||
rename("@context"),
|
||||
},
|
||||
|
||||
name {
|
||||
docs [
|
||||
"A simple, human-readable, plain-text name for the object.",
|
||||
"",
|
||||
"HTML markup MUST NOT be included. The name MAY be expressed using multiple language-tagged",
|
||||
"values.",
|
||||
"",
|
||||
"- Range: `xsd:string` | `rdf:langString`",
|
||||
"- Functional: false",
|
||||
],
|
||||
types [
|
||||
XsdString,
|
||||
RdfLangString,
|
||||
],
|
||||
alias [ "displayName" ],
|
||||
},
|
||||
|
||||
end_time {
|
||||
docs [
|
||||
"The date and time describing the actual or expected ending time of the object.",
|
||||
"",
|
||||
"When used with an Activity object, for instance, the endTime property specifies the moment",
|
||||
"the activity concluded or is expected to conclude.",
|
||||
"",
|
||||
"- Range: `xsd:dateTime`",
|
||||
"- Functional: true",
|
||||
],
|
||||
types [
|
||||
XsdDateTime,
|
||||
],
|
||||
functional,
|
||||
},
|
||||
|
||||
generator {
|
||||
docs [
|
||||
"Identifies the entity (e.g. an application) that generated the object.",
|
||||
"",
|
||||
"- Range: `Object` | `Link`",
|
||||
"- Functional: false",
|
||||
],
|
||||
types [
|
||||
XsdAnyUri,
|
||||
BaseBox,
|
||||
],
|
||||
},
|
||||
|
||||
icon {
|
||||
docs [
|
||||
"Indicates an entity that describes an icon for this object.",
|
||||
"",
|
||||
"The image should have an aspect ratio of one (horizontal) to one (vertical) and should be",
|
||||
"suitable for presentation at a small size.",
|
||||
"",
|
||||
"- Range: `Image` | `Link`",
|
||||
"- Functional: false",
|
||||
],
|
||||
types [
|
||||
XsdAnyUri,
|
||||
AnyImage,
|
||||
LinkBox,
|
||||
],
|
||||
},
|
||||
|
||||
image {
|
||||
docs [
|
||||
"Indicates an entity that describes an image for this object.",
|
||||
"",
|
||||
"Unlike the icon property, there are no aspect ratio or display size limitations assumed.",
|
||||
"",
|
||||
"- Range: `Image` | `Link`",
|
||||
"- Functional: false",
|
||||
],
|
||||
types [
|
||||
XsdAnyUri,
|
||||
AnyImage,
|
||||
LinkBox,
|
||||
],
|
||||
},
|
||||
|
||||
in_reply_to {
|
||||
docs [
|
||||
"Indicates one or more entities for which this object is considered a response.",
|
||||
"",
|
||||
"- Range: `Object` | `Link`",
|
||||
"- Functional: false",
|
||||
],
|
||||
types [
|
||||
XsdAnyUri,
|
||||
BaseBox,
|
||||
],
|
||||
},
|
||||
|
||||
location {
|
||||
docs [
|
||||
"Indicates one or more physical or logical locations associated with the object.",
|
||||
"",
|
||||
"- Range: `Object` | `Link`",
|
||||
"- Functional: false",
|
||||
],
|
||||
types [
|
||||
XsdAnyUri,
|
||||
BaseBox,
|
||||
],
|
||||
},
|
||||
|
||||
preview {
|
||||
docs [
|
||||
"Identifies an entity that provides a preview of this object.",
|
||||
"",
|
||||
"- Range: `Object` | `Link`",
|
||||
"- Functional: false",
|
||||
],
|
||||
types [
|
||||
XsdAnyUri,
|
||||
BaseBox,
|
||||
],
|
||||
},
|
||||
|
||||
published {
|
||||
docs [
|
||||
"The date and time at which the object was published.",
|
||||
"",
|
||||
"- Range: `xsd:dateTime`",
|
||||
"- Functional: true",
|
||||
],
|
||||
types [
|
||||
XsdDateTime,
|
||||
],
|
||||
functional,
|
||||
},
|
||||
|
||||
replies {
|
||||
docs [
|
||||
"Identifies a `Collection` containing objects considered to be responses to this object.",
|
||||
"",
|
||||
"- Range: `Object` | `Link`",
|
||||
"- Functional: false",
|
||||
],
|
||||
types [
|
||||
XsdAnyUri,
|
||||
BaseBox,
|
||||
],
|
||||
},
|
||||
|
||||
start_time {
|
||||
docs [
|
||||
"The date and time describing the actual or expected starting time of the object.",
|
||||
"",
|
||||
"When used with an `Activity` object, for instance, the `start_time` property specifies the",
|
||||
"moment the activity began or is scheduled to begin.",
|
||||
"",
|
||||
"- Range: `xsd:DateTime`",
|
||||
"- Functional: true",
|
||||
],
|
||||
types [
|
||||
XsdDateTime,
|
||||
],
|
||||
functional,
|
||||
},
|
||||
|
||||
summary {
|
||||
docs [
|
||||
"A natural language summarization of the object encoded as HTML.",
|
||||
"",
|
||||
"Multiple language tagged summaries MAY be provided.",
|
||||
"",
|
||||
"- Range: `xsd:string` | `rdf:langString`",
|
||||
"- Functional: false",
|
||||
],
|
||||
types [
|
||||
XsdString,
|
||||
RdfLangString,
|
||||
],
|
||||
},
|
||||
|
||||
tag {
|
||||
docs [
|
||||
"One or more \"tags\" that have been associated with an objects. A tag can be any kind of",
|
||||
"`Object`.",
|
||||
"",
|
||||
"The key difference between attachment and tag is that the former implies association by",
|
||||
"inclusion, while the latter implies associated by reference.",
|
||||
"",
|
||||
"- Range: `Object` | `Link`",
|
||||
"- Functional: false",
|
||||
],
|
||||
types [
|
||||
XsdAnyUri,
|
||||
BaseBox,
|
||||
],
|
||||
},
|
||||
|
||||
updated {
|
||||
docs [
|
||||
"The date and time at which the object was updated,",
|
||||
"",
|
||||
"- Range: `xsd:dateTime`",
|
||||
"- Functional: true",
|
||||
],
|
||||
types [
|
||||
XsdDateTime,
|
||||
],
|
||||
functional,
|
||||
},
|
||||
|
||||
url {
|
||||
docs [
|
||||
"Identifies one or more links to representations of the object.",
|
||||
"",
|
||||
"- Range: `xsd:anyUri` | `Link`",
|
||||
"- Functional: false",
|
||||
],
|
||||
types [
|
||||
XsdAnyUri,
|
||||
LinkBox,
|
||||
],
|
||||
},
|
||||
|
||||
to {
|
||||
docs [
|
||||
"Identifies an entity considered to be part of the public primary audience of an `Object`.",
|
||||
"",
|
||||
"- Range: `Object` | `Link`",
|
||||
"- Functional: false",
|
||||
],
|
||||
types [
|
||||
XsdAnyUri,
|
||||
BaseBox,
|
||||
],
|
||||
},
|
||||
|
||||
bto {
|
||||
docs [
|
||||
"Identifies an `Object` that is part of the private primary audience of this `Object`.",
|
||||
"",
|
||||
"- Range: `Object` | `Link`",
|
||||
"- Functional: false",
|
||||
],
|
||||
types [
|
||||
XsdAnyUri,
|
||||
BaseBox,
|
||||
],
|
||||
},
|
||||
|
||||
cc {
|
||||
docs [
|
||||
"Identifies an `Object` that is part of the public secondary audience of this `Object`.",
|
||||
"",
|
||||
"- Range: `Object` | `Link`",
|
||||
"- Functional: false",
|
||||
],
|
||||
types [
|
||||
XsdAnyUri,
|
||||
BaseBox,
|
||||
],
|
||||
},
|
||||
|
||||
bcc {
|
||||
docs [
|
||||
"Identifies one or more `Objects` that are part of the private secondary audience of this",
|
||||
"`Object`.",
|
||||
"",
|
||||
"- Range: `Object` | `Link`",
|
||||
"- Functional: false",
|
||||
],
|
||||
types [
|
||||
XsdAnyUri,
|
||||
BaseBox,
|
||||
],
|
||||
},
|
||||
|
||||
media_type {
|
||||
docs [
|
||||
"When used on an `Object`, identifies the MIME media type of the value of the content",
|
||||
"property.",
|
||||
"",
|
||||
"If not specified, the content property is assumed to contain text/html content.",
|
||||
"",
|
||||
"- Range: `Mime Media Type`",
|
||||
"- Functional: true",
|
||||
],
|
||||
types [
|
||||
MimeMediaType,
|
||||
],
|
||||
functional,
|
||||
},
|
||||
|
||||
duration {
|
||||
docs [
|
||||
"When the object describes a time-bound resource, such as an audio or video, a meeting, etc,",
|
||||
"the duration property indicates the object's approximate duration.",
|
||||
"",
|
||||
"The value MUST be expressed as an xsd:duration as defined by",
|
||||
"[[xmlschema11-2](https://www.w3.org/TR/xmlschema11-2/)], section",
|
||||
"3.3.6 (e.g. a period of 5 seconds is represented as \"PT5S\").",
|
||||
"",
|
||||
"- Range: `xsd:duration`",
|
||||
"- Functional: true",
|
||||
],
|
||||
types [
|
||||
XsdDuration,
|
||||
],
|
||||
functional,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
properties! {
|
||||
Place {
|
||||
docs [ "Define all the properties of the Location type as described by the Activity Streams vocabulary." ],
|
||||
accuracy {
|
||||
docs [
|
||||
"Indicates the accuracy of position coordinates on a `Place` objects.",
|
||||
"",
|
||||
"Expressed in properties of percentage. e.g. \"94.0\"means \"94.0% accurate\".",
|
||||
"",
|
||||
"- Range: `xsd:float` [>= 0.0f, <= 100.0f]",
|
||||
"- Functional: true",
|
||||
],
|
||||
types [
|
||||
XsdFloat,
|
||||
],
|
||||
functional,
|
||||
},
|
||||
|
||||
altitude {
|
||||
docs [
|
||||
"Indicates the altitude of a place. The measurement units is indicated using the units",
|
||||
"property.",
|
||||
"",
|
||||
"If units is not specified, the default is assumed to be \"m\" indicating meters.",
|
||||
"",
|
||||
"- Range: `xsd:float`",
|
||||
"- Functional: true",
|
||||
],
|
||||
types [
|
||||
XsdFloat,
|
||||
],
|
||||
functional,
|
||||
},
|
||||
|
||||
latitude {
|
||||
docs [
|
||||
"The latitude of a place.",
|
||||
"",
|
||||
"- Range: `xsd:float`",
|
||||
"- Functional: true",
|
||||
],
|
||||
types [
|
||||
XsdFloat,
|
||||
],
|
||||
functional,
|
||||
},
|
||||
|
||||
longitude {
|
||||
docs [
|
||||
"The longitude of a place.",
|
||||
"",
|
||||
"- Range: `xsd:float`",
|
||||
"- Functional: true",
|
||||
],
|
||||
types [
|
||||
XsdFloat,
|
||||
],
|
||||
functional,
|
||||
},
|
||||
|
||||
radius {
|
||||
docs [
|
||||
"The radius from the given latitude and longitude for a Place.",
|
||||
"",
|
||||
"The units is expressed by the units property. If units is not specified, the default is",
|
||||
"assumed to be \"m\" indicating meters.",
|
||||
"",
|
||||
"- Range: `xsd:float`",
|
||||
"- Functional: true",
|
||||
],
|
||||
types [
|
||||
XsdFloat,
|
||||
],
|
||||
functional,
|
||||
},
|
||||
|
||||
units {
|
||||
docs [
|
||||
"Specifies the measurement units for the radius and altitude properties on a `Place` object.",
|
||||
"",
|
||||
"If not specified, the default is assumed to be \"m\" for meters.",
|
||||
"",
|
||||
"- Range: `\"cm\"` | `\"feet\"` | `\"inches\"` | `\"km\"` | `\"m\"` | `xsd:anyUri` | `xsd:anyUri`",
|
||||
"- Functional: true",
|
||||
],
|
||||
types [
|
||||
Length,
|
||||
XsdAnyUri,
|
||||
],
|
||||
functional,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
properties! {
|
||||
Profile {
|
||||
docs [ "Define all the properties of the Profile type as described by the Activity Streams vocabulary." ],
|
||||
describes {
|
||||
docs [
|
||||
"On a `Profile` object, the describes property identifies the object described by the",
|
||||
"`Profile`.",
|
||||
"",
|
||||
"- Range: `Object`",
|
||||
"- Functional: true",
|
||||
],
|
||||
types [
|
||||
XsdAnyUri,
|
||||
ObjectBox,
|
||||
],
|
||||
functional,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
properties! {
|
||||
Relationship {
|
||||
docs [
|
||||
"Define all the properties of the Relationship type as described by the Activity Streams",
|
||||
"vocabulary.",
|
||||
],
|
||||
subject {
|
||||
docs [
|
||||
"On a `Relationship` object, the subject property identifies one of the connected",
|
||||
"individuals.",
|
||||
"",
|
||||
"For instance, for a `Relationship` object describing \"John is related to Sally\", subject",
|
||||
"would refer to John.",
|
||||
"",
|
||||
"- Range: `Object` | `Link`",
|
||||
"- Functional: true",
|
||||
],
|
||||
types [
|
||||
XsdAnyUri,
|
||||
BaseBox,
|
||||
],
|
||||
functional,
|
||||
},
|
||||
|
||||
object {
|
||||
docs [
|
||||
"When used within a `Relationship` describes the entity to which the subject is related.",
|
||||
"",
|
||||
"- Range: `Object` | `Link`",
|
||||
"- Functional: false",
|
||||
],
|
||||
types [
|
||||
XsdAnyUri,
|
||||
BaseBox,
|
||||
],
|
||||
},
|
||||
|
||||
relationship {
|
||||
docs [
|
||||
"On a `Relationship` object, the relationship property identifies the kind of relationship",
|
||||
"that exists between subject and object.",
|
||||
"",
|
||||
"- Range: `Object`",
|
||||
"- Functional: false",
|
||||
],
|
||||
types [
|
||||
XsdAnyUri,
|
||||
ObjectBox,
|
||||
],
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
properties! {
|
||||
Tombstone {
|
||||
docs [ "Define all the properties of the Tombstone type as described by the Activity Streams vocabulary." ],
|
||||
former_type {
|
||||
docs [
|
||||
"On a `Tombstone` object, the formerType property identifies the type of the object that was",
|
||||
"deleted.",
|
||||
"",
|
||||
"- Range: `Object`",
|
||||
"- Functional: false",
|
||||
],
|
||||
types [
|
||||
XsdAnyUri,
|
||||
XsdString,
|
||||
ObjectBox,
|
||||
],
|
||||
},
|
||||
|
||||
deleted {
|
||||
docs [
|
||||
"On a `Tombstone` object, the deleted property is a timestamp for when the object was",
|
||||
"deleted.",
|
||||
"",
|
||||
"- Range: `xsd:dateTime`",
|
||||
"- Functional: true",
|
||||
],
|
||||
types [
|
||||
XsdDateTime,
|
||||
],
|
||||
functional,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
properties! {
|
||||
ApObject {
|
||||
docs [
|
||||
"Define activitypub properties for the Object type as described by the Activity Pub vocabulary.",
|
||||
],
|
||||
|
||||
shares {
|
||||
docs [
|
||||
"This is a list of all Announce activities with this object as the object property, added as",
|
||||
"a side effect.",
|
||||
"",
|
||||
"The shares collection MUST be either an OrderedCollection or a Collection and MAY be",
|
||||
"filtered on privileges of an authenticated user or as appropriate when no authentication is",
|
||||
"given.",
|
||||
"",
|
||||
"- Range: `anyUri`",
|
||||
"- Functional: true",
|
||||
],
|
||||
types [ XsdAnyUri ],
|
||||
functional,
|
||||
},
|
||||
|
||||
likes {
|
||||
docs [
|
||||
"This is a list of all Like activities with this object as the object property, added as a",
|
||||
"side effect.",
|
||||
"",
|
||||
"The likes collection MUST be either an OrderedCollection or a Collection and MAY be",
|
||||
"filtered on privileges of an authenticated user or as appropriate when no authentication is",
|
||||
"given.",
|
||||
"",
|
||||
"- Range: `anyUri`",
|
||||
"- Functional: true",
|
||||
],
|
||||
types [ XsdAnyUri ],
|
||||
functional,
|
||||
},
|
||||
|
||||
source {
|
||||
docs [
|
||||
"The source property is intended to convey some sort of source from which the content markup",
|
||||
"was derived, as a form of provenance, or to support future editing by clients.",
|
||||
"",
|
||||
"In general, clients do the conversion from source to content, not the other way around.",
|
||||
"",
|
||||
"The value of source is itself an object which uses its own content and mediaType fields to",
|
||||
"supply source information.",
|
||||
"",
|
||||
"- Range: `Object`",
|
||||
"- Functional: true",
|
||||
],
|
||||
types [
|
||||
XsdAnyUri,
|
||||
ObjectBox,
|
||||
],
|
||||
functional,
|
||||
},
|
||||
|
||||
upload_media {
|
||||
docs [
|
||||
"Servers MAY support uploading document types to be referenced in activites, such as images,",
|
||||
"video or other binary data, but the precise mechanism is out of scope for this version of",
|
||||
"`ActivityPub`.",
|
||||
"",
|
||||
"The Social Web Community Group is refining the protocol in the",
|
||||
"[`ActivityPub` Media Upload report](https://www.w3.org/wiki/SocialCG/ActivityPub/MediaUpload).",
|
||||
"",
|
||||
"- Range: `anyUri`",
|
||||
"- Functional: false",
|
||||
],
|
||||
types [ XsdAnyUri ],
|
||||
},
|
||||
}
|
||||
}
|
|
@ -1,284 +0,0 @@
|
|||
/*
|
||||
* This file is part of ActivityStreams.
|
||||
*
|
||||
* Copyright © 2020 Riley Trautman
|
||||
*
|
||||
* ActivityStreams is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ActivityStreams is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ActivityStreams. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
use crate::{
|
||||
ext::Ext,
|
||||
object::{kind::*, properties::*, Object, ObjectBox},
|
||||
Base, BaseBox, Extensible, PropRefs,
|
||||
};
|
||||
|
||||
/// Represents any kind of multi-paragraph written work.
|
||||
#[derive(Clone, Debug, Default, Extensible, PropRefs, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[prop_refs(Object)]
|
||||
#[extension(ApObjectProperties)]
|
||||
pub struct Article {
|
||||
#[serde(rename = "type")]
|
||||
#[serde(alias = "objectType")]
|
||||
#[serde(alias = "verb")]
|
||||
kind: ArticleType,
|
||||
|
||||
/// Adds all valid object properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub object_props: ObjectProperties,
|
||||
}
|
||||
|
||||
/// Represents an audio document of any kind.
|
||||
#[derive(Clone, Debug, Default, Extensible, PropRefs, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[prop_refs(Object)]
|
||||
#[extension(ApObjectProperties)]
|
||||
pub struct Audio {
|
||||
#[serde(rename = "type")]
|
||||
#[serde(alias = "objectType")]
|
||||
#[serde(alias = "verb")]
|
||||
kind: AudioType,
|
||||
|
||||
/// Adds all valid object properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub object_props: ObjectProperties,
|
||||
}
|
||||
|
||||
/// Represents a document of any kind.
|
||||
#[derive(Clone, Debug, Default, Extensible, PropRefs, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[prop_refs(Object)]
|
||||
#[extension(ApObjectProperties)]
|
||||
pub struct Document {
|
||||
#[serde(rename = "type")]
|
||||
#[serde(alias = "objectType")]
|
||||
#[serde(alias = "verb")]
|
||||
kind: DocumentType,
|
||||
|
||||
/// Adds all valid object properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub object_props: ObjectProperties,
|
||||
}
|
||||
|
||||
/// Represents any kind of event.
|
||||
#[derive(Clone, Debug, Default, Extensible, PropRefs, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[prop_refs(Object)]
|
||||
#[extension(ApObjectProperties)]
|
||||
pub struct Event {
|
||||
#[serde(rename = "type")]
|
||||
#[serde(alias = "objectType")]
|
||||
#[serde(alias = "verb")]
|
||||
kind: EventType,
|
||||
|
||||
/// Adds all valid object properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub object_props: ObjectProperties,
|
||||
}
|
||||
|
||||
/// An image document of any kind
|
||||
#[derive(Clone, Debug, Default, Extensible, PropRefs, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[prop_refs(Object)]
|
||||
#[extension(ApObjectProperties)]
|
||||
pub struct Image {
|
||||
#[serde(rename = "type")]
|
||||
#[serde(alias = "objectType")]
|
||||
#[serde(alias = "verb")]
|
||||
kind: ImageType,
|
||||
|
||||
/// Adds all valid object properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub object_props: ObjectProperties,
|
||||
}
|
||||
|
||||
/// Represents a short written work typically less than a single paragraph in length.
|
||||
#[derive(Clone, Debug, Default, Extensible, PropRefs, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[prop_refs(Object)]
|
||||
#[extension(ApObjectProperties)]
|
||||
pub struct Note {
|
||||
#[serde(rename = "type")]
|
||||
#[serde(alias = "objectType")]
|
||||
#[serde(alias = "verb")]
|
||||
kind: NoteType,
|
||||
|
||||
/// Adds all valid object properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub object_props: ObjectProperties,
|
||||
}
|
||||
|
||||
/// Represents a Web Page.
|
||||
#[derive(Clone, Debug, Default, Extensible, PropRefs, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[prop_refs(Object)]
|
||||
#[extension(ApObjectProperties)]
|
||||
pub struct Page {
|
||||
#[serde(rename = "type")]
|
||||
#[serde(alias = "objectType")]
|
||||
#[serde(alias = "verb")]
|
||||
kind: PageType,
|
||||
|
||||
/// Adds all valid object properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub object_props: ObjectProperties,
|
||||
}
|
||||
|
||||
/// Represents a logical or physical location.
|
||||
///
|
||||
/// The Place object is used to represent both physical and logical locations. While numerous
|
||||
/// existing vocabularies exist for describing locations in a variety of ways, inconsistencies and
|
||||
/// incompatibilities between those vocabularies make it difficult to achieve appropriate
|
||||
/// interoperability between implementations. The Place object is included within the Activity
|
||||
/// vocabulary to provide a minimal, interoperable starting point for describing locations
|
||||
/// consistently across Activity Streams 2.0 implementations.
|
||||
///
|
||||
/// The Place object is intentionally flexible. It can, for instance, be used to identify a location
|
||||
/// simply by name, or by longitude and latitude.
|
||||
///
|
||||
/// The Place object can also describe an area around a given point using the radius property, the
|
||||
/// altitude of the location, and a degree of accuracy.
|
||||
///
|
||||
/// While publishers are not required to use these specific properties and MAY make use of other
|
||||
/// mechanisms for describing locations, consuming implementations that support the Place object
|
||||
/// MUST support the use of these properties.
|
||||
#[derive(Clone, Debug, Default, Extensible, PropRefs, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[prop_refs(Object)]
|
||||
#[extension(ApObjectProperties)]
|
||||
pub struct Place {
|
||||
#[serde(rename = "type")]
|
||||
#[serde(alias = "objectType")]
|
||||
#[serde(alias = "verb")]
|
||||
kind: PlaceType,
|
||||
|
||||
/// Adds all valid object properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub object_props: ObjectProperties,
|
||||
|
||||
/// Adds all valid place properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub place: PlaceProperties,
|
||||
}
|
||||
|
||||
/// A Profile is a content object that describes another `Object`, typically used to describe
|
||||
/// `Actor` Type objects.
|
||||
///
|
||||
/// The `describes` property is used to reference the object being described by the profile.
|
||||
#[derive(Clone, Debug, Default, Extensible, PropRefs, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[prop_refs(Object)]
|
||||
#[extension(ApObjectProperties)]
|
||||
pub struct Profile {
|
||||
#[serde(rename = "type")]
|
||||
#[serde(alias = "objectType")]
|
||||
#[serde(alias = "verb")]
|
||||
kind: ProfileType,
|
||||
|
||||
/// Adds all valid object properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub object_props: ObjectProperties,
|
||||
|
||||
/// Adds all valid profile properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub profile: ProfileProperties,
|
||||
}
|
||||
|
||||
/// Describes a relationship between two individuals.
|
||||
///
|
||||
/// The subject and object properties are used to identify the connected individuals.
|
||||
///
|
||||
/// The `Relationship` object is used to represent relationships between individuals. It can be
|
||||
/// used, for instance, to describe that one person is a friend of another, or that one person is a
|
||||
/// member of a particular organization. The intent of modeling Relationship in this way is to allow
|
||||
/// descriptions of activities that operate on the relationships in general, and to allow
|
||||
/// representation of Collections of relationships.
|
||||
///
|
||||
/// For instance, many social systems have a notion of a "friends list". These are the collection of
|
||||
/// individuals that are directly connected within a person's social graph. Suppose we have a user,
|
||||
/// Sally, with direct relationships to users Joe and Jane. Sally follows Joe's updates while Sally
|
||||
/// and Jane have a mutual relationship.
|
||||
#[derive(Clone, Debug, Default, Extensible, PropRefs, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[prop_refs(Object)]
|
||||
#[extension(ApObjectProperties)]
|
||||
pub struct Relationship {
|
||||
#[serde(rename = "type")]
|
||||
#[serde(alias = "objectType")]
|
||||
#[serde(alias = "verb")]
|
||||
kind: RelationshipType,
|
||||
|
||||
/// Adds all valid object properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub object_props: ObjectProperties,
|
||||
|
||||
/// Adds all valid relationship properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub relationship: RelationshipProperties,
|
||||
}
|
||||
|
||||
/// A Tombstone represents a content object that has been deleted.
|
||||
///
|
||||
/// It can be used in Collections to signify that there used to be an object at this position, but
|
||||
/// it has been deleted.
|
||||
#[derive(Clone, Debug, Default, Extensible, PropRefs, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[prop_refs(Object)]
|
||||
#[extension(ApObjectProperties)]
|
||||
pub struct Tombstone {
|
||||
#[serde(rename = "type")]
|
||||
#[serde(alias = "objectType")]
|
||||
#[serde(alias = "verb")]
|
||||
kind: TombstoneType,
|
||||
|
||||
/// Adds all valid object properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub object_props: ObjectProperties,
|
||||
|
||||
/// Adds all valid tombstone properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub tombstone_props: TombstoneProperties,
|
||||
}
|
||||
|
||||
/// Represents a video document of any kind.
|
||||
#[derive(Clone, Debug, Default, Extensible, PropRefs, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[prop_refs(Object)]
|
||||
#[extension(ApObjectProperties)]
|
||||
pub struct Video {
|
||||
#[serde(rename = "type")]
|
||||
#[serde(alias = "objectType")]
|
||||
#[serde(alias = "verb")]
|
||||
kind: VideoType,
|
||||
|
||||
/// Adds all valid object properties to this struct
|
||||
#[serde(flatten)]
|
||||
#[prop_refs]
|
||||
pub object_props: ObjectProperties,
|
||||
}
|
345
src/primitives/any_string.rs
Normal file
345
src/primitives/any_string.rs
Normal file
|
@ -0,0 +1,345 @@
|
|||
use crate::{
|
||||
either::Either,
|
||||
primitives::{OneOrMany, RdfLangString},
|
||||
};
|
||||
|
||||
/// A type representing any kind of string
|
||||
///
|
||||
/// In the ActivityStreams specification, string types are often defined as either an xsd:String or
|
||||
/// and rdf:langString. The AnyString type represents this union.
|
||||
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(transparent)]
|
||||
pub struct AnyString(Either<String, RdfLangString>);
|
||||
|
||||
impl AnyString {
|
||||
/// Borrow the AnyString as an &str
|
||||
///
|
||||
/// ```rust
|
||||
/// # fn main() -> Result<(), anyhow::Error> {
|
||||
/// # use activitystreams::primitives::AnyString;
|
||||
/// # let any_string = AnyString::from_xsd_string("hi");
|
||||
/// #
|
||||
/// let s_borrow = any_string
|
||||
/// .as_xsd_string()
|
||||
/// .ok_or(anyhow::Error::msg("Wrong string type"))?;
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn as_xsd_string(&self) -> Option<&str> {
|
||||
self.0.as_ref().left().map(|l| l.as_str())
|
||||
}
|
||||
|
||||
/// Borrow the AnyString as an RdfLangString
|
||||
///
|
||||
/// ```rust
|
||||
/// # fn main() -> Result<(), anyhow::Error> {
|
||||
/// # use activitystreams::primitives::{AnyString, RdfLangString};
|
||||
/// # let any_string = AnyString::from_rdf_lang_string(RdfLangString {
|
||||
/// # value: "hi".into(),
|
||||
/// # language: "en".into(),
|
||||
/// # });
|
||||
/// #
|
||||
/// let s_borrow = any_string
|
||||
/// .as_rdf_lang_string()
|
||||
/// .ok_or(anyhow::Error::msg("Wrong string type"))?;
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn as_rdf_lang_string(&self) -> Option<&RdfLangString> {
|
||||
self.0.as_ref().right()
|
||||
}
|
||||
|
||||
/// Take the AnyString as a String
|
||||
///
|
||||
/// ```rust
|
||||
/// # fn main() -> Result<(), anyhow::Error> {
|
||||
/// # use activitystreams::primitives::AnyString;
|
||||
/// # let any_string = AnyString::from_xsd_string("hi");
|
||||
/// #
|
||||
/// let xsd_string = any_string
|
||||
/// .xsd_string()
|
||||
/// .ok_or(anyhow::Error::msg("Wrong string type"))?;
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn xsd_string(self) -> Option<String> {
|
||||
self.0.left()
|
||||
}
|
||||
|
||||
/// Take the AnyString as an RdfLangString
|
||||
///
|
||||
/// ```rust
|
||||
/// # fn main() -> Result<(), anyhow::Error> {
|
||||
/// # use activitystreams::primitives::{AnyString, RdfLangString};
|
||||
/// # let any_string = AnyString::from_rdf_lang_string(RdfLangString {
|
||||
/// # value: "hi".into(),
|
||||
/// # language: "en".into(),
|
||||
/// # });
|
||||
/// #
|
||||
/// let rdf_lang_string = any_string
|
||||
/// .rdf_lang_string()
|
||||
/// .ok_or(anyhow::Error::msg("Wrong string type"))?;
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn rdf_lang_string(self) -> Option<RdfLangString> {
|
||||
self.0.right()
|
||||
}
|
||||
|
||||
/// Create a new AnyString from an `Into<String>`
|
||||
///
|
||||
/// ```rust
|
||||
/// use activitystreams::primitives::AnyString;
|
||||
///
|
||||
/// let any_string = AnyString::from_xsd_string("hi");
|
||||
/// ```
|
||||
pub fn from_xsd_string<T>(string: T) -> Self
|
||||
where
|
||||
T: Into<String>,
|
||||
{
|
||||
AnyString(Either::Left(string.into()))
|
||||
}
|
||||
|
||||
/// Create a new AnyString from an RdfLangString
|
||||
///
|
||||
/// ```rust
|
||||
/// use activitystreams::primitives::{AnyString, RdfLangString};
|
||||
///
|
||||
/// let any_string = AnyString::from_rdf_lang_string(RdfLangString {
|
||||
/// value: "hi".into(),
|
||||
/// language: "en".into(),
|
||||
/// });
|
||||
/// ```
|
||||
pub fn from_rdf_lang_string<T>(string: T) -> Self
|
||||
where
|
||||
T: Into<RdfLangString>,
|
||||
{
|
||||
AnyString(Either::Right(string.into()))
|
||||
}
|
||||
|
||||
/// Replace the contents of self with a String
|
||||
///
|
||||
/// ```rust
|
||||
/// use activitystreams::primitives::{AnyString, RdfLangString};
|
||||
///
|
||||
/// let mut any_string = AnyString::from_rdf_lang_string(RdfLangString {
|
||||
/// value: "hi".into(),
|
||||
/// language: "en".into(),
|
||||
/// });
|
||||
///
|
||||
/// any_string.set_xsd_string("hi");
|
||||
///
|
||||
/// assert!(any_string.as_xsd_string().is_some());
|
||||
/// ```
|
||||
pub fn set_xsd_string<T>(&mut self, string: T)
|
||||
where
|
||||
T: Into<String>,
|
||||
{
|
||||
self.0 = Either::Left(string.into());
|
||||
}
|
||||
|
||||
/// Replace the contents of self with an RdfLangString
|
||||
///
|
||||
/// ```rust
|
||||
/// use activitystreams::primitives::{AnyString, RdfLangString};
|
||||
///
|
||||
/// let mut any_string = AnyString::from_xsd_string("hi");
|
||||
///
|
||||
/// any_string.set_rdf_lang_string(RdfLangString {
|
||||
/// value: "hi".into(),
|
||||
/// language: "en".into(),
|
||||
/// });
|
||||
///
|
||||
/// assert!(any_string.as_rdf_lang_string().is_some());
|
||||
/// ```
|
||||
pub fn set_rdf_lang_string<T>(&mut self, string: T)
|
||||
where
|
||||
T: Into<RdfLangString>,
|
||||
{
|
||||
self.0 = Either::Right(string.into());
|
||||
}
|
||||
}
|
||||
|
||||
impl OneOrMany<AnyString> {
|
||||
/// Try to borrow a single String from the current object
|
||||
///
|
||||
/// ```rust
|
||||
/// # fn main() -> Result<(), anyhow::Error> {
|
||||
/// # use activitystreams::primitives::{OneOrMany, AnyString};
|
||||
/// # let string = OneOrMany::<AnyString>::from_xsd_string("Hey");
|
||||
/// string
|
||||
/// .as_single_xsd_string()
|
||||
/// .ok_or(anyhow::Error::msg("Wrong string type"))?;
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn as_single_xsd_string(&self) -> Option<&str> {
|
||||
self.as_one()
|
||||
.and_then(|any_string| any_string.as_xsd_string())
|
||||
}
|
||||
|
||||
/// Try to borrow a single RdfLangString from the current object
|
||||
///
|
||||
/// ```rust
|
||||
/// # fn main() -> Result<(), anyhow::Error> {
|
||||
/// # use activitystreams::primitives::{OneOrMany, RdfLangString};
|
||||
/// # let string = OneOrMany::from_rdf_lang_string(RdfLangString {
|
||||
/// # value: "hi".into(),
|
||||
/// # language: "en".into(),
|
||||
/// # });
|
||||
/// string
|
||||
/// .as_single_rdf_lang_string()
|
||||
/// .ok_or(anyhow::Error::msg("Wrong string type"))?;
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn as_single_rdf_lang_string(&self) -> Option<&RdfLangString> {
|
||||
self.as_one()
|
||||
.and_then(|any_string| any_string.as_rdf_lang_string())
|
||||
}
|
||||
|
||||
/// Try to take a single String from the current object
|
||||
///
|
||||
/// ```rust
|
||||
/// # fn main() -> Result<(), anyhow::Error> {
|
||||
/// # use activitystreams::primitives::{OneOrMany, AnyString};
|
||||
/// # let string = OneOrMany::<AnyString>::from_xsd_string("Hey");
|
||||
/// string
|
||||
/// .single_xsd_string()
|
||||
/// .ok_or(anyhow::Error::msg("Wrong string type"))?;
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn single_xsd_string(self) -> Option<String> {
|
||||
self.one().and_then(|any_string| any_string.xsd_string())
|
||||
}
|
||||
|
||||
/// Try to take a single RdfLangString from the current object
|
||||
///
|
||||
/// ```rust
|
||||
/// # fn main() -> Result<(), anyhow::Error> {
|
||||
/// # use activitystreams::primitives::{OneOrMany, RdfLangString};
|
||||
/// # let string = OneOrMany::from_rdf_lang_string(RdfLangString {
|
||||
/// # value: "hi".into(),
|
||||
/// # language: "en".into(),
|
||||
/// # });
|
||||
/// string
|
||||
/// .single_rdf_lang_string()
|
||||
/// .ok_or(anyhow::Error::msg("Wrong string type"))?;
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn single_rdf_lang_string(self) -> Option<RdfLangString> {
|
||||
self.one()
|
||||
.and_then(|any_string| any_string.rdf_lang_string())
|
||||
}
|
||||
|
||||
/// Create the object from a single String
|
||||
///
|
||||
/// ```rust
|
||||
/// use activitystreams::primitives::{OneOrMany, AnyString};
|
||||
///
|
||||
/// let string = OneOrMany::<AnyString>::from_xsd_string("hi");
|
||||
/// ```
|
||||
pub fn from_xsd_string<T>(string: T) -> Self
|
||||
where
|
||||
T: Into<String>,
|
||||
{
|
||||
Self::from_one(AnyString::from_xsd_string(string))
|
||||
}
|
||||
|
||||
/// Create the object from a single RdfLangString
|
||||
///
|
||||
/// ```rust
|
||||
/// use activitystreams::primitives::{OneOrMany, RdfLangString};
|
||||
///
|
||||
/// let string = OneOrMany::from_rdf_lang_string(RdfLangString {
|
||||
/// value: "hi".into(),
|
||||
/// language: "en".into(),
|
||||
/// });
|
||||
/// ```
|
||||
pub fn from_rdf_lang_string<T>(string: T) -> Self
|
||||
where
|
||||
T: Into<RdfLangString>,
|
||||
{
|
||||
Self::from_one(AnyString::from_rdf_lang_string(string))
|
||||
}
|
||||
|
||||
/// Add a String to the object, appending to whatever is currently included
|
||||
///
|
||||
/// ```rust
|
||||
/// use activitystreams::primitives::{OneOrMany, AnyString};
|
||||
///
|
||||
/// let mut string = OneOrMany::<AnyString>::from_xsd_string("Hello");
|
||||
///
|
||||
/// string
|
||||
/// .add_xsd_string("Hey")
|
||||
/// .add_xsd_string("hi");
|
||||
/// ```
|
||||
pub fn add_xsd_string<T>(&mut self, string: T) -> &mut Self
|
||||
where
|
||||
T: Into<String>,
|
||||
{
|
||||
self.add(string.into())
|
||||
}
|
||||
|
||||
/// Add an RdfLangString to the object, appending to whatever is currently included
|
||||
///
|
||||
/// ```rust
|
||||
/// use activitystreams::primitives::{AnyString, OneOrMany, RdfLangString};
|
||||
///
|
||||
/// let mut string = OneOrMany::<AnyString>::from_xsd_string("Hello");
|
||||
///
|
||||
/// string
|
||||
/// .add_rdf_lang_string(RdfLangString {
|
||||
/// value: "Hey".into(),
|
||||
/// language: "en".into(),
|
||||
/// })
|
||||
/// .add_rdf_lang_string(RdfLangString {
|
||||
/// value: "hi".into(),
|
||||
/// language: "en".into(),
|
||||
/// });
|
||||
/// ```
|
||||
pub fn add_rdf_lang_string<T>(&mut self, string: T) -> &mut Self
|
||||
where
|
||||
T: Into<RdfLangString>,
|
||||
{
|
||||
self.add(string.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&str> for AnyString {
|
||||
fn from(s: &str) -> Self {
|
||||
AnyString::from_xsd_string(s.to_owned())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<String> for AnyString {
|
||||
fn from(s: String) -> Self {
|
||||
AnyString::from_xsd_string(s)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<RdfLangString> for AnyString {
|
||||
fn from(s: RdfLangString) -> Self {
|
||||
AnyString::from_rdf_lang_string(s)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&str> for OneOrMany<AnyString> {
|
||||
fn from(s: &str) -> Self {
|
||||
OneOrMany::<AnyString>::from_xsd_string(s.to_owned())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<String> for OneOrMany<AnyString> {
|
||||
fn from(s: String) -> Self {
|
||||
OneOrMany::<AnyString>::from_xsd_string(s)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<RdfLangString> for OneOrMany<AnyString> {
|
||||
fn from(s: RdfLangString) -> Self {
|
||||
OneOrMany::<AnyString>::from_rdf_lang_string(s)
|
||||
}
|
||||
}
|
|
@ -1,139 +0,0 @@
|
|||
/*
|
||||
* This file is part of ActivityStreams.
|
||||
*
|
||||
* Copyright © 2020 Riley Trautman
|
||||
*
|
||||
* ActivityStreams is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ActivityStreams is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ActivityStreams. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/// A list of units of length that represent valid units for certain ActivityStreams objects
|
||||
#[derive(
|
||||
Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, serde::Deserialize, serde::Serialize,
|
||||
)]
|
||||
#[serde(untagged)]
|
||||
pub enum Length {
|
||||
#[serde(rename = "cm")]
|
||||
Centimeters,
|
||||
|
||||
#[serde(rename = "feet")]
|
||||
Feet,
|
||||
|
||||
#[serde(rename = "inches")]
|
||||
Inches,
|
||||
|
||||
#[serde(rename = "km")]
|
||||
Kilometers,
|
||||
|
||||
#[serde(rename = "m")]
|
||||
Meters,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, thiserror::Error)]
|
||||
#[error("Could not parse units")]
|
||||
/// The error type produced when a Length cannot be parsed
|
||||
pub struct LengthError;
|
||||
|
||||
impl Length {
|
||||
pub fn is_centimeters(&self) -> bool {
|
||||
match self {
|
||||
Length::Centimeters => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_feet(&self) -> bool {
|
||||
match self {
|
||||
Length::Feet => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_inches(&self) -> bool {
|
||||
match self {
|
||||
Length::Inches => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_kilometers(&self) -> bool {
|
||||
match self {
|
||||
Length::Kilometers => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_meters(&self) -> bool {
|
||||
match self {
|
||||
Length::Meters => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Length {
|
||||
fn default() -> Self {
|
||||
Length::Meters
|
||||
}
|
||||
}
|
||||
|
||||
impl std::str::FromStr for Length {
|
||||
type Err = LengthError;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
match s {
|
||||
"cm" => Ok(Length::Centimeters),
|
||||
"feet" => Ok(Length::Feet),
|
||||
"inches" => Ok(Length::Inches),
|
||||
"km" => Ok(Length::Kilometers),
|
||||
"m" => Ok(Length::Meters),
|
||||
_ => Err(LengthError),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::convert::TryFrom<&str> for Length {
|
||||
type Error = LengthError;
|
||||
|
||||
fn try_from(s: &str) -> Result<Self, Self::Error> {
|
||||
s.parse()
|
||||
}
|
||||
}
|
||||
|
||||
impl std::convert::TryFrom<&mut str> for Length {
|
||||
type Error = LengthError;
|
||||
|
||||
fn try_from(s: &mut str) -> Result<Self, Self::Error> {
|
||||
s.parse()
|
||||
}
|
||||
}
|
||||
|
||||
impl std::convert::TryFrom<String> for Length {
|
||||
type Error = LengthError;
|
||||
|
||||
fn try_from(s: String) -> Result<Self, Self::Error> {
|
||||
s.parse()
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for Length {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
match self {
|
||||
Length::Centimeters => write!(f, "cm"),
|
||||
Length::Feet => write!(f, "feet"),
|
||||
Length::Inches => write!(f, "inches"),
|
||||
Length::Kilometers => write!(f, "km"),
|
||||
Length::Meters => write!(f, "meters"),
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,114 +0,0 @@
|
|||
/*
|
||||
* This file is part of ActivityStreams.
|
||||
*
|
||||
* Copyright © 2020 Riley Trautman
|
||||
*
|
||||
* ActivityStreams is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ActivityStreams is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ActivityStreams. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/// A MIME Media Type consists of a top-level type and a subtype, which is further structured into
|
||||
/// trees.
|
||||
///
|
||||
/// Optionally, media types can define companion data, known as parameters.
|
||||
///
|
||||
/// See [`RFC 2045`](https://tools.ietf.org/html/rfc2045) and
|
||||
/// [`RFC 2046`](https://tools.ietf.org/html/rfc2046) for more information.
|
||||
#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
|
||||
pub struct MimeMediaType(mime::Mime);
|
||||
|
||||
#[derive(Clone, Debug, thiserror::Error)]
|
||||
#[error("Error parsing MIME")]
|
||||
/// The error type produced when a MimeMediaType cannot be parsed
|
||||
pub struct MimeMediaTypeError;
|
||||
|
||||
impl<'a> PartialEq<&'a str> for MimeMediaType {
|
||||
fn eq(&self, rhs: &&'a str) -> bool {
|
||||
self.0.eq(rhs)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<mime::Mime> for MimeMediaType {
|
||||
fn from(m: mime::Mime) -> Self {
|
||||
MimeMediaType(m)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<MimeMediaType> for mime::Mime {
|
||||
fn from(m: MimeMediaType) -> Self {
|
||||
m.0
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<mime::Mime> for MimeMediaType {
|
||||
fn as_ref(&self) -> &mime::Mime {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl AsMut<mime::Mime> for MimeMediaType {
|
||||
fn as_mut(&mut self) -> &mut mime::Mime {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl std::convert::TryFrom<String> for MimeMediaType {
|
||||
type Error = MimeMediaTypeError;
|
||||
|
||||
fn try_from(s: String) -> Result<Self, Self::Error> {
|
||||
s.parse()
|
||||
}
|
||||
}
|
||||
|
||||
impl std::convert::TryFrom<&str> for MimeMediaType {
|
||||
type Error = MimeMediaTypeError;
|
||||
|
||||
fn try_from(s: &str) -> Result<Self, Self::Error> {
|
||||
s.parse()
|
||||
}
|
||||
}
|
||||
|
||||
impl std::convert::TryFrom<&mut str> for MimeMediaType {
|
||||
type Error = MimeMediaTypeError;
|
||||
|
||||
fn try_from(s: &mut str) -> Result<Self, Self::Error> {
|
||||
s.parse()
|
||||
}
|
||||
}
|
||||
|
||||
impl std::str::FromStr for MimeMediaType {
|
||||
type Err = MimeMediaTypeError;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
Ok(MimeMediaType(s.parse().map_err(|_| MimeMediaTypeError)?))
|
||||
}
|
||||
}
|
||||
|
||||
impl serde::ser::Serialize for MimeMediaType {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: serde::ser::Serializer,
|
||||
{
|
||||
serializer.serialize_str(&self.0.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> serde::de::Deserialize<'de> for MimeMediaType {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: serde::de::Deserializer<'de>,
|
||||
{
|
||||
let s = String::deserialize(deserializer)?;
|
||||
s.parse().map_err(serde::de::Error::custom)
|
||||
}
|
||||
}
|
|
@ -1,78 +1,36 @@
|
|||
/*
|
||||
* This file is part of ActivityStreams.
|
||||
*
|
||||
* Copyright © 2020 Riley Trautman
|
||||
*
|
||||
* ActivityStreams is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ActivityStreams is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ActivityStreams. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//! Types defined as 'primitives' are used as building-blocks for ActivityStreams objects.
|
||||
//! Types creating the base for most ActivityStreams fields.
|
||||
//!
|
||||
//! For example, an `Object` may have a `summary` field, which is defined as a range of
|
||||
//! `xsd:string` and `rdf:langString`. As code, this is represented as an enum that either
|
||||
//! contains an `XsdString` or an `RdfLangString`.
|
||||
//! These types are not themselves defined by ActivityStreams, but are referenced by the
|
||||
//! specification.
|
||||
//!
|
||||
//! ```rust
|
||||
//! use activitystreams::primitives::{RdfLangString, XsdString};
|
||||
//! use activitystreams::primitives::{AnyString, OneOrMany, Unit};
|
||||
//!
|
||||
//! /// Define a terminating enum for the Summary field in Object Properties
|
||||
//! ///
|
||||
//! /// In this case, terminating means it does not contain child elements.
|
||||
//! pub enum ObjectPropertiesSummaryTermEnum {
|
||||
//! XsdString(XsdString),
|
||||
//! RdfLangString(RdfLangString),
|
||||
//! }
|
||||
//! let any_string = AnyString::from_xsd_string("hey");
|
||||
//!
|
||||
//! /// Since summary isn't functional, we can either have a single string, or multiple strings.
|
||||
//! pub enum ObjectPropertiesSummaryEnum {
|
||||
//! Term(ObjectPropertiesSummaryTermEnum),
|
||||
//! Array(Vec<ObjectPropertiesSummaryTermEnum>),
|
||||
//! }
|
||||
//! let one_or_many = OneOrMany::<i32>::from_one(1234);
|
||||
//!
|
||||
//! /// Define an excerpt from the ObjectProperties struct
|
||||
//! pub struct ObjectProperties {
|
||||
//! // ...
|
||||
//!
|
||||
//! /// Since summary isn't a required field, it's stored as an option
|
||||
//! summary: Option<ObjectPropertiesSummaryEnum>,
|
||||
//!
|
||||
//! // ...
|
||||
//! }
|
||||
//! #
|
||||
//! # fn main() {}
|
||||
//! let cm = Unit::centimeters();
|
||||
//! ```
|
||||
|
||||
mod length;
|
||||
mod mime_media_type;
|
||||
mod any_string;
|
||||
mod one_or_many;
|
||||
mod rdf_lang_string;
|
||||
mod xsd_any_uri;
|
||||
mod serde_parse;
|
||||
mod unit;
|
||||
mod xsd_datetime;
|
||||
mod xsd_duration;
|
||||
mod xsd_float;
|
||||
mod xsd_non_negative_float;
|
||||
mod xsd_non_negative_integer;
|
||||
mod xsd_string;
|
||||
|
||||
pub use self::{
|
||||
length::Length,
|
||||
mime_media_type::{MimeMediaType, MimeMediaTypeError},
|
||||
any_string::AnyString,
|
||||
one_or_many::OneOrMany,
|
||||
rdf_lang_string::RdfLangString,
|
||||
xsd_any_uri::{XsdAnyUri, XsdAnyUriError},
|
||||
xsd_datetime::{XsdDateTime, XsdDateTimeError},
|
||||
unit::Unit,
|
||||
xsd_datetime::XsdDateTime,
|
||||
xsd_duration::{XsdDuration, XsdDurationError},
|
||||
xsd_float::{XsdFloat, XsdFloatError},
|
||||
xsd_non_negative_float::{XsdNonNegativeFloat, XsdNonNegativeFloatError},
|
||||
xsd_non_negative_integer::{XsdNonNegativeInteger, XsdNonNegativeIntegerError},
|
||||
xsd_string::XsdString,
|
||||
};
|
||||
|
||||
use self::serde_parse::SerdeParse;
|
||||
|
||||
/// An alias for the mime::Mime struct with serde compatibility
|
||||
pub(crate) type MimeMediaType = SerdeParse<mime::Mime>;
|
||||
|
|
292
src/primitives/one_or_many.rs
Normal file
292
src/primitives/one_or_many.rs
Normal file
|
@ -0,0 +1,292 @@
|
|||
use crate::either::Either;
|
||||
|
||||
/// A type representing at least one value
|
||||
///
|
||||
/// When translated to JSON, it can represent the following structures:
|
||||
/// ```json
|
||||
/// {
|
||||
/// "key": value
|
||||
/// }
|
||||
/// ```
|
||||
/// ```json
|
||||
/// {
|
||||
/// "key": [],
|
||||
/// }
|
||||
/// ```
|
||||
/// ```json
|
||||
/// {
|
||||
/// "key": [value, ...]
|
||||
/// }
|
||||
/// ```
|
||||
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(transparent)]
|
||||
pub struct OneOrMany<T>(pub(crate) Either<T, Vec<T>>);
|
||||
|
||||
impl<T> OneOrMany<T> {
|
||||
/// Create a OneOrMany referencing the existing one
|
||||
///
|
||||
/// ```rust
|
||||
/// use activitystreams::primitives::OneOrMany;
|
||||
///
|
||||
/// let value = OneOrMany::from_one(String::from("hi"));
|
||||
/// let value_ref = value.as_ref();
|
||||
///
|
||||
/// assert_eq!(value_ref.one(), Some(&String::from("hi")));
|
||||
/// ```
|
||||
pub fn as_ref(&self) -> OneOrMany<&T> {
|
||||
OneOrMany(self.0.as_ref().map(|l| l, |r| r.iter().collect()))
|
||||
}
|
||||
|
||||
/// Map the value inside the OneOrMany from T to U
|
||||
///
|
||||
/// ```rust
|
||||
/// use activitystreams::primitives::OneOrMany;
|
||||
///
|
||||
/// let value = OneOrMany::from_one("Jake from StateFarm");
|
||||
/// let new_value = value.map(|s| format!("Hi, {}", s));
|
||||
///
|
||||
/// assert_eq!(new_value.one(), Some(String::from("Hi, Jake from StateFarm")));
|
||||
/// ```
|
||||
pub fn map<F, U>(self, f: F) -> OneOrMany<U>
|
||||
where
|
||||
F: Fn(T) -> U + Copy,
|
||||
{
|
||||
OneOrMany(self.0.map(f, |v| v.into_iter().map(f).collect()))
|
||||
}
|
||||
|
||||
/// Create a OneOrMany mutably referencing the existing one
|
||||
///
|
||||
/// ```rust
|
||||
/// use activitystreams::primitives::OneOrMany;
|
||||
///
|
||||
/// let mut value = OneOrMany::from_one(5);
|
||||
/// let value_mut = value.as_mut();
|
||||
/// ```
|
||||
pub fn as_mut(&mut self) -> OneOrMany<&mut T> {
|
||||
OneOrMany(self.0.as_mut().map(|l| l, |r| r.iter_mut().collect()))
|
||||
}
|
||||
|
||||
/// Get a reference to a single value
|
||||
///
|
||||
/// ```rust
|
||||
/// # use activitystreams::primitives::OneOrMany;
|
||||
/// # let value = OneOrMany::from_one(1);
|
||||
/// if let Some(v) = value.as_one() {
|
||||
/// println!("{:?}", v);
|
||||
/// }
|
||||
/// ```
|
||||
pub fn as_one(&self) -> Option<&T> {
|
||||
self.0.as_ref().left()
|
||||
}
|
||||
|
||||
/// Borrow one as mutable
|
||||
///
|
||||
/// ```rust
|
||||
/// use activitystreams::primitives::OneOrMany;
|
||||
///
|
||||
/// let mut value = OneOrMany::from_one(1);
|
||||
///
|
||||
/// if let Some(i) = value.one_mut() {
|
||||
/// *i += 1;
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(value.one(), Some(2));
|
||||
/// ```
|
||||
pub fn one_mut(&mut self) -> Option<&mut T> {
|
||||
self.0.as_mut().left()
|
||||
}
|
||||
|
||||
/// Take a single value
|
||||
///
|
||||
/// ```rust
|
||||
/// # use activitystreams::primitives::OneOrMany;
|
||||
/// # let value = OneOrMany::from_one(1);
|
||||
/// if let Some(v) = value.one() {
|
||||
/// println!("{:?}", v);
|
||||
/// }
|
||||
/// ```
|
||||
pub fn one(self) -> Option<T> {
|
||||
self.0.left()
|
||||
}
|
||||
|
||||
/// Get a slice of values
|
||||
///
|
||||
/// ```rust
|
||||
/// # use activitystreams::primitives::OneOrMany;
|
||||
/// # let value = OneOrMany::from_many(vec![1, 2, 3]);
|
||||
/// if let Some(v) = value.as_many() {
|
||||
/// for item in v.iter() {
|
||||
/// println!("{:?}", item);
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
pub fn as_many(&self) -> Option<&[T]> {
|
||||
self.0.as_ref().right().map(|v| v.as_ref())
|
||||
}
|
||||
|
||||
/// Borrow many as mutable
|
||||
///
|
||||
/// ```rust
|
||||
/// use activitystreams::primitives::OneOrMany;
|
||||
///
|
||||
/// let mut value = OneOrMany::from_many(vec![1, 2, 3]);
|
||||
///
|
||||
/// if let Some(v) = value.many_mut() {
|
||||
/// for i in v.iter_mut() {
|
||||
/// *i += 3;
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(value.many(), Some(vec![4, 5, 6]));
|
||||
/// ```
|
||||
pub fn many_mut(&mut self) -> Option<&mut [T]> {
|
||||
self.0.as_mut().right().map(|v| v.as_mut())
|
||||
}
|
||||
|
||||
/// Take a Vec of values
|
||||
///
|
||||
/// ```rust
|
||||
/// # use activitystreams::primitives::OneOrMany;
|
||||
/// # let value = OneOrMany::from_many(vec![1, 2, 3]);
|
||||
/// if let Some(v) = value.many() {
|
||||
/// for item in v.into_iter() {
|
||||
/// println!("{:?}", item);
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
pub fn many(self) -> Option<Vec<T>> {
|
||||
self.0.right()
|
||||
}
|
||||
|
||||
/// Consume the type, returning a vec
|
||||
///
|
||||
/// ```rust
|
||||
/// # use activitystreams::primitives::OneOrMany;
|
||||
/// # let value = OneOrMany::from_many(vec![1, 2, 3]);
|
||||
/// for item in value.unwrap_to_vec() {
|
||||
/// println!("{:?}", item);
|
||||
/// }
|
||||
/// ```
|
||||
pub fn unwrap_to_vec(self) -> Vec<T> {
|
||||
match self.0 {
|
||||
Either::Left(t) => vec![t],
|
||||
Either::Right(v) => v,
|
||||
}
|
||||
}
|
||||
|
||||
/// Produce a new object from one value
|
||||
///
|
||||
/// ```
|
||||
/// use activitystreams::primitives::OneOrMany;
|
||||
/// let v = OneOrMany::from_one(1234);
|
||||
/// ```
|
||||
pub fn from_one(t: T) -> Self {
|
||||
OneOrMany(Either::Left(t))
|
||||
}
|
||||
|
||||
/// Produce a new object from a vec of values
|
||||
///
|
||||
/// ```
|
||||
/// use activitystreams::primitives::OneOrMany;
|
||||
/// let v = OneOrMany::from_many(vec![1, 2, 3, 4]);
|
||||
/// ```
|
||||
pub fn from_many(items: Vec<T>) -> Self {
|
||||
OneOrMany(Either::Right(items))
|
||||
}
|
||||
|
||||
/// Overwrite the contents with a single value
|
||||
///
|
||||
/// ```
|
||||
/// # use activitystreams::primitives::OneOrMany;
|
||||
/// # let mut value = OneOrMany::from_many(vec![1, 2, 3]);
|
||||
/// value.set_one(3);
|
||||
///
|
||||
/// assert!(value.as_one().is_some());
|
||||
/// ```
|
||||
pub fn set_one<U>(&mut self, u: U) -> &mut Self
|
||||
where
|
||||
U: Into<T>,
|
||||
{
|
||||
self.0 = Either::Left(u.into());
|
||||
self
|
||||
}
|
||||
|
||||
/// Overwrite the contents with vec of values
|
||||
///
|
||||
/// ```
|
||||
/// # use activitystreams::primitives::OneOrMany;
|
||||
/// # let mut value = OneOrMany::from_one(1234);
|
||||
/// value.set_many(vec![1, 2, 3, 4]);
|
||||
///
|
||||
/// assert!(value.as_many().is_some());
|
||||
/// ```
|
||||
pub fn set_many<U>(&mut self, items: impl IntoIterator<Item = U>) -> &mut Self
|
||||
where
|
||||
U: Into<T>,
|
||||
{
|
||||
self.0 = Either::Right(items.into_iter().map(Into::into).collect());
|
||||
self
|
||||
}
|
||||
|
||||
/// Add a value to the object
|
||||
///
|
||||
/// This appends the value to the existing vec, or converts the single value into a vec, and
|
||||
/// then appends the new value
|
||||
///
|
||||
/// ```
|
||||
/// use activitystreams::primitives::OneOrMany;
|
||||
/// let mut value = OneOrMany::from_one(1234);
|
||||
/// value.add(4321);
|
||||
///
|
||||
/// assert!(value.as_many().is_some());
|
||||
/// ```
|
||||
pub fn add<U>(&mut self, u: U) -> &mut Self
|
||||
where
|
||||
U: Into<T>,
|
||||
{
|
||||
let mut v = match std::mem::replace(&mut self.0, Either::Right(vec![])) {
|
||||
Either::Left(one) => vec![one],
|
||||
Either::Right(v) => v,
|
||||
};
|
||||
v.push(u.into());
|
||||
self.0 = Either::Right(v);
|
||||
self
|
||||
}
|
||||
|
||||
/// Add many values to the object
|
||||
///
|
||||
/// This appends the values to the existing vec, or converts the single value into a vec, and
|
||||
/// then appends the new values
|
||||
///
|
||||
/// ```
|
||||
/// use activitystreams::primitives::OneOrMany;
|
||||
/// let mut value = OneOrMany::from_one(1234);
|
||||
/// value.add_many(vec![4321, 2345]);
|
||||
///
|
||||
/// assert!(value.as_many().is_some());
|
||||
/// ```
|
||||
pub fn add_many<U>(&mut self, items: impl IntoIterator<Item = U>) -> &mut Self
|
||||
where
|
||||
U: Into<T>,
|
||||
{
|
||||
let mut v = match std::mem::replace(&mut self.0, Either::Right(vec![])) {
|
||||
Either::Left(one) => vec![one],
|
||||
Either::Right(v) => v,
|
||||
};
|
||||
v.extend(items.into_iter().map(Into::into));
|
||||
self.0 = Either::Right(v);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<T> for OneOrMany<T> {
|
||||
fn from(t: T) -> Self {
|
||||
OneOrMany::from_one(t)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<Vec<T>> for OneOrMany<T> {
|
||||
fn from(t: Vec<T>) -> Self {
|
||||
OneOrMany::from_many(t)
|
||||
}
|
||||
}
|
|
@ -17,8 +17,6 @@
|
|||
* along with ActivityStreams. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
use crate::primitives::XsdString;
|
||||
|
||||
/// The rdf.langString type extends xs.string, and represents a language tagged string in RDF.
|
||||
#[derive(
|
||||
Clone, Debug, Default, Eq, Ord, PartialEq, PartialOrd, serde::Deserialize, serde::Serialize,
|
||||
|
@ -28,13 +26,13 @@ pub struct RdfLangString {
|
|||
///
|
||||
/// Represented in json as "@value"
|
||||
#[serde(rename = "@value")]
|
||||
pub value: XsdString,
|
||||
pub value: String,
|
||||
|
||||
/// The language identifier
|
||||
///
|
||||
/// Represented in json as "@language"
|
||||
#[serde(rename = "@language")]
|
||||
pub language: XsdString,
|
||||
pub language: String,
|
||||
}
|
||||
|
||||
impl std::fmt::Display for RdfLangString {
|
||||
|
|
89
src/primitives/serde_parse.rs
Normal file
89
src/primitives/serde_parse.rs
Normal file
|
@ -0,0 +1,89 @@
|
|||
/// A struct that wraps a type implementing FromStr and Display implements Serde's Deserialize and
|
||||
/// Serialize
|
||||
#[derive(Clone, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
|
||||
pub struct SerdeParse<T>(T);
|
||||
|
||||
impl<T> SerdeParse<T> {
|
||||
/// Extract the inner item from SerdeParse
|
||||
pub fn into_inner(self) -> T {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> std::ops::Deref for SerdeParse<T> {
|
||||
type Target = T;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> std::ops::DerefMut for SerdeParse<T> {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> AsRef<T> for SerdeParse<T> {
|
||||
fn as_ref(&self) -> &T {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> AsMut<T> for SerdeParse<T> {
|
||||
fn as_mut(&mut self) -> &mut T {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> std::str::FromStr for SerdeParse<T>
|
||||
where
|
||||
T: std::str::FromStr,
|
||||
{
|
||||
type Err = <T as std::str::FromStr>::Err;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
T::from_str(s).map(SerdeParse)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> std::fmt::Display for SerdeParse<T>
|
||||
where
|
||||
T: std::fmt::Display,
|
||||
{
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
self.0.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> serde::ser::Serialize for SerdeParse<T>
|
||||
where
|
||||
T: std::fmt::Display,
|
||||
{
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: serde::ser::Serializer,
|
||||
{
|
||||
self.0.to_string().serialize(serializer)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de, T> serde::de::Deserialize<'de> for SerdeParse<T>
|
||||
where
|
||||
T: std::str::FromStr,
|
||||
T::Err: std::fmt::Display,
|
||||
{
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: serde::de::Deserializer<'de>,
|
||||
{
|
||||
let s = String::deserialize(deserializer)?;
|
||||
s.parse().map_err(serde::de::Error::custom)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<T> for SerdeParse<T> {
|
||||
fn from(t: T) -> Self {
|
||||
SerdeParse(t)
|
||||
}
|
||||
}
|
342
src/primitives/unit.rs
Normal file
342
src/primitives/unit.rs
Normal file
|
@ -0,0 +1,342 @@
|
|||
use crate::either::Either;
|
||||
|
||||
/// A type representing units of length
|
||||
///
|
||||
/// It can be any of the following
|
||||
/// - Centimeters
|
||||
/// - Meters
|
||||
/// - Kilometers
|
||||
/// - Inches
|
||||
/// - Feet
|
||||
/// - A custom value
|
||||
#[derive(
|
||||
Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, serde::Deserialize, serde::Serialize,
|
||||
)]
|
||||
#[serde(transparent)]
|
||||
pub struct Unit(Either<Length, String>);
|
||||
|
||||
impl Unit {
|
||||
/// Create a new unit measuring Centimeters
|
||||
///
|
||||
/// ```rust
|
||||
/// use activitystreams::primitives::Unit;
|
||||
///
|
||||
/// Unit::centimeters();
|
||||
/// ```
|
||||
pub fn centimeters() -> Self {
|
||||
Unit(Either::Left(Length::Centimeters))
|
||||
}
|
||||
|
||||
/// Check if the unit is Centimeters
|
||||
///
|
||||
/// ```rust
|
||||
/// use activitystreams::primitives::Unit;
|
||||
///
|
||||
/// assert!(Unit::centimeters().is_centimeters());
|
||||
/// ```
|
||||
pub fn is_centimeters(&self) -> bool {
|
||||
self.0
|
||||
.as_ref()
|
||||
.left()
|
||||
.map(|l| l.is_centimeters())
|
||||
.unwrap_or(false)
|
||||
}
|
||||
|
||||
/// Create a new unit measuring Meters
|
||||
///
|
||||
/// ```rust
|
||||
/// use activitystreams::primitives::Unit;
|
||||
///
|
||||
/// Unit::meters();
|
||||
/// ```
|
||||
pub fn meters() -> Self {
|
||||
Unit(Either::Left(Length::Meters))
|
||||
}
|
||||
|
||||
/// Check if the unit is Meters
|
||||
///
|
||||
/// ```rust
|
||||
/// use activitystreams::primitives::Unit;
|
||||
///
|
||||
/// assert!(Unit::meters().is_meters());
|
||||
/// ```
|
||||
pub fn is_meters(&self) -> bool {
|
||||
self.0
|
||||
.as_ref()
|
||||
.left()
|
||||
.map(|l| l.is_meters())
|
||||
.unwrap_or(false)
|
||||
}
|
||||
|
||||
/// Create a new unit measuring Kilometers
|
||||
///
|
||||
/// ```rust
|
||||
/// use activitystreams::primitives::Unit;
|
||||
///
|
||||
/// Unit::kilometers();
|
||||
/// ```
|
||||
pub fn kilometers() -> Self {
|
||||
Unit(Either::Left(Length::Kilometers))
|
||||
}
|
||||
|
||||
/// Check if the unit is Kilometers
|
||||
///
|
||||
/// ```rust
|
||||
/// use activitystreams::primitives::Unit;
|
||||
///
|
||||
/// assert!(Unit::kilometers().is_kilometers());
|
||||
/// ```
|
||||
pub fn is_kilometers(&self) -> bool {
|
||||
self.0
|
||||
.as_ref()
|
||||
.left()
|
||||
.map(|l| l.is_kilometers())
|
||||
.unwrap_or(false)
|
||||
}
|
||||
|
||||
/// Create a new unit measuring Feet
|
||||
///
|
||||
/// ```rust
|
||||
/// use activitystreams::primitives::Unit;
|
||||
///
|
||||
/// Unit::feet();
|
||||
/// ```
|
||||
pub fn feet() -> Self {
|
||||
Unit(Either::Left(Length::Feet))
|
||||
}
|
||||
|
||||
/// Check if the unit is Feet
|
||||
///
|
||||
/// ```rust
|
||||
/// use activitystreams::primitives::Unit;
|
||||
///
|
||||
/// assert!(Unit::feet().is_feet());
|
||||
/// ```
|
||||
pub fn is_feet(&self) -> bool {
|
||||
self.0.as_ref().left().map(|l| l.is_feet()).unwrap_or(false)
|
||||
}
|
||||
|
||||
/// Create a new unit measuring Inches
|
||||
///
|
||||
/// ```rust
|
||||
/// use activitystreams::primitives::Unit;
|
||||
///
|
||||
/// Unit::inches();
|
||||
/// ```
|
||||
pub fn inches() -> Self {
|
||||
Unit(Either::Left(Length::Inches))
|
||||
}
|
||||
|
||||
/// Check if the unit is Inches
|
||||
///
|
||||
/// ```rust
|
||||
/// use activitystreams::primitives::Unit;
|
||||
///
|
||||
/// assert!(Unit::inches().is_inches());
|
||||
/// ```
|
||||
pub fn is_inches(&self) -> bool {
|
||||
self.0
|
||||
.as_ref()
|
||||
.left()
|
||||
.map(|l| l.is_inches())
|
||||
.unwrap_or(false)
|
||||
}
|
||||
|
||||
/// Create a new custom unit
|
||||
///
|
||||
/// ```rust
|
||||
/// use activitystreams::primitives::Unit;
|
||||
///
|
||||
/// Unit::custom("Yards");
|
||||
/// ```
|
||||
pub fn custom<T>(string: T) -> Self
|
||||
where
|
||||
T: Into<String>,
|
||||
{
|
||||
Unit(Either::Right(string.into()))
|
||||
}
|
||||
|
||||
/// Check if a unit is custom
|
||||
///
|
||||
/// ```rust
|
||||
/// use activitystreams::primitives::Unit;
|
||||
///
|
||||
/// assert!(Unit::custom("Yards").is_custom());
|
||||
/// ```
|
||||
pub fn is_custom(&self) -> bool {
|
||||
self.as_custom().is_some()
|
||||
}
|
||||
|
||||
/// Fetch a custom unit
|
||||
///
|
||||
/// ```rust
|
||||
/// use activitystreams::primitives::Unit;
|
||||
///
|
||||
/// assert!(Unit::custom("Yards").as_custom() == Some("Yards"));
|
||||
/// ```
|
||||
pub fn as_custom(&self) -> Option<&str> {
|
||||
self.0.as_ref().right().map(|r| r.as_str())
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Unit {
|
||||
fn default() -> Self {
|
||||
Self::meters()
|
||||
}
|
||||
}
|
||||
|
||||
impl std::str::FromStr for Unit {
|
||||
type Err = std::convert::Infallible;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
let unit = match s {
|
||||
"cm" => Self::centimeters(),
|
||||
"m" => Self::meters(),
|
||||
"km" => Self::kilometers(),
|
||||
"inches" => Self::inches(),
|
||||
"feet" => Self::feet(),
|
||||
other => Self::custom(other),
|
||||
};
|
||||
|
||||
Ok(unit)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<String> for Unit {
|
||||
fn from(s: String) -> Self {
|
||||
match s.parse() {
|
||||
Ok(u) => u,
|
||||
Err(e) => match e {},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&str> for Unit {
|
||||
fn from(s: &str) -> Self {
|
||||
match s.parse() {
|
||||
Ok(u) => u,
|
||||
Err(e) => match e {},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A list of units of length that represent valid units for certain ActivityStreams objects
|
||||
#[derive(
|
||||
Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, serde::Deserialize, serde::Serialize,
|
||||
)]
|
||||
#[serde(untagged)]
|
||||
enum Length {
|
||||
#[serde(rename = "cm")]
|
||||
Centimeters,
|
||||
|
||||
#[serde(rename = "feet")]
|
||||
Feet,
|
||||
|
||||
#[serde(rename = "inches")]
|
||||
Inches,
|
||||
|
||||
#[serde(rename = "km")]
|
||||
Kilometers,
|
||||
|
||||
#[serde(rename = "m")]
|
||||
Meters,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, thiserror::Error)]
|
||||
#[error("Could not parse units")]
|
||||
/// The error type produced when a Length cannot be parsed
|
||||
struct LengthError;
|
||||
|
||||
impl Length {
|
||||
fn is_centimeters(&self) -> bool {
|
||||
match self {
|
||||
Length::Centimeters => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn is_feet(&self) -> bool {
|
||||
match self {
|
||||
Length::Feet => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn is_inches(&self) -> bool {
|
||||
match self {
|
||||
Length::Inches => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn is_kilometers(&self) -> bool {
|
||||
match self {
|
||||
Length::Kilometers => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn is_meters(&self) -> bool {
|
||||
match self {
|
||||
Length::Meters => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Length {
|
||||
fn default() -> Self {
|
||||
Length::Meters
|
||||
}
|
||||
}
|
||||
|
||||
impl std::str::FromStr for Length {
|
||||
type Err = LengthError;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
match s {
|
||||
"cm" => Ok(Length::Centimeters),
|
||||
"feet" => Ok(Length::Feet),
|
||||
"inches" => Ok(Length::Inches),
|
||||
"km" => Ok(Length::Kilometers),
|
||||
"m" => Ok(Length::Meters),
|
||||
_ => Err(LengthError),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::convert::TryFrom<&str> for Length {
|
||||
type Error = LengthError;
|
||||
|
||||
fn try_from(s: &str) -> Result<Self, Self::Error> {
|
||||
s.parse()
|
||||
}
|
||||
}
|
||||
|
||||
impl std::convert::TryFrom<&mut str> for Length {
|
||||
type Error = LengthError;
|
||||
|
||||
fn try_from(s: &mut str) -> Result<Self, Self::Error> {
|
||||
s.parse()
|
||||
}
|
||||
}
|
||||
|
||||
impl std::convert::TryFrom<String> for Length {
|
||||
type Error = LengthError;
|
||||
|
||||
fn try_from(s: String) -> Result<Self, Self::Error> {
|
||||
s.parse()
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for Length {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
match self {
|
||||
Length::Centimeters => write!(f, "cm"),
|
||||
Length::Feet => write!(f, "feet"),
|
||||
Length::Inches => write!(f, "inches"),
|
||||
Length::Kilometers => write!(f, "km"),
|
||||
Length::Meters => write!(f, "meters"),
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,169 +0,0 @@
|
|||
/*
|
||||
* This file is part of ActivityStreams.
|
||||
*
|
||||
* Copyright © 2020 Riley Trautman
|
||||
*
|
||||
* ActivityStreams is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ActivityStreams is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ActivityStreams. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/// The type xsd:anyURI represents a Uniform Resource Identifier (URI) reference.
|
||||
///
|
||||
/// URIs are used to identify resources, and they may be absolute or relative. Absolute URIs
|
||||
/// provide the entire context for locating the resources, such as http://datypic.com/prod.html.
|
||||
/// Relative URIs are specified as the difference from a base URI, such as ../prod.html. It is also
|
||||
/// possible to specify a fragment identifier, using the # character, such as ../prod.html#shirt.
|
||||
///
|
||||
/// The three previous examples happen to be HTTP URLs (Uniform Resource Locators), but URIs also
|
||||
/// encompass URLs of other schemes (e.g., FTP, gopher, telnet), as well as URNs (Uniform Resource
|
||||
/// Names). URIs are not required to be dereferencable; that is, it is not necessary for there to
|
||||
/// be a web page at http://datypic.com/prod.html in order for this to be a valid URI.
|
||||
///
|
||||
/// URIs require that some characters be escaped with their hexadecimal Unicode code point preceded
|
||||
/// by the % character. This includes non-ASCII characters and some ASCII characters, namely
|
||||
/// control characters, spaces, and the following characters (unless they are used as deliimiters
|
||||
/// in the URI): <>#%{}|\^`. For example, ../édition.html must be represented instead as
|
||||
/// ../%C3%A9dition.html, with the é escaped as %C3%A9. However, the anyURI type will accept these
|
||||
/// characters either escaped or unescaped. With the exception of the characters % and #, it will
|
||||
/// assume that unescaped characters are intended to be escaped when used in an actual URI,
|
||||
/// although the schema processor will do nothing to alter them. It is valid for an anyURI value to
|
||||
/// contain a space, but this practice is strongly discouraged. Spaces should instead be escaped
|
||||
/// using %20.
|
||||
///
|
||||
/// The schema processor is not required to parse the contents of an xsd:anyURI value to determine
|
||||
/// whether it is valid according to any particular URI scheme. Since the bare minimum rules for
|
||||
/// valid URI references are fairly generic, the schema processor will accept most character
|
||||
/// strings, including an empty value. The only values that are not accepted are ones that make
|
||||
/// inappropriate use of reserved characters, such as ones that contain multiple # characters or
|
||||
/// have % characters that are not followed by two hexadecimal digits.
|
||||
///
|
||||
/// Note that when relative URI references such as "../prod" are used as values of xsd:anyURI, no
|
||||
/// attempt is made to determine or keep track of the base URI to which they may be applied. For
|
||||
/// more information on URIs, see RFC 2396, Uniform Resource Identifiers (URI): Generic Syntax.
|
||||
#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
|
||||
pub struct XsdAnyUri(url::Url);
|
||||
|
||||
/// The error type produced when an XsdAnyUri cannot be parsed
|
||||
#[derive(Clone, Debug, thiserror::Error)]
|
||||
#[error("Could not parse XsdAnyUri")]
|
||||
pub struct XsdAnyUriError;
|
||||
|
||||
impl XsdAnyUri {
|
||||
/// Borrow the underlying string from the XsdAnyUri
|
||||
pub fn as_str(&self) -> &str {
|
||||
self.as_ref()
|
||||
}
|
||||
|
||||
/// Borrow a `url::Url` from the XsdAnyUri
|
||||
pub fn as_url(&self) -> &url::Url {
|
||||
self.as_ref()
|
||||
}
|
||||
|
||||
/// Mutably borrow a `url::Url` from the XsdAnyUri
|
||||
pub fn as_url_mut(&mut self) -> &mut url::Url {
|
||||
self.as_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<url::Url> for XsdAnyUri {
|
||||
fn from(u: url::Url) -> Self {
|
||||
XsdAnyUri(u)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<XsdAnyUri> for url::Url {
|
||||
fn from(u: XsdAnyUri) -> Self {
|
||||
u.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for XsdAnyUri {
|
||||
fn default() -> Self {
|
||||
"data:text/plain,uwu".parse().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<str> for XsdAnyUri {
|
||||
fn as_ref(&self) -> &str {
|
||||
self.0.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<url::Url> for XsdAnyUri {
|
||||
fn as_ref(&self) -> &url::Url {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl AsMut<url::Url> for XsdAnyUri {
|
||||
fn as_mut(&mut self) -> &mut url::Url {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl std::convert::TryFrom<String> for XsdAnyUri {
|
||||
type Error = XsdAnyUriError;
|
||||
|
||||
fn try_from(s: String) -> Result<Self, Self::Error> {
|
||||
s.parse()
|
||||
}
|
||||
}
|
||||
|
||||
impl std::convert::TryFrom<&str> for XsdAnyUri {
|
||||
type Error = XsdAnyUriError;
|
||||
|
||||
fn try_from(s: &str) -> Result<Self, Self::Error> {
|
||||
s.parse()
|
||||
}
|
||||
}
|
||||
|
||||
impl std::convert::TryFrom<&mut str> for XsdAnyUri {
|
||||
type Error = XsdAnyUriError;
|
||||
|
||||
fn try_from(s: &mut str) -> Result<Self, Self::Error> {
|
||||
s.parse()
|
||||
}
|
||||
}
|
||||
|
||||
impl std::str::FromStr for XsdAnyUri {
|
||||
type Err = XsdAnyUriError;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
Ok(XsdAnyUri(s.parse().map_err(|_| XsdAnyUriError)?))
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for XsdAnyUri {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
std::fmt::Display::fmt(&self.0, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl serde::ser::Serialize for XsdAnyUri {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: serde::ser::Serializer,
|
||||
{
|
||||
serializer.serialize_str(&self.0.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> serde::de::Deserialize<'de> for XsdAnyUri {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: serde::de::Deserializer<'de>,
|
||||
{
|
||||
let s = String::deserialize(deserializer)?;
|
||||
s.parse().map_err(serde::de::Error::custom)
|
||||
}
|
||||
}
|
|
@ -31,14 +31,19 @@
|
|||
/// UTC, is represented as -05:00. If no time zone value is present, it is considered unknown; it
|
||||
/// is not assumed to be UTC.
|
||||
#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
|
||||
pub struct XsdDateTime(chrono::DateTime<chrono::FixedOffset>);
|
||||
|
||||
/// The error type produced when an XsdDateTime cannot be parsed
|
||||
#[derive(Clone, Debug, thiserror::Error)]
|
||||
#[error("Error parsing DateTime")]
|
||||
pub struct XsdDateTimeError;
|
||||
pub struct XsdDateTime(pub chrono::DateTime<chrono::FixedOffset>);
|
||||
|
||||
impl XsdDateTime {
|
||||
/// Create a XsdDateTime from a chrono::DateTime
|
||||
pub fn new(d: chrono::DateTime<chrono::FixedOffset>) -> Self {
|
||||
XsdDateTime(d)
|
||||
}
|
||||
|
||||
/// Extract the chrono::DateTime from XsdDateTime
|
||||
pub fn into_inner(self) -> chrono::DateTime<chrono::FixedOffset> {
|
||||
self.0
|
||||
}
|
||||
|
||||
/// Borrow the underlying `chrono::DateTime<chrono::FixedOffset>`
|
||||
pub fn as_datetime(&self) -> &chrono::DateTime<chrono::FixedOffset> {
|
||||
self.as_ref()
|
||||
|
@ -75,7 +80,7 @@ impl AsMut<chrono::DateTime<chrono::FixedOffset>> for XsdDateTime {
|
|||
}
|
||||
|
||||
impl std::convert::TryFrom<String> for XsdDateTime {
|
||||
type Error = XsdDateTimeError;
|
||||
type Error = chrono::format::ParseError;
|
||||
|
||||
fn try_from(s: String) -> Result<Self, Self::Error> {
|
||||
s.parse()
|
||||
|
@ -83,7 +88,7 @@ impl std::convert::TryFrom<String> for XsdDateTime {
|
|||
}
|
||||
|
||||
impl std::convert::TryFrom<&str> for XsdDateTime {
|
||||
type Error = XsdDateTimeError;
|
||||
type Error = chrono::format::ParseError;
|
||||
|
||||
fn try_from(s: &str) -> Result<Self, Self::Error> {
|
||||
s.parse()
|
||||
|
@ -91,7 +96,7 @@ impl std::convert::TryFrom<&str> for XsdDateTime {
|
|||
}
|
||||
|
||||
impl std::convert::TryFrom<&mut str> for XsdDateTime {
|
||||
type Error = XsdDateTimeError;
|
||||
type Error = chrono::format::ParseError;
|
||||
|
||||
fn try_from(s: &mut str) -> Result<Self, Self::Error> {
|
||||
s.parse()
|
||||
|
@ -99,12 +104,10 @@ impl std::convert::TryFrom<&mut str> for XsdDateTime {
|
|||
}
|
||||
|
||||
impl std::str::FromStr for XsdDateTime {
|
||||
type Err = XsdDateTimeError;
|
||||
type Err = chrono::format::ParseError;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
Ok(XsdDateTime(
|
||||
chrono::DateTime::parse_from_rfc3339(s).map_err(|_| XsdDateTimeError)?,
|
||||
))
|
||||
Ok(XsdDateTime(chrono::DateTime::parse_from_rfc3339(s)?))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@
|
|||
/// multiplying by 365. If this is an issue for your application, look into specifying days
|
||||
/// directly.
|
||||
#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
|
||||
pub struct XsdDuration(chrono::Duration);
|
||||
pub struct XsdDuration(pub chrono::Duration);
|
||||
|
||||
/// The error type produced when an XsdDuration cannot be parsed
|
||||
#[derive(Clone, Debug, thiserror::Error)]
|
||||
|
@ -50,6 +50,16 @@ pub struct XsdDuration(chrono::Duration);
|
|||
pub struct XsdDurationError;
|
||||
|
||||
impl XsdDuration {
|
||||
/// Create a new XsdDuration from a chrono::Duration
|
||||
pub fn new(duration: chrono::Duration) -> Self {
|
||||
XsdDuration(duration)
|
||||
}
|
||||
|
||||
/// Extract the chrono::Duration from an XsdDuration
|
||||
pub fn into_inner(self) -> chrono::Duration {
|
||||
self.0
|
||||
}
|
||||
|
||||
/// Borrow the underlying `chrono::Duration`
|
||||
pub fn as_duration(&self) -> &chrono::Duration {
|
||||
self.as_ref()
|
||||
|
|
|
@ -1,114 +0,0 @@
|
|||
/*
|
||||
* This file is part of ActivityStreams.
|
||||
*
|
||||
* Copyright © 2020 Riley Trautman
|
||||
*
|
||||
* ActivityStreams is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ActivityStreams is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ActivityStreams. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/// The type xsd:float represents an IEEE single-precision 32-bit floating-point number.
|
||||
///
|
||||
/// TODO: handle exponents, infinity, not-a-number
|
||||
///
|
||||
/// The format of xsd:float values is a mantissa (a number which conforms to the type decimal)
|
||||
/// followed, optionally, by the character "E" or "e" followed by an exponent. The exponent must be
|
||||
/// an integer. For example, 3E2 represents 3 times 10 to the 2nd power, or 300. The exponent must
|
||||
/// be an integer.
|
||||
///
|
||||
/// In addition, the following values are valid: INF (infinity), -INF (negative infinity), and NaN
|
||||
/// (Not a Number). INF is considered to be greater than all other values, while -INF is less than
|
||||
/// all other values. The value NaN cannot be compared to any other values, although it equals
|
||||
/// itself.
|
||||
#[derive(Clone, Debug, Default, PartialEq, PartialOrd, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(transparent)]
|
||||
pub struct XsdFloat(f64);
|
||||
|
||||
/// The error type produced when an XsdFloat cannot be parsed
|
||||
#[derive(Clone, Debug, thiserror::Error)]
|
||||
#[error("Error parsing Float")]
|
||||
pub struct XsdFloatError;
|
||||
|
||||
impl XsdFloat {
|
||||
/// Get an f64 from the XsdFloat
|
||||
pub fn to_f64(&self) -> f64 {
|
||||
self.0
|
||||
}
|
||||
|
||||
/// Get an XsdFloat from an f64
|
||||
pub fn from_f64(f: f64) -> Self {
|
||||
f.into()
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<f64> for XsdFloat {
|
||||
fn as_ref(&self) -> &f64 {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl AsMut<f64> for XsdFloat {
|
||||
fn as_mut(&mut self) -> &mut f64 {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl From<f64> for XsdFloat {
|
||||
fn from(f: f64) -> Self {
|
||||
XsdFloat(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<XsdFloat> for f64 {
|
||||
fn from(f: XsdFloat) -> Self {
|
||||
f.0
|
||||
}
|
||||
}
|
||||
|
||||
impl std::convert::TryFrom<String> for XsdFloat {
|
||||
type Error = XsdFloatError;
|
||||
|
||||
fn try_from(s: String) -> Result<Self, Self::Error> {
|
||||
s.parse()
|
||||
}
|
||||
}
|
||||
|
||||
impl std::convert::TryFrom<&str> for XsdFloat {
|
||||
type Error = XsdFloatError;
|
||||
|
||||
fn try_from(s: &str) -> Result<Self, Self::Error> {
|
||||
s.parse()
|
||||
}
|
||||
}
|
||||
|
||||
impl std::convert::TryFrom<&mut str> for XsdFloat {
|
||||
type Error = XsdFloatError;
|
||||
|
||||
fn try_from(s: &mut str) -> Result<Self, Self::Error> {
|
||||
s.parse()
|
||||
}
|
||||
}
|
||||
|
||||
impl std::str::FromStr for XsdFloat {
|
||||
type Err = XsdFloatError;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
Ok(XsdFloat(s.parse().map_err(|_| XsdFloatError)?))
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for XsdFloat {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
std::fmt::Display::fmt(&self.0, f)
|
||||
}
|
||||
}
|
|
@ -1,121 +0,0 @@
|
|||
/*
|
||||
* This file is part of ActivityStreams.
|
||||
*
|
||||
* Copyright © 2020 Riley Trautman
|
||||
*
|
||||
* ActivityStreams is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ActivityStreams is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ActivityStreams. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/// The type xsd:float represents an IEEE single-precision 32-bit floating-point number.
|
||||
///
|
||||
/// TODO: handle exponents, infinity, not-a-number
|
||||
///
|
||||
/// The format of xsd:float values is a mantissa (a number which conforms to the type decimal)
|
||||
/// followed, optionally, by the character "E" or "e" followed by an exponent. The exponent must be
|
||||
/// an integer. For example, 3E2 represents 3 times 10 to the 2nd power, or 300. The exponent must
|
||||
/// be an integer.
|
||||
///
|
||||
/// In addition, the following values are valid: INF (infinity), -INF (negative infinity), and NaN
|
||||
/// (Not a Number). INF is considered to be greater than all other values, while -INF is less than
|
||||
/// all other values. The value NaN cannot be compared to any other values, although it equals
|
||||
/// itself.
|
||||
///
|
||||
/// This type also validates that a float is at least 0.0
|
||||
#[derive(Clone, Debug, PartialEq, PartialOrd, Default, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(transparent)]
|
||||
pub struct XsdNonNegativeFloat(f64);
|
||||
|
||||
/// The error type produced when an XsdNonNegativeFloat cannot be parsed
|
||||
#[derive(Clone, Debug, thiserror::Error)]
|
||||
#[error("Error parsing NonNegativeFloat")]
|
||||
pub struct XsdNonNegativeFloatError;
|
||||
|
||||
impl XsdNonNegativeFloat {
|
||||
/// Get an f64 from this XsdNonNegativeFloat
|
||||
pub fn to_float(&self) -> f64 {
|
||||
self.0
|
||||
}
|
||||
|
||||
/// Try to get an XsdNonNegativeFloat from an f64
|
||||
pub fn from_float(f: f64) -> Result<Self, XsdNonNegativeFloatError> {
|
||||
use std::convert::TryInto;
|
||||
f.try_into()
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<f64> for XsdNonNegativeFloat {
|
||||
fn as_ref(&self) -> &f64 {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl From<XsdNonNegativeFloat> for f64 {
|
||||
fn from(f: XsdNonNegativeFloat) -> Self {
|
||||
f.0
|
||||
}
|
||||
}
|
||||
|
||||
impl std::convert::TryFrom<f64> for XsdNonNegativeFloat {
|
||||
type Error = XsdNonNegativeFloatError;
|
||||
|
||||
fn try_from(f: f64) -> Result<Self, Self::Error> {
|
||||
if f < 0.0 {
|
||||
return Err(XsdNonNegativeFloatError);
|
||||
}
|
||||
|
||||
Ok(XsdNonNegativeFloat(f))
|
||||
}
|
||||
}
|
||||
|
||||
impl std::convert::TryFrom<String> for XsdNonNegativeFloat {
|
||||
type Error = XsdNonNegativeFloatError;
|
||||
|
||||
fn try_from(s: String) -> Result<Self, Self::Error> {
|
||||
s.parse()
|
||||
}
|
||||
}
|
||||
|
||||
impl std::convert::TryFrom<&str> for XsdNonNegativeFloat {
|
||||
type Error = XsdNonNegativeFloatError;
|
||||
|
||||
fn try_from(s: &str) -> Result<Self, Self::Error> {
|
||||
s.parse()
|
||||
}
|
||||
}
|
||||
|
||||
impl std::convert::TryFrom<&mut str> for XsdNonNegativeFloat {
|
||||
type Error = XsdNonNegativeFloatError;
|
||||
|
||||
fn try_from(s: &mut str) -> Result<Self, Self::Error> {
|
||||
s.parse()
|
||||
}
|
||||
}
|
||||
|
||||
impl std::str::FromStr for XsdNonNegativeFloat {
|
||||
type Err = XsdNonNegativeFloatError;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
let f = s.parse().map_err(|_| XsdNonNegativeFloatError)?;
|
||||
if f < 0.0 {
|
||||
return Err(XsdNonNegativeFloatError);
|
||||
}
|
||||
Ok(XsdNonNegativeFloat(f))
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for XsdNonNegativeFloat {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
std::fmt::Display::fmt(&self.0, f)
|
||||
}
|
||||
}
|
|
@ -1,111 +0,0 @@
|
|||
/*
|
||||
* This file is part of ActivityStreams.
|
||||
*
|
||||
* Copyright © 2020 Riley Trautman
|
||||
*
|
||||
* ActivityStreams is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ActivityStreams is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ActivityStreams. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/// The type xsd:nonNegativeInteger represents an arbitrarily large non-negative integer.
|
||||
///
|
||||
/// An xsd:nonNegativeInteger is a sequence of digits, optionally preceded by a + sign. Leading
|
||||
/// zeros are permitted, but decimal points are not.
|
||||
#[derive(
|
||||
Clone,
|
||||
Debug,
|
||||
Default,
|
||||
Eq,
|
||||
Hash,
|
||||
Ord,
|
||||
PartialEq,
|
||||
PartialOrd,
|
||||
serde::Deserialize,
|
||||
serde::Serialize,
|
||||
)]
|
||||
#[serde(transparent)]
|
||||
pub struct XsdNonNegativeInteger(u64);
|
||||
|
||||
/// The error type produced when an XsdNonNegativeInteger cannot be parsed
|
||||
#[derive(Clone, Debug, thiserror::Error)]
|
||||
#[error("Error parsing NonNegativeInteger")]
|
||||
pub struct XsdNonNegativeIntegerError;
|
||||
|
||||
impl XsdNonNegativeInteger {
|
||||
/// Get a u64 from this XsdNonNegativeInteger
|
||||
pub fn to_u64(&self) -> u64 {
|
||||
self.0
|
||||
}
|
||||
|
||||
/// Get an XsdNonNegativeInteger from a u64
|
||||
pub fn from_u64(u: u64) -> Self {
|
||||
u.into()
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<u64> for XsdNonNegativeInteger {
|
||||
fn as_ref(&self) -> &u64 {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl From<XsdNonNegativeInteger> for u64 {
|
||||
fn from(i: XsdNonNegativeInteger) -> Self {
|
||||
i.0
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u64> for XsdNonNegativeInteger {
|
||||
fn from(f: u64) -> Self {
|
||||
XsdNonNegativeInteger(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::convert::TryFrom<String> for XsdNonNegativeInteger {
|
||||
type Error = XsdNonNegativeIntegerError;
|
||||
|
||||
fn try_from(s: String) -> Result<Self, Self::Error> {
|
||||
s.parse()
|
||||
}
|
||||
}
|
||||
|
||||
impl std::convert::TryFrom<&str> for XsdNonNegativeInteger {
|
||||
type Error = XsdNonNegativeIntegerError;
|
||||
|
||||
fn try_from(s: &str) -> Result<Self, Self::Error> {
|
||||
s.parse()
|
||||
}
|
||||
}
|
||||
|
||||
impl std::convert::TryFrom<&mut str> for XsdNonNegativeInteger {
|
||||
type Error = XsdNonNegativeIntegerError;
|
||||
|
||||
fn try_from(s: &mut str) -> Result<Self, Self::Error> {
|
||||
s.parse()
|
||||
}
|
||||
}
|
||||
|
||||
impl std::str::FromStr for XsdNonNegativeInteger {
|
||||
type Err = XsdNonNegativeIntegerError;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
let f = s.parse().map_err(|_| XsdNonNegativeIntegerError)?;
|
||||
Ok(XsdNonNegativeInteger(f))
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for XsdNonNegativeInteger {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
std::fmt::Display::fmt(&self.0, f)
|
||||
}
|
||||
}
|
|
@ -1,124 +0,0 @@
|
|||
/*
|
||||
* This file is part of ActivityStreams.
|
||||
*
|
||||
* Copyright © 2020 Riley Trautman
|
||||
*
|
||||
* ActivityStreams is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ActivityStreams is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ActivityStreams. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/// A string type that conforms to the xsd:string specification.
|
||||
///
|
||||
/// TODO: Escape `<` and `&` when converting
|
||||
///
|
||||
/// The type xsd:string represents a character string that may contain any Unicode character
|
||||
/// allowed by XML. Certain characters, namely the "less than" symbol (<) and the ampersand (&),
|
||||
/// must be escaped (using the entities < and &, respectively) when used in strings in XML
|
||||
/// instances.
|
||||
///
|
||||
/// The xsd:string type has a whiteSpace facet of preserve, which means that all whitespace
|
||||
/// characters (spaces, tabs, carriage returns, and line feeds) are preserved by the processor.
|
||||
/// This is in contrast to two types derived from it: normalizedString, and token.
|
||||
#[derive(
|
||||
Clone,
|
||||
Debug,
|
||||
Default,
|
||||
Eq,
|
||||
Hash,
|
||||
Ord,
|
||||
PartialEq,
|
||||
PartialOrd,
|
||||
serde::Deserialize,
|
||||
serde::Serialize,
|
||||
)]
|
||||
#[serde(transparent)]
|
||||
pub struct XsdString(String);
|
||||
|
||||
impl XsdString {
|
||||
/// Get an XsdString from a String
|
||||
pub fn from_string(s: String) -> Self {
|
||||
s.into()
|
||||
}
|
||||
|
||||
/// Borrow an &str from an XsdString
|
||||
pub fn as_str(&self) -> &str {
|
||||
self.as_ref()
|
||||
}
|
||||
|
||||
/// Consume the XsdString and get a String
|
||||
pub fn into_string(self) -> String {
|
||||
self.into()
|
||||
}
|
||||
}
|
||||
|
||||
impl std::str::FromStr for XsdString {
|
||||
type Err = std::convert::Infallible;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
Ok(s.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<String> for XsdString {
|
||||
fn from(s: String) -> Self {
|
||||
XsdString(s)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&str> for XsdString {
|
||||
fn from(s: &str) -> Self {
|
||||
XsdString(s.to_owned())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&mut str> for XsdString {
|
||||
fn from(s: &mut str) -> Self {
|
||||
XsdString(s.to_owned())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<XsdString> for String {
|
||||
fn from(s: XsdString) -> Self {
|
||||
s.0
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<str> for XsdString {
|
||||
fn as_ref(&self) -> &str {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<String> for XsdString {
|
||||
fn as_ref(&self) -> &String {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl AsMut<str> for XsdString {
|
||||
fn as_mut(&mut self) -> &mut str {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl AsMut<String> for XsdString {
|
||||
fn as_mut(&mut self) -> &mut String {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for XsdString {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
std::fmt::Display::fmt(&self.0, f)
|
||||
}
|
||||
}
|
325
src/unparsed.rs
Normal file
325
src/unparsed.rs
Normal file
|
@ -0,0 +1,325 @@
|
|||
//! Types and Traits for dealing with Unparsed data
|
||||
//!
|
||||
//! Since ActivityStreams is extensible, and structured in a heirarchy of types, Data that was not
|
||||
//! required to construct a given type might still come in handy when extending a into a subobject.
|
||||
//!
|
||||
//! For example, a `Create` activity is an extension of an `Object`, but if we need to store that
|
||||
//! type on another object, we need to make the type system happy. Since any number of types both
|
||||
//! provided and extended might need to be stored in the same key, a type called `AnyBase` exists.
|
||||
//! AnyBase, when containing a `Base`, can be extended into a `Create` activity so long as the
|
||||
//! required keys are present in it's `Unparsed` struct.
|
||||
//!
|
||||
//! For the most part, users of this library won't care about this module, but if you need to
|
||||
//! create an Extension, it will come in handy.
|
||||
//!
|
||||
//! Let's implement a part of the Security extension to be compatible with Mastodon.
|
||||
//!
|
||||
//! ```rust
|
||||
//! use activitystreams::{
|
||||
//! actor::{AsApActor, ApActor},
|
||||
//! base::{AsBase, Base, Extends},
|
||||
//! markers,
|
||||
//! object::{AsObject, Object},
|
||||
//! prelude::*,
|
||||
//! primitives::*,
|
||||
//! unparsed::*,
|
||||
//! url::Url,
|
||||
//! };
|
||||
//!
|
||||
//! /// First, we'll define our public key types
|
||||
//!
|
||||
//! #[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
|
||||
//! #[serde(rename_all = "camelCase")]
|
||||
//! pub struct PublicKeyValues {
|
||||
//! pub id: Url,
|
||||
//! pub owner: Url,
|
||||
//! pub public_key_pem: String,
|
||||
//! }
|
||||
//!
|
||||
//! #[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
|
||||
//! #[serde(rename_all = "camelCase")]
|
||||
//! pub struct PublicKey<Inner> {
|
||||
//! pub public_key: PublicKeyValues,
|
||||
//! pub inner: Inner,
|
||||
//! }
|
||||
//!
|
||||
//!
|
||||
//! /// Then, we'll implement Extends so we can produce a PublicKey<Object> from an AnyBase.
|
||||
//!
|
||||
//! impl<Inner, Kind> Extends<Kind> for PublicKey<Inner>
|
||||
//! where
|
||||
//! Inner: Extends<Kind, Error=serde_json::Error> + UnparsedMut,
|
||||
//! {
|
||||
//! type Error = serde_json::Error;
|
||||
//!
|
||||
//! fn extends(base: Base<Kind>) -> Result<Self, Self::Error> {
|
||||
//! let mut inner = Inner::extends(base)?;
|
||||
//!
|
||||
//! Ok(PublicKey {
|
||||
//! public_key: inner.unparsed_mut().remove("publicKey")?,
|
||||
//! inner,
|
||||
//! })
|
||||
//! }
|
||||
//!
|
||||
//! fn retracts(self) -> Result<Base<Kind>, Self::Error> {
|
||||
//! let PublicKey {
|
||||
//! public_key,
|
||||
//! mut inner,
|
||||
//! } = self;
|
||||
//!
|
||||
//! inner.unparsed_mut().insert("publicKey", public_key)?;
|
||||
//!
|
||||
//! inner.retracts()
|
||||
//! }
|
||||
//! }
|
||||
//!
|
||||
//!
|
||||
//! /// Auto-implement Base, Object, and Actor when Inner supports it
|
||||
//! impl<Inner> markers::Base for PublicKey<Inner> where Inner: markers::Base {}
|
||||
//! impl<Inner> markers::Object for PublicKey<Inner> where Inner: markers::Object {}
|
||||
//! impl<Inner> markers::Actor for PublicKey<Inner> where Inner: markers::Actor {}
|
||||
//!
|
||||
//!
|
||||
//! /// If we want to easily access getters and setters for internal types, we'll need to forward
|
||||
//! /// those, too.
|
||||
//!
|
||||
//! /// Forward for base methods
|
||||
//! ///
|
||||
//! /// This allows us to access methods related to `context`, `id`, `kind`, `name`,
|
||||
//! /// `media_type`, and `preview` directly from the PublicKey struct
|
||||
//! impl<Inner, Kind> AsBase<Kind> for PublicKey<Inner>
|
||||
//! where
|
||||
//! Inner: AsBase<Kind>,
|
||||
//! {
|
||||
//! fn base_ref(&self) -> &Base<Kind> {
|
||||
//! self.inner.base_ref()
|
||||
//! }
|
||||
//!
|
||||
//! fn base_mut(&mut self) -> &mut Base<Kind> {
|
||||
//! self.inner.base_mut()
|
||||
//! }
|
||||
//! }
|
||||
//!
|
||||
//! /// Forward for object methods
|
||||
//! ///
|
||||
//! /// This allows us to access methods related to `url`, `generator`, `start_time`, `duration`,
|
||||
//! /// and more directly from the PublicKey struct
|
||||
//! impl<Inner, Kind> AsObject<Kind> for PublicKey<Inner>
|
||||
//! where
|
||||
//! Inner: AsObject<Kind>,
|
||||
//! {
|
||||
//! fn object_ref(&self) -> &Object<Kind> {
|
||||
//! self.inner.object_ref()
|
||||
//! }
|
||||
//!
|
||||
//! fn object_mut(&mut self) -> &mut Object<Kind> {
|
||||
//! self.inner.object_mut()
|
||||
//! }
|
||||
//! }
|
||||
//!
|
||||
//! /// Forward for ActivityPub actor methods
|
||||
//! ///
|
||||
//! /// This allows us to access methods related to `inbox`, `outbox`, `following`, `followers`,
|
||||
//! /// `liked`, `streams`, `endpoints`, and more directly from the PublicKey struct
|
||||
//! impl<Inner1, Inner2> AsApActor<Inner2> for PublicKey<Inner1>
|
||||
//! where
|
||||
//! Inner1: AsApActor<Inner2>,
|
||||
//! {
|
||||
//! fn ap_actor_ref(&self) -> &ApActor<Inner2> {
|
||||
//! self.inner.ap_actor_ref()
|
||||
//! }
|
||||
//!
|
||||
//! fn ap_actor_mut(&mut self) -> &mut ApActor<Inner2> {
|
||||
//! self.inner.ap_actor_mut()
|
||||
//! }
|
||||
//! }
|
||||
//!
|
||||
//!
|
||||
//! /// If we want to be able to extend from our own type, we'll need to forward some
|
||||
//! /// implementations, and create some traits
|
||||
//!
|
||||
//! /// Make it easy for downstreams to get an Unparsed
|
||||
//! impl<Inner> UnparsedMut for PublicKey<Inner>
|
||||
//! where
|
||||
//! Inner: UnparsedMut,
|
||||
//! {
|
||||
//! fn unparsed_mut(&mut self) -> &mut Unparsed {
|
||||
//! self.inner.unparsed_mut()
|
||||
//! }
|
||||
//! }
|
||||
//!
|
||||
//! /// Create our own extensible trait
|
||||
//! pub trait AsPublicKey<Inner> {
|
||||
//! fn public_key_ref(&self) -> &PublicKey<Inner>;
|
||||
//! fn public_key_mut(&mut self) -> &mut PublicKey<Inner>;
|
||||
//! }
|
||||
//!
|
||||
//! /// Implement it
|
||||
//! impl<Inner> AsPublicKey<Inner> for PublicKey<Inner> {
|
||||
//! fn public_key_ref(&self) -> &Self {
|
||||
//! self
|
||||
//! }
|
||||
//!
|
||||
//! fn public_key_mut(&mut self) -> &mut Self {
|
||||
//! self
|
||||
//! }
|
||||
//! }
|
||||
//!
|
||||
//! /// And now create helper methods
|
||||
//! pub trait PublicKeyExt<Inner>: AsPublicKey<Inner> {
|
||||
//! /// Borrow the public key's ID
|
||||
//! fn key_id<'a>(&'a self) -> &'a Url
|
||||
//! where
|
||||
//! Inner: 'a,
|
||||
//! {
|
||||
//! &self.public_key_ref().public_key.id
|
||||
//! }
|
||||
//!
|
||||
//! /// Set the public key's ID
|
||||
//! fn set_key_id(&mut self, id: Url) -> &mut Self {
|
||||
//! self.public_key_mut().public_key.id = id;
|
||||
//! self
|
||||
//! }
|
||||
//!
|
||||
//! /// Borrow the public key's Owner
|
||||
//! fn key_owner<'a>(&'a self) -> &'a Url
|
||||
//! where
|
||||
//! Inner: 'a,
|
||||
//! {
|
||||
//! &self.public_key_ref().public_key.owner
|
||||
//! }
|
||||
//!
|
||||
//! /// Set the public key's Owner
|
||||
//! fn set_key_owner(&mut self, owner: Url) -> &mut Self {
|
||||
//! self.public_key_mut().public_key.owner = owner;
|
||||
//! self
|
||||
//! }
|
||||
//!
|
||||
//! /// Borrow the public key's PEM encoded value
|
||||
//! fn key_pem<'a>(&'a self) -> &'a str
|
||||
//! where
|
||||
//! Inner: 'a,
|
||||
//! {
|
||||
//! &self.public_key_ref().public_key.public_key_pem
|
||||
//! }
|
||||
//!
|
||||
//! /// Set the public key's PEM encoded value
|
||||
//! ///
|
||||
//! /// In a real application, this might take a different type, such as RSA's RSAPublicKey, or
|
||||
//! /// OpenSSL's or Ring's version
|
||||
//! fn set_key_pem<T>(&mut self, pem: T) -> &mut Self
|
||||
//! where
|
||||
//! T: Into<String>,
|
||||
//! {
|
||||
//! self.public_key_mut().public_key.public_key_pem = pem.into();
|
||||
//! self
|
||||
//! }
|
||||
//! }
|
||||
//!
|
||||
//! /// Finally, we'll automatically implement PublicKeyExt for any type implementing AsPublicKey
|
||||
//! impl<T, Inner> PublicKeyExt<Inner> for T where T: AsPublicKey<Inner> {}
|
||||
//!
|
||||
//!
|
||||
//! /// Now that eveything is implemented, we can use it like so:
|
||||
//! use activitystreams::{actor::{kind::PersonType, Person}, uri};
|
||||
//!
|
||||
//! pub type ExtendedPerson = PublicKey<ApActor<Person>>;
|
||||
//!
|
||||
//! impl ExtendedPerson {
|
||||
//! pub fn new(inbox: Url, mut owner: Url) -> Self {
|
||||
//! let id = owner.clone();
|
||||
//! owner.set_fragment(Some("main-key"));
|
||||
//! PublicKey {
|
||||
//! public_key: PublicKeyValues {
|
||||
//! id,
|
||||
//! owner,
|
||||
//! public_key_pem: String::new(),
|
||||
//! },
|
||||
//! inner: ApActor::new(inbox, Person::new()),
|
||||
//! }
|
||||
//! }
|
||||
//! }
|
||||
//!
|
||||
//! fn main() -> Result<(), anyhow::Error> {
|
||||
//! let mut extended_person = ExtendedPerson::new(
|
||||
//! uri!("https://example.com/user/inbox"),
|
||||
//! uri!("https://example.com/user"),
|
||||
//! );
|
||||
//!
|
||||
//! extended_person
|
||||
//! .set_kind(PersonType::Person)
|
||||
//! .set_id("https://example.com/user".parse()?)
|
||||
//! .set_name("Demo User")
|
||||
//! .set_preferred_username("user")
|
||||
//! .set_outbox("https://example.com/user/outbox".parse()?)
|
||||
//! .set_key_pem(
|
||||
//! "------ BEGIN PUBLIC KEY ------\nasdfasdfasdfasdfasdfasdf..."
|
||||
//! )
|
||||
//! .set_key_owner("https://example.com/user".parse()?)
|
||||
//! .set_key_id("https://example.com/user#main-key".parse()?);
|
||||
//!
|
||||
//! let string = serde_json::to_string(&extended_person)?;
|
||||
//! println!("{}", string);
|
||||
//! Ok(())
|
||||
//! }
|
||||
//! ```
|
||||
|
||||
/// A trait granting mutable access to an Unparsed struct
|
||||
///
|
||||
/// This is required for easy manipulation of Unparsed from potentially deeply nested structures.
|
||||
pub trait UnparsedMut {
|
||||
/// Get a mutable reference to Unparsed
|
||||
fn unparsed_mut(&mut self) -> &mut Unparsed;
|
||||
}
|
||||
|
||||
/// A helper trait providing two methods, 'insert' and 'remove', that is auto-implemented for
|
||||
/// UnparsedMut types.
|
||||
///
|
||||
/// These methods are provided for easily pulling values from and inserting values into the
|
||||
/// Unparsed struct.
|
||||
pub trait UnparsedMutExt: UnparsedMut {
|
||||
/// Remove a value from the Unparsed struct, provided it matches the expected type
|
||||
fn remove<T>(&mut self, key: &str) -> Result<T, serde_json::Error>
|
||||
where
|
||||
T: serde::de::DeserializeOwned,
|
||||
{
|
||||
serde_json::from_value(self.unparsed_mut().remove(key))
|
||||
}
|
||||
|
||||
/// Insert a value into the Unparsed struct if the value isn't Null
|
||||
fn insert<T>(&mut self, key: &str, value: T) -> Result<&mut Self, serde_json::Error>
|
||||
where
|
||||
T: serde::ser::Serialize,
|
||||
{
|
||||
let value = serde_json::to_value(value)?;
|
||||
|
||||
if !value.is_null() {
|
||||
self.unparsed_mut().insert(key.to_owned(), value);
|
||||
}
|
||||
|
||||
Ok(self)
|
||||
}
|
||||
}
|
||||
|
||||
/// The Unparsed struct itself,
|
||||
#[derive(Clone, Debug, Default, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(transparent)]
|
||||
pub struct Unparsed(std::collections::HashMap<String, serde_json::Value>);
|
||||
|
||||
impl Unparsed {
|
||||
pub(crate) fn remove(&mut self, key: &str) -> serde_json::Value {
|
||||
self.0.remove(key).unwrap_or(serde_json::Value::Null)
|
||||
}
|
||||
|
||||
pub(crate) fn insert(&mut self, key: String, value: serde_json::Value) {
|
||||
self.0.insert(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
impl UnparsedMut for Unparsed {
|
||||
fn unparsed_mut(&mut self) -> &mut Unparsed {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> UnparsedMutExt for T where T: UnparsedMut {}
|
Loading…
Reference in a new issue