// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

use core::sync::atomic::{AtomicU64, Ordering};
use s2n_quic_core::varint::VarInt;

#[derive(Clone, Copy, Debug)]
pub struct ExhaustionError;

#[derive(Debug, Default)]
pub struct Counter(AtomicU64);

impl Counter {
    #[inline]
    pub fn reset(&self) {
        self.0.store(0, Ordering::Relaxed)
    }

    #[inline]
    pub fn next(&self) -> Result<VarInt, ExhaustionError> {
        // https://marabos.nl/atomics/memory-ordering.html#relaxed
        // > While atomic operations using relaxed memory ordering do not
        // > provide any happens-before relationship, they do guarantee a total
        // > modification order of each individual atomic variable. This means
        // > that all modifications of the same atomic variable happen in an
        // > order that is the same from the perspective of every single thread.
        let pn = self.0.fetch_add(1, Ordering::Relaxed);
        VarInt::new(pn).map_err(|_| ExhaustionError)
    }
}
