Commit 17844d67cff2cd26be407a6676619a884f66f874

Cléo Rebert 2024-01-19T12:28:22

Merge pull request #64 from AntonnMal/docs-revision Added crate feature requirements to docs

diff --git a/Cargo.toml b/Cargo.toml
index e1f9fcf..fcf70b0 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -18,7 +18,8 @@ members = [
 ]
 
 [package.metadata.docs.rs]
-features = [ "qr", "serde_support", "gen_secret" ]
+all-features = true
+rustc-args = ["--cfg", "docsrs"]
 
 [features]
 default = []
@@ -39,4 +40,4 @@ url = { version = "2.4", optional = true }
 constant_time_eq = "0.2"
 rand = { version = "0.8", features = ["std_rng", "std"], optional = true, default-features = false }
 zeroize = { version = "1.6", features = ["alloc", "derive"], optional = true }
-qrcodegen-image = { version = "1.0", features = ["base64"], optional = true, path = "qrcodegen-image" }
\ No newline at end of file
+qrcodegen-image = { version = "1.0", features = ["base64"], optional = true, path = "qrcodegen-image" }
diff --git a/src/custom_providers.rs b/src/custom_providers.rs
index 08ec2e8..86750b1 100644
--- a/src/custom_providers.rs
+++ b/src/custom_providers.rs
@@ -2,6 +2,7 @@
 use crate::{Algorithm, TOTP};
 
 #[cfg(feature = "steam")]
+#[cfg_attr(docsrs, doc(cfg(feature = "steam")))]
 impl TOTP {
     #[cfg(feature = "otpauth")]
     /// Will create a new instance of TOTP using the Steam algorithm with given parameters. See [the doc](struct.TOTP.html#fields) for reference as to how to choose those values
@@ -9,6 +10,8 @@ impl TOTP {
     /// # Description
     /// * `secret`: expect a non-encoded value, to pass in base32 string use `Secret::Encoded(String)`
     ///
+    /// # Example
+    ///
     /// ```rust
     /// use totp_rs::{Secret, TOTP};
     /// let secret = Secret::Encoded("ABCDEFGHIJKLMNOPQRSTUVWXYZ234567".into());
@@ -32,6 +35,8 @@ impl TOTP {
     /// # Description
     /// * `secret`: expect a non-encoded value, to pass in base32 string use `Secret::Encoded(String)`
     ///
+    /// # Example
+    ///
     /// ```rust
     /// use totp_rs::{Secret, TOTP};
     /// let secret = Secret::Encoded("ABCDEFGHIJKLMNOPQRSTUVWXYZ234567".to_string());
diff --git a/src/lib.rs b/src/lib.rs
index 14d1ecd..9976977 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -47,6 +47,9 @@
 //! # }
 //! ```
 
+// enable `doc_cfg` feature for `docs.rs`.
+#![cfg_attr(docsrs, feature(doc_cfg))]
+
 mod custom_providers;
 mod rfc;
 mod secret;
@@ -88,6 +91,8 @@ pub enum Algorithm {
     SHA256,
     SHA512,
     #[cfg(feature = "steam")]
+    #[cfg_attr(docsrs, doc(cfg(feature = "steam")))]
+    /// Steam TOTP token algorithm
     Steam,
 }
 
@@ -153,11 +158,13 @@ pub struct TOTP {
     /// non-encoded value
     pub secret: Vec<u8>,
     #[cfg(feature = "otpauth")]
+    #[cfg_attr(docsrs, doc(cfg(feature = "otpauth")))]
     /// The "Github" part of "Github:constantoine@github.com". Must not contain a colon `:`
     /// For example, the name of your service/website.
     /// Not mandatory, but strongly recommended!
     pub issuer: Option<String>,
     #[cfg(feature = "otpauth")]
+    #[cfg_attr(docsrs, doc(cfg(feature = "otpauth")))]
     /// The "constantoine@github.com" part of "Github:constantoine@github.com". Must not contain a colon `:`
     /// For example, the name of your user's account.
     pub account_name: String,
@@ -210,6 +217,8 @@ impl core::fmt::Display for TOTP {
 }
 
 #[cfg(all(feature = "gen_secret", not(feature = "otpauth")))]
+// because `Default` is implemented regardless of `otpauth` feature we don't specify it here
+#[cfg_attr(docsrs, doc(cfg(feature = "gen_secret")))]
 impl Default for TOTP {
     fn default() -> Self {
         return TOTP::new(
@@ -224,6 +233,7 @@ impl Default for TOTP {
 }
 
 #[cfg(all(feature = "gen_secret", feature = "otpauth"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "gen_secret")))]
 impl Default for TOTP {
     fn default() -> Self {
         TOTP::new(
@@ -245,16 +255,18 @@ impl TOTP {
     ///
     /// # Description
     /// * `secret`: expect a non-encoded value, to pass in base32 string use `Secret::Encoded(String)`
+    /// * `digits`: MUST be between 6 & 8
+    /// * `secret`: Must have bitsize of at least 128
+    /// * `account_name`: Must not contain `:`
+    /// * `issuer`: Must not contain `:`
+    ///
+    /// # Example
     ///
     /// ```rust
     /// use totp_rs::{Secret, TOTP, Algorithm};
     /// let secret = Secret::Encoded("OBWGC2LOFVZXI4TJNZTS243FMNZGK5BNGEZDG".to_string());
     /// let totp = TOTP::new(Algorithm::SHA1, 6, 1, 30, secret.to_bytes().unwrap(), None, "".to_string()).unwrap();
     /// ```
-    /// * `digits`: MUST be between 6 & 8
-    /// * `secret`: Must have bitsize of at least 128
-    /// * `account_name`: Must not contain `:`
-    /// * `issuer`: Must not contain `:`
     ///
     /// # Errors
     ///
@@ -293,6 +305,8 @@ impl TOTP {
     /// # Description
     /// * `secret`: expect a non-encoded value, to pass in base32 string use `Secret::Encoded(String)`
     ///
+    /// # Example
+    ///
     /// ```rust
     /// use totp_rs::{Secret, TOTP, Algorithm};
     /// let secret = Secret::Encoded("OBWGC2LOFVZXI4TJNZTS243FMNZGK5BNGEZDG".to_string());
@@ -323,14 +337,16 @@ impl TOTP {
     ///
     /// # Description
     /// * `secret`: expect a non-encoded value, to pass in base32 string use `Secret::Encoded(String)`
+    /// * `digits`: MUST be between 6 & 8
+    /// * `secret`: Must have bitsize of at least 128
+    ///
+    /// # Example
     ///
     /// ```rust
     /// use totp_rs::{Secret, TOTP, Algorithm};
     /// let secret = Secret::Encoded("OBWGC2LOFVZXI4TJNZTS243FMNZGK5BNGEZDG".to_string());
     /// let totp = TOTP::new(Algorithm::SHA1, 6, 1, 30, secret.to_bytes().unwrap()).unwrap();
     /// ```
-    /// * `digits`: MUST be between 6 & 8
-    /// * `secret`: Must have bitsize of at least 128
     ///
     /// # Errors
     ///
@@ -353,6 +369,8 @@ impl TOTP {
     /// # Description
     /// * `secret`: expect a non-encoded value, to pass in base32 string use `Secret::Encoded(String)`
     ///
+    /// # Example
+    ///
     /// ```rust
     /// use totp_rs::{Secret, TOTP, Algorithm};
     /// let secret = Secret::Encoded("OBWGC2LOFVZXI4TJNZTS243FMNZGK5BNGEZDG".to_string());
@@ -475,6 +493,7 @@ impl TOTP {
 
     /// Generate a TOTP from the standard otpauth URL
     #[cfg(feature = "otpauth")]
+    #[cfg_attr(docsrs, doc(cfg(feature = "otpauth")))]
     pub fn from_url<S: AsRef<str>>(url: S) -> Result<TOTP, TotpUrlError> {
         let (algorithm, digits, skew, step, secret, issuer, account_name) =
             Self::parts_from_url(url)?;
@@ -483,6 +502,7 @@ impl TOTP {
 
     /// Generate a TOTP from the standard otpauth URL, using `TOTP::new_unchecked` internally
     #[cfg(feature = "otpauth")]
+    #[cfg_attr(docsrs, doc(cfg(feature = "otpauth")))]
     pub fn from_url_unchecked<S: AsRef<str>>(url: S) -> Result<TOTP, TotpUrlError> {
         let (algorithm, digits, skew, step, secret, issuer, account_name) =
             Self::parts_from_url(url)?;
@@ -614,6 +634,7 @@ impl TOTP {
     /// Label and issuer will be URL-encoded if needed be
     /// Secret will be base 32'd without padding, as per RFC.
     #[cfg(feature = "otpauth")]
+    #[cfg_attr(docsrs, doc(cfg(feature = "otpauth")))]
     pub fn get_url(&self) -> String {
         #[allow(unused_mut)]
         let mut host = "totp";
@@ -645,6 +666,7 @@ impl TOTP {
 }
 
 #[cfg(feature = "qr")]
+#[cfg_attr(docsrs, doc(cfg(feature = "qr")))]
 impl TOTP {
     #[deprecated(
         since = "5.3.0",
@@ -665,7 +687,8 @@ impl TOTP {
     /// This would require the get_url method to generate an url bigger than 2000 characters,
     /// Which would be too long for some browsers anyway.
     ///
-    /// It will also return an error in case it can't encode the qr into a png. This shouldn't happen unless either the qrcode library returns malformed data, or the image library doesn't encode the data correctly
+    /// It will also return an error in case it can't encode the qr into a png.
+    /// This shouldn't happen unless either the qrcode library returns malformed data, or the image library doesn't encode the data correctly
     pub fn get_qr_base64(&self) -> Result<String, String> {
         let url = self.get_url();
         qrcodegen_image::draw_base64(&url)
@@ -680,7 +703,8 @@ impl TOTP {
     /// This would require the get_url method to generate an url bigger than 2000 characters,
     /// Which would be too long for some browsers anyway.
     ///
-    /// It will also return an error in case it can't encode the qr into a png. This shouldn't happen unless either the qrcode library returns malformed data, or the image library doesn't encode the data correctly
+    /// It will also return an error in case it can't encode the qr into a png.
+    /// This shouldn't happen unless either the qrcode library returns malformed data, or the image library doesn't encode the data correctly
     pub fn get_qr_png(&self) -> Result<Vec<u8>, String> {
         let url = self.get_url();
         qrcodegen_image::draw_png(&url)
diff --git a/src/rfc.rs b/src/rfc.rs
index 28cf83e..f1457cb 100644
--- a/src/rfc.rs
+++ b/src/rfc.rs
@@ -78,11 +78,13 @@ pub struct Rfc6238 {
     /// As per [rfc-4226](https://tools.ietf.org/html/rfc4226#section-4) the secret should come from a strong source, most likely a CSPRNG. It should be at least 128 bits, but 160 are recommended.
     secret: Vec<u8>,
     #[cfg(feature = "otpauth")]
+    #[cfg_attr(docsrs, doc(cfg(feature = "otpauth")))]
     /// The "Github" part of "Github:constantoine@github.com". Must not contain a colon `:`
     /// For example, the name of your service/website.
     /// Not mandatory, but strongly recommended!
     issuer: Option<String>,
     #[cfg(feature = "otpauth")]
+    #[cfg_attr(docsrs, doc(cfg(feature = "otpauth")))]
     /// The "constantoine@github.com" part of "Github:constantoine@github.com". Must not contain a colon `:`.
     /// For example, the name of your user's account.
     account_name: String,
@@ -156,12 +158,14 @@ impl Rfc6238 {
     }
 
     #[cfg(feature = "otpauth")]
+    #[cfg_attr(docsrs, doc(cfg(feature = "otpauth")))]
     /// Set the `issuer`.
     pub fn issuer(&mut self, value: String) {
         self.issuer = Some(value);
     }
 
     #[cfg(feature = "otpauth")]
+    #[cfg_attr(docsrs, doc(cfg(feature = "otpauth")))]
     /// Set the `account_name`.
     pub fn account_name(&mut self, value: String) {
         self.account_name = value;
diff --git a/src/secret.rs b/src/secret.rs
index 5487870..aea6c88 100644
--- a/src/secret.rs
+++ b/src/secret.rs
@@ -119,6 +119,7 @@ impl PartialEq for Secret {
 }
 
 #[cfg(feature = "gen_secret")]
+#[cfg_attr(docsrs, doc(cfg(feature = "gen_secret")))]
 impl Default for Secret {
     fn default() -> Self {
         Secret::generate_secret()
@@ -158,8 +159,6 @@ impl Secret {
         }
     }
 
-    /// ⚠️ requires feature `gen_secret`.
-    ///
     /// Generate a CSPRNG binary value of 160 bits,
     /// the recomended size from [rfc-4226](https://www.rfc-editor.org/rfc/rfc4226#section-4).
     ///
@@ -168,6 +167,7 @@ impl Secret {
     ///
     /// ⚠️ The generated secret is not guaranteed to be a valid UTF-8 sequence.
     #[cfg(feature = "gen_secret")]
+    #[cfg_attr(docsrs, doc(cfg(feature = "gen_secret")))]
     pub fn generate_secret() -> Secret {
         use rand::Rng;
 
diff --git a/src/url_error.rs b/src/url_error.rs
index fe7184b..7714317 100644
--- a/src/url_error.rs
+++ b/src/url_error.rs
@@ -8,6 +8,7 @@ use crate::Rfc6238Error;
 pub enum TotpUrlError {
     /// Couldn't decode URL.
     #[cfg(feature = "otpauth")]
+    #[cfg_attr(docsrs, doc(cfg(feature = "otpauth")))]
     Url(ParseError),
     /// Invalid scheme.
     Scheme(String),