1use std::fmt;
4
5pub use iroh_metrics_derive::Iterable;
13
14use crate::{FamilyItem, MetricItem};
15
16pub trait Iterable {
18 fn metric_field_count(&self) -> usize;
20 fn metric_field_ref(&self, n: usize) -> Option<MetricItem<'_>>;
22 fn family_field_count(&self) -> usize {
24 0
25 }
26 fn family_field_ref(&self, _n: usize) -> Option<FamilyItem<'_>> {
28 None
29 }
30}
31
32pub trait IntoIterable {
34 fn as_iterable(&self) -> &dyn Iterable;
36
37 fn field_iter(&self) -> FieldIter<'_> {
39 FieldIter::new(self.as_iterable())
40 }
41
42 fn family_iter(&self) -> FamilyIter<'_> {
44 FamilyIter::new(self.as_iterable())
45 }
46}
47
48impl<T> IntoIterable for T
49where
50 T: Iterable,
51{
52 fn as_iterable(&self) -> &dyn Iterable {
53 self
54 }
55}
56
57pub struct FieldIter<'a> {
61 pos: usize,
62 inner: &'a dyn Iterable,
63}
64
65impl fmt::Debug for FieldIter<'_> {
66 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
67 write!(f, "FieldIter")
68 }
69}
70
71impl<'a> FieldIter<'a> {
72 pub(crate) fn new(inner: &'a dyn Iterable) -> Self {
73 Self { pos: 0, inner }
74 }
75}
76impl<'a> Iterator for FieldIter<'a> {
77 type Item = MetricItem<'a>;
78
79 fn next(&mut self) -> Option<Self::Item> {
80 if self.pos == self.inner.metric_field_count() {
81 None
82 } else {
83 let out = self.inner.metric_field_ref(self.pos);
84 self.pos += 1;
85 out
86 }
87 }
88
89 fn size_hint(&self) -> (usize, Option<usize>) {
90 let n = self.inner.metric_field_count() - self.pos;
91 (n, Some(n))
92 }
93}
94
95pub struct FamilyIter<'a> {
97 pos: usize,
98 inner: &'a dyn Iterable,
99}
100
101impl fmt::Debug for FamilyIter<'_> {
102 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
103 write!(f, "FamilyIter")
104 }
105}
106
107impl<'a> FamilyIter<'a> {
108 pub(crate) fn new(inner: &'a dyn Iterable) -> Self {
109 Self { pos: 0, inner }
110 }
111}
112
113impl<'a> Iterator for FamilyIter<'a> {
114 type Item = FamilyItem<'a>;
115
116 fn next(&mut self) -> Option<Self::Item> {
117 if self.pos == self.inner.family_field_count() {
118 None
119 } else {
120 let out = self.inner.family_field_ref(self.pos);
121 self.pos += 1;
122 out
123 }
124 }
125
126 fn size_hint(&self) -> (usize, Option<usize>) {
127 let n = self.inner.family_field_count() - self.pos;
128 (n, Some(n))
129 }
130}