use std::ops::{Deref, DerefMut};
use proc_macro2::TokenStream;
use crate::token_store::{AddTokens, TokenLevel, TokenStore};
#[derive(Debug, Default)]
pub struct PassedData<T> {
tokens: Option<TokenStream>,
data: T,
}
impl<T> Eq for PassedData<T> where T: Eq {}
impl<T> PartialEq for PassedData<T>
where
T: Eq,
{
fn eq(&self, other: &Self) -> bool {
let data_is_equal = self.data == other.data;
let self_string_tokens = self.tokens.as_ref().map(ToString::to_string);
let other_string_tokens = other.tokens.as_ref().map(ToString::to_string);
let tokens_are_equal = self_string_tokens == other_string_tokens;
data_is_equal && tokens_are_equal
}
}
impl<T> From<PassedData<T>> for TokenStream {
fn from(passed_data: PassedData<T>) -> Self {
passed_data.tokens.unwrap_or_default()
}
}
impl<T> PassedData<T> {
pub fn tokens(tokens: TokenStream) -> Self
where
T: Default,
{
Self {
tokens: Some(tokens),
data: T::default(),
}
}
pub fn data(data: T) -> Self {
Self { tokens: None, data }
}
pub fn without_data(self) -> PassedData<()> {
PassedData {
tokens: self.tokens,
data: (),
}
}
pub fn with_tokens(self, tokens: TokenStream) -> Self {
Self {
data: self.data,
tokens: Some(tokens),
}
}
pub(crate) fn seperate_tokens_into(
self,
token_level: TokenLevel,
token_store: &mut TokenStore,
) -> T {
token_store.add_tokens(token_level, self.tokens);
self.data
}
}
pub trait WithData {
fn with_data<T>(self, data: T) -> PassedData<T>;
}
impl WithData for TokenStream {
fn with_data<T>(self, data: T) -> PassedData<T> {
PassedData {
tokens: Some(self),
data,
}
}
}
impl<T> Deref for PassedData<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.data
}
}
impl<T> DerefMut for PassedData<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.data
}
}