running_buffer 0.1.1

data types for keeping track of changing values, allowing analysis in trends and histories.
Documentation
use circular_buffer::CircularBuffer;

#[derive(Debug, Clone, Default)]
pub struct SerdeCircularBuffer<const N: usize, T>(pub CircularBuffer<N, T>);

impl<const N: usize, T> SerdeCircularBuffer<N, T> {
    pub fn push_back(&mut self, item: T) -> Option<T> {
        self.0.push_back(item)
    }

    pub fn nth_back(&self, index: usize) -> Option<&T> {
        self.0.nth_back(index)
    }
}

#[cfg(feature = "serde")]
mod wrapper {
    use super::SerdeCircularBuffer;
    use circular_buffer::CircularBuffer;
    use core::fmt;
    use serde::{
        Deserialize, Deserializer, Serialize, Serializer,
        de::{SeqAccess, Visitor},
        ser::SerializeSeq,
    };
    impl<const N: usize, T> Serialize for SerdeCircularBuffer<N, T>
    where
        T: Serialize,
    {
        fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
        where
            S: Serializer,
        {
            let iter = self.0.iter();
            let mut seq = serializer.serialize_seq(Some(iter.len()))?;
            for elem in iter {
                seq.serialize_element(elem)?;
            }
            seq.end()
        }
    }

    impl<'de, const N: usize, T> Deserialize<'de> for SerdeCircularBuffer<N, T>
    where
        T: Deserialize<'de>,
    {
        fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
        where
            D: Deserializer<'de>,
        {
            struct CircularBufferVisitor<const N: usize, T> {
                marker: std::marker::PhantomData<T>,
            }

            impl<'de, const N: usize, T> Visitor<'de> for CircularBufferVisitor<N, T>
            where
                T: Deserialize<'de>,
            {
                type Value = SerdeCircularBuffer<N, T>;

                fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                    write!(formatter, "a sequence of elements up to capacity {}", N)
                }

                fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
                where
                    A: SeqAccess<'de>,
                {
                    let mut buffer = CircularBuffer::<N, T>::new();

                    // There is probably a tiny bit of performance gain to be gotten out
                    // of trying to first read it into a contiguous buffer with
                    // SeqAccessDeserializer, but that would require heap access.
                    // So instead, just use push_back a couple of times to do it in-place.

                    while let Some(elem) = seq.next_element()? {
                        buffer.push_back(elem);
                    }

                    Ok(SerdeCircularBuffer(buffer))
                }
            }

            deserializer.deserialize_seq(CircularBufferVisitor {
                marker: std::marker::PhantomData,
            })
        }
    }
}