use super::origin::Origin;
use super::{NativeAttribute, NativeAttributeOperandError, NativeTemplateComponent};
use crate::embed::{EmbedSource, prepare_attribute_value};
use vize_l0::Span;
mod failure;
mod frame;
pub use failure::NativeAttributeValueFailure;
use frame::Frame;
pub struct NativeAttributeValue<'a> {
origin: Origin<'a>,
frame: Frame,
source: EmbedSource<'a>,
}
impl<'a> NativeTemplateComponent<'a> {
pub fn observe_attribute_value(
&self,
attribute: NativeAttribute<'_, 'a>,
) -> Result<NativeAttributeValue<'a>, NativeAttributeValueFailure<'a>> {
let prepare = || {
Origin::check_original_header(self, &attribute)?;
let origin = Origin::from_attribute(self, &attribute)?;
let frame = Frame::original(&origin, &attribute)?;
let source = prepare_attribute_value(
self.component().allocator(),
origin.block.root_source(),
origin.value_span,
)
.map_err(NativeAttributeOperandError::Source)?;
Ok(NativeAttributeValue {
origin,
frame,
source,
})
};
prepare().map_err(|kind| NativeAttributeValueFailure::original(kind, &attribute))
}
}
impl<'a> NativeAttributeValue<'a> {
#[must_use]
pub const fn source(&self) -> EmbedSource<'a> {
self.source
}
#[must_use]
pub const fn raw_value(&self) -> &'a str {
self.origin.raw_value
}
#[must_use]
pub const fn name_span(&self) -> Span {
self.origin.name_span
}
#[must_use]
pub const fn value_span(&self) -> Span {
self.origin.value_span
}
#[must_use]
pub const fn full_value_span(&self) -> Span {
self.frame.value
}
#[must_use]
pub const fn equals_span(&self) -> Span {
self.frame.equals
}
#[must_use]
pub const fn quote_spans(&self) -> Option<(Span, Span)> {
self.frame.quotes
}
pub fn admitted_for<'s>(
&'s self,
selected: &'s NativeTemplateComponent<'a>,
attribute: NativeAttribute<'s, 'a>,
) -> Option<NativeAttributeValueView<'s, 'a>> {
self.origin
.matches(selected, &attribute)
.then_some(NativeAttributeValueView {
owner: self,
selected,
attribute,
})
}
#[must_use]
pub fn into_source(self) -> EmbedSource<'a> {
self.source
}
}
pub struct NativeAttributeValueView<'s, 'a> {
owner: &'s NativeAttributeValue<'a>,
selected: &'s NativeTemplateComponent<'a>,
attribute: NativeAttribute<'s, 'a>,
}
impl<'s, 'a> NativeAttributeValueView<'s, 'a> {
#[must_use]
pub fn selected(&self) -> &'s NativeTemplateComponent<'a> {
self.selected
}
#[must_use]
pub fn attribute(&self) -> &NativeAttribute<'s, 'a> {
&self.attribute
}
#[must_use]
pub fn observation(&self) -> &'s NativeAttributeValue<'a> {
self.owner
}
}
#[cfg(test)]
mod tests;