about summary refs log tree commit diff
path: root/indieauth
diff options
context:
space:
mode:
authorVika <vika@fireburn.ru>2024-08-04 21:37:40 +0300
committerVika <vika@fireburn.ru>2024-08-17 16:05:41 +0300
commit5d7e852c078506c30ea5d5d03da659c66a516559 (patch)
tree344d31c7cfb5bdd4c41b0a6948bfe92e2cbc0f1f /indieauth
parent63f56b43e72a602c765f44b71df6615bd5ce139b (diff)
downloadkittybox-5d7e852c078506c30ea5d5d03da659c66a516559.tar.zst
kittybox-indieauth: AuthorizationRequest::into_query_pairs()
This is a more efficient way of appending to a query string, as it
avoids a needless copy and borrows most things instead. We can't
really avoid copying here, since we'll need to write to the query
string, but we can avoid an extra copy by borrowing most of our way
through.
Diffstat (limited to 'indieauth')
-rw-r--r--indieauth/src/lib.rs38
1 files changed, 37 insertions, 1 deletions
diff --git a/indieauth/src/lib.rs b/indieauth/src/lib.rs
index 05122b0..741eb81 100644
--- a/indieauth/src/lib.rs
+++ b/indieauth/src/lib.rs
@@ -18,6 +18,8 @@
 //!
 //! [indieauth]: https://indieauth.spec.indieweb.org/20220212/
 //! [`axum`]: https://github.com/tokio-rs/axum
+use std::borrow::Cow;
+
 use serde::{Serialize, Deserialize};
 use url::Url;
 
@@ -302,7 +304,7 @@ impl AsRef<str> for State {
 ///     .parse()
 ///     .unwrap();
 ///
-/// url.set_query(Some(&serde_urlencoded::to_string(request).unwrap()));
+/// url.query_pairs_mut().extend_pairs(request.as_query_pairs().iter());
 ///
 /// // Open a user's browser to navigate to the authorization endpoint page...
 /// ```
@@ -336,6 +338,40 @@ pub struct AuthorizationRequest {
     pub me: Option<Url>,
 }
 
+impl AuthorizationRequest {
+    /// Transform this authorization request into a vector of string
+    /// pairs suitable into serialization into a query string.
+    ///
+    /// This is a bit more efficient than using serde, since it avoids
+    /// a deserialization an borrows where possible.
+    ///
+    /// (In the current implementation, only the scope field is owned.)
+    pub fn as_query_pairs(&'_ self) -> Vec<(&'static str, Cow<'_, str>)> {
+        let mut v = vec![
+            ("response_type", Cow::Borrowed(self.response_type.as_str())),
+            ("client_id", Cow::Borrowed(self.client_id.as_str())),
+            ("redirect_uri", Cow::Borrowed(self.redirect_uri.as_str())),
+            ("code_challenge", Cow::Borrowed(self.code_challenge.as_str())),
+            ("code_challenge_method", Cow::Borrowed(self.code_challenge.method().as_str())),
+            ("state", Cow::Borrowed(self.state.as_ref()))
+        ];
+
+        if let Some(ref scope) = self.scope {
+            v.push(
+                ("scope", Cow::Owned(scope.to_string()))
+            );
+        }
+
+        if let Some(ref me) = self.me {
+            v.push(
+                ("me", Cow::Borrowed(me.as_str()))
+            );
+        }
+
+        v
+    }
+}
+
 /// An authorization request that must be POSTed to an IndieAuth
 /// endpoint together with a token with a scope of
 /// `request_external_token:<scope>` to request external tokens with