Skip to content

Commit 7ede440

Browse files
authored
Added serde1 feature to Serialize/Deserialize WeightedIndex (#974)
Re-enable serde1 for all distributions, StepRng and IndexVec
1 parent 6a5f0d4 commit 7ede440

File tree

10 files changed

+152
-2
lines changed

10 files changed

+152
-2
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ A [separate changelog is kept for rand_core](rand_core/CHANGELOG.md).
88

99
You may also find the [Upgrade Guide](https://rust-random.github.io/book/update.html) useful.
1010

11+
## [Unreleased]
12+
### Additions
13+
- Added a `serde1` feature and added Serialize/Deserialize to `UniformInt` and `WeightedIndex` (#974)
14+
1115
## [0.7.3] - 2020-01-10
1216
### Fixes
1317
- The `Bernoulli` distribution constructors now reports an error on NaN and on

Cargo.toml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ appveyor = { repository = "rust-random/rand" }
2424
# Meta-features:
2525
default = ["std", "std_rng"]
2626
nightly = ["simd_support"] # enables all features requiring nightly rust
27-
serde1 = [] # does nothing, deprecated
27+
serde1 = ["serde"]
2828

2929
# Option (enabled by default): without "std" rand uses libcore; this option
3030
# enables functionality expected to be available on a standard platform.
@@ -58,6 +58,7 @@ members = [
5858
rand_core = { path = "rand_core", version = "0.5.1" }
5959
rand_pcg = { path = "rand_pcg", version = "0.2", optional = true }
6060
log = { version = "0.4.4", optional = true }
61+
serde = { version = "1.0.103", features = ["derive"], optional = true }
6162

6263
[dependencies.packed_simd]
6364
# NOTE: so far no version works reliably due to dependence on unstable features
@@ -81,6 +82,8 @@ rand_hc = { path = "rand_hc", version = "0.2", optional = true }
8182
rand_pcg = { path = "rand_pcg", version = "0.2" }
8283
# Only for benches:
8384
rand_hc = { path = "rand_hc", version = "0.2" }
85+
# Only to test serde1
86+
bincode = "1.2.1"
8487

8588
[package.metadata.docs.rs]
8689
all-features = true

src/distributions/bernoulli.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ use crate::distributions::Distribution;
1212
use crate::Rng;
1313
use core::{fmt, u64};
1414

15+
#[cfg(feature = "serde1")]
16+
use serde::{Serialize, Deserialize};
1517
/// The Bernoulli distribution.
1618
///
1719
/// This is a special case of the Binomial distribution where `n = 1`.
@@ -32,6 +34,7 @@ use core::{fmt, u64};
3234
/// so only probabilities that are multiples of 2<sup>-64</sup> can be
3335
/// represented.
3436
#[derive(Clone, Copy, Debug)]
37+
#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
3538
pub struct Bernoulli {
3639
/// Probability of success, relative to the maximal integer.
3740
p_int: u64,
@@ -143,6 +146,15 @@ mod test {
143146
use crate::distributions::Distribution;
144147
use crate::Rng;
145148

149+
#[test]
150+
#[cfg(feature="serde1")]
151+
fn test_serializing_deserializing_bernoulli() {
152+
let coin_flip = Bernoulli::new(0.5).unwrap();
153+
let de_coin_flip : Bernoulli = bincode::deserialize(&bincode::serialize(&coin_flip).unwrap()).unwrap();
154+
155+
assert_eq!(coin_flip.p_int, de_coin_flip.p_int);
156+
}
157+
146158
#[test]
147159
fn test_trivial() {
148160
let mut r = crate::test::rng(1);

src/distributions/float.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ use crate::Rng;
1414
use core::mem;
1515
#[cfg(feature = "simd_support")] use packed_simd::*;
1616

17+
#[cfg(feature = "serde1")]
18+
use serde::{Serialize, Deserialize};
19+
1720
/// A distribution to sample floating point numbers uniformly in the half-open
1821
/// interval `(0, 1]`, i.e. including 1 but not 0.
1922
///
@@ -39,6 +42,7 @@ use core::mem;
3942
/// [`Open01`]: crate::distributions::Open01
4043
/// [`Uniform`]: crate::distributions::uniform::Uniform
4144
#[derive(Clone, Copy, Debug)]
45+
#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
4246
pub struct OpenClosed01;
4347

4448
/// A distribution to sample floating point numbers uniformly in the open
@@ -65,6 +69,7 @@ pub struct OpenClosed01;
6569
/// [`OpenClosed01`]: crate::distributions::OpenClosed01
6670
/// [`Uniform`]: crate::distributions::uniform::Uniform
6771
#[derive(Clone, Copy, Debug)]
72+
#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
6873
pub struct Open01;
6974

7075

src/distributions/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,9 @@ pub mod uniform;
111111
#[cfg(feature = "alloc")] pub mod weighted;
112112
#[cfg(feature = "alloc")] mod weighted_index;
113113

114+
#[cfg(feature = "serde1")]
115+
use serde::{Serialize, Deserialize};
116+
114117
mod float;
115118
#[doc(hidden)]
116119
pub mod hidden_export {
@@ -320,6 +323,7 @@ where
320323
///
321324
/// [`Uniform`]: uniform::Uniform
322325
#[derive(Clone, Copy, Debug)]
326+
#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
323327
pub struct Standard;
324328

325329

src/distributions/other.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ use core::num::Wrapping;
1414
use crate::distributions::{Distribution, Standard, Uniform};
1515
use crate::Rng;
1616

17+
#[cfg(feature = "serde1")]
18+
use serde::{Serialize, Deserialize};
19+
1720
// ----- Sampling distributions -----
1821

1922
/// Sample a `char`, uniformly distributed over ASCII letters and numbers:
@@ -34,6 +37,7 @@ use crate::Rng;
3437
/// println!("Random chars: {}", chars);
3538
/// ```
3639
#[derive(Debug)]
40+
#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
3741
pub struct Alphanumeric;
3842

3943

src/distributions/uniform.rs

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,9 +115,11 @@ use crate::Rng;
115115
#[allow(unused_imports)] // rustc doesn't detect that this is actually used
116116
use crate::distributions::utils::Float;
117117

118-
119118
#[cfg(feature = "simd_support")] use packed_simd::*;
120119

120+
#[cfg(feature = "serde1")]
121+
use serde::{Serialize, Deserialize};
122+
121123
/// Sample values uniformly between two bounds.
122124
///
123125
/// [`Uniform::new`] and [`Uniform::new_inclusive`] construct a uniform
@@ -159,6 +161,7 @@ use crate::distributions::utils::Float;
159161
/// [`new`]: Uniform::new
160162
/// [`new_inclusive`]: Uniform::new_inclusive
161163
#[derive(Clone, Copy, Debug)]
164+
#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
162165
pub struct Uniform<X: SampleUniform>(X::Sampler);
163166

164167
impl<X: SampleUniform> Uniform<X> {
@@ -347,6 +350,7 @@ where Borrowed: SampleUniform
347350
/// multiply by `range`, the result is in the high word. Then comparing the low
348351
/// word against `zone` makes sure our distribution is uniform.
349352
#[derive(Clone, Copy, Debug)]
353+
#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
350354
pub struct UniformInt<X> {
351355
low: X,
352356
range: X,
@@ -644,6 +648,7 @@ uniform_simd_int_impl! {
644648
/// [`new_inclusive`]: UniformSampler::new_inclusive
645649
/// [`Standard`]: crate::distributions::Standard
646650
#[derive(Clone, Copy, Debug)]
651+
#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
647652
pub struct UniformFloat<X> {
648653
low: X,
649654
scale: X,
@@ -837,12 +842,14 @@ uniform_float_impl! { f64x8, u64x8, f64, u64, 64 - 52 }
837842
/// Unless you are implementing [`UniformSampler`] for your own types, this type
838843
/// should not be used directly, use [`Uniform`] instead.
839844
#[derive(Clone, Copy, Debug)]
845+
#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
840846
pub struct UniformDuration {
841847
mode: UniformDurationMode,
842848
offset: u32,
843849
}
844850

845851
#[derive(Debug, Copy, Clone)]
852+
#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
846853
enum UniformDurationMode {
847854
Small {
848855
secs: u64,
@@ -967,6 +974,56 @@ mod tests {
967974
use super::*;
968975
use crate::rngs::mock::StepRng;
969976

977+
#[test]
978+
#[cfg(feature = "serde1")]
979+
fn test_serialization_uniform_duration() {
980+
let distr = UniformDuration::new(std::time::Duration::from_secs(10), std::time::Duration::from_secs(60));
981+
let de_distr: UniformDuration = bincode::deserialize(&bincode::serialize(&distr).unwrap()).unwrap();
982+
assert_eq!(
983+
distr.offset, de_distr.offset
984+
);
985+
match (distr.mode, de_distr.mode) {
986+
(UniformDurationMode::Small {secs: a_secs, nanos: a_nanos}, UniformDurationMode::Small {secs, nanos}) => {
987+
assert_eq!(a_secs, secs);
988+
989+
assert_eq!(a_nanos.0.low, nanos.0.low);
990+
assert_eq!(a_nanos.0.range, nanos.0.range);
991+
assert_eq!(a_nanos.0.z, nanos.0.z);
992+
}
993+
(UniformDurationMode::Medium {nanos: a_nanos} , UniformDurationMode::Medium {nanos}) => {
994+
assert_eq!(a_nanos.0.low, nanos.0.low);
995+
assert_eq!(a_nanos.0.range, nanos.0.range);
996+
assert_eq!(a_nanos.0.z, nanos.0.z);
997+
}
998+
(UniformDurationMode::Large {max_secs:a_max_secs, max_nanos:a_max_nanos, secs:a_secs}, UniformDurationMode::Large {max_secs, max_nanos, secs} ) => {
999+
assert_eq!(a_max_secs, max_secs);
1000+
assert_eq!(a_max_nanos, max_nanos);
1001+
1002+
assert_eq!(a_secs.0.low, secs.0.low);
1003+
assert_eq!(a_secs.0.range, secs.0.range);
1004+
assert_eq!(a_secs.0.z, secs.0.z);
1005+
}
1006+
_ => panic!("`UniformDurationMode` was not serialized/deserialized correctly")
1007+
}
1008+
}
1009+
1010+
#[test]
1011+
#[cfg(feature = "serde1")]
1012+
fn test_uniform_serialization() {
1013+
let unit_box: Uniform<i32> = Uniform::new(-1, 1);
1014+
let de_unit_box: Uniform<i32> = bincode::deserialize(&bincode::serialize(&unit_box).unwrap()).unwrap();
1015+
1016+
assert_eq!(unit_box.0.low, de_unit_box.0.low);
1017+
assert_eq!(unit_box.0.range, de_unit_box.0.range);
1018+
assert_eq!(unit_box.0.z, de_unit_box.0.z);
1019+
1020+
let unit_box: Uniform<f32> = Uniform::new(-1., 1.);
1021+
let de_unit_box: Uniform<f32> = bincode::deserialize(&bincode::serialize(&unit_box).unwrap()).unwrap();
1022+
1023+
assert_eq!(unit_box.0.low, de_unit_box.0.low);
1024+
assert_eq!(unit_box.0.scale, de_unit_box.0.scale);
1025+
}
1026+
9701027
#[should_panic]
9711028
#[test]
9721029
fn test_uniform_bad_limits_equal_int() {

src/distributions/weighted_index.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ use core::fmt;
1717
// Note that this whole module is only imported if feature="alloc" is enabled.
1818
#[cfg(not(feature = "std"))] use crate::alloc::vec::Vec;
1919

20+
#[cfg(feature = "serde1")]
21+
use serde::{Serialize, Deserialize};
22+
2023
/// A distribution using weighted sampling of discrete items
2124
///
2225
/// Sampling a `WeightedIndex` distribution returns the index of a randomly
@@ -73,6 +76,7 @@ use core::fmt;
7376
/// [`Uniform<X>`]: crate::distributions::uniform::Uniform
7477
/// [`RngCore`]: crate::RngCore
7578
#[derive(Debug, Clone)]
79+
#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
7680
pub struct WeightedIndex<X: SampleUniform + PartialOrd> {
7781
cumulative_weights: Vec<X>,
7882
total_weight: X,
@@ -236,6 +240,23 @@ where X: SampleUniform + PartialOrd
236240
mod test {
237241
use super::*;
238242

243+
#[cfg(feature = "serde1")]
244+
#[test]
245+
fn test_weightedindex_serde1() {
246+
let weighted_index = WeightedIndex::new(vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]).unwrap();
247+
248+
let ser_weighted_index = bincode::serialize(&weighted_index).unwrap();
249+
let de_weighted_index: WeightedIndex<i32> =
250+
bincode::deserialize(&ser_weighted_index).unwrap();
251+
252+
assert_eq!(
253+
de_weighted_index.cumulative_weights,
254+
weighted_index.cumulative_weights
255+
);
256+
assert_eq!(de_weighted_index.total_weight, weighted_index.total_weight);
257+
}
258+
259+
239260
#[test]
240261
#[cfg_attr(miri, ignore)] // Miri is too slow
241262
fn test_weightedindex() {

src/rngs/mock.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@
1010
1111
use rand_core::{impls, Error, RngCore};
1212

13+
#[cfg(feature = "serde1")]
14+
use serde::{Serialize, Deserialize};
15+
1316
/// A simple implementation of `RngCore` for testing purposes.
1417
///
1518
/// This generates an arithmetic sequence (i.e. adds a constant each step)
@@ -25,6 +28,7 @@ use rand_core::{impls, Error, RngCore};
2528
/// assert_eq!(sample, [2, 3, 4]);
2629
/// ```
2730
#[derive(Debug, Clone)]
31+
#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
2832
pub struct StepRng {
2933
v: u64,
3034
a: u64,
@@ -65,3 +69,18 @@ impl RngCore for StepRng {
6569
Ok(())
6670
}
6771
}
72+
73+
#[cfg(test)]
74+
mod tests {
75+
use super::*;
76+
77+
#[test]
78+
#[cfg(feature = "serde1")]
79+
fn test_serialization_step_rng() {
80+
let some_rng = StepRng::new(42, 7);
81+
let de_some_rng: StepRng = bincode::deserialize(&bincode::serialize(&some_rng).unwrap()).unwrap();
82+
assert_eq!(some_rng.v, de_some_rng.v);
83+
assert_eq!(some_rng.a, de_some_rng.a);
84+
85+
}
86+
}

src/seq/index.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,14 @@ use crate::alloc::collections::BTreeSet;
2222
use crate::distributions::{uniform::SampleUniform, Distribution, Uniform};
2323
use crate::Rng;
2424

25+
#[cfg(feature = "serde1")]
26+
use serde::{Serialize, Deserialize};
27+
2528
/// A vector of indices.
2629
///
2730
/// Multiple internal representations are possible.
2831
#[derive(Clone, Debug)]
32+
#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
2933
pub enum IndexVec {
3034
#[doc(hidden)]
3135
U32(Vec<u32>),
@@ -376,6 +380,23 @@ where
376380
#[cfg(test)]
377381
mod test {
378382
use super::*;
383+
384+
#[test]
385+
#[cfg(feature = "serde1")]
386+
fn test_serialization_index_vec() {
387+
let some_index_vec = IndexVec::from(vec![254_usize, 234, 2, 1]);
388+
let de_some_index_vec: IndexVec = bincode::deserialize(&bincode::serialize(&some_index_vec).unwrap()).unwrap();
389+
match (some_index_vec, de_some_index_vec) {
390+
(IndexVec::U32(a), IndexVec::U32(b)) => {
391+
assert_eq!(a, b);
392+
},
393+
(IndexVec::USize(a), IndexVec::USize(b)) => {
394+
assert_eq!(a, b);
395+
},
396+
_ => {panic!("failed to seralize/deserialize `IndexVec`")}
397+
}
398+
}
399+
379400
#[cfg(all(feature = "alloc", not(feature = "std")))] use crate::alloc::vec;
380401
#[cfg(feature = "std")] use std::vec;
381402

0 commit comments

Comments
 (0)