use std::borrow::Cow;
use syntastica_highlight::HighlightConfiguration;
use tft::FileType;
use crate::Result;
use super::{LanguageSet, SupportedLanguage};
#[derive(Default)]
pub struct Union<L, R> {
left: L,
right: R,
}
#[derive(Debug, Hash, PartialEq, Eq)]
pub enum EitherLang<L, R> {
Left(L),
Right(R),
}
impl<L, R> Union<L, R> {
pub fn new(left: L, right: R) -> Self {
Self { left, right }
}
pub fn left(&self) -> &L {
&self.left
}
pub fn right(&self) -> &R {
&self.right
}
}
impl<'s, L, R> LanguageSet<'s> for Union<L, R>
where
L: LanguageSet<'s>,
R: LanguageSet<'s>,
{
type Language = EitherLang<L::Language, R::Language>;
fn get_language(&self, language: Self::Language) -> Result<&HighlightConfiguration> {
match language {
EitherLang::Left(lang) => self.left.get_language(lang),
EitherLang::Right(lang) => self.right.get_language(lang),
}
}
}
impl<L, R> From<L> for EitherLang<L, R> {
fn from(value: L) -> Self {
Self::Left(value)
}
}
impl<'set, L, R, S, T> SupportedLanguage<'set, Union<S, T>> for EitherLang<L, R>
where
L: SupportedLanguage<'set, S>,
R: SupportedLanguage<'set, T>,
{
fn name(&self) -> Cow<'_, str> {
match self {
EitherLang::Left(lang) => lang.name(),
EitherLang::Right(lang) => lang.name(),
}
}
fn for_name(name: impl AsRef<str>, set: &'set Union<S, T>) -> Result<Self> {
L::for_name(name.as_ref(), &set.left)
.map(Self::Left)
.or_else(|_| R::for_name(name, &set.right).map(Self::Right))
}
fn for_file_type(file_type: FileType, set: &'set Union<S, T>) -> Option<Self> {
L::for_file_type(file_type, &set.left)
.map(Self::Left)
.or_else(|| R::for_file_type(file_type, &set.right).map(Self::Right))
}
fn for_injection(name: impl AsRef<str>, set: &'set Union<S, T>) -> Option<Self> {
L::for_injection(name.as_ref(), &set.left)
.map(Self::Left)
.or_else(|| R::for_injection(name, &set.right).map(Self::Right))
}
}