#[derive(Clone, Debug, PartialEq, Eq)]
pub struct SpanRecoveryFrame<T> {
value: T,
from_expansion: bool,
}
impl<T> SpanRecoveryFrame<T> {
#[must_use]
pub const fn new(value: T, from_expansion: bool) -> Self {
Self {
value,
from_expansion,
}
}
#[must_use]
pub const fn value(&self) -> &T {
&self.value
}
#[must_use]
pub fn into_value(self) -> T {
self.value
}
#[must_use]
pub const fn from_expansion(&self) -> bool {
self.from_expansion
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum UserEditableSpan<T> {
Direct(T),
Recovered(T),
MacroOnly,
}
impl<T> UserEditableSpan<T> {
#[must_use]
pub fn into_option(self) -> Option<T> {
match self {
Self::Direct(value) | Self::Recovered(value) => Some(value),
Self::MacroOnly => None,
}
}
}
#[must_use]
pub fn recover_user_editable_span<T: Clone>(
frames: &[SpanRecoveryFrame<T>],
) -> UserEditableSpan<T> {
frames
.iter()
.enumerate()
.find(|(_, frame)| !frame.from_expansion())
.map_or(UserEditableSpan::MacroOnly, |(index, frame)| {
if index == 0 {
UserEditableSpan::Direct(frame.value().clone())
} else {
UserEditableSpan::Recovered(frame.value().clone())
}
})
}