• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //! Parsing and inspecting Rust literal tokens.
2 //!
3 //! This library offers functionality to parse Rust literals, i.e. tokens in the
4 //! Rust programming language that represent fixed values. The grammar for
5 //! those is defined [here][ref].
6 //!
7 //! This kind of functionality already exists in the crate `syn`. However, as
8 //! you oftentimes don't need (nor want) the full power of `syn`, `litrs` was
9 //! built. This crate also offers a bit more flexibility compared to `syn`
10 //! (only regarding literals, of course).
11 //!
12 //! ---
13 //!
14 //! The main types of this library are [`Literal`], representing any kind of
15 //! literal, and `*Lit`, like [`StringLit`] or [`FloatLit`], representing a
16 //! specific kind of literal.
17 //!
18 //! There are different ways to obtain such a literal type:
19 //!
20 //! - **`parse`**: parses a `&str` or `String` and returns `Result<_,
21 //!     ParseError>`. For example: [`Literal::parse`] and
22 //!     [`IntegerLit::parse`].
23 //!
24 //! - **`From<proc_macro::Literal> for Literal`**: turns a `Literal` value from
25 //!     the `proc_macro` crate into a `Literal` from this crate.
26 //!
27 //! - **`TryFrom<proc_macro::Literal> for *Lit`**: tries to turn a
28 //!     `proc_macro::Literal` into a specific literal type of this crate. If
29 //!     the input is a literal of a different kind, `Err(InvalidToken)` is
30 //!     returned.
31 //!
32 //! - **`TryFrom<proc_macro::TokenTree>`**: attempts to turn a token tree into a
33 //!     literal type of this crate. An error is returned if the token tree is
34 //!     not a literal, or if you are trying to turn it into a specific kind of
35 //!     literal and the token tree is a different kind of literal.
36 //!
37 //! All of the `From` and `TryFrom` conversions also work for reference to
38 //! `proc_macro` types. Additionally, if the crate feature `proc-macro2` is
39 //! enabled (which it is by default), all these `From` and `TryFrom` impls also
40 //! exist for the corresponding `proc_macro2` types.
41 //!
42 //! **Note**: `true` and `false` are `Ident`s when passed to your proc macro.
43 //! The `TryFrom<TokenTree>` impls check for those two special idents and
44 //! return a `BoolLit` appropriately. For that reason, there is also no
45 //! `TryFrom<proc_macro::Literal>` impl for `BoolLit`. The `proc_macro::Literal`
46 //! simply cannot represent bool literals.
47 //!
48 //!
49 //! # Examples
50 //!
51 //! In a proc-macro:
52 //!
53 //! ```ignore
54 //! use std::convert::TryFrom;
55 //! use proc_macro::TokenStream;
56 //! use litrs::FloatLit;
57 //!
58 //! #[proc_macro]
59 //! pub fn foo(input: TokenStream) -> TokenStream {
60 //!      let mut input = input.into_iter().collect::<Vec<_>>();
61 //!      if input.len() != 1 {
62 //!          // Please do proper error handling in your real code!
63 //!          panic!("expected exactly one token as input");
64 //!      }
65 //!      let token = input.remove(0);
66 //!
67 //!      match FloatLit::try_from(token) {
68 //!          Ok(float_lit) => { /* do something */ }
69 //!          Err(e) => return e.to_compile_error(),
70 //!      }
71 //!
72 //!      // Dummy output
73 //!      TokenStream::new()
74 //! }
75 //! ```
76 //!
77 //! Parsing from string:
78 //!
79 //! ```
80 //! use litrs::{FloatLit, Literal};
81 //!
82 //! // Parse a specific kind of literal (float in this case):
83 //! let float_lit = FloatLit::parse("3.14f32");
84 //! assert!(float_lit.is_ok());
85 //! assert_eq!(float_lit.unwrap().type_suffix(), Some(litrs::FloatType::F32));
86 //! assert!(FloatLit::parse("'c'").is_err());
87 //!
88 //! // Parse any kind of literal. After parsing, you can inspect the literal
89 //! // and decide what to do in each case.
90 //! let lit = Literal::parse("0xff80").expect("failed to parse literal");
91 //! match lit {
92 //!     Literal::Integer(lit) => { /* ... */ }
93 //!     Literal::Float(lit) => { /* ... */ }
94 //!     Literal::Bool(lit) => { /* ... */ }
95 //!     Literal::Char(lit) => { /* ... */ }
96 //!     Literal::String(lit) => { /* ... */ }
97 //!     Literal::Byte(lit) => { /* ... */ }
98 //!     Literal::ByteString(lit) => { /* ... */ }
99 //! }
100 //! ```
101 //!
102 //!
103 //!
104 //! # Crate features
105 //!
106 //! - `proc-macro2` (**default**): adds the dependency `proc_macro2`, a bunch of
107 //!   `From` and `TryFrom` impls, and [`InvalidToken::to_compile_error2`].
108 //!
109 //!
110 //! [ref]: https://doc.rust-lang.org/reference/tokens.html#literals
111 //!
112 
113 #![deny(missing_debug_implementations)]
114 
115 extern crate proc_macro;
116 
117 #[cfg(test)]
118 #[macro_use]
119 mod test_util;
120 
121 #[cfg(test)]
122 mod tests;
123 
124 mod bool;
125 mod byte;
126 mod bytestr;
127 mod char;
128 mod err;
129 mod escape;
130 mod float;
131 mod impls;
132 mod integer;
133 mod parse;
134 mod string;
135 
136 
137 use std::{borrow::{Borrow, Cow}, fmt, ops::{Deref, Range}};
138 
139 pub use self::{
140     bool::BoolLit,
141     byte::ByteLit,
142     bytestr::ByteStringLit,
143     char::CharLit,
144     err::{InvalidToken, ParseError},
145     float::{FloatLit, FloatType},
146     integer::{FromIntegerLiteral, IntegerLit, IntegerBase, IntegerType},
147     string::StringLit,
148 };
149 
150 
151 // ==============================================================================================
152 // ===== `Literal` and type defs
153 // ==============================================================================================
154 
155 /// A literal which owns the underlying buffer.
156 pub type OwnedLiteral = Literal<String>;
157 
158 /// A literal whose underlying buffer is borrowed.
159 pub type SharedLiteral<'a> = Literal<&'a str>;
160 
161 /// A literal. This is the main type of this library.
162 ///
163 /// This type is generic over the underlying buffer `B`, which can be `&str` or
164 /// `String`. There are two useful type aliases: [`OwnedLiteral`] and
165 /// [`SharedLiteral`].
166 ///
167 /// To create this type, you have to either call [`Literal::parse`] with an
168 /// input string or use the `From<_>` impls of this type. The impls are only
169 /// available of the corresponding crate features are enabled (they are enabled
170 /// by default).
171 #[derive(Debug, Clone, PartialEq, Eq)]
172 pub enum Literal<B: Buffer> {
173     Bool(BoolLit),
174     Integer(IntegerLit<B>),
175     Float(FloatLit<B>),
176     Char(CharLit<B>),
177     String(StringLit<B>),
178     Byte(ByteLit<B>),
179     ByteString(ByteStringLit<B>),
180 }
181 
182 impl Literal<&str> {
183     /// Makes a copy of the underlying buffer and returns the owned version of
184     /// `Self`.
into_owned(self) -> OwnedLiteral185     pub fn into_owned(self) -> OwnedLiteral {
186         match self {
187             Literal::Bool(l) => Literal::Bool(l.to_owned()),
188             Literal::Integer(l) => Literal::Integer(l.to_owned()),
189             Literal::Float(l) => Literal::Float(l.to_owned()),
190             Literal::Char(l) => Literal::Char(l.to_owned()),
191             Literal::String(l) => Literal::String(l.into_owned()),
192             Literal::Byte(l) => Literal::Byte(l.to_owned()),
193             Literal::ByteString(l) => Literal::ByteString(l.into_owned()),
194         }
195     }
196 }
197 
198 impl<B: Buffer> fmt::Display for Literal<B> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result199     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
200         match self {
201             Literal::Bool(l) => l.fmt(f),
202             Literal::Integer(l) => l.fmt(f),
203             Literal::Float(l) => l.fmt(f),
204             Literal::Char(l) => l.fmt(f),
205             Literal::String(l) => l.fmt(f),
206             Literal::Byte(l) => l.fmt(f),
207             Literal::ByteString(l) => l.fmt(f),
208         }
209     }
210 }
211 
212 
213 // ==============================================================================================
214 // ===== Buffer
215 // ==============================================================================================
216 
217 /// A shared or owned string buffer. Implemented for `String` and `&str`. *Implementation detail*.
218 ///
219 /// This is trait is implementation detail of this library, cannot be
220 /// implemented in other crates and is not subject to semantic versioning.
221 /// `litrs` only gurantees that this trait is implemented for `String` and
222 /// `for<'a> &'a str`.
223 pub trait Buffer: sealed::Sealed + Deref<Target = str> {
224     /// This is `Cow<'static, str>` for `String`, and `Cow<'a, str>` for `&'a str`.
225     type Cow: From<String> + AsRef<str> + Borrow<str> + Deref<Target = str>;
226 
227     #[doc(hidden)]
into_cow(self) -> Self::Cow228     fn into_cow(self) -> Self::Cow;
229 
230     /// This is `Cow<'static, [u8]>` for `String`, and `Cow<'a, [u8]>` for `&'a str`.
231     type ByteCow: From<Vec<u8>> + AsRef<[u8]> + Borrow<[u8]> + Deref<Target = [u8]>;
232 
233     #[doc(hidden)]
into_byte_cow(self) -> Self::ByteCow234     fn into_byte_cow(self) -> Self::ByteCow;
235 
236     /// Cuts away some characters at the beginning and some at the end. Given
237     /// range has to be in bounds.
238     #[doc(hidden)]
cut(self, range: Range<usize>) -> Self239     fn cut(self, range: Range<usize>) -> Self;
240 }
241 
242 mod sealed {
243     pub trait Sealed {}
244 }
245 
246 impl<'a> sealed::Sealed for &'a str {}
247 impl<'a> Buffer for &'a str {
248     #[doc(hidden)]
cut(self, range: Range<usize>) -> Self249     fn cut(self, range: Range<usize>) -> Self {
250         &self[range]
251     }
252 
253     type Cow = Cow<'a, str>;
254     #[doc(hidden)]
into_cow(self) -> Self::Cow255     fn into_cow(self) -> Self::Cow {
256         self.into()
257     }
258     type ByteCow = Cow<'a, [u8]>;
259     #[doc(hidden)]
into_byte_cow(self) -> Self::ByteCow260     fn into_byte_cow(self) -> Self::ByteCow {
261         self.as_bytes().into()
262     }
263 }
264 
265 impl sealed::Sealed for String {}
266 impl Buffer for String {
267     #[doc(hidden)]
cut(mut self, range: Range<usize>) -> Self268     fn cut(mut self, range: Range<usize>) -> Self {
269         // This is not the most efficient way, but it works. First we cut the
270         // end, then the beginning. Note that `drain` also removes the range if
271         // the iterator is not consumed.
272         self.truncate(range.end);
273         self.drain(..range.start);
274         self
275     }
276 
277     type Cow = Cow<'static, str>;
278     #[doc(hidden)]
into_cow(self) -> Self::Cow279     fn into_cow(self) -> Self::Cow {
280         self.into()
281     }
282 
283     type ByteCow = Cow<'static, [u8]>;
284     #[doc(hidden)]
into_byte_cow(self) -> Self::ByteCow285     fn into_byte_cow(self) -> Self::ByteCow {
286         self.into_bytes().into()
287     }
288 }
289