1use num::traits::SaturatingAdd;
6use sponge_hash_aes256::DEFAULT_DIGEST_SIZE;
7use std::{
8 num::NonZeroUsize,
9 process::ExitCode,
10 sync::atomic::{AtomicUsize, Ordering},
11};
12use tinyvec::{ArrayVec, TinyVec};
13
14pub const MAX_SNAIL_LEVEL: u8 = 4u8;
20
21pub const MAX_DIGEST_SIZE: usize = 8usize * DEFAULT_DIGEST_SIZE;
23
24pub type Digest = TinyVec<[u8; DEFAULT_DIGEST_SIZE]>;
26
27pub struct Aborted;
29
30pub enum ExitStatus {
36 Success,
38 Warning,
40 Failure,
42}
43
44impl From<ExitStatus> for ExitCode {
45 fn from(value: ExitStatus) -> Self {
46 match value {
47 ExitStatus::Success => Self::from(0u8),
48 ExitStatus::Warning => Self::from(1u8),
49 ExitStatus::Failure => Self::from(2u8),
50 }
51 }
52}
53
54impl From<Aborted> for ExitCode {
55 fn from(_value: Aborted) -> Self {
56 ExitCode::from(3u8)
57 }
58}
59
60pub struct Flag(AtomicUsize);
66
67pub struct UpdateError;
69
70const STATUS_RUNNING: usize = 0usize;
72const STATUS_STOPPED: usize = 1usize;
73const STATUS_ABORTED: usize = 2usize;
74
75impl Flag {
76 #[inline(always)]
80 pub fn running(&self) -> bool {
81 self.0.load(Ordering::Relaxed) == STATUS_RUNNING
82 }
83
84 #[inline]
86 pub fn stop_process(&self) -> Result<(), UpdateError> {
87 self.try_update(STATUS_STOPPED)
88 }
89
90 #[inline]
92 pub fn abort_process(&self) -> Result<(), UpdateError> {
93 self.try_update(STATUS_ABORTED)
94 }
95
96 #[inline(always)]
97 fn try_update(&self, new_state: usize) -> Result<(), UpdateError> {
98 match self.0.compare_exchange(STATUS_RUNNING, new_state, Ordering::AcqRel, Ordering::Acquire) {
99 Ok(_) => Ok(()),
100 Err(previous_state) => match previous_state == new_state {
101 true => Ok(()),
102 false => Err(UpdateError),
103 },
104 }
105 }
106}
107
108impl Default for Flag {
109 #[inline]
110 fn default() -> Self {
111 Self(AtomicUsize::new(STATUS_RUNNING))
112 }
113}
114
115pub trait TinyVecEx {
120 fn with_length(length: usize) -> Self;
121}
122
123impl<const N: usize, T: Copy + Default> TinyVecEx for TinyVec<[T; N]> {
124 #[inline(always)]
125 fn with_length(length: usize) -> Self {
126 if length <= N {
127 TinyVec::Inline(ArrayVec::from_array_len([T::default(); N], length))
128 } else {
129 TinyVec::Heap(vec![T::default(); length])
130 }
131 }
132}
133
134#[inline(always)]
140pub fn increment<T: SaturatingAdd + From<u8>>(counter: &mut T) {
141 *counter = counter.saturating_add(&T::from(1u8));
142}
143
144#[inline]
146pub fn get_capacity(thread_count: &NonZeroUsize) -> usize {
147 let capacity = thread_count.get().saturating_mul(2usize).saturating_add(1usize);
148 if capacity > isize::MAX as usize {
149 capacity
150 } else {
151 capacity.next_power_of_two()
152 }
153}
154
155#[macro_export]
161macro_rules! print_error {
162 ($args:ident, $fmt:literal $(,$arg:expr)*$(,)?) => {
163 if !$args.quiet {
164 eprintln!(concat!("[sponge256sum] ", $fmt) $(, $arg)*);
165 }
166 };
167}