1use crate::lex::Cursor;
2use crate::lit::Lit;
3use crate::{Ident, LexError, Scan, Span, Spanner};
4
5#[derive(Debug, Clone)]
6#[cfg_attr(feature = "serde", derive(serde::Serialize), serde(into = "String"))]
7pub struct LitBool {
8 value: bool,
9 span: Span,
10}
11
12impl LitBool {
13 #[inline]
14 pub fn new(value: bool, span: Span) -> Self {
15 Self { value, span }
16 }
17
18 #[inline]
19 pub fn value(&self) -> bool {
20 self.value
21 }
22
23 #[inline]
24 pub fn repr(&self) -> &str {
25 if self.value { "true" } else { "false" }
26 }
27
28 #[inline]
29 pub fn span(&self) -> Span {
30 self.span
31 }
32
33 #[inline]
34 pub fn set_span(&mut self, span: Span) {
35 self.span = span;
36 }
37}
38
39impl PartialEq for LitBool {
40 fn eq(&self, other: &Self) -> bool {
41 self.value == other.value
42 }
43}
44
45impl Eq for LitBool {}
46
47impl std::hash::Hash for LitBool {
48 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
49 self.value.hash(state);
50 }
51}
52
53impl std::fmt::Display for LitBool {
54 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
55 f.write_str(self.repr())
56 }
57}
58
59impl Spanner for LitBool {
60 fn span(&self) -> Span {
61 self.span
62 }
63}
64
65impl From<LitBool> for Lit {
66 fn from(value: LitBool) -> Self {
67 Self::Bool(value)
68 }
69}
70
71impl Scan for LitBool {
72 fn scan(cursor: Cursor<'_>) -> Result<(Cursor<'_>, Self), LexError> {
73 let (cursor, ident) = Ident::scan(cursor)?;
74
75 if !ident.is_raw() && (ident.text() == "true" || ident.text() == "false") {
76 Ok((cursor, Self::new(ident.text() == "true", ident.span())))
77 } else {
78 cursor.error().message("expected bool literal").into()
79 }
80 }
81}
82
83#[cfg(feature = "serde")]
84impl From<LitBool> for String {
85 fn from(value: LitBool) -> Self {
86 value.repr().to_string()
87 }
88}