Skip to main content

product_os_random/
lib.rs

1//! # Product OS Random
2//!
3//! A random number generation library providing cryptographically secure RNGs,
4//! random text/number generators, and word/name generators. Supports `no_std` environments.
5//!
6//! ## Features
7//!
8//! This crate provides multiple feature flags to control functionality and dependencies:
9//!
10//! ### Core Features
11//! - `default` - Basic random generation with `StdRng` and getrandom support
12//! - `core` - Full standard library support with `StdRng`, `ThreadRng`, and `OsRng`
13//! - `send_only` - Send-safe RNG variants only
14//! - `constrained` - Minimal allocation-only mode (no default RNG, user must provide)
15//! - `custom` - Custom RNG support with spin locks for `no_std` environments
16//! - `custom_send_only` - Custom Send-safe RNG support
17//!
18//! ### Dataset Features
19//! - `words` - Enable random word generation
20//! - `nouns` - Enable random noun generation
21//! - `adjectives` - Enable random adjective generation
22//! - `names` - Enable random full name generation
23//! - `first_names` - Enable random first name generation
24//! - `last_names` - Enable random last name generation
25//!
26//! ## Security Considerations
27//!
28//! ### Cryptographic vs Non-Cryptographic RNGs
29//!
30//! - **`CryptoRNG`**: Use for security-sensitive operations (passwords, keys, tokens).
31//!   Implements `CryptoRng` marker trait indicating cryptographic security.
32//! - **`RNG`**: General-purpose random generation. Some variants are cryptographically
33//!   secure (like `OsRng`), others are not (like seeded `StdRng`).
34//!
35//! ### Thread Safety
36//!
37//! - `RNG::Thread` uses `ThreadRng` which is thread-local
38//! - Custom RNG wrappers use `Arc<Mutex<>>` for thread-safe access
39//! - All RNG variants implement `Clone` for easy distribution
40//!
41//! ## Usage Examples
42//!
43//! ### Convenience Functions (Recommended)
44//!
45//! The simplest way to generate random data:
46//!
47//! ```rust
48//! # #[cfg(feature = "core")]
49//! # {
50//! let password = product_os_random::random_password(16);
51//! let code = product_os_random::random_alphanumeric(10);
52//! let port = product_os_random::random_usize(1025, 65535);
53//! let bytes = product_os_random::random_bytes(32);
54//! let key = product_os_random::generate_random_key(32);
55//! # }
56//! ```
57//!
58//! ### Stateful Generator with Custom RNG
59//!
60//! ```rust
61//! # #[cfg(feature = "core")]
62//! # {
63//! use product_os_random::{RandomGenerator, RandomGeneratorTemplate, RNG};
64//! use rand::SeedableRng;
65//!
66//! // Create a seeded RNG for reproducible results
67//! let rng = RNG::Std(rand::rngs::StdRng::seed_from_u64(42));
68//! let mut gen = RandomGenerator::new(Some(rng));
69//!
70//! // Generate random data
71//! let bytes = gen.get_random_bytes(32);
72//! let number = gen.get_random_usize(1, 100);
73//! let alphanumeric = gen.get_random_alphanumeric(10);
74//! # }
75//! ```
76//!
77//! ### Cryptographic Key Generation
78//!
79//! ```rust
80//! # #[cfg(feature = "core")]
81//! # {
82//! use product_os_random::RandomGenerator;
83//!
84//! // Generate a cryptographic key
85//! let key = RandomGenerator::generate_simple_key_one_time(32);
86//! assert_eq!(key.len(), 32);
87//! # }
88//! ```
89//!
90//! ### Using Feature-Gated Name Generation
91//!
92//! ```rust
93//! # #[cfg(all(feature = "core", feature = "names"))]
94//! # {
95//! use product_os_random::RandomGenerator;
96//!
97//! let username = RandomGenerator::get_simple_random_username_one_time(
98//!     Some(2),
99//!     Some(4),
100//!     Some("_".to_string())
101//! );
102//!
103//! let email = RandomGenerator::get_simple_random_email_one_time(
104//!     Some(2),
105//!     Some(3),
106//!     None,
107//!     vec!["example.com".to_string()]
108//! );
109//! # }
110//! ```
111//!
112//! ### Custom RNG Implementation
113//!
114//! ```rust
115//! # #[cfg(feature = "custom")]
116//! # {
117//! use product_os_random::{CustomRng, RNG};
118//! use rand::SeedableRng;
119//!
120//! let seed_rng = rand::rngs::StdRng::seed_from_u64(42);
121//! let custom = CustomRng::new(seed_rng);
122//! let rng = RNG::Custom(custom);
123//! # }
124//! ```
125//!
126//! ## Performance Characteristics
127//!
128//! - **String Generation**: Pre-allocates with `String::with_capacity` for efficiency
129//! - **Large Datasets**: Names datasets are large (~400K lines total), consider binary size
130//! - **Lock Contention**: Custom RNGs use mutexes, may have contention under high concurrency
131//! - **`no_std` Support**: Minimal overhead when used without standard library features
132
133#![no_std]
134// Clippy configuration
135#![warn(clippy::all, clippy::pedantic, clippy::cargo)]
136#![warn(missing_docs)]
137// Allow certain patterns that are intentional
138#![allow(clippy::module_name_repetitions)] // RandomGenerator naming is intentional
139#![allow(clippy::similar_names)] // rng, gen are standard in RNG code
140#![allow(unreachable_patterns)] // Patterns may be unreachable with certain feature combinations
141#![allow(clippy::too_many_lines)] // Large file is acceptable for now, will refactor later
142#![allow(clippy::must_use_candidate)] // Many functions could use #[must_use], will add gradually
143#![allow(clippy::missing_errors_doc)] // Error docs will be added with try_ variants
144#![allow(clippy::missing_panics_doc)] // Panic docs exist in main documentation
145#![allow(clippy::missing_docs_in_private_items)] // Private items don't need docs
146#![allow(clippy::if_same_then_else)] // Feature-gated code may look identical but isn't
147
148extern crate alloc;
149
150use alloc::string::String;
151#[cfg(any(feature = "custom", feature = "custom_send_only"))]
152use alloc::sync::Arc;
153#[cfg(feature = "rand")]
154use alloc::vec;
155use alloc::vec::Vec;
156
157#[cfg(feature = "adjectives")]
158mod adjectives;
159#[cfg(feature = "first_names")]
160mod first_names;
161#[cfg(feature = "last_names")]
162mod last_names;
163#[cfg(feature = "names")]
164mod names;
165#[cfg(feature = "nouns")]
166mod nouns;
167#[cfg(feature = "words")]
168mod words;
169
170#[cfg(any(feature = "core", feature = "send_only"))]
171pub use rand::rngs::StdRng;
172
173#[cfg(all(feature = "core", not(feature = "send_only")))]
174pub use rand::rngs::ThreadRng;
175
176#[cfg(feature = "core")]
177pub use rand::rngs::OsRng;
178
179#[cfg(feature = "custom")]
180pub use getrandom::register_custom_getrandom;
181
182#[cfg(feature = "rand")]
183pub use rand::{CryptoRng, Error, Rng, RngCore, SeedableRng};
184
185// Helper functions for character filtering and range operations
186// These reduce code duplication and fix clippy warnings
187
188/// Filters a character value to exclude certain special characters.
189/// Used in random string generation to ensure printable, alphanumeric-focused output.
190///
191/// Character ranges that get shifted:
192/// - 33-37 → +20 (shifts to 53-57, which are '5' to '9')
193/// - 38-47 → +10 (shifts to 48-57, which are '0' to '9')
194/// - 58-64 → +10 (shifts to 68-74, which are 'D' to 'J')
195/// - 91-96 → +10 (shifts to 101-106, which are 'e' to 'j')
196#[cfg(feature = "rand")]
197#[inline]
198fn filter_printable_char(mut value: u8) -> u8 {
199    if (33..=37).contains(&value) {
200        value += 20;
201    } else if (38..=47).contains(&value) {
202        value += 10;
203    } else if (58..=64).contains(&value) {
204        value += 10;
205    } else if (91..=96).contains(&value) {
206        value += 10;
207    }
208    value
209}
210
211/// Filters a character value for alphanumeric output (0-9, a-z, A-Z).
212///
213/// Character ranges that get shifted:
214/// - 58-64 → +10 (shifts to A-Z range)
215/// - 91-96 → +10 (shifts to a-z range)
216#[cfg(feature = "rand")]
217#[inline]
218fn filter_alphanumeric_char(mut value: u8) -> u8 {
219    if (58..=64).contains(&value) {
220        value += 10;
221    } else if (91..=96).contains(&value) {
222        value += 10;
223    }
224    value
225}
226
227/// Converts a string to title case (first letter uppercase, rest lowercase).
228///
229/// This is a simple implementation for single-word name data, replacing the
230/// `inflections` crate dependency. Handles Unicode correctly via `char::to_uppercase`
231/// and `char::to_lowercase`.
232#[cfg(any(feature = "first_names", feature = "last_names"))]
233#[allow(dead_code)]
234fn to_title_case(s: &str) -> String {
235    let mut chars = s.chars();
236    match chars.next() {
237        None => String::new(),
238        Some(first) => {
239            let mut result = String::with_capacity(s.len());
240            for c in first.to_uppercase() {
241                result.push(c);
242            }
243            for c in chars {
244                for lc in c.to_lowercase() {
245                    result.push(lc);
246                }
247            }
248            result
249        }
250    }
251}
252
253/// A thread-safe wrapper around any `RngCore` implementation for use in `no_std` environments.
254///
255/// This type wraps an RNG in `Arc<Mutex<>>` using a spin lock, making it shareable across
256/// threads in `no_std` contexts. The mutex ensures safe concurrent access to the underlying RNG.
257///
258/// # Thread Safety
259///
260/// Uses spin locks from the `spin` crate, which are suitable for `no_std` environments.
261/// Under high contention, spin locks may consume CPU cycles waiting for the lock.
262///
263/// # Examples
264///
265/// ```rust
266/// # #[cfg(feature = "custom")]
267/// # {
268/// use product_os_random::CustomRng;
269/// use rand::SeedableRng;
270///
271/// let seed_rng = rand::rngs::StdRng::seed_from_u64(42);
272/// let custom = CustomRng::new(seed_rng);
273/// # }
274/// ```
275#[cfg(feature = "custom")]
276#[derive(Clone)]
277pub struct CustomRng {
278    rng: Arc<spin::mutex::Mutex<dyn RngCore>>,
279}
280
281#[cfg(feature = "custom")]
282impl CustomRng {
283    /// Creates a new `CustomRng` wrapping the provided RNG.
284    ///
285    /// The RNG is wrapped in `Arc<Mutex<>>` to enable thread-safe cloning and concurrent access.
286    ///
287    /// # Examples
288    ///
289    /// ```rust
290    /// # #[cfg(feature = "custom")]
291    /// # {
292    /// use product_os_random::CustomRng;
293    /// use rand::SeedableRng;
294    ///
295    /// let rng = rand::rngs::StdRng::seed_from_u64(42);
296    /// let custom = CustomRng::new(rng);
297    /// # }
298    /// ```
299    pub fn new(rng: impl RngCore + 'static) -> Self {
300        Self {
301            rng: Arc::new(spin::mutex::Mutex::new(rng)),
302        }
303    }
304}
305
306#[cfg(feature = "custom")]
307impl RngCore for CustomRng {
308    fn next_u32(&mut self) -> u32 {
309        let mut rl = self.rng.lock();
310        rl.next_u32()
311    }
312
313    fn next_u64(&mut self) -> u64 {
314        let mut rl = self.rng.lock();
315        rl.next_u64()
316    }
317
318    fn fill_bytes(&mut self, dest: &mut [u8]) {
319        let mut rl = self.rng.lock();
320        rl.fill_bytes(dest);
321    }
322
323    fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
324        let mut rl = self.rng.lock();
325        rl.try_fill_bytes(dest)
326    }
327}
328
329/// Marker trait for cryptographically secure RNGs.
330///
331/// This trait combines `RngCore` and `CryptoRng` to indicate that an RNG is suitable
332/// for security-sensitive operations like key generation, password creation, and token generation.
333///
334/// # Security
335///
336/// Implementors of this trait must provide cryptographically secure random number generation.
337/// This typically means:
338/// - Output is indistinguishable from true randomness
339/// - Past outputs don't reveal future outputs
340/// - Sufficient entropy from a secure source
341///
342/// # Examples
343///
344/// ```rust
345/// # #[cfg(feature = "custom")]
346/// # {
347/// use product_os_random::{RngCore, CryptoRng, RngCrypto, Error};
348/// use rand::SeedableRng;
349///
350/// struct MyCryptoRng(rand::rngs::StdRng);
351///
352/// impl RngCore for MyCryptoRng {
353///     fn next_u32(&mut self) -> u32 { self.0.next_u32() }
354///     fn next_u64(&mut self) -> u64 { self.0.next_u64() }
355///     fn fill_bytes(&mut self, dest: &mut [u8]) { self.0.fill_bytes(dest) }
356///     fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
357///         self.0.try_fill_bytes(dest)
358///     }
359/// }
360///
361/// impl CryptoRng for MyCryptoRng {}
362/// impl RngCrypto for MyCryptoRng {}
363/// # }
364/// ```
365#[cfg(any(feature = "custom", feature = "custom_send_only"))]
366pub trait RngCrypto: RngCore + CryptoRng {}
367
368/// A thread-safe wrapper around cryptographically secure RNGs for use in `no_std` environments.
369///
370/// Similar to `CustomRng`, but specifically for RNGs that implement the `RngCrypto` trait,
371/// providing additional type safety for cryptographic operations.
372///
373/// # Security
374///
375/// This type should only wrap RNGs that are cryptographically secure. The wrapper itself
376/// doesn't add or remove security properties, it only provides thread-safe access.
377///
378/// # Examples
379///
380/// ```rust
381/// # #[cfg(feature = "custom")]
382/// # {
383/// use product_os_random::{CustomCryptoRng, RngCore, CryptoRng, RngCrypto, Error};
384/// use rand::SeedableRng;
385///
386/// #[derive(Clone)]
387/// struct MyCryptoRng(rand::rngs::StdRng);
388///
389/// impl RngCore for MyCryptoRng {
390///     fn next_u32(&mut self) -> u32 { self.0.next_u32() }
391///     fn next_u64(&mut self) -> u64 { self.0.next_u64() }
392///     fn fill_bytes(&mut self, dest: &mut [u8]) { self.0.fill_bytes(dest) }
393///     fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
394///         self.0.try_fill_bytes(dest)
395///     }
396/// }
397///
398/// impl CryptoRng for MyCryptoRng {}
399/// impl RngCrypto for MyCryptoRng {}
400///
401/// let rng = MyCryptoRng(rand::rngs::StdRng::seed_from_u64(42));
402/// let custom = CustomCryptoRng::new(rng);
403/// # }
404/// ```
405#[derive(Clone)]
406#[cfg(feature = "custom")]
407pub struct CustomCryptoRng {
408    rng: Arc<spin::mutex::Mutex<dyn RngCrypto>>,
409}
410
411#[cfg(feature = "custom")]
412impl CustomCryptoRng {
413    /// Creates a new `CustomCryptoRng` wrapping the provided cryptographic RNG.
414    ///
415    /// # Security
416    ///
417    /// The provided RNG must implement `RngCrypto`, ensuring it's suitable for
418    /// cryptographic operations.
419    ///
420    /// # Examples
421    ///
422    /// ```rust
423    /// # #[cfg(feature = "custom")]
424    /// # {
425    /// use product_os_random::{CustomCryptoRng, RngCore, CryptoRng, RngCrypto, Error};
426    /// use rand::SeedableRng;
427    ///
428    /// #[derive(Clone)]
429    /// struct MyCryptoRng(rand::rngs::StdRng);
430    ///
431    /// impl RngCore for MyCryptoRng {
432    ///     fn next_u32(&mut self) -> u32 { self.0.next_u32() }
433    ///     fn next_u64(&mut self) -> u64 { self.0.next_u64() }
434    ///     fn fill_bytes(&mut self, dest: &mut [u8]) { self.0.fill_bytes(dest) }
435    ///     fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
436    ///         self.0.try_fill_bytes(dest)
437    ///     }
438    /// }
439    ///
440    /// impl CryptoRng for MyCryptoRng {}
441    /// impl RngCrypto for MyCryptoRng {}
442    ///
443    /// let rng = MyCryptoRng(rand::rngs::StdRng::seed_from_u64(42));
444    /// let custom = CustomCryptoRng::new(rng);
445    /// # }
446    /// ```
447    pub fn new(rng: impl RngCrypto + 'static) -> Self {
448        Self {
449            rng: Arc::new(spin::mutex::Mutex::new(rng)),
450        }
451    }
452}
453
454#[cfg(feature = "custom")]
455impl RngCrypto for CustomCryptoRng {}
456
457#[cfg(feature = "custom")]
458impl CryptoRng for CustomCryptoRng {}
459
460#[cfg(feature = "custom")]
461impl RngCore for CustomCryptoRng {
462    fn next_u32(&mut self) -> u32 {
463        let mut rl = self.rng.lock();
464        rl.next_u32()
465    }
466
467    fn next_u64(&mut self) -> u64 {
468        let mut rl = self.rng.lock();
469        rl.next_u64()
470    }
471
472    fn fill_bytes(&mut self, dest: &mut [u8]) {
473        let mut rl = self.rng.lock();
474        rl.fill_bytes(dest);
475    }
476
477    fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
478        let mut rl = self.rng.lock();
479        rl.try_fill_bytes(dest)
480    }
481}
482
483/// Unified RNG enum supporting multiple random number generator backends.
484///
485/// This enum provides a common interface over different RNG implementations, allowing
486/// users to choose the appropriate RNG for their use case while maintaining a consistent API.
487///
488/// # Variants
489///
490/// - `Std` - Standard RNG (`StdRng`) - Fast, suitable for general use, can be seeded for reproducibility
491/// - `Thread` - Thread-local RNG (`ThreadRng`) - Convenient, automatically seeded, thread-local
492/// - `OS` - Operating system RNG (`OsRng`) - Cryptographically secure, uses OS entropy
493/// - `Custom` - Custom RNG wrapper - For user-provided RNG implementations
494/// - `CustomRaw` - Raw custom RNG with Arc/Mutex - For advanced use cases
495/// - `CustomRawSend` - Send-safe raw custom RNG - For concurrent scenarios
496/// - `CustomCrypto` - Custom cryptographic RNG - For custom crypto implementations
497/// - `CustomCryptoRaw` - Raw custom crypto RNG - Advanced crypto use cases
498/// - `CustomCryptoRawSend` - Send-safe raw custom crypto RNG - Concurrent crypto scenarios
499///
500/// # Feature Flags
501///
502/// Different variants are available under different feature flags:
503/// - `Std` requires `core` or `send_only`
504/// - `Thread` and `OS` require `core`
505/// - Custom variants require `custom` or `custom_send_only`
506///
507/// # Examples
508///
509/// ```rust
510/// # #[cfg(feature = "core")]
511/// # {
512/// use product_os_random::{RNG, RngCore};
513/// use rand::SeedableRng;
514///
515/// // Create a seeded RNG for reproducible results
516/// let rng = RNG::Std(rand::rngs::StdRng::seed_from_u64(42));
517///
518/// // Or use OS randomness for cryptographic security
519/// let crypto_rng = RNG::OS(rand::rngs::OsRng);
520/// # }
521/// ```
522///
523/// # Performance
524///
525/// - `StdRng`: Fast, suitable for simulations and general use
526/// - `ThreadRng`: Fast, convenient, good default choice
527/// - `OsRng`: Slower but cryptographically secure
528/// - Custom variants: Performance depends on the wrapped RNG
529///
530/// # Size Note
531///
532/// This enum has a large size difference between variants (`StdRng` is ~312 bytes while others
533/// are ~16 bytes). This is intentional to avoid boxing and maintain API compatibility.
534#[cfg(feature = "rand")]
535#[allow(clippy::large_enum_variant)]
536#[derive(Clone)]
537pub enum RNG {
538    /// Standard RNG (`StdRng`) - Fast, can be seeded for reproducible results.
539    #[cfg(any(feature = "core", feature = "send_only"))]
540    Std(StdRng),
541    /// Thread-local RNG (`ThreadRng`) - Convenient, automatically seeded, thread-local.
542    /// Excluded when `send_only` is active since `ThreadRng` is not `Send`.
543    #[cfg(all(feature = "core", not(feature = "send_only")))]
544    Thread(ThreadRng),
545    /// Operating system RNG (`OsRng`) - Cryptographically secure, uses OS entropy.
546    #[cfg(feature = "core")]
547    OS(OsRng),
548    /// Custom RNG wrapper - For user-provided RNG implementations.
549    #[cfg(feature = "custom")]
550    Custom(CustomRng),
551    /// Raw custom RNG with Arc/Mutex - For advanced use cases.
552    #[cfg(feature = "custom")]
553    CustomRaw(Arc<spin::mutex::Mutex<dyn RngCore>>),
554    /// Send-safe raw custom RNG - For concurrent scenarios.
555    #[cfg(any(feature = "custom", feature = "custom_send_only"))]
556    CustomRawSend(Arc<spin::mutex::Mutex<dyn RngCore + Send>>),
557    /// Custom cryptographic RNG - For custom crypto implementations.
558    #[cfg(feature = "custom")]
559    CustomCrypto(CustomCryptoRng),
560    /// Raw custom crypto RNG - Advanced crypto use cases.
561    #[cfg(feature = "custom")]
562    CustomCryptoRaw(Arc<spin::mutex::Mutex<dyn RngCrypto>>),
563    /// Send-safe raw custom crypto RNG - Concurrent crypto scenarios.
564    #[cfg(any(feature = "custom", feature = "custom_send_only"))]
565    CustomCryptoRawSend(Arc<spin::mutex::Mutex<dyn RngCrypto + Send>>),
566}
567
568#[cfg(feature = "rand")]
569impl RngCore for RNG {
570    fn next_u32(&mut self) -> u32 {
571        match self {
572            #[cfg(any(feature = "core", feature = "send_only"))]
573            RNG::Std(r) => r.next_u32(),
574            #[cfg(all(feature = "core", not(feature = "send_only")))]
575            RNG::Thread(r) => r.next_u32(),
576            #[cfg(feature = "core")]
577            RNG::OS(r) => r.next_u32(),
578            #[cfg(feature = "custom")]
579            RNG::Custom(r) => r.next_u32(),
580            #[cfg(feature = "custom")]
581            RNG::CustomRaw(r) => {
582                let mut rl = r.lock();
583                rl.next_u32()
584            }
585            #[cfg(any(feature = "custom", feature = "custom_send_only"))]
586            RNG::CustomRawSend(r) => {
587                let mut rl = r.lock();
588                rl.next_u32()
589            }
590            #[cfg(feature = "custom")]
591            RNG::CustomCrypto(r) => r.next_u32(),
592            #[cfg(feature = "custom")]
593            RNG::CustomCryptoRaw(r) => {
594                let mut rl = r.lock();
595                rl.next_u32()
596            }
597            #[cfg(any(feature = "custom", feature = "custom_send_only"))]
598            RNG::CustomCryptoRawSend(r) => {
599                let mut rl = r.lock();
600                rl.next_u32()
601            }
602            _ => panic!("No known random generator"),
603        }
604    }
605
606    fn next_u64(&mut self) -> u64 {
607        match self {
608            #[cfg(any(feature = "core", feature = "send_only"))]
609            RNG::Std(r) => r.next_u64(),
610            #[cfg(all(feature = "core", not(feature = "send_only")))]
611            RNG::Thread(r) => r.next_u64(),
612            #[cfg(feature = "core")]
613            RNG::OS(r) => r.next_u64(),
614            #[cfg(feature = "custom")]
615            RNG::Custom(r) => r.next_u64(),
616            #[cfg(feature = "custom")]
617            RNG::CustomRaw(r) => {
618                let mut rl = r.lock();
619                rl.next_u64()
620            }
621            #[cfg(any(feature = "custom", feature = "custom_send_only"))]
622            RNG::CustomRawSend(r) => {
623                let mut rl = r.lock();
624                rl.next_u64()
625            }
626            #[cfg(feature = "custom")]
627            RNG::CustomCrypto(r) => r.next_u64(),
628            #[cfg(feature = "custom")]
629            RNG::CustomCryptoRaw(r) => {
630                let mut rl = r.lock();
631                rl.next_u64()
632            }
633            #[cfg(any(feature = "custom", feature = "custom_send_only"))]
634            RNG::CustomCryptoRawSend(r) => {
635                let mut rl = r.lock();
636                rl.next_u64()
637            }
638            _ => panic!("No known random generator"),
639        }
640    }
641
642    #[allow(unused_variables)]
643    fn fill_bytes(&mut self, dest: &mut [u8]) {
644        match self {
645            #[cfg(any(feature = "core", feature = "send_only"))]
646            RNG::Std(r) => r.fill_bytes(dest),
647            #[cfg(all(feature = "core", not(feature = "send_only")))]
648            RNG::Thread(r) => r.fill_bytes(dest),
649            #[cfg(feature = "core")]
650            RNG::OS(r) => r.fill_bytes(dest),
651            #[cfg(feature = "custom")]
652            RNG::Custom(r) => r.fill_bytes(dest),
653            #[cfg(feature = "custom")]
654            RNG::CustomRaw(r) => {
655                let mut rl = r.lock();
656                rl.fill_bytes(dest);
657            }
658            #[cfg(any(feature = "custom", feature = "custom_send_only"))]
659            RNG::CustomRawSend(r) => {
660                let mut rl = r.lock();
661                rl.fill_bytes(dest);
662            }
663            #[cfg(feature = "custom")]
664            RNG::CustomCrypto(r) => r.fill_bytes(dest),
665            #[cfg(feature = "custom")]
666            RNG::CustomCryptoRaw(r) => {
667                let mut rl = r.lock();
668                rl.fill_bytes(dest);
669            }
670            #[cfg(any(feature = "custom", feature = "custom_send_only"))]
671            RNG::CustomCryptoRawSend(r) => {
672                let mut rl = r.lock();
673                rl.fill_bytes(dest);
674            }
675            _ => panic!("No known random generator"),
676        }
677    }
678
679    #[allow(unused_variables)]
680    fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
681        match self {
682            #[cfg(any(feature = "core", feature = "send_only"))]
683            RNG::Std(r) => r.try_fill_bytes(dest),
684            #[cfg(all(feature = "core", not(feature = "send_only")))]
685            RNG::Thread(r) => r.try_fill_bytes(dest),
686            #[cfg(feature = "core")]
687            RNG::OS(r) => r.try_fill_bytes(dest),
688            #[cfg(feature = "custom")]
689            RNG::Custom(r) => r.try_fill_bytes(dest),
690            #[cfg(feature = "custom")]
691            RNG::CustomRaw(r) => {
692                let mut rl = r.lock();
693                rl.try_fill_bytes(dest)
694            }
695            #[cfg(any(feature = "custom", feature = "custom_send_only"))]
696            RNG::CustomRawSend(r) => {
697                let mut rl = r.lock();
698                rl.try_fill_bytes(dest)
699            }
700            #[cfg(feature = "custom")]
701            RNG::CustomCrypto(r) => r.try_fill_bytes(dest),
702            #[cfg(feature = "custom")]
703            RNG::CustomCryptoRaw(r) => {
704                let mut rl = r.lock();
705                rl.try_fill_bytes(dest)
706            }
707            #[cfg(any(feature = "custom", feature = "custom_send_only"))]
708            RNG::CustomCryptoRawSend(r) => {
709                let mut rl = r.lock();
710                rl.try_fill_bytes(dest)
711            }
712            _ => panic!("No known random generator"),
713        }
714    }
715}
716
717/// Unified cryptographically secure RNG enum.
718///
719/// Similar to `RNG`, but all variants implement the `CryptoRng` marker trait, indicating
720/// they are suitable for security-sensitive operations.
721///
722/// # Security Guarantee
723///
724/// All variants of this enum provide cryptographically secure random number generation,
725/// suitable for:
726/// - Key generation
727/// - Password creation
728/// - Security tokens
729/// - Cryptographic nonces
730/// - Any security-critical random data
731///
732/// # Variants
733///
734/// - `Std` - `StdRng` (when used with proper entropy source)
735/// - `Thread` - `ThreadRng` (cryptographically secure)
736/// - `OS` - `OsRng` (uses OS-provided cryptographic RNG)
737/// - `CustomCrypto` - Custom crypto RNG wrapper
738/// - `CustomCryptoRaw` - Raw custom crypto RNG
739/// - `CustomCryptoRawSend` - Send-safe raw custom crypto RNG
740///
741/// # Examples
742///
743/// ```rust
744/// # #[cfg(feature = "core")]
745/// # {
746/// use product_os_random::{CryptoRNG, RngCore, CryptoRng};
747///
748/// // Use OS randomness for maximum security
749/// let mut rng = CryptoRNG::OS(rand::rngs::OsRng);
750///
751/// // Generate cryptographically secure random bytes
752/// let mut key = [0u8; 32];
753/// rng.fill_bytes(&mut key);
754/// # }
755/// ```
756///
757/// # Performance
758///
759/// Cryptographic RNGs are generally slower than non-cryptographic ones, as they
760/// must maintain security properties. `OsRng` may block if entropy is not available.
761///
762/// # Size Note
763///
764/// This enum has a large size difference between variants (`StdRng` is ~312 bytes while others
765/// are ~16 bytes). This is intentional to avoid boxing and maintain API compatibility.
766#[cfg(feature = "rand")]
767#[allow(clippy::large_enum_variant)]
768#[derive(Clone)]
769pub enum CryptoRNG {
770    /// Standard RNG (`StdRng`) - When used with proper entropy source.
771    #[cfg(any(feature = "core", feature = "send_only"))]
772    Std(StdRng),
773    /// Thread-local RNG (`ThreadRng`) - Cryptographically secure.
774    /// Excluded when `send_only` is active since `ThreadRng` is not `Send`.
775    #[cfg(all(feature = "core", not(feature = "send_only")))]
776    Thread(ThreadRng),
777    /// Operating system RNG (`OsRng`) - Uses OS-provided cryptographic RNG.
778    #[cfg(feature = "core")]
779    OS(OsRng),
780    /// Custom cryptographic RNG wrapper.
781    #[cfg(feature = "custom")]
782    CustomCrypto(CustomCryptoRng),
783    /// Raw custom crypto RNG with Arc/Mutex.
784    #[cfg(feature = "custom")]
785    CustomCryptoRaw(Arc<spin::mutex::Mutex<dyn RngCrypto>>),
786    /// Send-safe raw custom crypto RNG.
787    #[cfg(any(feature = "custom", feature = "custom_send_only"))]
788    CustomCryptoRawSend(Arc<spin::mutex::Mutex<dyn RngCrypto + Send>>),
789}
790
791#[cfg(feature = "rand")]
792impl CryptoRng for CryptoRNG {}
793
794#[cfg(feature = "rand")]
795impl RngCore for CryptoRNG {
796    fn next_u32(&mut self) -> u32 {
797        match self {
798            #[cfg(any(feature = "core", feature = "send_only"))]
799            CryptoRNG::Std(r) => r.next_u32(),
800            #[cfg(all(feature = "core", not(feature = "send_only")))]
801            CryptoRNG::Thread(r) => r.next_u32(),
802            #[cfg(feature = "core")]
803            CryptoRNG::OS(r) => r.next_u32(),
804            #[cfg(feature = "custom")]
805            CryptoRNG::CustomCrypto(r) => r.next_u32(),
806            #[cfg(feature = "custom")]
807            CryptoRNG::CustomCryptoRaw(r) => {
808                let mut rl = r.lock();
809                rl.next_u32()
810            }
811            #[cfg(any(feature = "custom", feature = "custom_send_only"))]
812            CryptoRNG::CustomCryptoRawSend(r) => {
813                let mut rl = r.lock();
814                rl.next_u32()
815            }
816            _ => panic!("No known random generator"),
817        }
818    }
819
820    fn next_u64(&mut self) -> u64 {
821        match self {
822            #[cfg(any(feature = "core", feature = "send_only"))]
823            CryptoRNG::Std(r) => r.next_u64(),
824            #[cfg(all(feature = "core", not(feature = "send_only")))]
825            CryptoRNG::Thread(r) => r.next_u64(),
826            #[cfg(feature = "core")]
827            CryptoRNG::OS(r) => r.next_u64(),
828            #[cfg(feature = "custom")]
829            CryptoRNG::CustomCrypto(r) => r.next_u64(),
830            #[cfg(feature = "custom")]
831            CryptoRNG::CustomCryptoRaw(r) => {
832                let mut rl = r.lock();
833                rl.next_u64()
834            }
835            #[cfg(any(feature = "custom", feature = "custom_send_only"))]
836            CryptoRNG::CustomCryptoRawSend(r) => {
837                let mut rl = r.lock();
838                rl.next_u64()
839            }
840            _ => panic!("No known random generator"),
841        }
842    }
843
844    #[allow(unused_variables)]
845    fn fill_bytes(&mut self, dest: &mut [u8]) {
846        match self {
847            #[cfg(any(feature = "core", feature = "send_only"))]
848            CryptoRNG::Std(r) => r.fill_bytes(dest),
849            #[cfg(all(feature = "core", not(feature = "send_only")))]
850            CryptoRNG::Thread(r) => r.fill_bytes(dest),
851            #[cfg(feature = "core")]
852            CryptoRNG::OS(r) => r.fill_bytes(dest),
853            #[cfg(feature = "custom")]
854            CryptoRNG::CustomCrypto(r) => r.fill_bytes(dest),
855            #[cfg(feature = "custom")]
856            CryptoRNG::CustomCryptoRaw(r) => {
857                let mut rl = r.lock();
858                rl.fill_bytes(dest);
859            }
860            #[cfg(any(feature = "custom", feature = "custom_send_only"))]
861            CryptoRNG::CustomCryptoRawSend(r) => {
862                let mut rl = r.lock();
863                rl.fill_bytes(dest);
864            }
865            _ => panic!("No known random generator"),
866        }
867    }
868
869    #[allow(unused_variables)]
870    fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
871        match self {
872            #[cfg(any(feature = "core", feature = "send_only"))]
873            CryptoRNG::Std(r) => r.try_fill_bytes(dest),
874            #[cfg(all(feature = "core", not(feature = "send_only")))]
875            CryptoRNG::Thread(r) => r.try_fill_bytes(dest),
876            #[cfg(feature = "core")]
877            CryptoRNG::OS(r) => r.try_fill_bytes(dest),
878            #[cfg(feature = "custom")]
879            CryptoRNG::CustomCrypto(r) => r.try_fill_bytes(dest),
880            #[cfg(feature = "custom")]
881            CryptoRNG::CustomCryptoRaw(r) => {
882                let mut rl = r.lock();
883                rl.try_fill_bytes(dest)
884            }
885            #[cfg(any(feature = "custom", feature = "custom_send_only"))]
886            CryptoRNG::CustomCryptoRawSend(r) => {
887                let mut rl = r.lock();
888                rl.try_fill_bytes(dest)
889            }
890            _ => panic!("No known random generator"),
891        }
892    }
893}
894
895/// High-level random data generator with stateful RNG.
896///
897/// `RandomGenerator` provides convenient methods for generating various types of random data
898/// while maintaining an internal RNG state. It implements the `RandomGeneratorTemplate` trait
899/// for instance methods and provides static methods for one-time generation.
900///
901/// # Usage Patterns
902///
903/// ## Stateful Generation
904///
905/// Create a generator once and reuse it for multiple operations:
906///
907/// ```rust
908/// # #[cfg(feature = "core")]
909/// # {
910/// use product_os_random::{RandomGenerator, RandomGeneratorTemplate};
911///
912/// let mut gen = RandomGenerator::new(None); // Uses default RNG
913/// let bytes1 = gen.get_random_bytes(10);
914/// let bytes2 = gen.get_random_bytes(10);
915/// let number = gen.get_random_usize(1, 100);
916/// # }
917/// ```
918///
919/// ## One-Time Generation
920///
921/// Use static methods for single random values without maintaining state:
922///
923/// ```rust
924/// # #[cfg(feature = "core")]
925/// # {
926/// use product_os_random::RandomGenerator;
927///
928/// let password = RandomGenerator::get_simple_random_password_one_time(16);
929/// let alphanumeric = RandomGenerator::get_simple_random_alphanumeric_one_time(10);
930/// # }
931/// ```
932///
933/// # Feature-Gated Behavior
934///
935/// - With `core` or `send_only`: Can create generator without providing RNG (uses `StdRng::from_entropy()`)
936/// - With `constrained` only: Must provide an RNG, panics if None given
937///
938/// # Panics
939///
940/// Methods will panic in `constrained` mode if no RNG is provided. In `core` or `send_only` modes,
941/// a default RNG is used when None is provided.
942#[cfg(feature = "rand")]
943#[derive(Clone)]
944pub struct RandomGenerator {
945    generator: RNG,
946}
947
948#[cfg(any(feature = "constrained", feature = "core", feature = "send_only"))]
949impl RandomGenerator {
950    /// Creates a new `RandomGenerator` with the provided RNG, or uses a default RNG.
951    ///
952    /// # Arguments
953    ///
954    /// * `gen` - Optional RNG to use. If `None` is provided:
955    ///   - In `core` or `send_only` mode: Uses `StdRng::from_entropy()`
956    ///   - In `constrained` mode: Panics with "No generator provided"
957    ///
958    /// # Examples
959    ///
960    /// ```rust
961    /// # #[cfg(feature = "core")]
962    /// # {
963    /// use product_os_random::{RandomGenerator, RNG};
964    /// use rand::SeedableRng;
965    ///
966    /// // With custom RNG
967    /// let rng = RNG::Std(rand::rngs::StdRng::seed_from_u64(42));
968    /// let gen = RandomGenerator::new(Some(rng));
969    ///
970    /// // With default RNG (core/send_only only)
971    /// let gen2 = RandomGenerator::new(None);
972    /// # }
973    /// ```
974    ///
975    /// # Panics
976    ///
977    /// Panics in `constrained` mode if `gen` is `None`.
978    pub fn new(gen: Option<RNG>) -> Self {
979        let generator = {
980            #[cfg(all(
981                feature = "constrained",
982                all(not(feature = "core"), not(feature = "send_only"))
983            ))]
984            {
985                match gen {
986                    Some(g) => g,
987                    None => panic!("No generator provided"),
988                }
989            }
990            #[cfg(any(feature = "core", feature = "send_only"))]
991            {
992                gen.unwrap_or_else(|| RNG::Std(StdRng::from_entropy()))
993            }
994        };
995
996        Self { generator }
997    }
998
999    /// Generates a cryptographic key of the specified length (simple version, no custom RNG).
1000    ///
1001    /// This is a convenience method that generates a key without requiring an RNG parameter.
1002    /// Uses `StdRng::from_entropy()` in `core`/`send_only` mode.
1003    ///
1004    /// # Arguments
1005    ///
1006    /// * `len` - Length of the key in bytes
1007    ///
1008    /// # Returns
1009    ///
1010    /// A `Vec<u8>` containing `len` random bytes suitable for cryptographic use.
1011    ///
1012    /// # Examples
1013    ///
1014    /// ```rust
1015    /// # #[cfg(feature = "core")]
1016    /// # {
1017    /// use product_os_random::RandomGenerator;
1018    ///
1019    /// let key = RandomGenerator::generate_simple_key_one_time(32);
1020    /// assert_eq!(key.len(), 32);
1021    /// # }
1022    /// ```
1023    pub fn generate_simple_key_one_time(len: usize) -> Vec<u8> {
1024        RandomGenerator::generate_key_one_time(len, &mut None::<RNG>)
1025    }
1026
1027    /// Generates a cryptographic key of the specified length with an optional custom RNG.
1028    ///
1029    /// # Arguments
1030    ///
1031    /// * `len` - Length of the key in bytes
1032    /// * `gen` - Optional RNG to use. If `None`, uses default RNG (in `core`/`send_only` mode)
1033    ///
1034    /// # Returns
1035    ///
1036    /// A `Vec<u8>` containing `len` random bytes.
1037    ///
1038    /// # Panics
1039    ///
1040    /// Panics in `constrained` mode if `gen` is `None`.
1041    ///
1042    /// # Examples
1043    ///
1044    /// ```rust
1045    /// # #[cfg(feature = "core")]
1046    /// # {
1047    /// use product_os_random::RandomGenerator;
1048    /// use rand::SeedableRng;
1049    ///
1050    /// let mut rng = Some(rand::rngs::StdRng::seed_from_u64(42));
1051    /// let key = RandomGenerator::generate_key_one_time(32, &mut rng);
1052    /// assert_eq!(key.len(), 32);
1053    /// # }
1054    /// ```
1055    pub fn generate_key_one_time(len: usize, gen: &mut Option<impl RngCore>) -> Vec<u8> {
1056        #[cfg(all(
1057            feature = "constrained",
1058            all(not(feature = "core"), not(feature = "send_only"))
1059        ))]
1060        {
1061            match gen {
1062                Some(rng) => {
1063                    let mut key = Vec::with_capacity(len);
1064                    for _ in 0..len {
1065                        key.push(rng.gen());
1066                    }
1067                    key
1068                }
1069                None => panic!("No generator provided"),
1070            }
1071        }
1072        #[cfg(any(feature = "core", feature = "send_only"))]
1073        {
1074            if let Some(rng) = gen {
1075                let mut key = Vec::with_capacity(len);
1076                for _ in 0..len {
1077                    key.push(rng.gen());
1078                }
1079                key
1080            } else {
1081                let mut rng = StdRng::from_entropy();
1082                let mut key = Vec::with_capacity(len);
1083                for _ in 0..len {
1084                    key.push(rng.gen());
1085                }
1086                key
1087            }
1088        }
1089    }
1090
1091    /// Generates random bytes (simple version, no custom RNG needed).
1092    ///
1093    /// This is a convenience wrapper around `get_random_bytes_one_time` that uses the default RNG.
1094    ///
1095    /// # Arguments
1096    ///
1097    /// * `len` - Number of bytes to generate
1098    ///
1099    /// # Returns
1100    ///
1101    /// A `Vec<u8>` containing `len` random bytes (0-255).
1102    pub fn get_simple_random_bytes_one_time(len: usize) -> Vec<u8> {
1103        RandomGenerator::get_random_bytes_one_time(len, &mut None::<RNG>)
1104    }
1105
1106    /// Generates random bytes with an optional custom RNG.
1107    ///
1108    /// # Arguments
1109    ///
1110    /// * `len` - Number of bytes to generate
1111    /// * `gen` - Optional RNG to use. If `None`, uses default RNG (in `core`/`send_only` mode)
1112    ///
1113    /// # Returns
1114    ///
1115    /// A `Vec<u8>` containing `len` random bytes (0-255).
1116    ///
1117    /// # Panics
1118    ///
1119    /// Panics in `constrained` mode if `gen` is `None`.
1120    pub fn get_random_bytes_one_time(len: usize, gen: &mut Option<impl RngCore>) -> Vec<u8> {
1121        let mut bytes = vec![0u8; len];
1122        #[cfg(all(
1123            feature = "constrained",
1124            all(not(feature = "core"), not(feature = "send_only"))
1125        ))]
1126        {
1127            match gen {
1128                Some(rng) => {
1129                    rng.fill_bytes(&mut bytes);
1130                }
1131                None => panic!("No generator provided"),
1132            }
1133        }
1134        #[cfg(any(feature = "core", feature = "send_only"))]
1135        {
1136            if let Some(rng) = gen {
1137                rng.fill_bytes(&mut bytes);
1138            } else {
1139                let mut rng = StdRng::from_entropy();
1140                rng.fill_bytes(&mut bytes);
1141            }
1142        }
1143        bytes
1144    }
1145
1146    /// Generates a random `usize` within range (simple version, no custom RNG).
1147    ///
1148    /// This is a convenience method that generates a random number without requiring an RNG parameter.
1149    ///
1150    /// # Arguments
1151    ///
1152    /// * `min` - Minimum value (inclusive)
1153    /// * `max` - Maximum value (inclusive)
1154    ///
1155    /// # Returns
1156    ///
1157    /// A random `usize` in the range `[min, max]`.
1158    pub fn get_simple_random_usize_one_time(min: usize, max: usize) -> usize {
1159        RandomGenerator::get_random_usize_one_time(min, max, &mut None::<RNG>)
1160    }
1161
1162    /// Generates a random `usize` within range with an optional custom RNG.
1163    ///
1164    /// # Arguments
1165    ///
1166    /// * `min` - Minimum value (inclusive)
1167    /// * `max` - Maximum value (inclusive)
1168    /// * `gen` - Optional RNG to use. If `None`, uses default RNG (in `core`/`send_only` mode)
1169    ///
1170    /// # Returns
1171    ///
1172    /// A random `usize` in the range `[min, max]`.
1173    ///
1174    /// # Panics
1175    ///
1176    /// Panics in `constrained` mode if `gen` is `None`.
1177    pub fn get_random_usize_one_time(
1178        min: usize,
1179        max: usize,
1180        gen: &mut Option<impl RngCore>,
1181    ) -> usize {
1182        #[cfg(all(
1183            feature = "constrained",
1184            all(not(feature = "core"), not(feature = "send_only"))
1185        ))]
1186        {
1187            match gen {
1188                Some(rng) => rng.gen_range(min..=max),
1189                None => panic!("No generator provided"),
1190            }
1191        }
1192        #[cfg(any(feature = "core", feature = "send_only"))]
1193        {
1194            if let Some(rng) = gen {
1195                rng.gen_range(min..=max)
1196            } else {
1197                let mut rng = StdRng::from_entropy();
1198                rng.gen_range(min..=max)
1199            }
1200        }
1201    }
1202
1203    /// Generates a random string of printable ASCII characters (simple version).
1204    ///
1205    /// Generates a string containing random printable ASCII characters in the ranges:
1206    /// - Letters (a-z, A-Z)
1207    /// - Numbers (0-9)
1208    ///
1209    /// Special characters and symbols are excluded through character range filtering.
1210    ///
1211    /// # Arguments
1212    ///
1213    /// * `len` - Length of the string
1214    ///
1215    /// # Returns
1216    ///
1217    /// A `String` of length `len` containing random printable characters.
1218    ///
1219    /// # Examples
1220    ///
1221    /// ```rust
1222    /// # #[cfg(feature = "core")]
1223    /// # {
1224    /// use product_os_random::RandomGenerator;
1225    ///
1226    /// let s = RandomGenerator::get_simple_random_string_one_time(10);
1227    /// assert_eq!(s.len(), 10);
1228    /// # }
1229    /// ```
1230    pub fn get_simple_random_string_one_time(len: usize) -> String {
1231        RandomGenerator::get_random_string_one_time(len, &mut None::<RNG>)
1232    }
1233
1234    /// Generates a random string of printable ASCII characters with optional custom RNG.
1235    ///
1236    /// Character generation uses ASCII codes 33-122, with filtering to exclude certain
1237    /// special characters and symbols, resulting in alphanumeric and common punctuation.
1238    ///
1239    /// # Arguments
1240    ///
1241    /// * `len` - Length of the string
1242    /// * `gen` - Optional RNG to use. If `None`, uses default RNG (in `core`/`send_only` mode)
1243    ///
1244    /// # Returns
1245    ///
1246    /// A `String` of length `len` containing random characters.
1247    ///
1248    /// # Panics
1249    ///
1250    /// Panics in `constrained` mode if `gen` is `None`.
1251    pub fn get_random_string_one_time(len: usize, gen: &mut Option<impl RngCore>) -> String {
1252        let mut str = String::with_capacity(len);
1253        #[cfg(all(
1254            feature = "constrained",
1255            all(not(feature = "core"), not(feature = "send_only"))
1256        ))]
1257        {
1258            match gen {
1259                Some(rng) => {
1260                    for _ in 0..len {
1261                        let value: u8 = rng.gen_range(33..=122);
1262                        let filtered = filter_printable_char(value);
1263                        str.push(char::from(filtered));
1264                    }
1265                }
1266                None => panic!("No generator provided"),
1267            }
1268        }
1269        #[cfg(any(feature = "core", feature = "send_only"))]
1270        {
1271            if let Some(rng) = gen {
1272                for _ in 0..len {
1273                    let value: u8 = rng.gen_range(33..=122);
1274                    let filtered = filter_printable_char(value);
1275                    str.push(char::from(filtered));
1276                }
1277            } else {
1278                let mut rng = StdRng::from_entropy();
1279                for _ in 0..len {
1280                    let value: u8 = rng.gen_range(33..=122);
1281                    let filtered = filter_printable_char(value);
1282                    str.push(char::from(filtered));
1283                }
1284            }
1285        }
1286        str
1287    }
1288
1289    /// Generates a random string from a character set (simple version, no custom RNG).
1290    ///
1291    /// # Arguments
1292    ///
1293    /// * `len` - Length of the string
1294    /// * `characters` - String containing the character set to choose from
1295    ///
1296    /// # Returns
1297    ///
1298    /// A `String` of length `len` with characters randomly selected from `characters`.
1299    pub fn get_simple_random_from_characters_one_time(len: usize, characters: &str) -> String {
1300        RandomGenerator::get_random_from_characters_one_time(len, characters, &mut None::<RNG>)
1301    }
1302
1303    /// Generates a random string from a character set with an optional custom RNG.
1304    ///
1305    /// # Arguments
1306    ///
1307    /// * `len` - Length of the string
1308    /// * `characters` - String containing the character set to choose from
1309    /// * `gen` - Optional RNG to use. If `None`, uses default RNG (in `core`/`send_only` mode)
1310    ///
1311    /// # Returns
1312    ///
1313    /// A `String` of length `len` with characters randomly selected from `characters`.
1314    ///
1315    /// # Panics
1316    ///
1317    /// Panics in `constrained` mode if `gen` is `None`.
1318    /// May panic if `characters` is empty.
1319    pub fn get_random_from_characters_one_time(
1320        len: usize,
1321        characters: &str,
1322        gen: &mut Option<impl RngCore>,
1323    ) -> String {
1324        let mut str = String::with_capacity(len);
1325        let char_vec: Vec<char> = characters.chars().collect();
1326        let char_count = char_vec.len();
1327
1328        #[cfg(all(
1329            feature = "constrained",
1330            all(not(feature = "core"), not(feature = "send_only"))
1331        ))]
1332        {
1333            match gen {
1334                Some(rng) => {
1335                    for _ in 0..len {
1336                        let ch = char_vec[rng.gen_range(0..char_count)];
1337                        str.push(ch);
1338                    }
1339                }
1340                None => panic!("No generator provided"),
1341            }
1342        }
1343        #[cfg(any(feature = "core", feature = "send_only"))]
1344        {
1345            if let Some(rng) = gen {
1346                for _ in 0..len {
1347                    let ch = char_vec[rng.gen_range(0..char_count)];
1348                    str.push(ch);
1349                }
1350            } else {
1351                let mut rng = StdRng::from_entropy();
1352                for _ in 0..len {
1353                    let ch = char_vec[rng.gen_range(0..char_count)];
1354                    str.push(ch);
1355                }
1356            }
1357        }
1358
1359        str
1360    }
1361
1362    /// Generates a random alphanumeric string (simple version).
1363    ///
1364    /// Creates a string containing only letters (a-z, A-Z) and digits (0-9).
1365    /// Suitable for identifiers, codes, and non-security-critical tokens.
1366    ///
1367    /// # Arguments
1368    ///
1369    /// * `len` - Length of the string
1370    ///
1371    /// # Returns
1372    ///
1373    /// A `String` of length `len` containing random alphanumeric characters.
1374    ///
1375    /// # Examples
1376    ///
1377    /// ```rust
1378    /// # #[cfg(feature = "core")]
1379    /// # {
1380    /// use product_os_random::RandomGenerator;
1381    ///
1382    /// let code = RandomGenerator::get_simple_random_alphanumeric_one_time(10);
1383    /// assert_eq!(code.len(), 10);
1384    /// assert!(code.chars().all(|c| c.is_alphanumeric()));
1385    /// # }
1386    /// ```
1387    pub fn get_simple_random_alphanumeric_one_time(len: usize) -> String {
1388        RandomGenerator::get_random_alphanumeric_one_time(len, &mut None::<RNG>)
1389    }
1390
1391    /// Generates a random alphanumeric string with an optional custom RNG.
1392    ///
1393    /// Creates a string containing only letters (a-z, A-Z) and digits (0-9).
1394    ///
1395    /// # Arguments
1396    ///
1397    /// * `len` - Length of the string
1398    /// * `gen` - Optional RNG to use. If `None`, uses default RNG (in `core`/`send_only` mode)
1399    ///
1400    /// # Returns
1401    ///
1402    /// A `String` of length `len` containing only alphanumeric characters.
1403    ///
1404    /// # Panics
1405    ///
1406    /// Panics in `constrained` mode if `gen` is `None`.
1407    pub fn get_random_alphanumeric_one_time(len: usize, gen: &mut Option<impl RngCore>) -> String {
1408        let mut str = String::with_capacity(len);
1409        #[cfg(all(
1410            feature = "constrained",
1411            all(not(feature = "core"), not(feature = "send_only"))
1412        ))]
1413        {
1414            match gen {
1415                Some(rng) => {
1416                    for _ in 0..len {
1417                        let value: u8 = rng.gen_range(48..=122);
1418                        let filtered = filter_alphanumeric_char(value);
1419                        str.push(char::from(filtered));
1420                    }
1421                }
1422                None => panic!("No generator provided"),
1423            }
1424        }
1425        #[cfg(any(feature = "core", feature = "send_only"))]
1426        {
1427            if let Some(rng) = gen {
1428                for _ in 0..len {
1429                    let value: u8 = rng.gen_range(48..=122);
1430                    let filtered = filter_alphanumeric_char(value);
1431                    str.push(char::from(filtered));
1432                }
1433            } else {
1434                let mut rng = StdRng::from_entropy();
1435                for _ in 0..len {
1436                    let value: u8 = rng.gen_range(48..=122);
1437                    let filtered = filter_alphanumeric_char(value);
1438                    str.push(char::from(filtered));
1439                }
1440            }
1441        }
1442        str
1443    }
1444
1445    /// Generates a random password string (simple version).
1446    ///
1447    /// Creates a password containing a wide range of printable ASCII characters (33-122),
1448    /// including letters, digits, and special characters.
1449    ///
1450    /// # Security Note
1451    ///
1452    /// For production password generation, consider using `CryptoRNG` with `OsRng` to ensure
1453    /// cryptographic security.
1454    ///
1455    /// # Arguments
1456    ///
1457    /// * `len` - Length of the password
1458    ///
1459    /// # Returns
1460    ///
1461    /// A `String` of length `len` containing random password characters.
1462    ///
1463    /// # Examples
1464    ///
1465    /// ```rust
1466    /// # #[cfg(feature = "core")]
1467    /// # {
1468    /// use product_os_random::RandomGenerator;
1469    ///
1470    /// let password = RandomGenerator::get_simple_random_password_one_time(16);
1471    /// assert_eq!(password.len(), 16);
1472    /// # }
1473    /// ```
1474    pub fn get_simple_random_password_one_time(len: usize) -> String {
1475        RandomGenerator::get_random_password_one_time(len, &mut None::<RNG>)
1476    }
1477
1478    /// Generates a random password string with an optional custom RNG.
1479    ///
1480    /// Creates a password containing a wide range of printable ASCII characters (33-122),
1481    /// including letters, digits, and special characters.
1482    ///
1483    /// # Security Note
1484    ///
1485    /// For production password generation, consider using `CryptoRNG` with `OsRng` to ensure
1486    /// cryptographic security.
1487    ///
1488    /// # Arguments
1489    ///
1490    /// * `len` - Length of the password
1491    /// * `gen` - Optional RNG to use. If `None`, uses default RNG (in `core`/`send_only` mode)
1492    ///
1493    /// # Returns
1494    ///
1495    /// A `String` of length `len` containing random password characters.
1496    ///
1497    /// # Panics
1498    ///
1499    /// Panics in `constrained` mode if `gen` is `None`.
1500    pub fn get_random_password_one_time(len: usize, gen: &mut Option<impl RngCore>) -> String {
1501        let mut str = String::with_capacity(len);
1502        #[cfg(all(
1503            feature = "constrained",
1504            all(not(feature = "core"), not(feature = "send_only"))
1505        ))]
1506        {
1507            match gen {
1508                Some(rng) => {
1509                    for _ in 0..len {
1510                        let value: u8 = rng.gen_range(33..=122);
1511                        str.push(char::from(value));
1512                    }
1513                }
1514                None => panic!("No generator provided"),
1515            }
1516        }
1517        #[cfg(any(feature = "core", feature = "send_only"))]
1518        {
1519            if let Some(rng) = gen {
1520                for _ in 0..len {
1521                    let value: u8 = rng.gen_range(33..=122);
1522                    str.push(char::from(value));
1523                }
1524            } else {
1525                let mut rng = StdRng::from_entropy();
1526                for _ in 0..len {
1527                    let value: u8 = rng.gen_range(33..=122);
1528                    str.push(char::from(value));
1529                }
1530            }
1531        }
1532        str
1533    }
1534
1535    /// Generates a random email address using a default RNG.
1536    ///
1537    /// This is a convenience wrapper around `get_random_email_one_time` that uses
1538    /// a default RNG instance.
1539    ///
1540    /// # Arguments
1541    ///
1542    /// * `num_names` - Optional number of name components (default: 2)
1543    /// * `num_numbers` - Optional number of numeric components (default: 0)
1544    /// * `separator` - Optional separator between components (default: ".")
1545    /// * `domains` - List of possible email domains to choose from
1546    ///
1547    /// # Returns
1548    ///
1549    /// A random email address string
1550    ///
1551    /// # Examples
1552    ///
1553    /// ```rust
1554    /// # #[cfg(all(feature = "core", feature = "names"))]
1555    /// # {
1556    /// use product_os_random::RandomGenerator;
1557    ///
1558    /// let email = RandomGenerator::get_simple_random_email_one_time(
1559    ///     Some(2), Some(0), Some(".".to_string()), vec!["example.com".to_string()]
1560    /// );
1561    /// println!("Random email: {}", email);
1562    /// # }
1563    /// ```
1564    #[cfg(feature = "names")]
1565    pub fn get_simple_random_email_one_time(
1566        num_names: Option<usize>,
1567        num_numbers: Option<usize>,
1568        separator: Option<String>,
1569        domains: Vec<String>,
1570    ) -> String {
1571        RandomGenerator::get_random_email_one_time(
1572            num_names,
1573            num_numbers,
1574            separator,
1575            domains,
1576            &mut None::<RNG>,
1577        )
1578    }
1579
1580    /// Generates a random email address using the provided RNG.
1581    ///
1582    /// Creates an email address by combining random names, optional numbers, and
1583    /// a domain from the provided list.
1584    ///
1585    /// # Arguments
1586    ///
1587    /// * `num_names` - Optional number of name components (default: 2)
1588    /// * `num_numbers` - Optional number of numeric components (default: 0)
1589    /// * `separator` - Optional separator between components (default: ".")
1590    /// * `domains` - List of possible email domains to choose from
1591    /// * `gen` - Mutable reference to an optional RNG instance
1592    ///
1593    /// # Returns
1594    ///
1595    /// A random email address string
1596    #[cfg(feature = "names")]
1597    #[allow(clippy::needless_pass_by_value)] // Keep Vec<String> for API compatibility
1598    pub fn get_random_email_one_time(
1599        num_names: Option<usize>,
1600        num_numbers: Option<usize>,
1601        separator: Option<String>,
1602        domains: Vec<String>,
1603        gen: &mut Option<impl RngCore>,
1604    ) -> String {
1605        let num_names = num_names.unwrap_or(2);
1606
1607        let num_numbers = num_numbers.unwrap_or(3);
1608
1609        let separator = separator.unwrap_or_default();
1610
1611        let mut str = String::new();
1612
1613        let username = RandomGenerator::get_random_username_one_time(
1614            Some(num_names),
1615            Some(num_numbers),
1616            Some(separator.clone()),
1617            gen,
1618        );
1619
1620        str.push_str(username.as_str());
1621        str.push('@');
1622
1623        let num_domains = domains.len();
1624
1625        #[cfg(all(
1626            feature = "constrained",
1627            all(not(feature = "core"), not(feature = "send_only"))
1628        ))]
1629        {
1630            match gen {
1631                Some(rng) => {
1632                    let pick_domain = rng.gen_range(0..num_domains);
1633                    str.push_str(domains.get(pick_domain).unwrap().as_str());
1634                }
1635                None => panic!("No generator provided"),
1636            }
1637        }
1638        #[cfg(any(feature = "core", feature = "send_only"))]
1639        {
1640            if let Some(rng) = gen {
1641                let pick_domain = rng.gen_range(0..num_domains);
1642                str.push_str(domains.get(pick_domain).unwrap().as_str());
1643            } else {
1644                let mut rng = StdRng::from_entropy();
1645                let pick_domain = rng.gen_range(0..num_domains);
1646                str.push_str(domains.get(pick_domain).unwrap().as_str());
1647            }
1648        }
1649
1650        str
1651    }
1652
1653    /// Generates a random username using a default RNG.
1654    ///
1655    /// This is a convenience wrapper around `get_random_username_one_time` that uses
1656    /// a default RNG instance.
1657    ///
1658    /// # Arguments
1659    ///
1660    /// * `num_names` - Optional number of name components (default: 2)
1661    /// * `num_numbers` - Optional number of numeric components (default: 0)
1662    /// * `separator` - Optional separator between components (default: "_")
1663    ///
1664    /// # Returns
1665    ///
1666    /// A random username string
1667    ///
1668    /// # Examples
1669    ///
1670    /// ```rust
1671    /// # #[cfg(all(feature = "core", feature = "names"))]
1672    /// # {
1673    /// use product_os_random::RandomGenerator;
1674    ///
1675    /// let username = RandomGenerator::get_simple_random_username_one_time(
1676    ///     Some(2), Some(3), Some("_".to_string())
1677    /// );
1678    /// println!("Random username: {}", username);
1679    /// # }
1680    /// ```
1681    #[cfg(feature = "names")]
1682    pub fn get_simple_random_username_one_time(
1683        num_names: Option<usize>,
1684        num_numbers: Option<usize>,
1685        separator: Option<String>,
1686    ) -> String {
1687        RandomGenerator::get_random_username_one_time(
1688            num_names,
1689            num_numbers,
1690            separator,
1691            &mut None::<RNG>,
1692        )
1693    }
1694
1695    /// Generates a random username using the provided RNG.
1696    ///
1697    /// Creates a username by combining random names and optional numbers with a separator.
1698    ///
1699    /// # Arguments
1700    ///
1701    /// * `num_names` - Optional number of name components (default: 2)
1702    /// * `num_numbers` - Optional number of numeric components (default: 0)
1703    /// * `separator` - Optional separator between components (default: "_")
1704    /// * `gen` - Mutable reference to an optional RNG instance
1705    ///
1706    /// # Returns
1707    ///
1708    /// A random username string
1709    #[cfg(feature = "names")]
1710    pub fn get_random_username_one_time(
1711        num_names: Option<usize>,
1712        num_numbers: Option<usize>,
1713        separator: Option<String>,
1714        gen: &mut Option<impl RngCore>,
1715    ) -> String {
1716        let names_count = names::NAMES.len();
1717
1718        let num_names = num_names.unwrap_or(2);
1719
1720        let num_numbers = num_numbers.unwrap_or(5);
1721
1722        let separator = separator.unwrap_or_default();
1723
1724        let mut str = String::new();
1725
1726        #[cfg(all(
1727            feature = "constrained",
1728            all(not(feature = "core"), not(feature = "send_only"))
1729        ))]
1730        {
1731            match gen {
1732                Some(rng) => {
1733                    for counter in 0..num_names {
1734                        let value: usize = rng.gen_range(0..names_count);
1735                        if counter > 0 {
1736                            str.push_str(separator.as_str());
1737                        }
1738                        str.push_str(names::NAMES[value].to_lowercase().as_str());
1739                    }
1740
1741                    if num_numbers > 0 {
1742                        str.push_str(separator.as_str());
1743                    }
1744
1745                    for _ in 0..num_numbers {
1746                        let value: u8 = rng.gen_range(48..57);
1747                        str.push(char::from(value));
1748                    }
1749                }
1750                None => panic!("No generator provided"),
1751            }
1752        }
1753        #[cfg(any(feature = "core", feature = "send_only"))]
1754        {
1755            if let Some(rng) = gen {
1756                for counter in 0..num_names {
1757                    let value: usize = rng.gen_range(0..names_count);
1758                    if counter > 0 {
1759                        str.push_str(separator.as_str());
1760                    }
1761                    str.push_str(names::NAMES[value].to_lowercase().as_str());
1762                }
1763
1764                if num_numbers > 0 {
1765                    str.push_str(separator.as_str());
1766                }
1767
1768                for _ in 0..num_numbers {
1769                    let value: u8 = rng.gen_range(48..57);
1770                    str.push(char::from(value));
1771                }
1772            } else {
1773                let mut rng = StdRng::from_entropy();
1774                for counter in 0..num_names {
1775                    let value: usize = rng.gen_range(0..names_count);
1776                    if counter > 0 {
1777                        str.push_str(separator.as_str());
1778                    }
1779                    str.push_str(names::NAMES[value].to_lowercase().as_str());
1780                }
1781
1782                if num_numbers > 0 {
1783                    str.push_str(separator.as_str());
1784                }
1785
1786                for _ in 0..num_numbers {
1787                    let value: u8 = rng.gen_range(48..57);
1788                    str.push(char::from(value));
1789                }
1790            }
1791        }
1792
1793        str
1794    }
1795
1796    /// Generates a random full name using a default RNG.
1797    ///
1798    /// This is a convenience wrapper around `get_random_name_one_time` that uses
1799    /// a default RNG instance.
1800    ///
1801    /// # Returns
1802    ///
1803    /// A random full name string (first name + last name)
1804    ///
1805    /// # Examples
1806    ///
1807    /// ```rust
1808    /// # #[cfg(all(feature = "core", feature = "names", feature = "first_names", feature = "last_names"))]
1809    /// # {
1810    /// use product_os_random::RandomGenerator;
1811    ///
1812    /// let name = RandomGenerator::get_simple_random_name_one_time();
1813    /// println!("Random name: {}", name);
1814    /// # }
1815    /// ```
1816    #[cfg(feature = "names")]
1817    pub fn get_simple_random_name_one_time() -> String {
1818        RandomGenerator::get_random_name_one_time(&mut None::<RNG>)
1819    }
1820
1821    /// Generates a random full name using the provided RNG.
1822    ///
1823    /// Creates a full name by combining a random first name and last name.
1824    ///
1825    /// # Arguments
1826    ///
1827    /// * `gen` - Mutable reference to an optional RNG instance
1828    ///
1829    /// # Returns
1830    ///
1831    /// A random full name string (first name + last name)
1832    #[cfg(feature = "names")]
1833    pub fn get_random_name_one_time(gen: &mut Option<impl RngCore>) -> String {
1834        let names_count = names::NAMES.len();
1835
1836        let mut str = String::new();
1837
1838        #[cfg(all(
1839            feature = "constrained",
1840            all(not(feature = "core"), not(feature = "send_only"))
1841        ))]
1842        {
1843            match gen {
1844                Some(rng) => {
1845                    let value: usize = rng.gen_range(0..names_count);
1846                    str.push_str(names::NAMES[value]);
1847                }
1848                None => panic!("No generator provided"),
1849            }
1850        }
1851        #[cfg(any(feature = "core", feature = "send_only"))]
1852        {
1853            if let Some(rng) = gen {
1854                let value: usize = rng.gen_range(0..names_count);
1855                str.push_str(names::NAMES[value]);
1856            } else {
1857                let mut rng = StdRng::from_entropy();
1858                let value: usize = rng.gen_range(0..names_count);
1859                str.push_str(names::NAMES[value]);
1860            }
1861        }
1862        str
1863    }
1864
1865    /// Generates a random first name using a default RNG.
1866    ///
1867    /// This is a convenience wrapper around `get_random_first_name_one_time` that uses
1868    /// a default RNG instance.
1869    ///
1870    /// # Returns
1871    ///
1872    /// A random first name string (capitalized)
1873    ///
1874    /// # Examples
1875    ///
1876    /// ```rust
1877    /// # #[cfg(all(feature = "core", feature = "names", feature = "first_names"))]
1878    /// # {
1879    /// use product_os_random::RandomGenerator;
1880    ///
1881    /// let first_name = RandomGenerator::get_simple_random_first_name_one_time();
1882    /// println!("Random first name: {}", first_name);
1883    /// # }
1884    /// ```
1885    #[cfg(feature = "names")]
1886    pub fn get_simple_random_first_name_one_time() -> String {
1887        RandomGenerator::get_random_first_name_one_time(&mut None::<RNG>)
1888    }
1889
1890    /// Generates a random first name using the provided RNG.
1891    ///
1892    /// Selects a random first name from the built-in dataset and capitalizes it.
1893    ///
1894    /// # Arguments
1895    ///
1896    /// * `gen` - Mutable reference to an optional RNG instance
1897    ///
1898    /// # Returns
1899    ///
1900    /// A random first name string (capitalized)
1901    #[cfg(feature = "first_names")]
1902    pub fn get_random_first_name_one_time(gen: &mut Option<impl RngCore>) -> String {
1903        let names_count = first_names::FIRSTNAMES.len();
1904
1905        let mut str = String::new();
1906
1907        #[cfg(all(
1908            feature = "constrained",
1909            all(not(feature = "core"), not(feature = "send_only"))
1910        ))]
1911        {
1912            match gen {
1913                Some(rng) => {
1914                    let value: usize = rng.gen_range(0..names_count);
1915                    str.push_str(to_title_case(first_names::FIRSTNAMES[value]).as_str());
1916                }
1917                None => panic!("No generator provided"),
1918            }
1919        }
1920        #[cfg(any(feature = "core", feature = "send_only"))]
1921        {
1922            if let Some(rng) = gen {
1923                let value: usize = rng.gen_range(0..names_count);
1924                str.push_str(to_title_case(first_names::FIRSTNAMES[value]).as_str());
1925            } else {
1926                let mut rng = StdRng::from_entropy();
1927                let value: usize = rng.gen_range(0..names_count);
1928                str.push_str(to_title_case(first_names::FIRSTNAMES[value]).as_str());
1929            }
1930        }
1931
1932        str
1933    }
1934
1935    /// Generates a random last name using a default RNG.
1936    ///
1937    /// This is a convenience wrapper around `get_random_last_name_one_time` that uses
1938    /// a default RNG instance.
1939    ///
1940    /// # Returns
1941    ///
1942    /// A random last name string (capitalized)
1943    ///
1944    /// # Examples
1945    ///
1946    /// ```rust
1947    /// # #[cfg(all(feature = "core", feature = "names", feature = "last_names"))]
1948    /// # {
1949    /// use product_os_random::RandomGenerator;
1950    ///
1951    /// let last_name = RandomGenerator::get_simple_random_last_name_one_time();
1952    /// println!("Random last name: {}", last_name);
1953    /// # }
1954    /// ```
1955    #[cfg(feature = "names")]
1956    pub fn get_simple_random_last_name_one_time() -> String {
1957        RandomGenerator::get_random_last_name_one_time(&mut None::<RNG>)
1958    }
1959
1960    /// Generates a random last name using the provided RNG.
1961    ///
1962    /// Selects a random last name from the built-in dataset and capitalizes it.
1963    ///
1964    /// # Arguments
1965    ///
1966    /// * `gen` - Mutable reference to an optional RNG instance
1967    ///
1968    /// # Returns
1969    ///
1970    /// A random last name string (capitalized)
1971    #[cfg(feature = "last_names")]
1972    pub fn get_random_last_name_one_time(gen: &mut Option<impl RngCore>) -> String {
1973        let names_count = last_names::LASTNAMES.len();
1974
1975        let mut str = String::new();
1976
1977        #[cfg(all(
1978            feature = "constrained",
1979            all(not(feature = "core"), not(feature = "send_only"))
1980        ))]
1981        {
1982            match gen {
1983                Some(rng) => {
1984                    let value: usize = rng.gen_range(0..names_count);
1985                    str.push_str(to_title_case(last_names::LASTNAMES[value]).as_str());
1986                }
1987                None => panic!("No generator provided"),
1988            }
1989        }
1990        #[cfg(any(feature = "core", feature = "send_only"))]
1991        {
1992            if let Some(rng) = gen {
1993                let value: usize = rng.gen_range(0..names_count);
1994                str.push_str(to_title_case(last_names::LASTNAMES[value]).as_str());
1995            } else {
1996                let mut rng = StdRng::from_entropy();
1997                let value: usize = rng.gen_range(0..names_count);
1998                str.push_str(to_title_case(last_names::LASTNAMES[value]).as_str());
1999            }
2000        }
2001
2002        str
2003    }
2004}
2005
2006#[cfg(feature = "rand")]
2007impl RandomGeneratorTemplate for RandomGenerator {
2008    fn get_random_bytes(&mut self, len: usize) -> Vec<u8> {
2009        let mut bytes = vec![0u8; len];
2010        self.generator.fill_bytes(&mut bytes);
2011        bytes
2012    }
2013
2014    fn get_random_usize(&mut self, min: usize, max: usize) -> usize {
2015        self.generator.gen_range(min..=max)
2016    }
2017
2018    fn get_random_u32(&mut self) -> u32 {
2019        self.generator.next_u32()
2020    }
2021
2022    fn get_random_u64(&mut self) -> u64 {
2023        self.generator.next_u64()
2024    }
2025
2026    fn get_random_string(&mut self, len: usize) -> String {
2027        let mut str = String::with_capacity(len);
2028        for _ in 0..len {
2029            let value: u8 = self.generator.gen_range(33..=122);
2030            let filtered = filter_printable_char(value);
2031            str.push(char::from(filtered));
2032        }
2033        str
2034    }
2035
2036    fn get_random_from_characters(&mut self, len: usize, characters: &str) -> String {
2037        let mut str = String::with_capacity(len);
2038        let char_vec: Vec<char> = characters.chars().collect();
2039        let char_count = char_vec.len();
2040
2041        for _ in 0..len {
2042            let ch = char_vec[self.generator.gen_range(0..char_count)];
2043            str.push(ch);
2044        }
2045
2046        str
2047    }
2048
2049    fn get_random_alphanumeric(&mut self, len: usize) -> String {
2050        let mut str = String::with_capacity(len);
2051        for _ in 0..len {
2052            let value: u8 = self.generator.gen_range(48..=122);
2053            let filtered = filter_alphanumeric_char(value);
2054            str.push(char::from(filtered));
2055        }
2056        str
2057    }
2058
2059    fn generate_key(&mut self, len: usize) -> Vec<u8> {
2060        let mut key = Vec::with_capacity(len);
2061        for _ in 0..len {
2062            key.push(self.generator.gen());
2063        }
2064        key
2065    }
2066}
2067
2068/// Template trait defining instance methods for random data generation.
2069///
2070/// This trait defines the interface for stateful random generation. Types implementing
2071/// this trait maintain an internal RNG state and provide methods for generating various
2072/// types of random data.
2073///
2074/// # Implementation
2075///
2076/// `RandomGenerator` implements this trait, providing all these methods as instance methods
2077/// that use the generator's internal RNG.
2078///
2079/// # Examples
2080///
2081/// ```rust
2082/// # #[cfg(feature = "core")]
2083/// # {
2084/// use product_os_random::{RandomGenerator, RandomGeneratorTemplate};
2085///
2086/// let mut gen = RandomGenerator::new(None);
2087///
2088/// // Generate various random data
2089/// let bytes = gen.get_random_bytes(16);
2090/// let number = gen.get_random_usize(1, 100);
2091/// let text = gen.get_random_string(20);
2092/// let alphanum = gen.get_random_alphanumeric(10);
2093/// let key = gen.generate_key(32);
2094/// # }
2095/// ```
2096pub trait RandomGeneratorTemplate {
2097    /// Generates a vector of random bytes.
2098    ///
2099    /// # Arguments
2100    ///
2101    /// * `len` - Number of bytes to generate
2102    ///
2103    /// # Returns
2104    ///
2105    /// A `Vec<u8>` containing `len` random bytes (0-255).
2106    fn get_random_bytes(&mut self, len: usize) -> Vec<u8>;
2107
2108    /// Generates a random `usize` within the specified range (inclusive).
2109    ///
2110    /// # Arguments
2111    ///
2112    /// * `min` - Minimum value (inclusive)
2113    /// * `max` - Maximum value (inclusive)
2114    ///
2115    /// # Returns
2116    ///
2117    /// A random `usize` in the range `[min, max]`.
2118    fn get_random_usize(&mut self, min: usize, max: usize) -> usize;
2119
2120    /// Generates a random `u32`.
2121    ///
2122    /// # Returns
2123    ///
2124    /// A random 32-bit unsigned integer.
2125    fn get_random_u32(&mut self) -> u32;
2126
2127    /// Generates a random `u64`.
2128    ///
2129    /// # Returns
2130    ///
2131    /// A random 64-bit unsigned integer.
2132    fn get_random_u64(&mut self) -> u64;
2133
2134    /// Generates a random string of printable characters.
2135    ///
2136    /// # Arguments
2137    ///
2138    /// * `len` - Length of the string
2139    ///
2140    /// # Returns
2141    ///
2142    /// A `String` containing `len` random printable characters.
2143    fn get_random_string(&mut self, len: usize) -> String;
2144
2145    /// Generates a random string from the provided character set.
2146    ///
2147    /// # Arguments
2148    ///
2149    /// * `len` - Length of the string
2150    /// * `characters` - String containing the character set to choose from
2151    ///
2152    /// # Returns
2153    ///
2154    /// A `String` of length `len` with characters randomly selected from `characters`.
2155    ///
2156    /// # Panics
2157    ///
2158    /// May panic if `characters` is empty or contains invalid UTF-8.
2159    fn get_random_from_characters(&mut self, len: usize, characters: &str) -> String;
2160
2161    /// Generates a random alphanumeric string.
2162    ///
2163    /// # Arguments
2164    ///
2165    /// * `len` - Length of the string
2166    ///
2167    /// # Returns
2168    ///
2169    /// A `String` of length `len` containing only letters (a-z, A-Z) and digits (0-9).
2170    fn get_random_alphanumeric(&mut self, len: usize) -> String;
2171
2172    /// Generates a cryptographic key.
2173    ///
2174    /// # Arguments
2175    ///
2176    /// * `len` - Length of the key in bytes
2177    ///
2178    /// # Returns
2179    ///
2180    /// A `Vec<u8>` containing `len` random bytes suitable for use as a cryptographic key.
2181    fn generate_key(&mut self, len: usize) -> Vec<u8>;
2182}
2183
2184// =============================================================================
2185// Top-level convenience functions
2186// =============================================================================
2187//
2188// These free functions provide the simplest possible API for one-time random
2189// generation. They use the default RNG internally and require no parameters
2190// beyond the generation settings.
2191
2192/// Generates a random `usize` within the specified range (inclusive).
2193///
2194/// # Arguments
2195///
2196/// * `min` - Minimum value (inclusive)
2197/// * `max` - Maximum value (inclusive)
2198///
2199/// # Returns
2200///
2201/// A random `usize` in the range `[min, max]`.
2202///
2203/// # Examples
2204///
2205/// ```rust
2206/// # #[cfg(feature = "core")]
2207/// # {
2208/// let value = product_os_random::random_usize(1, 100);
2209/// assert!((1..=100).contains(&value));
2210/// # }
2211/// ```
2212#[cfg(any(feature = "core", feature = "send_only", feature = "constrained"))]
2213pub fn random_usize(min: usize, max: usize) -> usize {
2214    RandomGenerator::get_simple_random_usize_one_time(min, max)
2215}
2216
2217/// Generates a random string of printable ASCII characters.
2218///
2219/// # Arguments
2220///
2221/// * `len` - Length of the string
2222///
2223/// # Returns
2224///
2225/// A `String` of length `len` containing random printable characters.
2226///
2227/// # Examples
2228///
2229/// ```rust
2230/// # #[cfg(feature = "core")]
2231/// # {
2232/// let s = product_os_random::random_string(10);
2233/// assert_eq!(s.len(), 10);
2234/// # }
2235/// ```
2236#[cfg(any(feature = "core", feature = "send_only", feature = "constrained"))]
2237pub fn random_string(len: usize) -> String {
2238    RandomGenerator::get_simple_random_string_one_time(len)
2239}
2240
2241/// Generates a random alphanumeric string (a-z, A-Z, 0-9).
2242///
2243/// # Arguments
2244///
2245/// * `len` - Length of the string
2246///
2247/// # Returns
2248///
2249/// A `String` of length `len` containing only alphanumeric characters.
2250///
2251/// # Examples
2252///
2253/// ```rust
2254/// # #[cfg(feature = "core")]
2255/// # {
2256/// let s = product_os_random::random_alphanumeric(10);
2257/// assert_eq!(s.len(), 10);
2258/// assert!(s.chars().all(|c| c.is_alphanumeric()));
2259/// # }
2260/// ```
2261#[cfg(any(feature = "core", feature = "send_only", feature = "constrained"))]
2262pub fn random_alphanumeric(len: usize) -> String {
2263    RandomGenerator::get_simple_random_alphanumeric_one_time(len)
2264}
2265
2266/// Generates random bytes.
2267///
2268/// # Arguments
2269///
2270/// * `len` - Number of bytes to generate
2271///
2272/// # Returns
2273///
2274/// A `Vec<u8>` containing `len` random bytes (0-255).
2275///
2276/// # Examples
2277///
2278/// ```rust
2279/// # #[cfg(feature = "core")]
2280/// # {
2281/// let bytes = product_os_random::random_bytes(16);
2282/// assert_eq!(bytes.len(), 16);
2283/// # }
2284/// ```
2285#[cfg(any(feature = "core", feature = "send_only", feature = "constrained"))]
2286pub fn random_bytes(len: usize) -> Vec<u8> {
2287    RandomGenerator::get_simple_random_bytes_one_time(len)
2288}
2289
2290/// Generates a random password string of printable ASCII characters.
2291///
2292/// # Arguments
2293///
2294/// * `len` - Length of the password
2295///
2296/// # Returns
2297///
2298/// A `String` of length `len` containing random characters suitable for passwords.
2299///
2300/// # Examples
2301///
2302/// ```rust
2303/// # #[cfg(feature = "core")]
2304/// # {
2305/// let pw = product_os_random::random_password(16);
2306/// assert_eq!(pw.len(), 16);
2307/// # }
2308/// ```
2309#[cfg(any(feature = "core", feature = "send_only", feature = "constrained"))]
2310pub fn random_password(len: usize) -> String {
2311    RandomGenerator::get_simple_random_password_one_time(len)
2312}
2313
2314/// Generates a random string from a given character set.
2315///
2316/// # Arguments
2317///
2318/// * `len` - Length of the string
2319/// * `characters` - String containing the character set to choose from
2320///
2321/// # Returns
2322///
2323/// A `String` of length `len` with characters randomly selected from `characters`.
2324///
2325/// # Examples
2326///
2327/// ```rust
2328/// # #[cfg(feature = "core")]
2329/// # {
2330/// let s = product_os_random::random_from_characters(8, "abc123");
2331/// assert_eq!(s.len(), 8);
2332/// assert!(s.chars().all(|c| "abc123".contains(c)));
2333/// # }
2334/// ```
2335#[cfg(any(feature = "core", feature = "send_only", feature = "constrained"))]
2336pub fn random_from_characters(len: usize, characters: &str) -> String {
2337    RandomGenerator::get_simple_random_from_characters_one_time(len, characters)
2338}
2339
2340/// Generates a cryptographic key of the specified length.
2341///
2342/// # Arguments
2343///
2344/// * `len` - Length of the key in bytes
2345///
2346/// # Returns
2347///
2348/// A `Vec<u8>` containing `len` random bytes suitable for cryptographic use.
2349///
2350/// # Examples
2351///
2352/// ```rust
2353/// # #[cfg(feature = "core")]
2354/// # {
2355/// let key = product_os_random::generate_random_key(32);
2356/// assert_eq!(key.len(), 32);
2357/// # }
2358/// ```
2359#[cfg(any(feature = "core", feature = "send_only", feature = "constrained"))]
2360pub fn generate_random_key(len: usize) -> Vec<u8> {
2361    RandomGenerator::generate_simple_key_one_time(len)
2362}