Skip to content

Commit

Permalink
docs: add comprehensive documentation
Browse files Browse the repository at this point in the history
Add extensive documentation across the entire codebase:
- Module overviews and architecture explanations
- Type and trait documentation with examples
- Method documentation including error and panic conditions
- Cross-references between related components

This improves code maintainability and makes the library
more accessible to new users and contributors.

Documentation generated with assistance from GitHub Copilot
Claude 3.5 Sonnet.
  • Loading branch information
roderickvd committed Nov 29, 2024
1 parent 059a116 commit 7e3e551
Show file tree
Hide file tree
Showing 31 changed files with 4,676 additions and 567 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html)
and [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/).

## [Unreleased]

### Added
- [docs] Comprehensive documentation for all public APIs and internals

## [0.3.0] - 2024-11-28

### Added
Expand Down Expand Up @@ -67,6 +72,7 @@ Initial release of pleezer, a headless streaming player for the Deezer Connect p
- Debug and trace logging capabilities
- Command-line interface with various configuration options

[Unreleased]: https://github.com/roderickvd/pleezer/compare/v0.3.0...HEAD
[0.3.0]: https://github.com/roderickvd/pleezer/releases/tag/v0.3.0
[0.2.0]: https://github.com/roderickvd/pleezer/releases/tag/v0.2.0
[0.1.0]: https://github.com/roderickvd/pleezer/releases/tag/v0.1.0
8 changes: 3 additions & 5 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,9 @@ name = "pleezer"
path = "src/main.rs"
required-features = ["binary"]

[lib]
doctest = false

[dependencies.clap]
version = "4.0"
features = ["cargo", "derive", "env", "wrap_help"]
Expand Down Expand Up @@ -136,8 +139,3 @@ extended-description = """\
A headless streaming player built around the Deezer Connect protocol. \
Enables streaming from Deezer to any Linux system without a graphical interface, \
making it ideal for DIY setups, server-based systems, or custom integrations."""

[package.metadata.docs.rs]
# Disable documentation build on docs.rs
# Remove this section when ready to publish documentation
private = true
146 changes: 142 additions & 4 deletions src/arl.rs
Original file line number Diff line number Diff line change
@@ -1,33 +1,140 @@
use veil::Redact;
//! ARL validation and handling.
//!
//! Provides secure handling of Authentication Reference Links (ARLs) with:
//! * Validation of token format
//! * Cookie-safe character checking
//! * Automatic URL parsing
//! * Debug redaction
//!
//! # Security
//!
//! ARLs are sensitive credentials that provide full account access. This
//! implementation:
//! * Validates token contents
//! * Redacts tokens in debug output
//! * Uses constant-time comparison
//! * Prevents logging/display
//!
//! # Examples
//!
//! ```rust
//! use std::str::FromStr;
//! use pleezer::arl::Arl;
//!
//! // Parse and validate an ARL
//! let arl = Arl::from_str("valid_token")?;
//!
//! // Handles full callback URLs
//! let arl = Arl::from_str("deezer://autolog/valid_token")?;
//!
//! // Rejects invalid characters
//! assert!(Arl::from_str("invalid;token").is_err());
//! ```
use crate::error::{Error, Result};
use std::{fmt, ops::Deref, str::FromStr};
use veil::Redact;

/// Authentication Reference Link for Deezer services.
///
/// Provides validated storage and handling of ARL tokens, ensuring they
/// contain only cookie-safe characters and are properly formatted.
///
/// # Validation
///
/// ARLs must:
/// * Contain only ASCII characters
/// * Not contain control characters or whitespace
/// * Not contain `"`, `,`, `;`, or `\`
/// * Be extractable from callback URLs
///
/// # Security Notes
///
/// ARLs should be treated as sensitive credentials:
/// * Store securely
/// * Never log or display
/// * Protect from unauthorized access
/// * Validate all input
#[derive(Clone, Redact, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[redact(all)]
pub struct Arl(String);

impl Arl {
/// TODO
/// Creates a new validated ARL from a string.
///
/// # Arguments
///
/// * `arl` - The ARL string to validate and wrap
///
/// # Errors
///
/// Will return `Err` if:
/// - `arl` contains invalid characters
/// Returns `Error::InvalidArgument` if the string contains:
/// * Non-ASCII characters
/// * ASCII control characters
/// * Whitespace
/// * Special characters: `"`, `,`, `;`, `\`
///
/// # Examples
///
/// ```rust
/// use pleezer::arl::Arl;
///
/// // Valid ARL
/// let arl = Arl::new("valid_token".to_string())?;
///
/// // Invalid characters
/// assert!(Arl::new("invalid;token".to_string()).is_err());
/// assert!(Arl::new("spaces not allowed".to_string()).is_err());
/// assert!(Arl::new("控制字符".to_string()).is_err());
/// ```
pub fn new(arl: String) -> Result<Self> {
Ok(Self(arl))
}
}

impl Deref for Arl {
/// Target type for deref coercion.
///
/// Allows read-only access to the underlying string while maintaining
/// validation invariants.
type Target = String;

/// Provides read-only access to the validated ARL string.
///
/// # Examples
///
/// ```rust
/// use pleezer::arl::Arl;
///
/// let arl = Arl::new("token123".to_string())?;
/// assert_eq!(arl.len(), 8); // Access String methods
/// assert_eq!(&*arl, "token123"); // Direct string access
/// ```
fn deref(&self) -> &Self::Target {
&self.0
}
}

impl fmt::Display for Arl {
/// Formats the ARL for string representation.
///
/// Note: While this implementation allows displaying the token,
/// this should only be used when absolutely necessary, as it
/// exposes sensitive credentials.
///
/// # Examples
///
/// ```rust
/// use pleezer::arl::Arl;
///
/// let arl = Arl::new("token123".to_string())?;
///
/// // Avoid this in production code:
/// println!("{}", arl); // Prints: token123
///
/// // Debug output is safely redacted:
/// println!("{:?}", arl); // Prints: Arl("REDACTED")
/// ```
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)
}
Expand All @@ -36,6 +143,37 @@ impl fmt::Display for Arl {
impl FromStr for Arl {
type Err = Error;

/// Parses and validates an ARL from a string.
///
/// This implementation:
/// 1. Extracts the token from callback URLs if present
/// 2. Validates all characters for cookie safety
/// 3. Creates a new validated ARL instance
///
/// # Examples
///
/// ```rust
/// use std::str::FromStr;
/// use pleezer::arl::Arl;
///
/// // Direct token
/// let arl = Arl::from_str("valid_token")?;
///
/// // From callback URL
/// let arl = Arl::from_str("deezer://autolog/valid_token")?;
///
/// // Invalid characters
/// assert!(Arl::from_str("invalid;token").is_err());
/// ```
///
/// # Errors
///
/// Returns `Error::InvalidArgument` if:
/// * The string contains non-cookie-safe characters:
/// - Non-ASCII characters
/// - Control characters
/// - Whitespace
/// - Special characters (`"`, `,`, `;`, `\`)
fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
let mut arl = s;

Expand Down
Loading

0 comments on commit 7e3e551

Please sign in to comment.