Skip to content

Commit 658b663

Browse files
feat: add support for the Rust range types, guarded by a new_range_api flag
1 parent d6fc618 commit 658b663

2 files changed

Lines changed: 75 additions & 10 deletions

File tree

Cargo.toml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,15 +61,19 @@ unbiased = []
6161
# Deprecated option: enable logging
6262
log = []
6363

64+
new_range_api = []
65+
6466
[dependencies]
6567
rand_core = { version = "0.10.0", default-features = false }
6668
serde = { version = "1.0.103", features = ["derive"], optional = true }
67-
chacha20 = { version = "0.10.0", default-features = false, features = ["rng"], optional = true }
69+
chacha20 = { version = "0.10.0", default-features = false, features = [
70+
"rng",
71+
], optional = true }
6872
getrandom = { version = "0.4.0", optional = true }
6973

7074
[dev-dependencies]
7175
rand_pcg = "0.10"
7276
# Only to test serde
73-
postcard = {version = "1.1.3", default-features = false, features = ["alloc"]}
77+
postcard = { version = "1.1.3", default-features = false, features = ["alloc"] }
7478
rayon = "1.7"
7579
serde_json = "1.0.140"

src/distr/uniform.rs

Lines changed: 69 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,6 @@ mod other;
110110
pub use other::{UniformChar, UniformDuration};
111111

112112
use core::fmt;
113-
use core::ops::{Range, RangeInclusive, RangeTo, RangeToInclusive};
114113

115114
use crate::Rng;
116115
use crate::distr::Distribution;
@@ -371,22 +370,40 @@ pub trait UniformSampler: Sized {
371370
}
372371
}
373372

374-
impl<X: SampleUniform> TryFrom<Range<X>> for Uniform<X> {
373+
impl<X: SampleUniform> TryFrom<::core::ops::Range<X>> for Uniform<X> {
375374
type Error = Error;
376375

377-
fn try_from(r: Range<X>) -> Result<Uniform<X>, Error> {
376+
fn try_from(r: ::core::ops::Range<X>) -> Result<Uniform<X>, Error> {
378377
Uniform::new(r.start, r.end)
379378
}
380379
}
381380

382-
impl<X: SampleUniform> TryFrom<RangeInclusive<X>> for Uniform<X> {
381+
#[cfg(feature = "new_range_api")]
382+
impl<X: SampleUniform> TryFrom<::core::range::Range<X>> for Uniform<X> {
383+
type Error = Error;
384+
385+
fn try_from(r: ::core::range::Range<X>) -> Result<Uniform<X>, Error> {
386+
Uniform::new(r.start, r.end)
387+
}
388+
}
389+
390+
impl<X: SampleUniform> TryFrom<::core::ops::RangeInclusive<X>> for Uniform<X> {
383391
type Error = Error;
384392

385393
fn try_from(r: ::core::ops::RangeInclusive<X>) -> Result<Uniform<X>, Error> {
386394
Uniform::new_inclusive(r.start(), r.end())
387395
}
388396
}
389397

398+
#[cfg(feature = "new_range_api")]
399+
impl<X: SampleUniform> TryFrom<::core::range::RangeInclusive<X>> for Uniform<X> {
400+
type Error = Error;
401+
402+
fn try_from(r: ::core::range::RangeInclusive<X>) -> Result<Uniform<X>, Error> {
403+
Uniform::new_inclusive(r.start, r.last)
404+
}
405+
}
406+
390407
/// Helper trait similar to [`Borrow`] but implemented
391408
/// only for [`SampleUniform`] and references to [`SampleUniform`]
392409
/// in order to resolve ambiguity issues.
@@ -429,7 +446,20 @@ pub trait SampleRange<T> {
429446
fn is_empty(&self) -> bool;
430447
}
431448

432-
impl<T: SampleUniform + PartialOrd> SampleRange<T> for Range<T> {
449+
impl<T: SampleUniform + PartialOrd> SampleRange<T> for ::core::ops::Range<T> {
450+
#[inline]
451+
fn sample_single<R: Rng + ?Sized>(self, rng: &mut R) -> Result<T, Error> {
452+
T::Sampler::sample_single(self.start, self.end, rng)
453+
}
454+
455+
#[inline]
456+
fn is_empty(&self) -> bool {
457+
!(self.start < self.end)
458+
}
459+
}
460+
461+
#[cfg(feature = "new_range_api")]
462+
impl<T: SampleUniform + PartialOrd> SampleRange<T> for ::core::range::Range<T> {
433463
#[inline]
434464
fn sample_single<R: Rng + ?Sized>(self, rng: &mut R) -> Result<T, Error> {
435465
T::Sampler::sample_single(self.start, self.end, rng)
@@ -441,7 +471,7 @@ impl<T: SampleUniform + PartialOrd> SampleRange<T> for Range<T> {
441471
}
442472
}
443473

444-
impl<T: SampleUniform + PartialOrd> SampleRange<T> for RangeInclusive<T> {
474+
impl<T: SampleUniform + PartialOrd> SampleRange<T> for ::core::ops::RangeInclusive<T> {
445475
#[inline]
446476
fn sample_single<R: Rng + ?Sized>(self, rng: &mut R) -> Result<T, Error> {
447477
T::Sampler::sample_single_inclusive(self.start(), self.end(), rng)
@@ -453,9 +483,22 @@ impl<T: SampleUniform + PartialOrd> SampleRange<T> for RangeInclusive<T> {
453483
}
454484
}
455485

486+
#[cfg(feature = "new_range_api")]
487+
impl<T: SampleUniform + PartialOrd> SampleRange<T> for ::core::range::RangeInclusive<T> {
488+
#[inline]
489+
fn sample_single<R: Rng + ?Sized>(self, rng: &mut R) -> Result<T, Error> {
490+
T::Sampler::sample_single_inclusive(self.start, self.last, rng)
491+
}
492+
493+
#[inline]
494+
fn is_empty(&self) -> bool {
495+
!(self.start <= self.last)
496+
}
497+
}
498+
456499
macro_rules! impl_sample_range_u {
457500
($t:ty) => {
458-
impl SampleRange<$t> for RangeTo<$t> {
501+
impl SampleRange<$t> for ::core::ops::RangeTo<$t> {
459502
#[inline]
460503
fn sample_single<R: Rng + ?Sized>(self, rng: &mut R) -> Result<$t, Error> {
461504
<$t as SampleUniform>::Sampler::sample_single(0, self.end, rng)
@@ -467,7 +510,7 @@ macro_rules! impl_sample_range_u {
467510
}
468511
}
469512

470-
impl SampleRange<$t> for RangeToInclusive<$t> {
513+
impl SampleRange<$t> for ::core::ops::RangeToInclusive<$t> {
471514
#[inline]
472515
fn sample_single<R: Rng + ?Sized>(self, rng: &mut R) -> Result<$t, Error> {
473516
<$t as SampleUniform>::Sampler::sample_single_inclusive(0, self.end, rng)
@@ -478,6 +521,24 @@ macro_rules! impl_sample_range_u {
478521
false
479522
}
480523
}
524+
525+
// `core::range::RangeTo` is set to be a re-export of `core::ops::RangeTo`:
526+
// > A Rust version in the near future will also add `core::range::RangeFull` and `core::range::RangeTo`
527+
// as re-exports from `core::ops` (these do not implement `Iterator` and already implement `Copy`)
528+
// Source: https://blog.rust-lang.org/2026/05/28/Rust-1.96.0/#new-range-types
529+
530+
#[cfg(feature = "new_range_api")]
531+
impl SampleRange<$t> for ::core::range::RangeToInclusive<$t> {
532+
#[inline]
533+
fn sample_single<R: Rng + ?Sized>(self, rng: &mut R) -> Result<$t, Error> {
534+
<$t as SampleUniform>::Sampler::sample_single_inclusive(0, self.last, rng)
535+
}
536+
537+
#[inline]
538+
fn is_empty(&self) -> bool {
539+
false
540+
}
541+
}
481542
};
482543
}
483544

0 commit comments

Comments
 (0)