From 5d7e852c078506c30ea5d5d03da659c66a516559 Mon Sep 17 00:00:00 2001 From: Vika Date: Sun, 4 Aug 2024 21:37:40 +0300 Subject: 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. --- indieauth/src/lib.rs | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) (limited to 'indieauth') 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 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, } +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:` to request external tokens with -- cgit 1.4.1