use std::{convert::Infallible, fmt, str::FromStr};
use crate::{
ast::{
node::{roots::Roots, TypeExpr},
RootEntry, Value,
},
Spanned,
};
mod kind;
use crate::span::Span;
pub use kind::*;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum FileKind {
Prop,
Patch,
Unknown,
}
impl FileKind {
pub fn as_str(&self) -> &'static str {
match self {
Self::Prop => "PROP",
Self::Patch => "PTCH",
Self::Unknown => "unknown",
}
}
}
impl fmt::Display for FileKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.as_str())
}
}
impl FromStr for FileKind {
type Err = Infallible;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(match s {
"PROP" => Self::Prop,
"PTCH" => Self::Patch,
_ => Self::Unknown,
})
}
}
#[derive(Debug, Clone, Copy)]
pub struct KnownRoot<V> {
pub(crate) idx: usize,
pub value: V,
}
impl<V> KnownRoot<V> {
pub fn original<'a>(&self, roots: &'a Roots) -> &'a Root {
&roots.all[self.idx]
}
pub fn into_inner(self) -> V {
self.value
}
}
#[cfg(feature = "span_print")]
impl<V: crate::span::DebugSpans> crate::span::DebugSpans for KnownRoot<V> {
fn fmt(&self, text: &str, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("KnownRoot")
.field("idx", &self.idx)
.field("value", &crate::span::debug_with_source(&self.value, text))
.finish()
}
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "span_print", derive(crate::span::DebugSpans))]
pub struct Root {
pub idx: usize,
pub name: Spanned<RootKind>,
pub type_expr: Spanned<Option<TypeExpr>>,
pub value: Option<RootValue>,
}
impl Root {
#[inline(always)]
#[must_use]
pub fn span(&self) -> Span {
self.name.span.cover(
self.value
.as_ref()
.map(RootValue::span)
.unwrap_or(self.type_expr.span),
)
}
#[must_use]
pub(crate) fn value_span(&self) -> Span {
self.value.as_ref().map_or(self.span(), RootValue::span)
}
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "span_print", derive(crate::span::DebugSpans))]
pub enum RootValue {
Value(Value),
Entries(Spanned<Vec<RootEntry>>),
}
impl RootValue {
pub fn as_value(&self) -> Option<&Value> {
match self {
RootValue::Value(v) => Some(v),
_ => None,
}
}
pub fn span(&self) -> Span {
match self {
RootValue::Value(v) => v.span(),
RootValue::Entries(e) => e.span,
}
}
}