prometheus_client/
encoding.rs

1//! Exposition format implementations.
2
3pub use prometheus_client_derive_encode::*;
4
5use crate::metrics::exemplar::Exemplar;
6use crate::metrics::MetricType;
7use crate::registry::{Prefix, Unit};
8use std::borrow::Cow;
9use std::collections::HashMap;
10use std::fmt::Write;
11use std::ops::Deref;
12use std::rc::Rc;
13use std::sync::Arc;
14
15#[cfg(feature = "protobuf")]
16#[cfg_attr(docsrs, doc(cfg(feature = "protobuf")))]
17pub mod protobuf;
18pub mod text;
19
20macro_rules! for_both_mut {
21    ($self:expr, $inner:ident, $pattern:pat, $fn:expr) => {
22        match &mut $self.0 {
23            $inner::Text($pattern) => $fn,
24            #[cfg(feature = "protobuf")]
25            $inner::Protobuf($pattern) => $fn,
26        }
27    };
28}
29
30macro_rules! for_both {
31    ($self:expr, $inner:ident, $pattern:pat, $fn:expr) => {
32        match $self.0 {
33            $inner::Text($pattern) => $fn,
34            #[cfg(feature = "protobuf")]
35            $inner::Protobuf($pattern) => $fn,
36        }
37    };
38}
39
40/// Trait implemented by each metric type, e.g.
41/// [`Counter`](crate::metrics::counter::Counter), to implement its encoding in
42/// the OpenMetric text format.
43pub trait EncodeMetric {
44    /// Encode the given instance in the OpenMetrics text encoding.
45    // TODO: Lifetimes on MetricEncoder needed?
46    fn encode(&self, encoder: MetricEncoder) -> Result<(), std::fmt::Error>;
47
48    /// The OpenMetrics metric type of the instance.
49    // One can not use [`TypedMetric`] directly, as associated constants are not
50    // object safe and thus can not be used with dynamic dispatching.
51    fn metric_type(&self) -> MetricType;
52}
53
54impl EncodeMetric for Box<dyn EncodeMetric> {
55    fn encode(&self, encoder: MetricEncoder) -> Result<(), std::fmt::Error> {
56        self.deref().encode(encoder)
57    }
58
59    fn metric_type(&self) -> MetricType {
60        self.deref().metric_type()
61    }
62}
63
64/// Encoder for a Metric Descriptor.
65#[derive(Debug)]
66pub struct DescriptorEncoder<'a>(DescriptorEncoderInner<'a>);
67
68#[derive(Debug)]
69enum DescriptorEncoderInner<'a> {
70    Text(text::DescriptorEncoder<'a>),
71
72    #[cfg(feature = "protobuf")]
73    Protobuf(protobuf::DescriptorEncoder<'a>),
74}
75
76impl<'a> From<text::DescriptorEncoder<'a>> for DescriptorEncoder<'a> {
77    fn from(e: text::DescriptorEncoder<'a>) -> Self {
78        Self(DescriptorEncoderInner::Text(e))
79    }
80}
81
82#[cfg(feature = "protobuf")]
83impl<'a> From<protobuf::DescriptorEncoder<'a>> for DescriptorEncoder<'a> {
84    fn from(e: protobuf::DescriptorEncoder<'a>) -> Self {
85        Self(DescriptorEncoderInner::Protobuf(e))
86    }
87}
88
89impl DescriptorEncoder<'_> {
90    pub(crate) fn with_prefix_and_labels<'s>(
91        &'s mut self,
92        prefix: Option<&'s Prefix>,
93        labels: &'s [(Cow<'static, str>, Cow<'static, str>)],
94        // TODO: result needed?
95    ) -> DescriptorEncoder<'s> {
96        for_both_mut!(
97            self,
98            DescriptorEncoderInner,
99            e,
100            e.with_prefix_and_labels(prefix, labels).into()
101        )
102    }
103
104    /// Encode a descriptor.
105    pub fn encode_descriptor<'s>(
106        &'s mut self,
107        name: &'s str,
108        help: &str,
109        unit: Option<&'s Unit>,
110        metric_type: MetricType,
111    ) -> Result<MetricEncoder<'s>, std::fmt::Error> {
112        for_both_mut!(
113            self,
114            DescriptorEncoderInner,
115            e,
116            Ok(e.encode_descriptor(name, help, unit, metric_type)?.into())
117        )
118    }
119}
120
121/// Encoder for a metric.
122#[derive(Debug)]
123pub struct MetricEncoder<'a>(MetricEncoderInner<'a>);
124
125#[derive(Debug)]
126enum MetricEncoderInner<'a> {
127    Text(text::MetricEncoder<'a>),
128
129    #[cfg(feature = "protobuf")]
130    Protobuf(protobuf::MetricEncoder<'a>),
131}
132
133impl<'a> From<text::MetricEncoder<'a>> for MetricEncoder<'a> {
134    fn from(e: text::MetricEncoder<'a>) -> Self {
135        Self(MetricEncoderInner::Text(e))
136    }
137}
138
139#[cfg(feature = "protobuf")]
140impl<'a> From<protobuf::MetricEncoder<'a>> for MetricEncoder<'a> {
141    fn from(e: protobuf::MetricEncoder<'a>) -> Self {
142        Self(MetricEncoderInner::Protobuf(e))
143    }
144}
145
146impl MetricEncoder<'_> {
147    /// Encode a counter.
148    pub fn encode_counter<
149        S: EncodeLabelSet,
150        CounterValue: EncodeCounterValue,
151        ExemplarValue: EncodeExemplarValue,
152    >(
153        &mut self,
154        v: &CounterValue,
155        exemplar: Option<&Exemplar<S, ExemplarValue>>,
156    ) -> Result<(), std::fmt::Error> {
157        for_both_mut!(self, MetricEncoderInner, e, e.encode_counter(v, exemplar))
158    }
159
160    /// Encode a gauge.
161    pub fn encode_gauge<GaugeValue: EncodeGaugeValue>(
162        &mut self,
163        v: &GaugeValue,
164    ) -> Result<(), std::fmt::Error> {
165        for_both_mut!(self, MetricEncoderInner, e, e.encode_gauge(v))
166    }
167
168    /// Encode an info.
169    pub fn encode_info(&mut self, label_set: &impl EncodeLabelSet) -> Result<(), std::fmt::Error> {
170        for_both_mut!(self, MetricEncoderInner, e, e.encode_info(label_set))
171    }
172
173    /// Encode a histogram.
174    pub fn encode_histogram<S: EncodeLabelSet>(
175        &mut self,
176        sum: f64,
177        count: u64,
178        buckets: &[(f64, u64)],
179        exemplars: Option<&HashMap<usize, Exemplar<S, f64>>>,
180    ) -> Result<(), std::fmt::Error> {
181        for_both_mut!(
182            self,
183            MetricEncoderInner,
184            e,
185            e.encode_histogram(sum, count, buckets, exemplars)
186        )
187    }
188
189    /// Encode a metric family.
190    pub fn encode_family<'s, S: EncodeLabelSet>(
191        &'s mut self,
192        label_set: &'s S,
193    ) -> Result<MetricEncoder<'s>, std::fmt::Error> {
194        for_both_mut!(
195            self,
196            MetricEncoderInner,
197            e,
198            e.encode_family(label_set).map(Into::into)
199        )
200    }
201}
202
203/// An encodable label set.
204pub trait EncodeLabelSet {
205    /// Encode oneself into the given encoder.
206    fn encode(&self, encoder: LabelSetEncoder) -> Result<(), std::fmt::Error>;
207}
208
209/// Encoder for a label set.
210#[derive(Debug)]
211pub struct LabelSetEncoder<'a>(LabelSetEncoderInner<'a>);
212
213#[derive(Debug)]
214enum LabelSetEncoderInner<'a> {
215    Text(text::LabelSetEncoder<'a>),
216    #[cfg(feature = "protobuf")]
217    Protobuf(protobuf::LabelSetEncoder<'a>),
218}
219
220impl<'a> From<text::LabelSetEncoder<'a>> for LabelSetEncoder<'a> {
221    fn from(e: text::LabelSetEncoder<'a>) -> Self {
222        Self(LabelSetEncoderInner::Text(e))
223    }
224}
225
226#[cfg(feature = "protobuf")]
227impl<'a> From<protobuf::LabelSetEncoder<'a>> for LabelSetEncoder<'a> {
228    fn from(e: protobuf::LabelSetEncoder<'a>) -> Self {
229        Self(LabelSetEncoderInner::Protobuf(e))
230    }
231}
232
233impl LabelSetEncoder<'_> {
234    /// Encode the given label.
235    pub fn encode_label(&mut self) -> LabelEncoder {
236        for_both_mut!(self, LabelSetEncoderInner, e, e.encode_label().into())
237    }
238}
239
240impl<T: EncodeLabel, const N: usize> EncodeLabelSet for [T; N] {
241    fn encode(&self, encoder: LabelSetEncoder) -> Result<(), std::fmt::Error> {
242        self.as_ref().encode(encoder)
243    }
244}
245
246impl<T: EncodeLabel> EncodeLabelSet for &[T] {
247    fn encode(&self, mut encoder: LabelSetEncoder) -> Result<(), std::fmt::Error> {
248        if self.is_empty() {
249            return Ok(());
250        }
251
252        for label in self.iter() {
253            label.encode(encoder.encode_label())?
254        }
255
256        Ok(())
257    }
258}
259
260impl<T: EncodeLabel> EncodeLabelSet for Vec<T> {
261    fn encode(&self, encoder: LabelSetEncoder) -> Result<(), std::fmt::Error> {
262        self.as_slice().encode(encoder)
263    }
264}
265
266/// Uninhabited type to represent the lack of a label set for a metric
267#[derive(Debug)]
268pub enum NoLabelSet {}
269
270impl EncodeLabelSet for NoLabelSet {
271    fn encode(&self, _encoder: LabelSetEncoder) -> Result<(), std::fmt::Error> {
272        Ok(())
273    }
274}
275
276/// An encodable label.
277pub trait EncodeLabel {
278    /// Encode oneself into the given encoder.
279    fn encode(&self, encoder: LabelEncoder) -> Result<(), std::fmt::Error>;
280}
281
282/// Encoder for a label.
283#[derive(Debug)]
284pub struct LabelEncoder<'a>(LabelEncoderInner<'a>);
285
286#[derive(Debug)]
287enum LabelEncoderInner<'a> {
288    Text(text::LabelEncoder<'a>),
289    #[cfg(feature = "protobuf")]
290    Protobuf(protobuf::LabelEncoder<'a>),
291}
292
293impl<'a> From<text::LabelEncoder<'a>> for LabelEncoder<'a> {
294    fn from(e: text::LabelEncoder<'a>) -> Self {
295        Self(LabelEncoderInner::Text(e))
296    }
297}
298
299#[cfg(feature = "protobuf")]
300impl<'a> From<protobuf::LabelEncoder<'a>> for LabelEncoder<'a> {
301    fn from(e: protobuf::LabelEncoder<'a>) -> Self {
302        Self(LabelEncoderInner::Protobuf(e))
303    }
304}
305
306impl LabelEncoder<'_> {
307    /// Encode a label.
308    pub fn encode_label_key(&mut self) -> Result<LabelKeyEncoder, std::fmt::Error> {
309        for_both_mut!(
310            self,
311            LabelEncoderInner,
312            e,
313            e.encode_label_key().map(Into::into)
314        )
315    }
316}
317
318impl<K: EncodeLabelKey, V: EncodeLabelValue> EncodeLabel for (K, V) {
319    fn encode(&self, mut encoder: LabelEncoder) -> Result<(), std::fmt::Error> {
320        let (key, value) = self;
321
322        let mut label_key_encoder = encoder.encode_label_key()?;
323        key.encode(&mut label_key_encoder)?;
324
325        let mut label_value_encoder = label_key_encoder.encode_label_value()?;
326        value.encode(&mut label_value_encoder)?;
327        label_value_encoder.finish()?;
328
329        Ok(())
330    }
331}
332
333/// An encodable label key.
334pub trait EncodeLabelKey {
335    /// Encode oneself into the given encoder.
336    fn encode(&self, encoder: &mut LabelKeyEncoder) -> Result<(), std::fmt::Error>;
337}
338
339/// Encoder for a label key.
340#[derive(Debug)]
341pub struct LabelKeyEncoder<'a>(LabelKeyEncoderInner<'a>);
342
343#[derive(Debug)]
344enum LabelKeyEncoderInner<'a> {
345    Text(text::LabelKeyEncoder<'a>),
346    #[cfg(feature = "protobuf")]
347    Protobuf(protobuf::LabelKeyEncoder<'a>),
348}
349
350impl<'a> From<text::LabelKeyEncoder<'a>> for LabelKeyEncoder<'a> {
351    fn from(e: text::LabelKeyEncoder<'a>) -> Self {
352        Self(LabelKeyEncoderInner::Text(e))
353    }
354}
355
356#[cfg(feature = "protobuf")]
357impl<'a> From<protobuf::LabelKeyEncoder<'a>> for LabelKeyEncoder<'a> {
358    fn from(e: protobuf::LabelKeyEncoder<'a>) -> Self {
359        Self(LabelKeyEncoderInner::Protobuf(e))
360    }
361}
362
363impl std::fmt::Write for LabelKeyEncoder<'_> {
364    fn write_str(&mut self, s: &str) -> std::fmt::Result {
365        for_both_mut!(self, LabelKeyEncoderInner, e, e.write_str(s))
366    }
367}
368
369impl<'a> LabelKeyEncoder<'a> {
370    /// Encode a label value.
371    pub fn encode_label_value(self) -> Result<LabelValueEncoder<'a>, std::fmt::Error> {
372        for_both!(
373            self,
374            LabelKeyEncoderInner,
375            e,
376            e.encode_label_value().map(LabelValueEncoder::from)
377        )
378    }
379}
380
381impl EncodeLabelKey for &str {
382    fn encode(&self, encoder: &mut LabelKeyEncoder) -> Result<(), std::fmt::Error> {
383        encoder.write_str(self)?;
384        Ok(())
385    }
386}
387
388impl EncodeLabelKey for String {
389    fn encode(&self, encoder: &mut LabelKeyEncoder) -> Result<(), std::fmt::Error> {
390        EncodeLabelKey::encode(&self.as_str(), encoder)
391    }
392}
393
394impl EncodeLabelKey for Cow<'_, str> {
395    fn encode(&self, encoder: &mut LabelKeyEncoder) -> Result<(), std::fmt::Error> {
396        EncodeLabelKey::encode(&self.as_ref(), encoder)
397    }
398}
399
400impl<T> EncodeLabelKey for Box<T>
401where
402    for<'a> &'a T: EncodeLabelKey,
403{
404    fn encode(&self, encoder: &mut LabelKeyEncoder) -> Result<(), std::fmt::Error> {
405        EncodeLabelKey::encode(&self.as_ref(), encoder)
406    }
407}
408
409impl<T> EncodeLabelKey for Arc<T>
410where
411    for<'a> &'a T: EncodeLabelKey,
412{
413    fn encode(&self, encoder: &mut LabelKeyEncoder) -> Result<(), std::fmt::Error> {
414        EncodeLabelKey::encode(&self.as_ref(), encoder)
415    }
416}
417
418impl<T> EncodeLabelKey for Rc<T>
419where
420    for<'a> &'a T: EncodeLabelKey,
421{
422    fn encode(&self, encoder: &mut LabelKeyEncoder) -> Result<(), std::fmt::Error> {
423        EncodeLabelKey::encode(&self.as_ref(), encoder)
424    }
425}
426
427/// An encodable label value.
428pub trait EncodeLabelValue {
429    /// Encode oneself into the given encoder.
430    fn encode(&self, encoder: &mut LabelValueEncoder) -> Result<(), std::fmt::Error>;
431}
432
433/// Encoder for a label value.
434#[derive(Debug)]
435pub struct LabelValueEncoder<'a>(LabelValueEncoderInner<'a>);
436
437#[derive(Debug)]
438enum LabelValueEncoderInner<'a> {
439    Text(text::LabelValueEncoder<'a>),
440    #[cfg(feature = "protobuf")]
441    Protobuf(protobuf::LabelValueEncoder<'a>),
442}
443
444impl<'a> From<text::LabelValueEncoder<'a>> for LabelValueEncoder<'a> {
445    fn from(e: text::LabelValueEncoder<'a>) -> Self {
446        LabelValueEncoder(LabelValueEncoderInner::Text(e))
447    }
448}
449
450#[cfg(feature = "protobuf")]
451impl<'a> From<protobuf::LabelValueEncoder<'a>> for LabelValueEncoder<'a> {
452    fn from(e: protobuf::LabelValueEncoder<'a>) -> Self {
453        LabelValueEncoder(LabelValueEncoderInner::Protobuf(e))
454    }
455}
456
457impl std::fmt::Write for LabelValueEncoder<'_> {
458    fn write_str(&mut self, s: &str) -> std::fmt::Result {
459        for_both_mut!(self, LabelValueEncoderInner, e, e.write_str(s))
460    }
461}
462
463impl LabelValueEncoder<'_> {
464    /// Finish encoding the label value.
465    pub fn finish(self) -> Result<(), std::fmt::Error> {
466        for_both!(self, LabelValueEncoderInner, e, e.finish())
467    }
468}
469
470impl EncodeLabelValue for &str {
471    fn encode(&self, encoder: &mut LabelValueEncoder) -> Result<(), std::fmt::Error> {
472        encoder.write_str(self)?;
473        Ok(())
474    }
475}
476
477impl EncodeLabelValue for String {
478    fn encode(&self, encoder: &mut LabelValueEncoder) -> Result<(), std::fmt::Error> {
479        EncodeLabelValue::encode(&self.as_str(), encoder)
480    }
481}
482
483impl EncodeLabelValue for &String {
484    fn encode(&self, encoder: &mut LabelValueEncoder) -> Result<(), std::fmt::Error> {
485        EncodeLabelValue::encode(&self.as_str(), encoder)
486    }
487}
488
489impl EncodeLabelValue for Cow<'_, str> {
490    fn encode(&self, encoder: &mut LabelValueEncoder) -> Result<(), std::fmt::Error> {
491        EncodeLabelValue::encode(&self.as_ref(), encoder)
492    }
493}
494
495impl<T> EncodeLabelValue for Box<T>
496where
497    for<'a> &'a T: EncodeLabelValue,
498{
499    fn encode(&self, encoder: &mut LabelValueEncoder) -> Result<(), std::fmt::Error> {
500        EncodeLabelValue::encode(&self.as_ref(), encoder)
501    }
502}
503
504impl<T> EncodeLabelValue for Arc<T>
505where
506    for<'a> &'a T: EncodeLabelValue,
507{
508    fn encode(&self, encoder: &mut LabelValueEncoder) -> Result<(), std::fmt::Error> {
509        EncodeLabelValue::encode(&self.as_ref(), encoder)
510    }
511}
512
513impl<T> EncodeLabelValue for Rc<T>
514where
515    for<'a> &'a T: EncodeLabelValue,
516{
517    fn encode(&self, encoder: &mut LabelValueEncoder) -> Result<(), std::fmt::Error> {
518        EncodeLabelValue::encode(&self.as_ref(), encoder)
519    }
520}
521
522impl EncodeLabelValue for f64 {
523    fn encode(&self, encoder: &mut LabelValueEncoder) -> Result<(), std::fmt::Error> {
524        encoder.write_str(dtoa::Buffer::new().format(*self))
525    }
526}
527
528impl<T> EncodeLabelValue for Option<T>
529where
530    T: EncodeLabelValue,
531{
532    fn encode(&self, encoder: &mut LabelValueEncoder) -> Result<(), std::fmt::Error> {
533        match self {
534            Some(v) => EncodeLabelValue::encode(v, encoder),
535            None => EncodeLabelValue::encode(&"", encoder),
536        }
537    }
538}
539
540impl EncodeLabelValue for bool {
541    fn encode(&self, encoder: &mut LabelValueEncoder) -> Result<(), std::fmt::Error> {
542        encoder.write_str(if *self { "true" } else { "false" })
543    }
544}
545
546macro_rules! impl_encode_label_value_for_integer {
547    ($($t:ident),*) => {$(
548        impl EncodeLabelValue for $t {
549            fn encode(&self, encoder: &mut LabelValueEncoder) -> Result<(), std::fmt::Error> {
550                encoder.write_str(itoa::Buffer::new().format(*self))
551            }
552        }
553    )*};
554}
555
556impl_encode_label_value_for_integer!(
557    u128, i128, u64, i64, u32, i32, u16, i16, u8, i8, usize, isize
558);
559
560/// An encodable gauge value.
561pub trait EncodeGaugeValue {
562    /// Encode the given instance in the OpenMetrics text encoding.
563    fn encode(&self, encoder: &mut GaugeValueEncoder) -> Result<(), std::fmt::Error>;
564}
565
566impl EncodeGaugeValue for u32 {
567    fn encode(&self, encoder: &mut GaugeValueEncoder) -> Result<(), std::fmt::Error> {
568        encoder.encode_u32(*self)
569    }
570}
571
572impl EncodeGaugeValue for i64 {
573    fn encode(&self, encoder: &mut GaugeValueEncoder) -> Result<(), std::fmt::Error> {
574        encoder.encode_i64(*self)
575    }
576}
577
578impl EncodeGaugeValue for u64 {
579    fn encode(&self, encoder: &mut GaugeValueEncoder) -> Result<(), std::fmt::Error> {
580        // Between forcing end users to do endless as i64 for things that are
581        // clearly u64 and having one error case for rarely used protobuf when
582        // a gauge is set to u64::MAX, the latter seems like the right choice.
583        if *self == u64::MAX {
584            return Err(std::fmt::Error);
585        }
586
587        encoder.encode_i64(*self as i64)
588    }
589}
590
591impl EncodeGaugeValue for f64 {
592    fn encode(&self, encoder: &mut GaugeValueEncoder) -> Result<(), std::fmt::Error> {
593        encoder.encode_f64(*self)
594    }
595}
596
597impl EncodeGaugeValue for i32 {
598    fn encode(&self, encoder: &mut GaugeValueEncoder) -> Result<(), std::fmt::Error> {
599        encoder.encode_i64(*self as i64)
600    }
601}
602
603impl EncodeGaugeValue for f32 {
604    fn encode(&self, encoder: &mut GaugeValueEncoder) -> Result<(), std::fmt::Error> {
605        encoder.encode_f64(*self as f64)
606    }
607}
608
609/// Encoder for a gauge value.
610#[derive(Debug)]
611pub struct GaugeValueEncoder<'a>(GaugeValueEncoderInner<'a>);
612
613#[derive(Debug)]
614enum GaugeValueEncoderInner<'a> {
615    Text(text::GaugeValueEncoder<'a>),
616    #[cfg(feature = "protobuf")]
617    Protobuf(protobuf::GaugeValueEncoder<'a>),
618}
619
620impl GaugeValueEncoder<'_> {
621    fn encode_u32(&mut self, v: u32) -> Result<(), std::fmt::Error> {
622        for_both_mut!(self, GaugeValueEncoderInner, e, e.encode_u32(v))
623    }
624
625    fn encode_i64(&mut self, v: i64) -> Result<(), std::fmt::Error> {
626        for_both_mut!(self, GaugeValueEncoderInner, e, e.encode_i64(v))
627    }
628
629    fn encode_f64(&mut self, v: f64) -> Result<(), std::fmt::Error> {
630        for_both_mut!(self, GaugeValueEncoderInner, e, e.encode_f64(v))
631    }
632}
633
634impl<'a> From<text::GaugeValueEncoder<'a>> for GaugeValueEncoder<'a> {
635    fn from(e: text::GaugeValueEncoder<'a>) -> Self {
636        GaugeValueEncoder(GaugeValueEncoderInner::Text(e))
637    }
638}
639
640#[cfg(feature = "protobuf")]
641impl<'a> From<protobuf::GaugeValueEncoder<'a>> for GaugeValueEncoder<'a> {
642    fn from(e: protobuf::GaugeValueEncoder<'a>) -> Self {
643        GaugeValueEncoder(GaugeValueEncoderInner::Protobuf(e))
644    }
645}
646
647/// An encodable counter value.
648pub trait EncodeCounterValue {
649    /// Encode the given instance in the OpenMetrics text encoding.
650    fn encode(&self, encoder: &mut CounterValueEncoder) -> Result<(), std::fmt::Error>;
651}
652
653impl EncodeCounterValue for u64 {
654    fn encode(&self, encoder: &mut CounterValueEncoder) -> Result<(), std::fmt::Error> {
655        encoder.encode_u64(*self)
656    }
657}
658
659impl EncodeCounterValue for f64 {
660    fn encode(&self, encoder: &mut CounterValueEncoder) -> Result<(), std::fmt::Error> {
661        encoder.encode_f64(*self)
662    }
663}
664
665impl EncodeCounterValue for u32 {
666    fn encode(&self, encoder: &mut CounterValueEncoder) -> Result<(), std::fmt::Error> {
667        encoder.encode_u64(*self as u64)
668    }
669}
670
671impl EncodeCounterValue for f32 {
672    fn encode(&self, encoder: &mut CounterValueEncoder) -> Result<(), std::fmt::Error> {
673        encoder.encode_f64(*self as f64)
674    }
675}
676
677/// Encoder for a counter value.
678#[derive(Debug)]
679pub struct CounterValueEncoder<'a>(CounterValueEncoderInner<'a>);
680
681#[derive(Debug)]
682enum CounterValueEncoderInner<'a> {
683    Text(text::CounterValueEncoder<'a>),
684    #[cfg(feature = "protobuf")]
685    Protobuf(protobuf::CounterValueEncoder<'a>),
686}
687
688impl<'a> From<text::CounterValueEncoder<'a>> for CounterValueEncoder<'a> {
689    fn from(e: text::CounterValueEncoder<'a>) -> Self {
690        CounterValueEncoder(CounterValueEncoderInner::Text(e))
691    }
692}
693
694#[cfg(feature = "protobuf")]
695impl<'a> From<protobuf::CounterValueEncoder<'a>> for CounterValueEncoder<'a> {
696    fn from(e: protobuf::CounterValueEncoder<'a>) -> Self {
697        CounterValueEncoder(CounterValueEncoderInner::Protobuf(e))
698    }
699}
700
701impl CounterValueEncoder<'_> {
702    fn encode_f64(&mut self, v: f64) -> Result<(), std::fmt::Error> {
703        for_both_mut!(self, CounterValueEncoderInner, e, e.encode_f64(v))
704    }
705
706    fn encode_u64(&mut self, v: u64) -> Result<(), std::fmt::Error> {
707        for_both_mut!(self, CounterValueEncoderInner, e, e.encode_u64(v))
708    }
709}
710
711/// An encodable exemplar value.
712pub trait EncodeExemplarValue {
713    /// Encode the given instance in the OpenMetrics text encoding.
714    fn encode(&self, encoder: ExemplarValueEncoder) -> Result<(), std::fmt::Error>;
715}
716
717impl EncodeExemplarValue for f64 {
718    fn encode(&self, mut encoder: ExemplarValueEncoder) -> Result<(), std::fmt::Error> {
719        encoder.encode(*self)
720    }
721}
722
723impl EncodeExemplarValue for u64 {
724    fn encode(&self, mut encoder: ExemplarValueEncoder) -> Result<(), std::fmt::Error> {
725        encoder.encode(*self as f64)
726    }
727}
728
729impl EncodeExemplarValue for f32 {
730    fn encode(&self, mut encoder: ExemplarValueEncoder) -> Result<(), std::fmt::Error> {
731        encoder.encode(*self as f64)
732    }
733}
734
735impl EncodeExemplarValue for u32 {
736    fn encode(&self, mut encoder: ExemplarValueEncoder) -> Result<(), std::fmt::Error> {
737        encoder.encode(*self as f64)
738    }
739}
740
741/// Encoder for an exemplar value.
742#[derive(Debug)]
743pub struct ExemplarValueEncoder<'a>(ExemplarValueEncoderInner<'a>);
744
745#[derive(Debug)]
746enum ExemplarValueEncoderInner<'a> {
747    Text(text::ExemplarValueEncoder<'a>),
748    #[cfg(feature = "protobuf")]
749    Protobuf(protobuf::ExemplarValueEncoder<'a>),
750}
751
752impl<'a> From<text::ExemplarValueEncoder<'a>> for ExemplarValueEncoder<'a> {
753    fn from(e: text::ExemplarValueEncoder<'a>) -> Self {
754        ExemplarValueEncoder(ExemplarValueEncoderInner::Text(e))
755    }
756}
757
758#[cfg(feature = "protobuf")]
759impl<'a> From<protobuf::ExemplarValueEncoder<'a>> for ExemplarValueEncoder<'a> {
760    fn from(e: protobuf::ExemplarValueEncoder<'a>) -> Self {
761        ExemplarValueEncoder(ExemplarValueEncoderInner::Protobuf(e))
762    }
763}
764
765impl ExemplarValueEncoder<'_> {
766    fn encode(&mut self, v: f64) -> Result<(), std::fmt::Error> {
767        for_both_mut!(self, ExemplarValueEncoderInner, e, e.encode(v))
768    }
769}