pub struct Decoded<T, W> {
pub value: T,
#[cfg(any(feature = "alloc", feature = "std"))]
pub warnings: alloc::vec::Vec<W>,
#[cfg(not(any(feature = "alloc", feature = "std")))]
pub warnings: [Option<W>; 8],
#[cfg(not(any(feature = "alloc", feature = "std")))]
pub num_warnings: usize,
}
impl<T, W> Decoded<T, W> {
pub(crate) const fn new(value: T) -> Self {
Self {
value,
#[cfg(any(feature = "alloc", feature = "std"))]
warnings: alloc::vec::Vec::new(),
#[cfg(not(any(feature = "alloc", feature = "std")))]
warnings: [const { None }; 8],
#[cfg(not(any(feature = "alloc", feature = "std")))]
num_warnings: 0,
}
}
pub(crate) fn push_warning(&mut self, warning: W) {
#[cfg(any(feature = "alloc", feature = "std"))]
self.warnings.push(warning);
#[cfg(not(any(feature = "alloc", feature = "std")))]
if self.num_warnings < 8 {
self.warnings[self.num_warnings] = Some(warning);
self.num_warnings += 1;
}
}
pub(crate) fn wrap<U, V>(
self,
frame_fn: impl FnOnce(T) -> U,
warn_fn: impl Fn(W) -> V,
) -> Decoded<U, V> {
let mut out = Decoded::new(frame_fn(self.value));
#[cfg(any(feature = "alloc", feature = "std"))]
for w in self.warnings {
out.push_warning(warn_fn(w));
}
#[cfg(not(any(feature = "alloc", feature = "std")))]
{
let n = self.num_warnings;
for (i, opt) in self.warnings.into_iter().enumerate() {
if i >= n {
break;
}
if let Some(w) = opt {
out.push_warning(warn_fn(w));
}
}
}
out
}
#[cfg(any(feature = "alloc", feature = "std"))]
pub fn iter_warnings(&self) -> impl Iterator<Item = &W> {
self.warnings.iter()
}
#[cfg(not(any(feature = "alloc", feature = "std")))]
pub fn iter_warnings(&self) -> impl Iterator<Item = &W> {
self.warnings[..self.num_warnings]
.iter()
.filter_map(|w| w.as_ref())
}
}
#[cfg(any(feature = "alloc", feature = "std"))]
impl<T: core::fmt::Debug, W: core::fmt::Debug> core::fmt::Debug for Decoded<T, W> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("Decoded")
.field("value", &self.value)
.field("warnings", &self.warnings)
.finish()
}
}
#[cfg(not(any(feature = "alloc", feature = "std")))]
impl<T: core::fmt::Debug, W: core::fmt::Debug> core::fmt::Debug for Decoded<T, W> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("Decoded")
.field("value", &self.value)
.field("warnings", &&self.warnings[..self.num_warnings])
.finish()
}
}
#[cfg(test)]
#[path = "decoded_tests.rs"]
mod tests;