use std::borrow::Cow;
use std::num::NonZeroUsize;
use std::path::{Path, PathBuf};
use crate::token::{self, Depth, Text, TokenVariance};
pub use crate::diagnostics::{LocatedError, Span};
pub use crate::token::Boundedness;
pub use Boundedness::{Bounded, Unbounded};
pub type VariantRange = Boundedness<BoundedVariantRange>;
impl VariantRange {
pub fn lower(&self) -> Boundedness<NonZeroUsize> {
match self {
Bounded(range) => range.lower(),
_ => Unbounded,
}
}
pub fn upper(&self) -> Boundedness<NonZeroUsize> {
match self {
Bounded(range) => range.upper(),
_ => Unbounded,
}
}
}
impl From<token::VariantRange> for VariantRange {
fn from(range: token::VariantRange) -> Self {
range.map_bounded(From::from)
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct BoundedVariantRange {
lower: Boundedness<NonZeroUsize>,
upper: Boundedness<NonZeroUsize>,
}
impl BoundedVariantRange {
pub fn lower(&self) -> Boundedness<NonZeroUsize> {
self.lower
}
pub fn upper(&self) -> Boundedness<NonZeroUsize> {
self.upper
}
}
impl From<token::BoundedVariantRange> for BoundedVariantRange {
fn from(range: token::BoundedVariantRange) -> Self {
BoundedVariantRange {
lower: range.lower().into_bound(),
upper: range.upper().into_bound(),
}
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum Variance<T, B> {
Invariant(T),
Variant(B),
}
impl<T, B> Variance<T, B> {
pub fn invariant(self) -> Option<T> {
match self {
Variance::Invariant(invariant) => Some(invariant),
_ => None,
}
}
pub fn variant(self) -> Option<B> {
match self {
Variance::Variant(bound) => Some(bound),
_ => None,
}
}
pub fn as_ref(&self) -> Variance<&T, &B> {
match self {
Variance::Invariant(invariant) => Variance::Invariant(invariant),
Variance::Variant(bound) => Variance::Variant(bound),
}
}
pub fn is_invariant(&self) -> bool {
matches!(self, Variance::Invariant(_))
}
pub fn is_variant(&self) -> bool {
matches!(self, Variance::Variant(_))
}
}
pub type DepthVariance = Variance<usize, VariantRange>;
impl From<TokenVariance<Depth>> for DepthVariance {
fn from(depth: TokenVariance<Depth>) -> Self {
match depth {
TokenVariance::Invariant(depth) => DepthVariance::Invariant(depth.into()),
TokenVariance::Variant(bounds) => DepthVariance::Variant(bounds.into()),
}
}
}
pub type TextVariance<'t> = Variance<Cow<'t, str>, ()>;
impl<'t> TextVariance<'t> {
pub fn into_path_buf(self) -> Option<PathBuf> {
self.invariant().map(Cow::into_owned).map(From::from)
}
pub fn as_path(&self) -> Option<&Path> {
self.as_ref().invariant().map(|text| text.as_ref().as_ref())
}
}
impl<'t> From<TokenVariance<Text<'t>>> for TextVariance<'t> {
fn from(text: TokenVariance<Text<'t>>) -> Self {
match text {
TokenVariance::Invariant(text) => TextVariance::Invariant(text.to_string()),
TokenVariance::Variant(_) => TextVariance::Variant(()),
}
}
}
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum When {
Always,
Sometimes,
Never,
}
impl When {
pub fn and(self, other: Self) -> Self {
use When::{Always, Never, Sometimes};
match (self, other) {
(Never, _) | (_, Never) => Never,
(Sometimes, _) | (_, Sometimes) => Sometimes,
(Always, Always) => Always,
}
}
pub fn or(self, other: Self) -> Self {
use When::{Always, Never, Sometimes};
match (self, other) {
(Always, _) | (_, Always) => Always,
(Sometimes, _) | (_, Sometimes) => Sometimes,
(Never, Never) => Never,
}
}
pub fn certainty(self, other: Self) -> Self {
use When::{Always, Never, Sometimes};
match (self, other) {
(Always, Always) => Always,
(Never, Never) => Never,
(Sometimes, _) | (_, Sometimes) | (Always, _) | (_, Always) => Sometimes,
}
}
pub fn is_always(&self) -> bool {
matches!(self, When::Always)
}
pub fn is_sometimes(&self) -> bool {
matches!(self, When::Sometimes)
}
pub fn is_never(&self) -> bool {
matches!(self, When::Never)
}
pub fn is_maybe_true(&self) -> bool {
!self.is_never()
}
pub fn is_maybe_false(&self) -> bool {
!self.is_always()
}
}
impl From<bool> for When {
fn from(is_always: bool) -> Self {
if is_always { When::Always } else { When::Never }
}
}
impl From<Option<bool>> for When {
fn from(when: Option<bool>) -> Self {
match when {
Some(true) => When::Always,
None => When::Sometimes,
Some(false) => When::Never,
}
}
}
impl From<When> for Option<bool> {
fn from(when: When) -> Self {
match when {
When::Always => Some(true),
When::Sometimes => None,
When::Never => Some(false),
}
}
}
#[derive(Clone, Copy, Debug)]
pub struct CapturingToken {
index: usize,
span: Span,
}
impl CapturingToken {
pub(crate) fn new(index: usize, span: Span) -> Self {
CapturingToken { index, span }
}
pub fn index(&self) -> usize {
self.index
}
pub fn span(&self) -> Span {
self.span
}
}