Skip to content

Commit 4c52651

Browse files
jturner314LukeMathWalker
authored andcommitted
Prevent other crates from implementing our traits (#38)
* Prevent other crates from implementing our traits This allows us to freely add new functionality to the traits without breaking changes. * Make PrivateMarker a param instead of return type This still prevents other crates from implementing our traits, but it has the advantage that it also prevents them from calling the `__private__` methods. * Improve docs of __private__ method
1 parent 5abbc48 commit 4c52651

File tree

10 files changed

+72
-0
lines changed

10 files changed

+72
-0
lines changed

src/correlation.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,8 @@ where
119119
fn pearson_correlation(&self) -> Array2<A>
120120
where
121121
A: Float + FromPrimitive;
122+
123+
private_decl! {}
122124
}
123125

124126
impl<A: 'static, S> CorrelationExt<A, S> for ArrayBase<S, Ix2>
@@ -164,6 +166,8 @@ where
164166
// element-wise division
165167
cov / std_matrix
166168
}
169+
170+
private_impl! {}
167171
}
168172

169173
#[cfg(test)]

src/entropy.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,8 @@ where
120120
where
121121
S2: Data<Elem = A>,
122122
A: Float;
123+
124+
private_decl! {}
123125
}
124126

125127
impl<A, S, D> EntropyExt<A, S, D> for ArrayBase<S, D>
@@ -212,6 +214,8 @@ where
212214
let cross_entropy = -temp.sum();
213215
Ok(cross_entropy)
214216
}
217+
218+
private_impl! {}
215219
}
216220

217221
#[cfg(test)]

src/histogram/histograms.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,8 @@ where
147147
fn histogram(&self, grid: Grid<A>) -> Histogram<A>
148148
where
149149
A: Ord;
150+
151+
private_decl! {}
150152
}
151153

152154
impl<A, S> HistogramExt<A, S> for ArrayBase<S, Ix2>
@@ -161,4 +163,6 @@ where
161163
}
162164
histogram
163165
}
166+
167+
private_impl! {}
164168
}

src/lib.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,39 @@ pub use quantile::{interpolate, Quantile1dExt, QuantileExt};
4848
pub use sort::Sort1dExt;
4949
pub use summary_statistics::SummaryStatisticsExt;
5050

51+
#[macro_use]
52+
mod private {
53+
/// This is a public type in a private module, so it can be included in
54+
/// public APIs, but other crates can't access it.
55+
pub struct PrivateMarker;
56+
57+
/// Defines an associated function for a trait that is impossible for other
58+
/// crates to implement. This makes it possible to add new associated
59+
/// types/functions/consts/etc. to the trait without breaking changes.
60+
macro_rules! private_decl {
61+
() => {
62+
/// This method makes this trait impossible to implement outside of
63+
/// `ndarray-stats` so that we can freely add new methods, etc., to
64+
/// this trait without breaking changes.
65+
///
66+
/// We don't anticipate any other crates needing to implement this
67+
/// trait, but if you do have such a use-case, please let us know.
68+
///
69+
/// **Warning** This method is not considered part of the public
70+
/// API, and client code should not rely on it being present. It
71+
/// may be removed in a non-breaking release.
72+
fn __private__(&self, _: crate::private::PrivateMarker);
73+
};
74+
}
75+
76+
/// Implements the associated function defined by `private_decl!`.
77+
macro_rules! private_impl {
78+
() => {
79+
fn __private__(&self, _: crate::private::PrivateMarker) {}
80+
};
81+
}
82+
}
83+
5184
mod correlation;
5285
mod entropy;
5386
pub mod errors;

src/maybe_nan/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,8 @@ where
289289
S: DataMut,
290290
D: RemoveAxis,
291291
F: FnMut(ArrayViewMut1<'a, A::NotNan>) -> B;
292+
293+
private_decl! {}
292294
}
293295

294296
impl<A, S, D> MaybeNanExt<A, S, D> for ArrayBase<S, D>
@@ -365,6 +367,8 @@ where
365367
{
366368
self.map_axis_mut(axis, |lane| mapping(A::remove_nan_mut(lane)))
367369
}
370+
371+
private_impl! {}
368372
}
369373

370374
#[cfg(test)]

src/quantile/interpolate.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ pub trait Interpolate<T> {
4444
/// or if `None` is provided for the higher value when it's needed.
4545
#[doc(hidden)]
4646
fn interpolate(lower: Option<T>, higher: Option<T>, q: N64, len: usize) -> T;
47+
48+
private_decl! {}
4749
}
4850

4951
/// Select the higher value.
@@ -69,6 +71,7 @@ impl<T> Interpolate<T> for Higher {
6971
fn interpolate(_lower: Option<T>, higher: Option<T>, _q: N64, _len: usize) -> T {
7072
higher.unwrap()
7173
}
74+
private_impl! {}
7275
}
7376

7477
impl<T> Interpolate<T> for Lower {
@@ -81,6 +84,7 @@ impl<T> Interpolate<T> for Lower {
8184
fn interpolate(lower: Option<T>, _higher: Option<T>, _q: N64, _len: usize) -> T {
8285
lower.unwrap()
8386
}
87+
private_impl! {}
8488
}
8589

8690
impl<T> Interpolate<T> for Nearest {
@@ -97,6 +101,7 @@ impl<T> Interpolate<T> for Nearest {
97101
higher.unwrap()
98102
}
99103
}
104+
private_impl! {}
100105
}
101106

102107
impl<T> Interpolate<T> for Midpoint
@@ -115,6 +120,7 @@ where
115120
let higher = higher.unwrap();
116121
lower.clone() + (higher.clone() - lower.clone()) / denom.clone()
117122
}
123+
private_impl! {}
118124
}
119125

120126
impl<T> Interpolate<T> for Linear
@@ -135,4 +141,5 @@ where
135141
let higher_f64 = higher.to_f64().unwrap();
136142
lower.clone() + T::from_f64(fraction * (higher_f64 - lower_f64)).unwrap()
137143
}
144+
private_impl! {}
138145
}

src/quantile/mod.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,8 @@ where
295295
A::NotNan: Clone + Ord,
296296
S: DataMut,
297297
I: Interpolate<A::NotNan>;
298+
299+
private_decl! {}
298300
}
299301

300302
impl<A, S, D> QuantileExt<A, S, D> for ArrayBase<S, D>
@@ -568,6 +570,8 @@ where
568570
});
569571
Ok(quantile)
570572
}
573+
574+
private_impl! {}
571575
}
572576

573577
/// Quantile methods for 1-D arrays.
@@ -635,6 +639,8 @@ where
635639
S: DataMut,
636640
S2: Data<Elem = N64>,
637641
I: Interpolate<A>;
642+
643+
private_decl! {}
638644
}
639645

640646
impl<A, S> Quantile1dExt<A, S> for ArrayBase<S, Ix1>
@@ -665,6 +671,8 @@ where
665671
{
666672
self.quantiles_axis_mut(Axis(0), qs, interpolate)
667673
}
674+
675+
private_impl! {}
668676
}
669677

670678
pub mod interpolate;

src/sort.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,8 @@ where
103103
where
104104
A: Ord + Clone,
105105
S: DataMut;
106+
107+
private_decl! {}
106108
}
107109

108110
impl<A, S> Sort1dExt<A, S> for ArrayBase<S, Ix1>
@@ -183,6 +185,8 @@ where
183185
self.swap(0, i - 1);
184186
i - 1
185187
}
188+
189+
private_impl! {}
186190
}
187191

188192
/// To retrieve multiple indexes from the sorted array in an optimized fashion,

src/summary_statistics/means.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,8 @@ where
105105
}
106106
}
107107
}
108+
109+
private_impl! {}
108110
}
109111

110112
/// Returns a vector containing all moments of the array elements up to

src/summary_statistics/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,8 @@ where
140140
fn central_moments(&self, order: u16) -> Result<Vec<A>, EmptyInput>
141141
where
142142
A: Float + FromPrimitive;
143+
144+
private_decl! {}
143145
}
144146

145147
mod means;

0 commit comments

Comments
 (0)