use crate::parent::Parent;
use crate::{field, Metadata};
use std::num::NonZeroU64;
#[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"))
}
pub fn into_u64(&self) -> u64 {
self.0.get()
}
}
impl<'a> Into<Option<Id>> for &'a Id {
fn into(self) -> Option<Id> {
Some(self.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 {
match self.parent {
Parent::Root => true,
_ => false,
}
}
pub fn is_contextual(&self) -> bool {
match self.parent {
Parent::Current => true,
_ => false,
}
}
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()
}
}
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 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 {
match self.inner {
CurrentInner::Unknown => false,
_ => true,
}
}
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 { ref metadata, .. } => Some(*metadata),
_ => None,
}
}
}
impl<'a> Into<Option<&'a Id>> for &'a Current {
fn into(self) -> Option<&'a Id> {
self.id()
}
}
impl<'a> Into<Option<Id>> for &'a Current {
fn into(self) -> Option<Id> {
self.id().cloned()
}
}
impl Into<Option<Id>> for Current {
fn into(self) -> Option<Id> {
self.id().cloned()
}
}
impl<'a> Into<Option<&'static Metadata<'static>>> for &'a Current {
fn into(self) -> Option<&'static Metadata<'static>> {
self.metadata()
}
}