1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
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 {}