1#![cfg_attr(
11 feature = "docs",
12 cfg_attr(doc, doc = ::document_features::document_features!(feature_label = r#"<span class="stab portability"><code>{feature}</code></span>"#))
13)]
14#![cfg_attr(all(doc, CHANNEL_NIGHTLY), feature(doc_auto_cfg))]
15#![warn(rust_2018_idioms)]
16#![deny(missing_docs)]
17
18mod display;
19mod error;
20mod lex;
21mod parser;
22
23use std::{
24 borrow::Cow,
25 fmt::{self, Display, Formatter},
26 ops::{Deref, DerefMut},
27};
28
29pub use error::*;
30use lex::Token;
31use parser::Parser;
32
33pub fn from_slice(input: &(impl AsRef<[u8]> + ?Sized)) -> Result<Sexpr<'_>> {
50 let (mut sexprs, mut errors) = Parser::parse(lex::lex(input.as_ref()));
51 if sexprs.len() > 1 {
52 errors.push(Error::ExtraSexprs);
53 }
54 match errors.is_empty() {
55 true => match sexprs.is_empty() {
56 true => Err(vec![Error::EmptyInput]),
57 false => Ok(sexprs.swap_remove(0)),
58 },
59 false => Err(errors),
60 }
61}
62
63pub fn from_slice_multi(input: &(impl AsRef<[u8]> + ?Sized)) -> Result<Sexprs<'_>> {
78 let (sexprs, errors) = Parser::parse(lex::lex(input.as_ref()));
79 match errors.is_empty() {
80 true => Ok(sexprs),
81 false => Err(errors),
82 }
83}
84
85#[derive(Debug, Clone, Hash, PartialEq, Eq)]
88pub struct Sexprs<'src>(Vec<Sexpr<'src>>);
89
90#[derive(Debug, Clone, Hash, PartialEq, Eq)]
93pub struct OwnedSexprs(Vec<OwnedSexpr>);
94
95#[derive(Debug, Clone, Hash, PartialEq, Eq)]
124pub enum Sexpr<'src> {
125 List(Sexprs<'src>),
127 Group(Sexprs<'src>),
129 String(Cow<'src, [u8]>),
131 Atom(&'src [u8]),
133 #[cfg(feature = "comments")]
135 Comment(&'src [u8]),
136}
137
138#[derive(Debug, Clone, Hash, PartialEq, Eq)]
164pub enum OwnedSexpr {
165 List(OwnedSexprs),
167 Group(OwnedSexprs),
169 String(Vec<u8>),
171 Atom(Vec<u8>),
173 #[cfg(feature = "comments")]
175 Comment(Vec<u8>),
176}
177
178impl<'src> Deref for Sexprs<'src> {
183 type Target = Vec<Sexpr<'src>>;
184
185 fn deref(&self) -> &Self::Target {
186 &self.0
187 }
188}
189
190impl Deref for OwnedSexprs {
191 type Target = Vec<OwnedSexpr>;
192
193 fn deref(&self) -> &Self::Target {
194 &self.0
195 }
196}
197
198impl DerefMut for Sexprs<'_> {
199 fn deref_mut(&mut self) -> &mut Self::Target {
200 &mut self.0
201 }
202}
203
204impl DerefMut for OwnedSexprs {
205 fn deref_mut(&mut self) -> &mut Self::Target {
206 &mut self.0
207 }
208}
209
210impl<'src> FromIterator<Sexpr<'src>> for Sexprs<'src> {
211 fn from_iter<T: IntoIterator<Item = Sexpr<'src>>>(iter: T) -> Self {
212 Self(Vec::from_iter(iter))
213 }
214}
215
216impl FromIterator<OwnedSexpr> for OwnedSexprs {
217 fn from_iter<T: IntoIterator<Item = OwnedSexpr>>(iter: T) -> Self {
218 Self(Vec::from_iter(iter))
219 }
220}
221
222impl<'src> IntoIterator for Sexprs<'src> {
223 type Item = Sexpr<'src>;
224 type IntoIter = std::vec::IntoIter<Sexpr<'src>>;
225
226 fn into_iter(self) -> Self::IntoIter {
227 self.0.into_iter()
228 }
229}
230
231impl IntoIterator for OwnedSexprs {
232 type Item = OwnedSexpr;
233 type IntoIter = std::vec::IntoIter<OwnedSexpr>;
234
235 fn into_iter(self) -> Self::IntoIter {
236 self.0.into_iter()
237 }
238}
239
240impl<'a, 'src> IntoIterator for &'a Sexprs<'src> {
241 type Item = &'a Sexpr<'src>;
242 type IntoIter = std::slice::Iter<'a, Sexpr<'src>>;
243
244 fn into_iter(self) -> Self::IntoIter {
245 self.0.iter()
246 }
247}
248
249impl<'a> IntoIterator for &'a OwnedSexprs {
250 type Item = &'a OwnedSexpr;
251 type IntoIter = std::slice::Iter<'a, OwnedSexpr>;
252
253 fn into_iter(self) -> Self::IntoIter {
254 self.0.iter()
255 }
256}
257
258impl<'a, 'src> IntoIterator for &'a mut Sexprs<'src> {
259 type Item = &'a mut Sexpr<'src>;
260 type IntoIter = std::slice::IterMut<'a, Sexpr<'src>>;
261
262 fn into_iter(self) -> Self::IntoIter {
263 self.0.iter_mut()
264 }
265}
266
267impl<'a> IntoIterator for &'a mut OwnedSexprs {
268 type Item = &'a mut OwnedSexpr;
269 type IntoIter = std::slice::IterMut<'a, OwnedSexpr>;
270
271 fn into_iter(self) -> Self::IntoIter {
272 self.0.iter_mut()
273 }
274}
275
276impl<'a> From<&'a OwnedSexprs> for Sexprs<'a> {
277 fn from(value: &'a OwnedSexprs) -> Self {
278 value.iter().map(Sexpr::from).collect()
279 }
280}
281
282impl From<Sexprs<'_>> for OwnedSexprs {
283 fn from(value: Sexprs<'_>) -> Self {
284 value.into_iter().map(OwnedSexpr::from).collect()
285 }
286}
287
288impl<'src> From<Vec<Sexpr<'src>>> for Sexprs<'src> {
289 fn from(value: Vec<Sexpr<'src>>) -> Self {
290 Self(value)
291 }
292}
293
294impl From<Vec<OwnedSexpr>> for OwnedSexprs {
295 fn from(value: Vec<OwnedSexpr>) -> Self {
296 Self(value)
297 }
298}
299
300impl Default for Sexprs<'_> {
301 fn default() -> Self {
302 Self::new()
303 }
304}
305
306impl Default for OwnedSexprs {
307 fn default() -> Self {
308 Self::new()
309 }
310}
311
312impl<'a> From<&'a OwnedSexpr> for Sexpr<'a> {
313 fn from(value: &'a OwnedSexpr) -> Self {
314 match value {
315 OwnedSexpr::List(list) => Self::List(list.into()),
316 OwnedSexpr::Group(group) => Self::Group(group.iter().map(Sexpr::from).collect()),
317 OwnedSexpr::String(string) => Self::String(Cow::Borrowed(string)),
318 OwnedSexpr::Atom(atom) => Self::Atom(atom),
319 #[cfg(feature = "comments")]
320 OwnedSexpr::Comment(comment) => Self::Comment(comment),
321 }
322 }
323}
324
325impl From<Sexpr<'_>> for OwnedSexpr {
326 fn from(value: Sexpr<'_>) -> Self {
327 match value {
328 Sexpr::List(list) => Self::List(list.into()),
329 Sexpr::Group(group) => Self::Group(group.into()),
330 Sexpr::String(string) => Self::String(string.into_owned()),
331 Sexpr::Atom(atom) => Self::Atom(atom.to_vec()),
332 #[cfg(feature = "comments")]
333 Sexpr::Comment(comment) => Self::Comment(comment.to_vec()),
334 }
335 }
336}
337
338impl Sexprs<'_> {
343 pub fn new() -> Self {
345 Self(vec![])
346 }
347}
348
349impl OwnedSexprs {
350 pub fn new() -> Self {
352 Self(vec![])
353 }
354}
355
356macro_rules! impl_unwrap {
357 ($type:ident, $func_name:ident, $func_name_ref:ident, $variant:ident, $result:ty, $name:literal) => {
358 #[doc = concat!("Returns the contained [`", stringify!($variant), "`](", stringify!($type), "::", stringify!($variant), ") value, consuming `self`.")]
359 #[doc = ""]
360 #[doc = "## Panics"]
361 #[doc = concat!("Panics if `self` is not [`", stringify!($variant), "`](", stringify!($type), "::", stringify!($variant), ").")]
362 pub fn $func_name(self) -> $result {
363 match self {
364 $type::$variant(val) => val,
365 other => panic!(
366 concat!(
367 "called `",
368 stringify!($type),
369 "::",
370 stringify!($func_name),
371 "()` on a non-",
372 $name,
373 " value: {}"
374 ),
375 other
376 ),
377 }
378 }
379
380 #[doc = concat!("Returns the contained [`", stringify!($variant), "`](", stringify!($type), "::", stringify!($variant), ") value by reference.")]
381 #[doc = ""]
382 #[doc = "## Panics"]
383 #[doc = concat!("Panics if `self` is not [`", stringify!($variant), "`](", stringify!($type), "::", stringify!($variant), ").")]
384 pub fn $func_name_ref(&self) -> &$result {
385 match self {
386 $type::$variant(val) => val,
387 other => panic!(
388 concat!(
389 "called `",
390 stringify!($type),
391 "::",
392 stringify!($func_name_ref),
393 "()` on a non-",
394 $name,
395 " value: {}"
396 ),
397 other
398 ),
399 }
400 }
401 };
402}
403
404impl<'src> Sexpr<'src> {
405 impl_unwrap!(
406 Sexpr,
407 unwrap_list,
408 unwrap_list_ref,
409 List,
410 Sexprs<'src>,
411 "list"
412 );
413 impl_unwrap!(
414 Sexpr,
415 unwrap_group,
416 unwrap_group_ref,
417 Group,
418 Sexprs<'src>,
419 "group"
420 );
421 impl_unwrap!(
422 Sexpr,
423 unwrap_string,
424 unwrap_string_ref,
425 String,
426 Cow<'src, [u8]>,
427 "string"
428 );
429 impl_unwrap!(
430 Sexpr,
431 unwrap_atom,
432 unwrap_atom_ref,
433 Atom,
434 &'src [u8],
435 "atom"
436 );
437}
438
439impl OwnedSexpr {
440 impl_unwrap!(
441 OwnedSexpr,
442 unwrap_list,
443 unwrap_list_ref,
444 List,
445 OwnedSexprs,
446 "list"
447 );
448 impl_unwrap!(
449 OwnedSexpr,
450 unwrap_group,
451 unwrap_group_ref,
452 Group,
453 OwnedSexprs,
454 "group"
455 );
456 impl_unwrap!(
457 OwnedSexpr,
458 unwrap_string,
459 unwrap_string_ref,
460 String,
461 Vec<u8>,
462 "string"
463 );
464 impl_unwrap!(
465 OwnedSexpr,
466 unwrap_atom,
467 unwrap_atom_ref,
468 Atom,
469 Vec<u8>,
470 "atom"
471 );
472}
473
474#[derive(Debug, Clone, PartialEq, Eq)]
477pub enum ParenKind {
478 Round,
480 Square,
482}
483
484impl From<&ParenKind> for Token<'_> {
485 fn from(value: &ParenKind) -> Self {
486 match value {
487 ParenKind::Round => Self::RParen,
488 ParenKind::Square => Self::RBrack,
489 }
490 }
491}
492
493impl Display for ParenKind {
494 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
495 match self {
496 Self::Round => write!(f, ")"),
497 Self::Square => write!(f, "]"),
498 }
499 }
500}