1use num::{Num, NumCast, Zero};
8use std::convert::Infallible;
9use std::fmt::Debug;
10use std::num::NonZeroUsize;
11use std::{cmp, io};
12use thiserror::Error;
13
14use crate::experimental::clock::MonotonicityError;
15use crate::experimental::series::buffer::{BufferStrategy, RingBuffer};
16use crate::experimental::series::interpolation::InterpolationKind;
17use crate::experimental::series::interval::SamplingInterval;
18use crate::experimental::series::{BitSet, Counter, DataSemantic, Gauge};
19use crate::experimental::vec1::Vec1;
20
21pub mod recipe {
22 use crate::experimental::series::statistic::{ArithmeticMean, Transform};
25
26 pub type ArithmeticMeanTransform<T, A> = Transform<ArithmeticMean<T>, A>;
27}
28
29#[derive(Debug, Error)]
33#[non_exhaustive]
34pub enum FoldError {
35 #[error(transparent)]
36 Io(#[from] io::Error),
37 #[error(transparent)]
38 Monotonicity(#[from] MonotonicityError),
39 #[error("overflow in statistic computation")]
40 Overflow,
41 #[error("timed sample dropped: channel is closed or buffer is exhausted")]
45 Buffer,
46 #[error("failed to fold one or more buffered samples")]
47 Flush(Vec1<FoldError>),
48}
49
50impl From<Infallible> for FoldError {
51 fn from(_: Infallible) -> Self {
52 unreachable!()
53 }
54}
55
56pub trait Statistic: Clone {
58 type Semantic: DataSemantic;
60 type Sample: Clone;
62 type Aggregation: Clone;
64
65 fn fold(&mut self, sample: Self::Sample) -> Result<(), FoldError>;
71
72 fn fill(&mut self, sample: Self::Sample, n: NonZeroUsize) -> Result<(), FoldError> {
82 for _ in 0..n.get() {
83 self.fold(sample.clone())?;
84 }
85 Ok(())
86 }
87
88 fn reset(&mut self);
99
100 fn aggregation(&self) -> Option<Self::Aggregation>;
104}
105
106pub trait StatisticExt: Statistic {
108 fn get_aggregation_and_reset(&mut self) -> Option<Self::Aggregation> {
110 let aggregation = self.aggregation();
111 self.reset();
112 aggregation
113 }
114}
115
116impl<F> StatisticExt for F where F: Statistic {}
117
118pub trait SerialStatistic<P>: Statistic
126where
127 P: InterpolationKind,
128{
129 type Buffer: Clone + RingBuffer<Self::Aggregation>;
130
131 fn buffer(interval: &SamplingInterval) -> Self::Buffer;
132}
133
134impl<F, P> SerialStatistic<P> for F
139where
140 F: Statistic,
141 F::Semantic: BufferStrategy<F::Aggregation, P>,
144 P: InterpolationKind,
145{
146 type Buffer = <F::Semantic as BufferStrategy<F::Aggregation, P>>::Buffer;
147
148 fn buffer(interval: &SamplingInterval) -> Self::Buffer {
149 <F::Semantic>::buffer(interval)
150 }
151}
152
153pub type Semantic<F> = <F as Statistic>::Semantic;
155
156pub type Metadata<F> = <Semantic<F> as DataSemantic>::Metadata;
158
159pub type Sample<F> = <F as Statistic>::Sample;
161
162pub type Aggregation<F> = <F as Statistic>::Aggregation;
164
165#[derive(Clone, Debug)]
173pub struct ArithmeticMean<T> {
174 sum: T,
176 n: u64,
178}
179
180impl<T> ArithmeticMean<T> {
181 pub fn with_sum(sum: T) -> Self {
182 ArithmeticMean { sum, n: 0 }
183 }
184
185 fn fill(&mut self, sample: T, n: NonZeroUsize) -> Result<(), FoldError>
186 where
187 Self: Statistic<Sample = T>,
188 T: Clone + Num + NumCast,
189 {
190 Ok(match num::cast::<_, T>(n.get()) {
191 Some(m) => {
192 self.fold(sample * m)?;
193 self.increment((n.get() as u64) - 1)?;
194 }
195 _ => {
196 for _ in 0..n.get() {
197 self.fold(sample.clone())?;
198 }
199 }
200 })
201 }
202
203 fn increment(&mut self, m: u64) -> Result<(), FoldError> {
204 self.n.checked_add(m).inspect(|sum| self.n = *sum).map(|_| ()).ok_or(FoldError::Overflow)
209 }
210
211 fn reset(&mut self)
212 where
213 T: Zero,
214 {
215 *self = Default::default()
216 }
217}
218
219impl<T> Default for ArithmeticMean<T>
220where
221 T: Zero,
222{
223 fn default() -> Self {
224 ArithmeticMean::with_sum(T::zero())
225 }
226}
227
228impl Statistic for ArithmeticMean<f32> {
229 type Semantic = Gauge;
230 type Sample = f32;
231 type Aggregation = f32;
232
233 fn fold(&mut self, sample: Self::Sample) -> Result<(), FoldError> {
234 self.sum = match sample {
236 _ if sample.is_nan() => self.sum,
237 sample if sample.is_infinite() => sample,
238 sample => self.sum + sample,
241 };
242 self.increment(1)
243 }
244
245 fn fill(&mut self, sample: Self::Sample, n: NonZeroUsize) -> Result<(), FoldError> {
246 ArithmeticMean::fill(self, sample, n)
247 }
248
249 fn reset(&mut self) {
250 ArithmeticMean::reset(self)
251 }
252
253 fn aggregation(&self) -> Option<Self::Aggregation> {
254 (self.n > 0).then(|| self.sum / (self.n as f32))
257 }
258}
259
260impl Statistic for ArithmeticMean<i64> {
261 type Semantic = Gauge;
262 type Sample = i64;
263 type Aggregation = f32;
264
265 fn fold(&mut self, sample: Self::Sample) -> Result<(), FoldError> {
266 self.sum = self.sum.checked_add(sample).ok_or(FoldError::Overflow)?;
271 self.increment(1)
272 }
273
274 fn fill(&mut self, sample: Self::Sample, n: NonZeroUsize) -> Result<(), FoldError> {
275 ArithmeticMean::fill(self, sample, n)
276 }
277
278 fn reset(&mut self) {
279 ArithmeticMean::reset(self)
280 }
281
282 fn aggregation(&self) -> Option<Self::Aggregation> {
283 (self.n > 0).then(|| self.sum as f32 / (self.n as f32))
286 }
287}
288
289impl Statistic for ArithmeticMean<u64> {
290 type Semantic = Gauge;
291 type Sample = u64;
292 type Aggregation = f32;
293
294 fn fold(&mut self, sample: Self::Sample) -> Result<(), FoldError> {
295 self.sum = self.sum.checked_add(sample).ok_or(FoldError::Overflow)?;
300 self.increment(1)
301 }
302
303 fn fill(&mut self, sample: Self::Sample, n: NonZeroUsize) -> Result<(), FoldError> {
304 ArithmeticMean::fill(self, sample, n)
305 }
306
307 fn reset(&mut self) {
308 ArithmeticMean::reset(self)
309 }
310
311 fn aggregation(&self) -> Option<Self::Aggregation> {
312 (self.n > 0).then(|| self.sum as f32 / (self.n as f32))
315 }
316}
317
318#[derive(Clone, Debug)]
324pub struct Sum<T> {
325 sum: T,
327}
328
329impl<T> Sum<T> {
330 pub fn with_sum(sum: T) -> Self {
331 Sum { sum }
332 }
333
334 fn fill(&mut self, sample: T, n: NonZeroUsize) -> Result<(), FoldError>
335 where
336 Self: Statistic<Sample = T>,
337 T: Clone + Num + NumCast,
338 {
339 if let Some(n) = num::cast::<_, T>(n.get()) {
340 self.fold(sample * n)
341 } else {
342 Ok(for _ in 0..n.get() {
343 self.fold(sample.clone())?;
344 })
345 }
346 }
347
348 fn reset(&mut self)
349 where
350 T: Zero,
351 {
352 *self = Default::default();
353 }
354}
355
356impl<T> Default for Sum<T>
357where
358 T: Zero,
359{
360 fn default() -> Self {
361 Sum::with_sum(T::zero())
362 }
363}
364
365impl Statistic for Sum<u64> {
366 type Semantic = Gauge;
367 type Sample = u64;
368 type Aggregation = u64;
369
370 fn fold(&mut self, sample: Self::Sample) -> Result<(), FoldError> {
371 self.sum
373 .checked_add(sample)
374 .inspect(|sum| self.sum = *sum)
375 .map(|_| ())
376 .ok_or(FoldError::Overflow)
377 }
378
379 fn fill(&mut self, sample: Self::Sample, n: NonZeroUsize) -> Result<(), FoldError> {
380 Sum::fill(self, sample, n)
381 }
382
383 fn reset(&mut self) {
384 Sum::reset(self)
385 }
386
387 fn aggregation(&self) -> Option<Self::Aggregation> {
388 let sum = self.sum;
389 Some(sum)
390 }
391}
392
393impl Statistic for Sum<i64> {
394 type Semantic = Gauge;
395 type Sample = i64;
396 type Aggregation = i64;
397
398 fn fold(&mut self, sample: Self::Sample) -> Result<(), FoldError> {
399 self.sum
401 .checked_add(sample)
402 .inspect(|sum| self.sum = *sum)
403 .map(|_| ())
404 .ok_or(FoldError::Overflow)
405 }
406
407 fn fill(&mut self, sample: Self::Sample, n: NonZeroUsize) -> Result<(), FoldError> {
408 Sum::fill(self, sample, n)
409 }
410
411 fn reset(&mut self) {
412 Sum::reset(self)
413 }
414
415 fn aggregation(&self) -> Option<Self::Aggregation> {
416 let sum = self.sum;
417 Some(sum)
418 }
419}
420
421#[derive(Clone, Debug)]
423pub struct Min<T> {
424 min: Option<T>,
426}
427
428impl<T> Min<T> {
429 pub fn with_min(min: T) -> Self {
430 Min { min: Some(min) }
431 }
432}
433
434impl<T> Default for Min<T> {
435 fn default() -> Self {
436 Min { min: Default::default() }
437 }
438}
439
440impl<T> Statistic for Min<T>
441where
442 T: Ord + Copy + Zero + Num + NumCast,
443{
444 type Semantic = Gauge;
445 type Sample = T;
446 type Aggregation = T;
447
448 fn fold(&mut self, sample: Self::Sample) -> Result<(), FoldError> {
449 self.min = Some(match self.min {
450 Some(min) => cmp::min(min, sample),
451 _ => sample,
452 });
453 Ok(())
454 }
455
456 fn fill(&mut self, sample: Self::Sample, _n: NonZeroUsize) -> Result<(), FoldError> {
457 self.fold(sample)
458 }
459
460 fn reset(&mut self) {
461 *self = Default::default();
462 }
463
464 fn aggregation(&self) -> Option<Self::Aggregation> {
465 self.min
466 }
467}
468
469#[derive(Clone, Debug)]
471pub struct Max<T> {
472 max: Option<T>,
474}
475
476impl<T> Max<T> {
477 pub fn with_max(max: T) -> Self {
478 Max { max: Some(max) }
479 }
480}
481
482impl<T> Default for Max<T> {
483 fn default() -> Self {
484 Max { max: Default::default() }
485 }
486}
487
488impl<T> Statistic for Max<T>
489where
490 T: Ord + Copy + Zero + Num + NumCast,
491{
492 type Semantic = Gauge;
493 type Sample = T;
494 type Aggregation = T;
495
496 fn fold(&mut self, sample: Self::Sample) -> Result<(), FoldError> {
497 self.max = Some(match self.max {
498 Some(max) => cmp::max(max, sample),
499 _ => sample,
500 });
501 Ok(())
502 }
503
504 fn fill(&mut self, sample: Self::Sample, _n: NonZeroUsize) -> Result<(), FoldError> {
505 self.fold(sample)
506 }
507
508 fn reset(&mut self) {
509 *self = Default::default();
510 }
511
512 fn aggregation(&self) -> Option<Self::Aggregation> {
513 self.max
514 }
515}
516
517#[derive(Clone, Debug)]
519pub struct Last<T> {
520 last: Option<T>,
522}
523
524impl<T> Last<T> {
525 pub fn with_sample(sample: T) -> Self {
526 Last { last: Some(sample) }
527 }
528}
529
530impl<T> Default for Last<T> {
531 fn default() -> Self {
532 Last { last: Default::default() }
533 }
534}
535
536impl<T> Statistic for Last<T>
537where
538 T: Copy + Zero + Num + NumCast,
539{
540 type Semantic = Gauge;
541 type Sample = T;
542 type Aggregation = T;
543
544 fn fold(&mut self, sample: Self::Sample) -> Result<(), FoldError> {
545 self.last = Some(sample);
546 Ok(())
547 }
548
549 fn fill(&mut self, sample: Self::Sample, _n: NonZeroUsize) -> Result<(), FoldError> {
550 self.fold(sample)
551 }
552
553 fn reset(&mut self) {
554 *self = Default::default();
555 }
556
557 fn aggregation(&self) -> Option<Self::Aggregation> {
558 self.last
559 }
560}
561
562#[derive(Clone, Debug)]
563pub struct Union<T> {
564 bits: T,
565}
566
567impl<T> Union<T> {
568 pub fn with_bits(bits: T) -> Self {
569 Union { bits }
570 }
571}
572
573impl<T> Default for Union<T>
574where
575 T: Zero,
576{
577 fn default() -> Self {
578 Union::with_bits(T::zero())
579 }
580}
581
582impl Statistic for Union<u64> {
583 type Semantic = BitSet;
584 type Sample = u64;
585 type Aggregation = u64;
586
587 fn fold(&mut self, sample: Self::Sample) -> Result<(), FoldError> {
588 self.bits = self.bits | sample;
589 Ok(())
590 }
591
592 fn fill(&mut self, sample: Self::Sample, _n: NonZeroUsize) -> Result<(), FoldError> {
593 self.fold(sample)
594 }
595
596 fn reset(&mut self) {
597 *self = Default::default();
598 }
599
600 fn aggregation(&self) -> Option<Self::Aggregation> {
601 Some(self.bits)
602 }
603}
604
605#[derive(Clone, Debug)]
609pub struct LatchMax<T> {
610 last: Option<T>,
612 max: Option<T>,
614 sum: T,
616}
617
618impl<T> LatchMax<T> {
619 pub fn with_max(max: T) -> Self
620 where
621 T: Zero,
622 {
623 LatchMax::with_max_and_sum(max, T::zero())
624 }
625
626 pub fn with_max_and_sum(max: T, sum: T) -> Self {
627 LatchMax { last: None, max: Some(max), sum }
628 }
629}
630
631impl<T> Default for LatchMax<T>
632where
633 T: Zero,
634{
635 fn default() -> Self {
636 LatchMax { last: None, max: None, sum: T::zero() }
637 }
638}
639
640impl Statistic for LatchMax<u64> {
641 type Semantic = Counter;
642 type Sample = u64;
643 type Aggregation = u64;
644
645 fn fold(&mut self, sample: Self::Sample) -> Result<(), FoldError> {
646 match self.last {
647 Some(last) if sample < last => {
648 self.sum = self.sum.checked_add(last).ok_or(FoldError::Overflow)?;
650 }
651 _ => {}
652 }
653 self.last = Some(sample);
654
655 let sum = sample.checked_add(self.sum).ok_or(FoldError::Overflow)?;
656 self.max = Some(match self.max {
657 Some(max) => cmp::max(max, sum),
658 _ => sum,
659 });
660 Ok(())
661 }
662
663 fn fill(&mut self, sample: Self::Sample, _n: NonZeroUsize) -> Result<(), FoldError> {
664 self.fold(sample)
665 }
666
667 fn reset(&mut self) {}
668
669 fn aggregation(&self) -> Option<Self::Aggregation> {
670 self.max
671 }
672}
673
674#[derive(Clone, Copy, Debug)]
681pub struct PostAggregation<F, R> {
682 statistic: F,
683 transform: R,
684}
685
686pub type Transform<F, A> = PostAggregation<F, fn(Aggregation<F>) -> A>;
691
692impl<F, R> PostAggregation<F, R> {
693 pub fn with(statistic: F, transform: R) -> Self {
694 PostAggregation { statistic, transform }
695 }
696
697 pub fn from_transform(transform: R) -> Self
701 where
702 F: Default,
703 {
704 PostAggregation { statistic: F::default(), transform }
705 }
706}
707
708impl<A, F, R> Statistic for PostAggregation<F, R>
709where
710 F: Statistic,
711 R: Clone + Fn(F::Aggregation) -> A,
712 A: Clone,
713{
714 type Semantic = F::Semantic;
715 type Sample = F::Sample;
716 type Aggregation = A;
717
718 fn fold(&mut self, sample: F::Sample) -> Result<(), FoldError> {
719 self.statistic.fold(sample)
720 }
721
722 fn fill(&mut self, sample: F::Sample, n: NonZeroUsize) -> Result<(), FoldError> {
723 self.statistic.fill(sample, n)
724 }
725
726 fn reset(&mut self) {
727 self.statistic.reset()
728 }
729
730 fn aggregation(&self) -> Option<Self::Aggregation> {
731 self.statistic.aggregation().map(|aggregation| (self.transform)(aggregation))
732 }
733}
734
735#[derive(Clone, Copy, Debug)]
740pub struct Reset<F, R> {
741 statistic: F,
742 reset: R,
743}
744
745impl<F, R> Reset<F, R>
746where
747 F: Statistic,
748 R: FnMut() -> F,
749{
750 pub fn with(statistic: F, reset: R) -> Self {
751 Reset { statistic, reset }
752 }
753}
754
755impl<F, R> Statistic for Reset<F, R>
756where
757 F: Statistic,
758 R: Clone + FnMut() -> F,
759{
760 type Semantic = F::Semantic;
761 type Sample = F::Sample;
762 type Aggregation = F::Aggregation;
763
764 fn fold(&mut self, sample: F::Sample) -> Result<(), FoldError> {
765 self.statistic.fold(sample)
766 }
767
768 fn fill(&mut self, sample: F::Sample, n: NonZeroUsize) -> Result<(), FoldError> {
769 self.statistic.fill(sample, n)
770 }
771
772 fn reset(&mut self) {
773 self.statistic = (self.reset)();
774 }
775
776 fn aggregation(&self) -> Option<Self::Aggregation> {
777 self.statistic.aggregation()
778 }
779}
780
781#[cfg(test)]
782mod tests {
783 use assert_matches::assert_matches;
784 use std::num::NonZeroUsize;
785
786 use crate::experimental::series::statistic::{
787 ArithmeticMean, FoldError, Last, LatchMax, Max, Min, PostAggregation, Reset, Statistic,
788 Sum, Union,
789 };
790
791 #[test]
792 fn arithmetic_mean_aggregation() {
793 let mut mean = ArithmeticMean::<f32>::default();
794 mean.fold(1.0).unwrap();
795 mean.fold(1.0).unwrap();
796 mean.fold(1.0).unwrap();
797 let aggregation = mean.aggregation().unwrap();
798 assert!(aggregation > 0.99 && aggregation < 1.01); let mut mean = ArithmeticMean::<f32>::default();
801 mean.fold(0.0).unwrap();
802 mean.fold(1.0).unwrap();
803 mean.fold(2.0).unwrap();
804 let aggregation = mean.aggregation().unwrap();
805 assert!(aggregation > 0.99 && aggregation < 1.01); }
807
808 #[test]
809 fn arithmetic_mean_aggregation_fill() {
810 let mut mean = ArithmeticMean::<f32>::default();
811 mean.fill(1.0, NonZeroUsize::new(1000).unwrap()).unwrap();
812 let aggregation = mean.aggregation().unwrap();
813 assert!(aggregation > 0.99 && aggregation < 1.01); }
815
816 #[test]
817 fn arithmetic_mean_count_overflow() {
818 let mut mean = ArithmeticMean::<f32> { sum: 1.0, n: u64::MAX };
819 let result = mean.fold(1.0);
820 assert_matches!(result, Err(FoldError::Overflow));
821 }
822
823 #[test]
824 fn arithmetic_mean_i64_aggregation() {
825 let mut mean = ArithmeticMean::<i64>::default();
826 mean.fold(1).unwrap();
827 mean.fold(1).unwrap();
828 mean.fold(1).unwrap();
829 let aggregation = mean.aggregation().unwrap();
830 assert!(aggregation > 0.99 && aggregation < 1.01); let mut mean = ArithmeticMean::<i64>::default();
833 mean.fold(0).unwrap();
834 mean.fold(1).unwrap();
835 mean.fold(2).unwrap();
836 let aggregation = mean.aggregation().unwrap();
837 assert!(aggregation > 0.99 && aggregation < 1.01); }
839
840 #[test]
841 fn arithmetic_mean_i64_aggregation_fill() {
842 let mut mean = ArithmeticMean::<i64>::default();
843 mean.fill(1, NonZeroUsize::new(1000).unwrap()).unwrap();
844 let aggregation = mean.aggregation().unwrap();
845 assert!(aggregation > 0.99 && aggregation < 1.01); }
847
848 #[test]
849 fn arithmetic_mean_i64_sum_overflow() {
850 let mut mean = ArithmeticMean::<i64> { sum: i64::MAX, n: 1 };
851 let result = mean.fold(1);
852 assert_matches!(result, Err(FoldError::Overflow));
853 }
854
855 #[test]
856 fn arithmetic_mean_i64_count_overflow() {
857 let mut mean = ArithmeticMean::<i64> { sum: 1, n: u64::MAX };
858 let result = mean.fold(1);
859 assert_matches!(result, Err(FoldError::Overflow));
860 }
861
862 #[test]
863 fn arithmetic_mean_u64_aggregation() {
864 let mut mean = ArithmeticMean::<u64>::default();
865 mean.fold(1).unwrap();
866 mean.fold(1).unwrap();
867 mean.fold(1).unwrap();
868 let aggregation = mean.aggregation().unwrap();
869 assert!(aggregation > 0.99 && aggregation < 1.01); let mut mean = ArithmeticMean::<u64>::default();
872 mean.fold(0).unwrap();
873 mean.fold(1).unwrap();
874 mean.fold(2).unwrap();
875 let aggregation = mean.aggregation().unwrap();
876 assert!(aggregation > 0.99 && aggregation < 1.01); }
878
879 #[test]
880 fn arithmetic_mean_u64_aggregation_fill() {
881 let mut mean = ArithmeticMean::<u64>::default();
882 mean.fill(1, NonZeroUsize::new(1000).unwrap()).unwrap();
883 let aggregation = mean.aggregation().unwrap();
884 assert!(aggregation > 0.99 && aggregation < 1.01); }
886
887 #[test]
888 fn arithmetic_mean_u64_sum_overflow() {
889 let mut mean = ArithmeticMean::<u64> { sum: u64::MAX, n: 1 };
890 let result = mean.fold(1);
891 assert_matches!(result, Err(FoldError::Overflow));
892 }
893
894 #[test]
895 fn arithmetic_mean_u64_count_overflow() {
896 let mut mean = ArithmeticMean::<u64> { sum: 1, n: u64::MAX };
897 let result = mean.fold(1);
898 assert_matches!(result, Err(FoldError::Overflow));
899 }
900
901 #[test]
902 fn sum_aggregation() {
903 let mut sum = Sum::<u64>::default();
904 sum.fold(1).unwrap();
905 sum.fold(1).unwrap();
906 sum.fold(1).unwrap();
907 let aggregation = sum.aggregation().unwrap();
908 assert_eq!(aggregation, 3);
909
910 let mut sum = Sum::<u64>::default();
911 sum.fold(0).unwrap();
912 sum.fold(1).unwrap();
913 sum.fold(2).unwrap();
914 let aggregation = sum.aggregation().unwrap();
915 assert_eq!(aggregation, 3);
916 }
917
918 #[test]
919 fn sum_aggregation_fill() {
920 let mut sum = Sum::<u64>::default();
921 sum.fill(10, NonZeroUsize::new(1000).unwrap()).unwrap();
922 let aggregation = sum.aggregation().unwrap();
923 assert_eq!(aggregation, 10_000);
924 }
925
926 #[test]
927 fn sum_overflow() {
928 let mut sum = Sum::<u64> { sum: u64::MAX };
929 let result = sum.fold(1);
930 assert_matches!(result, Err(FoldError::Overflow));
931 }
932
933 #[test]
934 fn sum_i64_aggregation() {
935 let mut sum = Sum::<i64>::default();
936 sum.fold(1).unwrap();
937 sum.fold(1).unwrap();
938 sum.fold(1).unwrap();
939 let aggregation = sum.aggregation().unwrap();
940 assert_eq!(aggregation, 3);
941
942 let mut sum = Sum::<i64>::default();
943 sum.fold(0).unwrap();
944 sum.fold(1).unwrap();
945 sum.fold(2).unwrap();
946 let aggregation = sum.aggregation().unwrap();
947 assert_eq!(aggregation, 3);
948 }
949
950 #[test]
951 fn sum_i64_aggregation_fill() {
952 let mut sum = Sum::<i64>::default();
953 sum.fill(10, NonZeroUsize::new(1000).unwrap()).unwrap();
954 let aggregation = sum.aggregation().unwrap();
955 assert_eq!(aggregation, 10_000);
956 }
957
958 #[test]
959 fn sum_i64_overflow() {
960 let mut sum = Sum::<i64> { sum: i64::MAX };
961 let result = sum.fold(1);
962 assert_matches!(result, Err(FoldError::Overflow));
963 }
964
965 #[test]
966 fn min_aggregation() {
967 let mut min = Min::<u64>::default();
968 min.fold(10).unwrap();
969 min.fold(1337).unwrap();
970 min.fold(42).unwrap();
971 let aggregation = min.aggregation().unwrap();
972 assert_eq!(aggregation, 10);
973 }
974
975 #[test]
976 fn min_aggregation_fill() {
977 let mut min = Min::<u64>::default();
978 min.fill(42, NonZeroUsize::new(1000).unwrap()).unwrap();
979 let aggregation = min.aggregation().unwrap();
980 assert_eq!(aggregation, 42);
981 }
982
983 #[test]
984 fn max_aggregation() {
985 let mut max = Max::<u64>::default();
986 max.fold(0).unwrap();
987 max.fold(1337).unwrap();
988 max.fold(42).unwrap();
989 let aggregation = max.aggregation().unwrap();
990 assert_eq!(aggregation, 1337);
991 }
992
993 #[test]
994 fn max_aggregation_fill() {
995 let mut max = Max::<u64>::default();
996 max.fill(42, NonZeroUsize::new(1000).unwrap()).unwrap();
997 let aggregation = max.aggregation().unwrap();
998 assert_eq!(aggregation, 42);
999 }
1000
1001 #[test]
1002 fn last_aggregation() {
1003 let mut last = Last::<u64>::default();
1004 last.fold(0).unwrap();
1005 last.fold(1337).unwrap();
1006 last.fold(42).unwrap();
1007 let aggregation = last.aggregation().unwrap();
1008 assert_eq!(aggregation, 42);
1009 }
1010
1011 #[test]
1012 fn last_aggregation_fill() {
1013 let mut last = Last::<u64>::default();
1014 last.fill(42, NonZeroUsize::new(1000).unwrap()).unwrap();
1015 let aggregation = last.aggregation().unwrap();
1016 assert_eq!(aggregation, 42);
1017 }
1018
1019 #[test]
1020 fn union_aggregation() {
1021 let mut value = Union::<u64>::default();
1022 value.fold(1 << 1).unwrap();
1023 value.fold(1 << 3).unwrap();
1024 value.fold(1 << 5).unwrap();
1025 let aggregation = value.aggregation().unwrap();
1026 assert_eq!(aggregation, 0b101010);
1027 }
1028
1029 #[test]
1030 fn union_aggregation_fill() {
1031 let mut value = Union::<u64>::default();
1032 value.fill(1 << 2, NonZeroUsize::new(1000).unwrap()).unwrap();
1033 let aggregation = value.aggregation().unwrap();
1034 assert_eq!(aggregation, 0b100);
1035 }
1036
1037 #[test]
1038 fn latch_max_aggregation() {
1039 let mut max = LatchMax::<u64>::default();
1040 max.fold(1).unwrap();
1041 max.fold(1).unwrap();
1042 max.fold(1).unwrap();
1043 let aggregation = max.aggregation().unwrap();
1044 assert_eq!(aggregation, 1);
1045
1046 let mut max = LatchMax::<u64>::default();
1047 max.fold(0).unwrap();
1048 max.fold(1).unwrap();
1049 max.fold(2).unwrap();
1050 let aggregation = max.aggregation().unwrap();
1051 assert_eq!(aggregation, 2);
1052
1053 let mut max = LatchMax::<u64>::default();
1054 max.fold(1).unwrap();
1055 max.fold(5).unwrap();
1056 max.fold(6).unwrap();
1057 max.fold(2).unwrap(); max.fold(9).unwrap();
1059 max.fold(3).unwrap(); max.fold(5).unwrap();
1061 let aggregation = max.aggregation().unwrap();
1062 assert_eq!(aggregation, 20);
1063 }
1064
1065 #[test]
1066 fn latch_max_aggregation_fill() {
1067 let mut max = LatchMax::<u64>::default();
1068 max.fill(10, NonZeroUsize::new(1000).unwrap()).unwrap();
1069 let aggregation = max.aggregation().unwrap();
1070 assert_eq!(aggregation, 10);
1071 }
1072
1073 #[test]
1074 fn latch_max_overflow_max() {
1075 let mut max = LatchMax::<u64>::default();
1076 max.fold(1).unwrap();
1077 max.fold(0).unwrap(); let result = max.fold(u64::MAX); assert_matches!(result, Err(FoldError::Overflow));
1080 }
1081
1082 #[test]
1083 fn post_sum_aggregation() {
1084 let mut sum = PostAggregation::<Sum<u64>, _>::from_transform(|sum| sum + 1);
1085 sum.fold(0).unwrap();
1086 sum.fold(1).unwrap();
1087 sum.fold(2).unwrap();
1088 let aggregation = sum.aggregation().unwrap();
1089 assert_eq!(aggregation, 4);
1090 }
1091
1092 #[test]
1093 fn reset_with_function() {
1094 let mut sum = Reset::with(Sum::<u64>::default(), || Sum::with_sum(3));
1095
1096 assert_eq!(sum.aggregation().unwrap(), 0);
1097 sum.fold(1).unwrap();
1098 assert_eq!(sum.aggregation().unwrap(), 1);
1099
1100 sum.reset();
1101 assert_eq!(sum.aggregation().unwrap(), 3);
1102 sum.fold(1).unwrap();
1103 assert_eq!(sum.aggregation().unwrap(), 4);
1104 }
1105}