Skip to content

Commit 942f4f4

Browse files
marshallpierceMarshall Pierce
authored and
Marshall Pierce
committed
Use enums for errors.
1 parent 1976604 commit 942f4f4

File tree

3 files changed

+54
-21
lines changed

3 files changed

+54
-21
lines changed

src/lib.rs

Lines changed: 50 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,42 @@ pub struct Histogram<T: Counter> {
240240
counts: Vec<T>,
241241
}
242242

243+
/// Errors that can occur when creating a histogram.
244+
#[derive(Debug, Eq, PartialEq, Clone, Copy)]
245+
pub enum CreationError {
246+
/// Lowest discernible value must be >= 1
247+
LowTooSmall,
248+
/// Lowest discernible value must be <= u64::max_value() / 2
249+
LowTooBig,
250+
/// Highest trackable value must be >= 2 * lowest discernible value
251+
HighLessThanTwiceLow,
252+
/// Number of significant digits must be between 0 and 5
253+
SigFigTooBig,
254+
/// Cannot represent sigfig worth of values beyond low
255+
CannotRepresentSigFigBeyondLow
256+
}
257+
258+
/// Errors that can occur when adding another histogram.
259+
#[derive(Debug, Eq, PartialEq, Clone, Copy)]
260+
pub enum AdditionError {
261+
/// The other histogram includes values that do not fit in this histogram's range.
262+
/// Only possible when auto resize is disabled.
263+
OtherAddendValuesExceedRange
264+
}
265+
266+
/// Errors that can occur when subtracting another histogram.
267+
#[derive(Debug, Eq, PartialEq, Clone, Copy)]
268+
pub enum SubtractionError {
269+
/// The other histogram includes values that do not fit in this histogram's range.
270+
/// Only possible when auto resize is disabled.
271+
SubtrahendValuesExceedMinuendRange,
272+
/// The other histogram includes counts that are higher than the current count for a value, and
273+
/// counts cannot go negative. The subtraction may have been partially applied to some counts as
274+
/// this error is returned when the first impossible subtraction is detected.
275+
SubtrahendCountExceedsMinuendCount
276+
}
277+
278+
243279
/// Module containing the implementations of all `Histogram` iterators.
244280
pub mod iterators;
245281

@@ -356,7 +392,7 @@ impl<T: Counter> Histogram<T> {
356392

357393
/// Overwrite this histogram with the given histogram. All data and statistics in this
358394
/// histogram will be overwritten.
359-
pub fn set_to<B: Borrow<Histogram<T>>>(&mut self, source: B) -> Result<(), &'static str> {
395+
pub fn set_to<B: Borrow<Histogram<T>>>(&mut self, source: B) -> Result<(), AdditionError> {
360396
self.reset();
361397
self.add(source.borrow())
362398
}
@@ -380,15 +416,14 @@ impl<T: Counter> Histogram<T> {
380416
///
381417
/// May fail if values in the other histogram are higher than `.high()`, and auto-resize is
382418
/// disabled.
383-
pub fn add<B: Borrow<Histogram<T>>>(&mut self, source: B) -> Result<(), &'static str> {
419+
pub fn add<B: Borrow<Histogram<T>>>(&mut self, source: B) -> Result<(), AdditionError> {
384420
let source = source.borrow();
385421

386422
// make sure we can take the values in source
387423
let top = self.highest_equivalent(self.value_for(self.last()));
388424
if top < source.max() {
389425
if !self.auto_resize {
390-
return Err("The other histogram includes values that do not fit in this \
391-
histogram's range.");
426+
return Err(AdditionError::OtherAddendValuesExceedRange);
392427
}
393428
self.resize(source.max());
394429
}
@@ -480,15 +515,14 @@ impl<T: Counter> Histogram<T> {
480515
/// disabled. Or, if the count for a given value in the other histogram is higher than that of
481516
/// this histogram. In the latter case, some of the counts may still have been updated, which
482517
/// may cause data corruption.
483-
pub fn subtract<B: Borrow<Histogram<T>>>(&mut self, other: B) -> Result<(), &'static str> {
518+
pub fn subtract<B: Borrow<Histogram<T>>>(&mut self, other: B) -> Result<(), SubtractionError> {
484519
let other = other.borrow();
485520

486521
// make sure we can take the values in source
487522
let top = self.highest_equivalent(self.value_for(self.last()));
488523
if top < other.max() {
489524
if !self.auto_resize {
490-
return Err("The other histogram includes values that do not fit in this \
491-
histogram's range.");
525+
return Err(SubtractionError::SubtrahendValuesExceedMinuendRange);
492526
}
493527
self.resize(other.max());
494528
}
@@ -498,8 +532,7 @@ impl<T: Counter> Histogram<T> {
498532
if other_count != T::zero() {
499533
let other_value = other.value_for(i);
500534
if self.count_at(other_value).unwrap() < other_count {
501-
return Err("The other histogram includes counts that are higher than the \
502-
current count for that value.");
535+
return Err(SubtractionError::SubtrahendCountExceedsMinuendCount);
503536
}
504537
self.alter_n(other_value, other_count, false).expect("value should fit by now");
505538
}
@@ -556,7 +589,7 @@ impl<T: Counter> Histogram<T> {
556589
/// `sigfig` specifies the number of significant value digits to preserve in the recorded data.
557590
/// This is the number of significant decimal digits to which the histogram will maintain value
558591
/// resolution and separation. Must be a non-negative integer between 0 and 5.
559-
pub fn new(sigfig: u8) -> Result<Histogram<T>, &'static str> {
592+
pub fn new(sigfig: u8) -> Result<Histogram<T>, CreationError> {
560593
let mut h = Self::new_with_bounds(1, 2, sigfig);
561594
if let Ok(ref mut h) = h {
562595
h.auto_resize = true;
@@ -572,7 +605,7 @@ impl<T: Counter> Histogram<T> {
572605
/// that is >= 2. `sigfig` specifies the number of significant figures to maintain. This is the
573606
/// number of significant decimal digits to which the histogram will maintain value resolution
574607
/// and separation. Must be a non-negative integer between 0 and 5.
575-
pub fn new_with_max(high: u64, sigfig: u8) -> Result<Histogram<T>, &'static str> {
608+
pub fn new_with_max(high: u64, sigfig: u8) -> Result<Histogram<T>, CreationError> {
576609
Self::new_with_bounds(1, high, sigfig)
577610
}
578611

@@ -589,20 +622,20 @@ impl<T: Counter> Histogram<T> {
589622
/// figures to maintain. This is the number of significant decimal digits to which the
590623
/// histogram will maintain value resolution and separation. Must be a non-negative integer
591624
/// between 0 and 5.
592-
pub fn new_with_bounds(low: u64, high: u64, sigfig: u8) -> Result<Histogram<T>, &'static str> {
625+
pub fn new_with_bounds(low: u64, high: u64, sigfig: u8) -> Result<Histogram<T>, CreationError> {
593626
// Verify argument validity
594627
if low < 1 {
595-
return Err("lowest discernible value must be >= 1");
628+
return Err(CreationError::LowTooSmall);
596629
}
597630
if low > u64::max_value() / 2 {
598631
// avoid overflow in 2 * low
599-
return Err("lowest discernible value must be <= u64::max_value() / 2")
632+
return Err(CreationError::LowTooBig)
600633
}
601634
if high < 2 * low {
602-
return Err("highest trackable value must be >= 2 * lowest discernible value");
635+
return Err(CreationError::HighLessThanTwiceLow);
603636
}
604637
if sigfig > 5 {
605-
return Err("number of significant digits must be between 0 and 5");
638+
return Err(CreationError::SigFigTooBig);
606639
}
607640

608641
// Given a 3 decimal point accuracy, the expectation is obviously for "+/- 1 unit at 1000".
@@ -634,7 +667,7 @@ impl<T: Counter> Histogram<T> {
634667
// histogram vs ones whose magnitude here fits in 63 bits is debatable, and it makes
635668
// it harder to work through the logic. Sums larger than 64 are totally broken as
636669
// leading_zero_count_base would go negative.
637-
return Err("Cannot represent sigfig worth of values beyond low");
670+
return Err(CreationError::CannotRepresentSigFigBeyondLow);
638671
};
639672

640673
let sub_bucket_half_count = sub_bucket_count / 2;

src/tests/index_calculation.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use super::Histogram;
1+
use super::super::{CreationError, Histogram};
22
use tests::helpers::histo64;
33

44
#[test]
@@ -114,7 +114,7 @@ fn unit_magnitude_52_sub_bucket_magnitude_11_index_calculations() {
114114

115115
#[test]
116116
fn unit_magnitude_53_sub_bucket_magnitude_11_throws() {
117-
assert_eq!("Cannot represent sigfig worth of values beyond low",
117+
assert_eq!(CreationError::CannotRepresentSigFigBeyondLow,
118118
Histogram::<u64>::new_with_bounds(1_u64 << 53, 1_u64 << 63, 3).unwrap_err());
119119
}
120120

src/tests/tests.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use super::Histogram;
1+
use super::{CreationError, Histogram};
22

33
#[path = "helpers.rs"]
44
mod helpers;
@@ -10,5 +10,5 @@ mod index_calculation;
1010
#[test]
1111
fn new_err_high_not_double_low() {
1212
let res = Histogram::<u64>::new_with_bounds(10, 15, 0);
13-
assert_eq!("highest trackable value must be >= 2 * lowest discernible value", res.unwrap_err());
13+
assert_eq!(CreationError::HighLessThanTwiceLow, res.unwrap_err());
1414
}

0 commit comments

Comments
 (0)