Skip to content

Commit 3115a78

Browse files
marshallpierceMarshall Pierce
authored and
Marshall Pierce
committed
Use enums for errors.
1 parent e2891c7 commit 3115a78

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
@@ -242,6 +242,42 @@ pub struct Histogram<T: Counter> {
242242
counts: Vec<T>,
243243
}
244244

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

@@ -360,7 +396,7 @@ impl<T: Counter> Histogram<T> {
360396

361397
/// Overwrite this histogram with the given histogram. All data and statistics in this
362398
/// histogram will be overwritten.
363-
pub fn set_to<B: Borrow<Histogram<T>>>(&mut self, source: B) -> Result<(), &'static str> {
399+
pub fn set_to<B: Borrow<Histogram<T>>>(&mut self, source: B) -> Result<(), AdditionError> {
364400
self.reset();
365401
self.add(source.borrow())
366402
}
@@ -384,15 +420,14 @@ impl<T: Counter> Histogram<T> {
384420
///
385421
/// May fail if values in the other histogram are higher than `.high()`, and auto-resize is
386422
/// disabled.
387-
pub fn add<B: Borrow<Histogram<T>>>(&mut self, source: B) -> Result<(), &'static str> {
423+
pub fn add<B: Borrow<Histogram<T>>>(&mut self, source: B) -> Result<(), AdditionError> {
388424
let source = source.borrow();
389425

390426
// make sure we can take the values in source
391427
let top = self.highest_equivalent(self.value_for(self.last()));
392428
if top < source.max() {
393429
if !self.auto_resize {
394-
return Err("The other histogram includes values that do not fit in this \
395-
histogram's range.");
430+
return Err(AdditionError::OtherAddendValuesExceedRange);
396431
}
397432
self.resize(source.max());
398433
}
@@ -484,15 +519,14 @@ impl<T: Counter> Histogram<T> {
484519
/// disabled. Or, if the count for a given value in the other histogram is higher than that of
485520
/// this histogram. In the latter case, some of the counts may still have been updated, which
486521
/// may cause data corruption.
487-
pub fn subtract<B: Borrow<Histogram<T>>>(&mut self, other: B) -> Result<(), &'static str> {
522+
pub fn subtract<B: Borrow<Histogram<T>>>(&mut self, other: B) -> Result<(), SubtractionError> {
488523
let other = other.borrow();
489524

490525
// make sure we can take the values in source
491526
let top = self.highest_equivalent(self.value_for(self.last()));
492527
if top < other.max() {
493528
if !self.auto_resize {
494-
return Err("The other histogram includes values that do not fit in this \
495-
histogram's range.");
529+
return Err(SubtractionError::SubtrahendValuesExceedMinuendRange);
496530
}
497531
self.resize(other.max());
498532
}
@@ -502,8 +536,7 @@ impl<T: Counter> Histogram<T> {
502536
if other_count != T::zero() {
503537
let other_value = other.value_for(i);
504538
if self.count_at(other_value).unwrap() < other_count {
505-
return Err("The other histogram includes counts that are higher than the \
506-
current count for that value.");
539+
return Err(SubtractionError::SubtrahendCountExceedsMinuendCount);
507540
}
508541
self.alter_n(other_value, other_count, false).expect("value should fit by now");
509542
}
@@ -560,7 +593,7 @@ impl<T: Counter> Histogram<T> {
560593
/// `sigfig` specifies the number of significant value digits to preserve in the recorded data.
561594
/// This is the number of significant decimal digits to which the histogram will maintain value
562595
/// resolution and separation. Must be a non-negative integer between 0 and 5.
563-
pub fn new(sigfig: u8) -> Result<Histogram<T>, &'static str> {
596+
pub fn new(sigfig: u8) -> Result<Histogram<T>, CreationError> {
564597
let mut h = Self::new_with_bounds(1, 2, sigfig);
565598
if let Ok(ref mut h) = h {
566599
h.auto_resize = true;
@@ -576,7 +609,7 @@ impl<T: Counter> Histogram<T> {
576609
/// that is >= 2. `sigfig` specifies the number of significant figures to maintain. This is the
577610
/// number of significant decimal digits to which the histogram will maintain value resolution
578611
/// and separation. Must be a non-negative integer between 0 and 5.
579-
pub fn new_with_max(high: u64, sigfig: u8) -> Result<Histogram<T>, &'static str> {
612+
pub fn new_with_max(high: u64, sigfig: u8) -> Result<Histogram<T>, CreationError> {
580613
Self::new_with_bounds(1, high, sigfig)
581614
}
582615

@@ -593,20 +626,20 @@ impl<T: Counter> Histogram<T> {
593626
/// figures to maintain. This is the number of significant decimal digits to which the
594627
/// histogram will maintain value resolution and separation. Must be a non-negative integer
595628
/// between 0 and 5.
596-
pub fn new_with_bounds(low: u64, high: u64, sigfig: u8) -> Result<Histogram<T>, &'static str> {
629+
pub fn new_with_bounds(low: u64, high: u64, sigfig: u8) -> Result<Histogram<T>, CreationError> {
597630
// Verify argument validity
598631
if low < 1 {
599-
return Err("lowest discernible value must be >= 1");
632+
return Err(CreationError::LowTooSmall);
600633
}
601634
if low > u64::max_value() / 2 {
602635
// avoid overflow in 2 * low
603-
return Err("lowest discernible value must be <= u64::max_value() / 2")
636+
return Err(CreationError::LowTooBig)
604637
}
605638
if high < 2 * low {
606-
return Err("highest trackable value must be >= 2 * lowest discernible value");
639+
return Err(CreationError::HighLessThanTwiceLow);
607640
}
608641
if sigfig > 5 {
609-
return Err("number of significant digits must be between 0 and 5");
642+
return Err(CreationError::SigFigTooBig);
610643
}
611644

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

644677
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)