1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
use chrono::{DateTime, Utc};
use crate::Spline;
/// The result type returned by every fallible splimes function.
pub type Result<T, E = Error> = std::result::Result<T, E>;
/// Everything that can go wrong in splimes.
///
/// The enum is `#[non_exhaustive]`: match the variants you handle and keep a `_` arm, so
/// a new failure mode in a minor release isn't a breaking change.
#[derive(Debug, Clone, PartialEq, thiserror::Error)]
#[non_exhaustive]
pub enum Error {
/// No input points were supplied.
#[error("no input points to interpolate")]
NoPoints,
/// `start` is after `end`.
#[error("invalid time range: start {start} is after end {end}")]
InvalidTimeRange {
/// The requested start of the output grid.
start: DateTime<Utc>,
/// The requested end of the output grid.
end: DateTime<Utc>,
},
/// A polynomial degree of 0 or above [`MAX_POLYNOMIAL_DEGREE`](crate::MAX_POLYNOMIAL_DEGREE).
#[error("invalid polynomial degree {degree}: must be between 1 and {max}")]
InvalidDegree {
/// The degree that was asked for.
degree: usize,
/// The largest supported degree.
max: usize,
},
/// The timestamp and value columns passed to
/// [`Interpolator::run_f64`](crate::Interpolator::run_f64) differ in length.
#[error("{timestamps} timestamps but {values} values")]
LengthMismatch {
/// Length of the timestamp column.
timestamps: usize,
/// Length of the value column.
values: usize,
},
/// A polynomial `bounds_factor` that is negative, NaN or infinite.
#[error("invalid bounds factor {0}: must be finite and not negative")]
InvalidBoundsFactor(f64),
/// An input value has no finite `f64` representation (its magnitude is above about
/// 1.8 × 10³⁰⁸), or an `f64` input is NaN or infinite.
#[error("input value at {timestamp} is not representable as a finite f64")]
ValueOutOfRange {
/// Timestamp of the offending input point.
timestamp: DateTime<Utc>,
},
/// The interpolated value at this timestamp is beyond `f64`'s range: extrapolating far
/// outside the data with a high-degree method, or values near `f64`'s limits. It names
/// the first such grid point, on every backend.
#[error("interpolated value at {timestamp} is beyond f64's range")]
NonFiniteResult {
/// Timestamp of the output point that overflowed.
timestamp: DateTime<Utc>,
},
/// The output grid has more points than [`Interpolator::max_points`](crate::Interpolator::max_points)
/// allows or than can be allocated, for example a nanosecond grid spanning years.
#[error("output grid of {points} points is too large")]
OutputTooLarge {
/// The number of grid points the request describes.
points: u128,
},
/// Too few distinct timestamps for the requested method, and fallback was disabled
/// with [`Interpolator::exact`](crate::Interpolator::exact).
#[error("{spline} needs at least {required} distinct points, got {available}")]
InsufficientPoints {
/// The method that was asked for.
spline: Spline,
/// Distinct timestamps the method needs.
required: usize,
/// Distinct timestamps supplied.
available: usize,
},
/// No usable GPU: the `gpu` feature is off, no adapter was found, the device was
/// lost, or the adapter can't run the requested precision.
#[error("GPU unavailable: {0}")]
GpuUnavailable(String),
/// The GPU reported an error (validation, out of memory, or an internal error) while
/// running an interpolation. [`Backend::Auto`](crate::Backend::Auto) catches this and
/// reruns on the CPU.
#[error("GPU error: {0}")]
Gpu(String),
/// [`configure_gpu`](crate::configure_gpu) was called after the GPU had already
/// started, or a second time.
#[error("GPU already configured: {0}")]
GpuAlreadyConfigured(&'static str),
/// A string didn't name a [`Resolution`](crate::Resolution) or
/// [`Spline`](crate::Spline).
#[error("cannot parse {kind} from {input:?}")]
Parse {
/// What was being parsed: `"resolution"` or `"spline"`.
kind: &'static str,
/// The input that failed to parse.
input: String,
},
/// The task running an interpolation for async code failed: the interpolation
/// panicked (a bug), tokio cancelled its blocking task
/// (`Interpolator::run_async`), or an
/// [`InterpolationFuture`](crate::InterpolationFuture) was polled after it completed.
#[error("interpolation task failed: {0}")]
Task(String),
}