use super::tree::{AstNode, ParsedFile};
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum LiteralValue {
Str(String),
Bytes(String),
Int(i128),
Float(u64),
}
impl LiteralValue {
pub(super) fn negated(&self) -> Option<Self> {
match self {
Self::Int(value) => value.checked_neg().map(Self::Int),
Self::Float(bits) => Some(Self::float(-f64::from_bits(*bits))),
Self::Str(_) | Self::Bytes(_) => None,
}
}
fn float(value: f64) -> Self {
Self::Float(if value == 0.0 { 0.0_f64 } else { value }.to_bits())
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum LiteralRole {
ConstantDefinition,
Inline,
}
pub struct LiteralOccurrence<'a> {
pub(crate) node: AstNode<'a>,
pub(crate) value: LiteralValue,
pub(in crate::code_lint) role: LiteralRole,
}
#[must_use]
pub fn collect_literal_occurrences(file: &ParsedFile) -> Vec<LiteralOccurrence<'_>> {
dispatch_lang!(file.lang(), collect_literal_occurrences(file))
}
pub(super) fn parse_integer_literal(text: &str) -> Option<LiteralValue> {
let digits = text.replace('_', "");
let (radix, digits) = match digits.get(..2) {
Some("0x" | "0X") => (16, &digits[2..]),
Some("0o" | "0O") => (8, &digits[2..]),
Some("0b" | "0B") => (2, &digits[2..]),
_ => (10, digits.as_str()),
};
i128::from_str_radix(digits, radix)
.ok()
.map(LiteralValue::Int)
}
pub(super) fn parse_float_literal(text: &str) -> Option<LiteralValue> {
text.replace('_', "").parse().ok().map(LiteralValue::float)
}