#![allow(clippy::module_name_repetitions)]
#[cfg(doc)]
use crate::*;
use crate::{
Error, Literal, Parse, Parser, RefineErr, Result, ToTokens, TokenIter, TokenStream, TokenTree,
};
#[derive(Debug, Clone)]
pub struct LiteralInteger {
literal: Literal,
value: u128,
}
impl LiteralInteger {
#[must_use]
pub fn new(value: u128) -> Self {
let literal = Literal::u128_unsuffixed(value);
Self { literal, value }
}
#[must_use]
pub const fn value(&self) -> u128 {
self.value
}
pub fn set(&mut self, value: u128) {
*self = Self {
literal: Literal::u128_unsuffixed(value),
value,
};
}
#[must_use]
pub fn into_inner(self) -> Literal {
self.literal
}
}
impl Parser for LiteralInteger {
fn parser(tokens: &mut TokenIter) -> Result<Self> {
let at = tokens.clone().next();
let literal = Literal::parser(tokens).refine_err::<Self>()?;
let value: u128 = match literal.to_string().parse() {
Ok(v) => v,
Err(e) => return Error::dynamic::<Self>(at, tokens, e),
};
Ok(Self { literal, value })
}
}
impl ToTokens for LiteralInteger {
fn to_tokens(&self, tokens: &mut TokenStream) {
self.literal.to_tokens(tokens);
}
}
impl PartialEq<u128> for LiteralInteger {
fn eq(&self, other: &u128) -> bool {
&self.value == other
}
}
impl From<LiteralInteger> for TokenTree {
fn from(lit: LiteralInteger) -> Self {
TokenTree::Literal(lit.into_inner())
}
}
#[test]
fn test_literalinteger_into_tt() {
let lit = LiteralInteger::new(42);
let _: TokenTree = lit.into();
}
#[derive(Debug, Clone)]
pub struct ConstInteger<const V: u128>(LiteralInteger);
impl<const V: u128> ConstInteger<V> {
#[must_use]
pub const fn value(&self) -> u128 {
self.0.value
}
#[must_use]
pub fn into_inner(self) -> LiteralInteger {
self.0
}
}
impl<const V: u128> Parser for ConstInteger<V> {
fn parser(tokens: &mut TokenIter) -> Result<Self> {
let at = tokens.clone().next();
Parse::parse_with(tokens, |this: LiteralInteger, e| {
if this.value == V {
Ok(Self(this))
} else {
Error::unexpected_token(at, e)
}
})
.refine_err::<Self>()
}
}
impl<const V: u128> ToTokens for ConstInteger<V> {
fn to_tokens(&self, tokens: &mut TokenStream) {
self.0.to_tokens(tokens);
}
}
impl<const V: u128> Default for ConstInteger<V> {
fn default() -> Self {
Self(LiteralInteger::new(V))
}
}
#[derive(Debug, Clone)]
pub struct LiteralCharacter {
literal: Literal,
value: char,
}
impl LiteralCharacter {
#[must_use]
pub fn new(value: char) -> Self {
let literal = Literal::character(value);
Self { literal, value }
}
#[must_use]
pub const fn value(&self) -> char {
self.value
}
pub fn set(&mut self, value: char) {
*self = Self {
literal: Literal::character(value),
value,
};
}
#[must_use]
pub fn into_inner(self) -> Literal {
self.literal
}
}
impl Parser for LiteralCharacter {
fn parser(tokens: &mut TokenIter) -> Result<Self> {
let at = tokens.clone().next();
let literal = Literal::parser(tokens).refine_err::<Self>()?;
let string = literal.to_string();
let mut chars = string.chars();
if let (Some('\''), Some(value)) = (chars.next(), chars.next()) {
Ok(Self { literal, value })
} else {
Error::unexpected_token(at, tokens)
}
}
}
impl ToTokens for LiteralCharacter {
fn to_tokens(&self, tokens: &mut TokenStream) {
self.literal.to_tokens(tokens);
}
}
impl PartialEq<char> for LiteralCharacter {
fn eq(&self, other: &char) -> bool {
&self.value == other
}
}
impl From<LiteralCharacter> for TokenTree {
fn from(lit: LiteralCharacter) -> Self {
TokenTree::Literal(lit.into_inner())
}
}
#[test]
fn test_literalcharacter_into_tt() {
let lit = LiteralCharacter::new('c');
let _: TokenTree = lit.into();
}
#[derive(Debug, Clone)]
pub struct ConstCharacter<const V: char>(LiteralCharacter);
impl<const V: char> ConstCharacter<V> {
#[must_use]
pub const fn value(&self) -> char {
self.0.value
}
#[must_use]
pub fn into_inner(self) -> LiteralCharacter {
self.0
}
}
impl<const V: char> Parser for ConstCharacter<V> {
fn parser(tokens: &mut TokenIter) -> Result<Self> {
let at = tokens.clone().next();
Parse::parse_with(tokens, |this: LiteralCharacter, e| {
if this.value == V {
Ok(Self(this))
} else {
Error::unexpected_token(at, e)
}
})
.refine_err::<Self>()
}
}
impl<const V: char> ToTokens for ConstCharacter<V> {
fn to_tokens(&self, tokens: &mut TokenStream) {
self.0.to_tokens(tokens);
}
}
impl<const V: char> Default for ConstCharacter<V> {
fn default() -> Self {
Self(LiteralCharacter::new(V))
}
}
#[derive(Debug, Clone)]
pub struct LiteralString {
literal: Literal,
value: String,
}
impl LiteralString {
#[must_use]
pub fn new(value: String) -> Self {
assert!(value.starts_with('"') && value.ends_with('"'));
let literal = Literal::string(&value);
Self { literal, value }
}
#[must_use]
#[allow(clippy::should_implement_trait)]
pub fn from_str(string: impl AsRef<str>) -> Self {
let string = string.as_ref();
let value = format!(r#""{string}""#);
let literal = Literal::string(string);
Self { literal, value }
}
#[must_use]
#[allow(clippy::missing_const_for_fn)] pub fn value(&self) -> &str {
&self.value
}
#[must_use]
pub fn as_str(&self) -> &str {
&self.value[1..self.value.len() - 1]
}
pub fn set(&mut self, value: String) {
*self = Self {
literal: Literal::string(&value),
value,
};
}
#[must_use]
pub fn into_inner(self) -> Literal {
self.literal
}
}
impl Parser for LiteralString {
fn parser(tokens: &mut TokenIter) -> Result<Self> {
let at = tokens.clone().next();
let literal = Literal::parser(tokens).refine_err::<Self>()?;
let string = literal.to_string();
if &string[0..1] == "\"" {
Ok(Self {
literal,
value: string,
})
} else {
Error::unexpected_token(at, tokens)
}
}
}
impl ToTokens for LiteralString {
fn to_tokens(&self, tokens: &mut TokenStream) {
self.literal.to_tokens(tokens);
}
}
impl PartialEq<&str> for LiteralString {
fn eq(&self, other: &&str) -> bool {
self.as_str() == *other
}
}
impl From<LiteralString> for TokenTree {
fn from(lit: LiteralString) -> Self {
TokenTree::Literal(lit.into_inner())
}
}
#[test]
fn test_literalstring_into_tt() {
let lit = LiteralString::from_str("foobar");
let _: TokenTree = lit.into();
}