use crate::field::FieldSet;
use crate::parent::Parent;
use crate::stdlib::num::NonZeroU64;
use crate::{field, Metadata};
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct Id(NonZeroU64);
#[derive(Debug)]
pub struct Attributes<'a> {
metadata: &'static Metadata<'static>,
values: &'a field::ValueSet<'a>,
parent: Parent,
}
#[derive(Debug)]
pub struct Record<'a> {
values: &'a field::ValueSet<'a>,
}
#[derive(Debug)]
pub struct Current {
inner: CurrentInner,
}
#[derive(Debug)]
enum CurrentInner {
Current {
id: Id,
metadata: &'static Metadata<'static>,
},
None,
Unknown,
}
impl Id {
pub fn from_u64(u: u64) -> Self {
Id(NonZeroU64::new(u).expect("span IDs must be > 0"))
}
#[inline]
pub const fn from_non_zero_u64(id: NonZeroU64) -> Self {
Id(id)
}
#[allow(clippy::wrong_self_convention)]
pub fn into_u64(&self) -> u64 {
self.0.get()
}
#[allow(clippy::wrong_self_convention)]
#[inline]
pub const fn into_non_zero_u64(&self) -> NonZeroU64 {
self.0
}
}
impl<'a> From<&'a Id> for Option<Id> {
fn from(id: &'a Id) -> Self {
Some(id.clone())
}
}
impl<'a> Attributes<'a> {
pub fn new(metadata: &'static Metadata<'static>, values: &'a field::ValueSet<'a>) -> Self {
Attributes {
metadata,
values,
parent: Parent::Current,
}
}
pub fn new_root(metadata: &'static Metadata<'static>, values: &'a field::ValueSet<'a>) -> Self {
Attributes {
metadata,
values,
parent: Parent::Root,
}
}
pub fn child_of(
parent: Id,
metadata: &'static Metadata<'static>,
values: &'a field::ValueSet<'a>,
) -> Self {
Attributes {
metadata,
values,
parent: Parent::Explicit(parent),
}
}
pub fn metadata(&self) -> &'static Metadata<'static> {
self.metadata
}
pub fn values(&self) -> &field::ValueSet<'a> {
self.values
}
pub fn is_root(&self) -> bool {
matches!(self.parent, Parent::Root)
}
pub fn is_contextual(&self) -> bool {
matches!(self.parent, Parent::Current)
}
pub fn parent(&self) -> Option<&Id> {
match self.parent {
Parent::Explicit(ref p) => Some(p),
_ => None,
}
}
pub fn record(&self, visitor: &mut dyn field::Visit) {
self.values.record(visitor)
}
pub fn contains(&self, field: &field::Field) -> bool {
self.values.contains(field)
}
pub fn is_empty(&self) -> bool {
self.values.is_empty()
}
pub fn fields(&self) -> &FieldSet {
self.values.field_set()
}
}
impl<'a> Record<'a> {
pub fn new(values: &'a field::ValueSet<'a>) -> Self {
Self { values }
}
pub fn record(&self, visitor: &mut dyn field::Visit) {
self.values.record(visitor)
}
pub fn len(&self) -> usize {
self.values.len()
}
pub fn contains(&self, field: &field::Field) -> bool {
self.values.contains(field)
}
pub fn is_empty(&self) -> bool {
self.values.is_empty()
}
}
impl Current {
pub fn new(id: Id, metadata: &'static Metadata<'static>) -> Self {
Self {
inner: CurrentInner::Current { id, metadata },
}
}
pub fn none() -> Self {
Self {
inner: CurrentInner::None,
}
}
pub(crate) fn unknown() -> Self {
Self {
inner: CurrentInner::Unknown,
}
}
pub fn is_known(&self) -> bool {
!matches!(self.inner, CurrentInner::Unknown)
}
pub fn into_inner(self) -> Option<(Id, &'static Metadata<'static>)> {
match self.inner {
CurrentInner::Current { id, metadata } => Some((id, metadata)),
_ => None,
}
}
pub fn id(&self) -> Option<&Id> {
match self.inner {
CurrentInner::Current { ref id, .. } => Some(id),
_ => None,
}
}
pub fn metadata(&self) -> Option<&'static Metadata<'static>> {
match self.inner {
CurrentInner::Current { metadata, .. } => Some(metadata),
_ => None,
}
}
}
impl<'a> From<&'a Current> for Option<&'a Id> {
fn from(cur: &'a Current) -> Self {
cur.id()
}
}
impl<'a> From<&'a Current> for Option<Id> {
fn from(cur: &'a Current) -> Self {
cur.id().cloned()
}
}
impl From<Current> for Option<Id> {
fn from(cur: Current) -> Self {
match cur.inner {
CurrentInner::Current { id, .. } => Some(id),
_ => None,
}
}
}
impl<'a> From<&'a Current> for Option<&'static Metadata<'static>> {
fn from(cur: &'a Current) -> Self {
cur.metadata()
}
}