diff --git a/src/application.rs b/src/application.rs index e8a12d8eb..c13c4d35a 100644 --- a/src/application.rs +++ b/src/application.rs @@ -77,7 +77,10 @@ impl FromStr for OAuthToken { } } -// These trait impls are similar to FromStr (but are infallible) +/// Converts a string slice into an `AppId`. +/// +/// This implementation is infallible because the underlying `FromStr::from_str` +/// for `AppId` always succeeds (it simply wraps the input string without validation). impl<'a> From<&'a str> for AppId where Self: FromStr, @@ -87,6 +90,10 @@ where } } +/// Converts a string slice into an `AppKey`. +/// +/// This implementation is infallible because the underlying `FromStr::from_str` +/// for `AppKey` always succeeds (it simply wraps the input string without validation). impl<'a> From<&'a str> for AppKey where Self: FromStr, @@ -96,6 +103,10 @@ where } } +/// Converts a string slice into a `UserKey`. +/// +/// This implementation is infallible because the underlying `FromStr::from_str` +/// for `UserKey` always succeeds (it simply wraps the input string without validation). impl<'a> From<&'a str> for UserKey where Self: FromStr, @@ -105,6 +116,10 @@ where } } +/// Converts a string slice into an `OAuthToken`. +/// +/// This implementation is infallible because the underlying `FromStr::from_str` +/// for `OAuthToken` always succeeds (it simply wraps the input string without validation). impl<'a> From<&'a str> for OAuthToken where Self: FromStr, diff --git a/src/credentials.rs b/src/credentials.rs index 0d08a637b..50f398db5 100644 --- a/src/credentials.rs +++ b/src/credentials.rs @@ -49,7 +49,10 @@ impl FromStr for ServiceToken { } } -// These trait impls are similar to FromStr (but are infallible) +/// Converts a string slice into a `ProviderKey`. +/// +/// This implementation is infallible because the underlying `FromStr::from_str` +/// for `ProviderKey` always succeeds (it simply wraps the input string without validation). impl From<&str> for ProviderKey where Self: FromStr, @@ -59,6 +62,10 @@ where } } +/// Converts a string slice into a `ServiceToken`. +/// +/// This implementation is infallible because the underlying `FromStr::from_str` +/// for `ServiceToken` always succeeds (it simply wraps the input string without validation). impl From<&str> for ServiceToken where Self: FromStr, @@ -162,6 +169,10 @@ impl FromStr for ServiceId { } } +/// Converts a string slice into a `ServiceId`. +/// +/// This implementation is infallible because the underlying `FromStr::from_str` +/// for `ServiceId` always succeeds (it simply wraps the input string without validation). impl From<&str> for ServiceId where Self: FromStr, diff --git a/src/extensions.rs b/src/extensions.rs index 7a4e68f06..2149c1d99 100644 --- a/src/extensions.rs +++ b/src/extensions.rs @@ -1,3 +1,12 @@ +//! Extensions for 3scale API calls. +//! +//! Extensions allow you to request additional data or modify the behavior of API calls +//! to the 3scale Service Management API. Common extensions include: +//! - `list_app_keys`: Request the list of application keys for an app +//! - `hierarchy`: Request the metrics hierarchy in the response +//! - `flat_usage`: Use a flat structure for usage data instead of nested +//! - `no_body`: Request that the response body be omitted + mod extension; mod list; diff --git a/src/extensions/extension.rs b/src/extensions/extension.rs index 2eb7d69f1..6bbc86af5 100644 --- a/src/extensions/extension.rs +++ b/src/extensions/extension.rs @@ -2,6 +2,18 @@ use std::prelude::v1::*; use std::borrow::Cow; +/// Represents an extension parameter for 3scale API calls. +/// +/// Extensions modify the behavior or output of API calls. Each variant represents a different +/// type of extension that can be added to an API request. +/// +/// # Variants +/// +/// - `FlatUsage`: Changes usage reporting format to a flat structure +/// - `Hierarchy`: Requests the metrics hierarchy in the response +/// - `NoBody`: Requests that the response body be omitted +/// - `ListAppKeys`: Requests the list of application keys for an app +/// - `Other`: Any custom extension with arbitrary key-value pairs #[derive(Debug, Clone, PartialEq, Eq)] #[non_exhaustive] pub enum Extension<'s> { @@ -13,6 +25,9 @@ pub enum Extension<'s> { } impl Extension<'_> { + /// Returns the key name for this extension. + /// + /// The key is used when serializing the extension as a parameter. pub fn key(&self) -> &'_ str { match self { Extension::Other(k, _) => k, @@ -23,6 +38,10 @@ impl Extension<'_> { } } + /// Returns the value for this extension. + /// + /// For known extensions, this returns the configured value. + /// For extensions without values, this returns "1". pub fn value(&self) -> &'_ str { match self { Extension::Other(_, v) | Extension::FlatUsage(v) | Extension::ListAppKeys(v) => v, @@ -30,6 +49,10 @@ impl Extension<'_> { } } + /// Returns this extension as a URL-encoded key-value pair. + /// + /// For known extensions, the key is not encoded. For custom extensions, + /// both key and value are URL-encoded. pub fn to_cow(&self) -> Cow<'_, str> { use crate::encoding::encode; diff --git a/src/extensions/list.rs b/src/extensions/list.rs index 21c1a6483..bda9c566f 100644 --- a/src/extensions/list.rs +++ b/src/extensions/list.rs @@ -4,6 +4,20 @@ use std::{borrow::Cow, iter::FromIterator, vec::IntoIter}; use super::Extension; +/// A list of extensions for a 3scale API call. +/// +/// `List` provides a builder-like API for constructing a set of extensions to include +/// in an API request. Most methods are chainable and return `self` to allow fluent construction. +/// +/// # Examples +/// +/// ``` +/// use threescalers::extensions::{List, Extension}; +/// +/// let extensions = List::new() +/// .hierarchy() +/// .no_body(); +/// ``` #[repr(transparent)] #[derive(Debug, Clone, PartialEq, Eq, Default)] pub struct List<'s>(Vec>); @@ -15,63 +29,79 @@ impl<'s> From>> for List<'s> { } impl<'s> List<'s> { + /// Creates a new empty list of extensions. pub fn new() -> Self { Self(Vec::new()) } + /// Creates a new list with space for at least `capacity` extensions. pub fn with_capacity(capacity: usize) -> Self { Self(Vec::with_capacity(capacity)) } + /// Consumes this list and returns the underlying vector of extensions. pub fn into_inner(self) -> Vec> { self.0 } + /// Returns a reference to the underlying vector of extensions. pub fn as_vec(&self) -> &Vec> { self.0.as_ref() } + /// Returns a mutable reference to the underlying vector of extensions. pub fn as_mut_vec(&mut self) -> &mut Vec> { self.0.as_mut() } + /// Returns the number of extensions in this list. pub fn len(&self) -> usize { self.0.len() } + /// Returns `true` if this list contains no extensions. pub fn is_empty(&self) -> bool { self.0.is_empty() } + /// Removes all extensions from the list and returns the number that were removed. pub fn clear(&mut self) -> usize { let cleared = self.len(); self.0.clear(); cleared } + /// Returns the number of extensions this list can hold without reallocating. pub fn capacity(&self) -> usize { self.0.capacity() } + /// Reserves space for at least `additional` more extensions. pub fn reserve(mut self, additional: usize) -> Self { self.0.reserve(additional); self } + /// Shrinks the capacity of this list to match its current length. pub fn shrink_to_fit(mut self) -> Self { self.0.shrink_to_fit(); self } + /// Appends an extension to the list and returns self for chaining. pub fn push(mut self, e: Extension<'s>) -> Self { self.0.push(e); self } + /// Appends a custom extension with the given key and value. pub fn push_other(self, key: Cow<'s, str>, value: Cow<'s, str>) -> Self { self.push(Extension::Other(key, value)) } + /// Removes the first occurrence of the given extension from the list. + /// + /// Returns `Some` containing the removed extension, or `None` if the extension was not found. pub fn remove_item(&mut self, e: &Extension<'s>) -> Option> { match self.0.iter().position(|elem| elem == e) { Some(idx) => Some(self.0.remove(idx)), @@ -79,6 +109,9 @@ impl<'s> List<'s> { } } + /// Removes all occurrences of the given extension from the list. + /// + /// Returns the number of extensions that were removed. pub fn remove_all(&mut self, e: &Extension<'s>) -> usize { let before = self.len(); self.0.retain(|elem| elem != e); @@ -86,18 +119,22 @@ impl<'s> List<'s> { before - self.len() } + /// Adds a `no_body` extension to request that the response body be omitted. pub fn no_body(self) -> Self { self.push(Extension::NoBody) } + /// Adds a `hierarchy` extension to request the metrics hierarchy in the response. pub fn hierarchy(self) -> Self { self.push(Extension::Hierarchy) } + /// Adds a `flat_usage` extension with the specified nesting level. pub fn flat_usage(self, level: u32) -> Self { self.push(Extension::FlatUsage(level.to_string().into())) } + /// Adds a `list_app_keys` extension with the specified level. pub fn list_app_keys(self, level: u32) -> Self { self.push(Extension::ListAppKeys(level.to_string().into())) } diff --git a/src/response/app_keys_list.rs b/src/response/app_keys_list.rs index 77f90d086..5861ef256 100644 --- a/src/response/app_keys_list.rs +++ b/src/response/app_keys_list.rs @@ -12,6 +12,10 @@ use crate::{ credentials::ServiceId, }; +/// Contains the list of application keys returned by the `list_app_keys` extension. +/// +/// This structure holds the keys associated with a 3scale application, along with +/// metadata about which service and application they belong to. #[derive(Debug, Clone, PartialEq, Eq)] pub struct ListAppKeys { service_id: Option, @@ -20,6 +24,13 @@ pub struct ListAppKeys { } impl ListAppKeys { + /// Creates a new `ListAppKeys` structure. + /// + /// # Arguments + /// + /// * `service_id` - Optional service ID + /// * `app_id` - Optional application ID + /// * `keys` - Iterator of application keys pub fn new, A: Into, K: Into, I: IntoIterator>( service_id: Option, app_id: Option, @@ -32,14 +43,17 @@ impl ListAppKeys { } } + /// Returns the service ID if available. pub fn service_id(&self) -> Option<&ServiceId> { self.service_id.as_ref() } + /// Returns the application ID if available. pub fn app_id(&self) -> Option<&AppId> { self.app_id.as_ref() } + /// Returns the list of application keys as a slice. pub fn keys(&self) -> &[AppKey] { self.keys.as_slice() } diff --git a/src/user.rs b/src/user.rs index b86551702..e229d7660 100644 --- a/src/user.rs +++ b/src/user.rs @@ -42,7 +42,10 @@ impl FromStr for OAuthToken { } } -// These trait impls are similar to FromStr (but are infallible) +/// Converts a string slice into a `UserId`. +/// +/// This implementation is infallible because the underlying `FromStr::from_str` +/// for `UserId` always succeeds (it simply wraps the input string without validation). impl From<&str> for UserId where Self: FromStr, @@ -52,6 +55,10 @@ where } } +/// Converts a string slice into an `OAuthToken`. +/// +/// This implementation is infallible because the underlying `FromStr::from_str` +/// for `OAuthToken` always succeeds (it simply wraps the input string without validation). impl From<&str> for OAuthToken where Self: FromStr,