lexpr/value/mod.rs
1//! The Value enum, a dynamically typed way of representing any valid S-expression value.
2//!
3//! # Constructing S-Expressions
4//!
5//! Lexpr provides a [`sexp!` macro][macro] to build `lexpr::Value`
6//! objects with very natural S-expression syntax.
7//!
8//! ```
9//! use lexpr::sexp;
10//!
11//! // The type of `john` is `lexpr::Value`
12//! let john = sexp!((
13//! (name . "John Doe")
14//! (age . 43)
15//! (phones "+44 1234567" "+44 2345678")
16//! ));
17//!
18//! println!("first phone number: {}", john["phones"][0]);
19//!
20//! // Convert to a string of S-expression data and print it out
21//! println!("{}", john.to_string());
22//! ```
23//!
24//! The `Value::to_string()` function converts a `lexpr::Value` into a
25//! `String` of S-expression text.
26//!
27//! One neat thing about the `sexp!` macro is that variables and
28//! expressions can be interpolated directly into the S-expression
29//! value as you are building it. The macro will check at compile time
30//! that the value you are interpolating is able to be represented as
31//! S-expression data.
32//!
33//! To interpolate, use the comma (`,`, also known as "unqote" in
34//! Lisp). The interpolated expression must either be a single token,
35//! or surrounded by round or curly braces.
36//!
37//! ```
38//! # use lexpr::sexp;
39//! #
40//! # fn random_phone() -> u16 { 0 }
41//! #
42//! let full_name = "John Doe";
43//! let age_last_year = 42;
44//!
45//! // The type of `john` is `lexpr::Value`
46//! let john = sexp!((
47//! (name . ,full_name)
48//! (age . ,(age_last_year + 1))
49//! (phones ,{ format!("+44 {}", random_phone()) })
50//! ));
51//! ```
52//!
53//! A string of S-expression data can be parsed into a `lexpr::Value` by the
54//! [`lexpr::from_str`][from_str] function. There is also
55//! [`from_slice`][from_slice] for parsing from a byte slice `&[u8]` and
56//! [`from_reader`][from_reader] for parsing from any `io::Read` like a file or
57//! a TCP stream. For all these functions there also is a `_custom` variant
58//! which allows for specifying parser options, in case the input deviates from
59//! the `lexpr` default behavior.
60//!
61//! ```
62//! use lexpr::{sexp, parse::Error, Value};
63//!
64//! # fn main() -> Result<(), Error> {
65//! // Some S-expression input data as a &str. Maybe this comes from the user.
66//! let data = r#"(
67//! (name . "John Doe")
68//! (age . 43)
69//! (phones . (
70//! "+44 1234567"
71//! "+44 2345678"
72//! ))
73//! )"#;
74//!
75//! // Parse the string of data into lexpr::Value.
76//! let v: Value = lexpr::from_str(data)?;
77//!
78//! // Access parts of the data by indexing with square brackets.
79//! println!("Please call {} at the number {}", v["name"], v["phones"][0]);
80//! # Ok(())
81//! # }
82//! ```
83//!
84//! [macro]: ../macro.sexp.html
85//! [from_str]: ../parse/fn.from_str.html
86//! [from_slice]: ../parse/fn.from_slice.html
87//! [from_reader]: ../parse/fn.from_reader.html
88
89use std::fmt;
90use std::io;
91use std::str;
92
93use crate::cons::{self, Cons};
94use crate::number::Number;
95
96pub use self::index::Index;
97
98/// Represents an S-expression value.
99///
100/// See the [`lexpr::value`] module documentation for usage examples.
101///
102/// [`lexpr::value`]: index.html
103#[derive(Debug, PartialEq, Clone)]
104pub enum Value {
105 /// The special "nil" value.
106 ///
107 /// This is kind of an oddball value. In traditional Lisps (e.g., Common
108 /// Lisp or Emacs Lisp) the empty list can be written as the symbol `nil`,
109 /// while in Scheme, `nil` is just a regular symbol. Furthermore,
110 /// traditional Lisps don't have a separate boolean data type, and represent
111 /// true and false by the symbols `t` and `nil` instead. The `lexpr` parser
112 /// can be instructed to parse the `nil` symbol as the `Nil` value (see
113 /// [`NilSymbol::Special`]), allowing to choose its representation when
114 /// converting to text again (see [`NilSyntax`]). Note that the empty list,
115 /// when written as `()` or implicitly constructed as a list terminator, is
116 /// always parsed as [`Value::Null`], not `Value::Nil`.
117 ///
118 /// In addition to being useful for conversions between S-expression
119 /// variants, this value is also potentially returned when using the square
120 /// bracket indexing operator on `Value`.
121 ///
122 /// [`NilSymbol::Special`]: crate::parse::NilSymbol::Special
123 /// [`NilSyntax`]: ../print/enum.NilSyntax.html
124 Nil,
125
126 /// The empty list.
127 ///
128 /// This value terminates a chain of cons cells forming a proper list.
129 Null,
130
131 /// A boolean value.
132 Bool(bool),
133
134 /// A number.
135 Number(Number),
136
137 /// A character.
138 Char(char),
139
140 /// A string.
141 String(Box<str>),
142
143 /// A symbol.
144 Symbol(Box<str>),
145
146 /// A keyword.
147 Keyword(Box<str>),
148
149 /// A byte vector.
150 Bytes(Box<[u8]>),
151
152 /// Represents a Lisp "cons cell".
153 ///
154 /// Cons cells are often used to form singly-linked lists.
155 /// ```
156 /// # use lexpr::sexp;
157 /// let v = sexp!((a list 1 2 3));
158 /// assert!(v.is_cons());
159 /// assert_eq!(v[4], sexp!(3));
160 /// ```
161 Cons(Cons),
162
163 /// A Lisp vector.
164 Vector(Box<[Value]>),
165}
166
167impl Value {
168 /// Construct a symbol, given its name.
169 pub fn symbol(name: impl Into<Box<str>>) -> Self {
170 Value::Symbol(name.into())
171 }
172
173 /// Construct a keyword, given its name.
174 ///
175 /// ```
176 /// # use lexpr::Value;
177 /// let value = Value::keyword("foo");
178 /// assert!(value.is_keyword());
179 /// assert_eq!(value.as_keyword().unwrap(), "foo");
180 /// ```
181 pub fn keyword(name: impl Into<Box<str>>) -> Self {
182 Value::Keyword(name.into())
183 }
184
185 /// Construct a string.
186 ///
187 /// ```
188 /// # use lexpr::Value;
189 /// let value = Value::string("foo");
190 /// assert!(value.is_string());
191 /// assert_eq!(value.as_str().unwrap(), "foo");
192 /// ```
193 pub fn string(s: impl Into<Box<str>>) -> Self {
194 Value::String(s.into())
195 }
196
197 /// Construct a byte vector.
198 ///
199 /// ```
200 /// # use lexpr::Value;
201 /// let value = Value::bytes(b"foo" as &[u8]);
202 /// assert!(value.is_bytes());
203 /// assert_eq!(value.as_bytes().unwrap(), b"foo");
204 /// ```
205 pub fn bytes(bv: impl Into<Box<[u8]>>) -> Self {
206 Value::Bytes(bv.into())
207 }
208
209 /// Create a cons cell given its `car` and `cdr` fields.
210 ///
211 /// ```
212 /// # use lexpr::Value;
213 /// let value = Value::cons(1, Value::Null);
214 /// assert!(value.is_cons());
215 /// assert_eq!(value.as_pair().unwrap(), (&Value::from(1), &Value::Null));
216 /// ```
217 ///
218 /// Note that you can also construct a cons cell from a Rust pair via the
219 /// `From` trait:
220 ///
221 /// ```
222 /// # use lexpr::Value;
223 /// let value = Value::from((42, "answer"));
224 /// assert!(value.is_cons());
225 /// assert_eq!(value.as_pair().unwrap(), (&Value::from(42), &Value::string("answer")));
226 /// ```
227 pub fn cons<T, U>(car: T, cdr: U) -> Self
228 where
229 T: Into<Value>,
230 U: Into<Value>,
231 {
232 Value::Cons(Cons::new(car, cdr))
233 }
234
235 /// Create a list value from elements convertible into `Value`.
236 ///
237 /// ```
238 /// # use lexpr::{sexp, Value};
239 /// assert_eq!(Value::list(vec![1, 2, 3]), sexp!((1 2 3)));
240 /// ```
241 pub fn list<I>(elements: I) -> Self
242 where
243 I: IntoIterator,
244 I::Item: Into<Value>,
245 {
246 Self::append(elements, Value::Null)
247 }
248
249 /// Returns true if the value is a (proper) list.
250 pub fn is_list(&self) -> bool {
251 match self {
252 Value::Null => true,
253 Value::Cons(pair) => pair
254 .iter()
255 .all(|p| matches!(p.cdr(), Value::Null | Value::Cons(_))),
256 _ => false,
257 }
258 }
259
260 /// Returns true if the value is a dotted (improper) list.
261 ///
262 /// Note that all values that are not pairs are considered dotted lists.
263 ///
264 /// ```
265 /// # use lexpr::{sexp, Value};
266 /// let list = sexp!((1 2 3));
267 /// assert!(!list.is_dotted_list());
268 /// let dotted = sexp!((1 2 . 3));
269 /// assert!(dotted.is_dotted_list());
270 /// ```
271 pub fn is_dotted_list(&self) -> bool {
272 match self {
273 Value::Null => false,
274 Value::Cons(pair) => pair.iter().all(|p| !matches!(p.cdr(), Value::Null)),
275 _ => true,
276 }
277 }
278
279 /// Create a list value from elements convertible into `Value`, using a
280 /// given value as a tail.
281 ///
282 /// ```
283 /// # use lexpr::{sexp, Value};
284 /// assert_eq!(Value::append(vec![1u32, 2], 3), sexp!((1 2 . 3)));
285 /// assert_eq!(Value::append(vec![1u32, 2, 3], sexp!((4 5))), sexp!((1 2 3 4 5)));
286 /// ```
287 pub fn append<I, T>(elements: I, tail: T) -> Self
288 where
289 I: IntoIterator,
290 I::Item: Into<Value>,
291 T: Into<Value>,
292 {
293 let mut list = Cons::new(Value::Nil, Value::Null);
294 let mut pair = &mut list;
295 let mut have_value = false;
296 for item in elements {
297 if have_value {
298 pair.set_cdr(Value::from((Value::Nil, Value::Null)));
299 pair = pair.cdr_mut().as_cons_mut().unwrap();
300 }
301 pair.set_car(item.into());
302 have_value = true;
303 }
304 if have_value {
305 pair.set_cdr(tail.into());
306 Value::Cons(list)
307 } else {
308 tail.into()
309 }
310 }
311
312 /// Create a vector value from elements convertible into `Value`.
313 ///
314 /// ```
315 /// # use lexpr::{sexp, Value};
316 /// assert_eq!(Value::vector(vec![1u32, 2, 3]), sexp!(#(1 2 3)));
317 /// ```
318 pub fn vector<I>(elements: I) -> Self
319 where
320 I: IntoIterator,
321 I::Item: Into<Value>,
322 {
323 let v: Vec<_> = elements.into_iter().map(Into::into).collect();
324 Value::Vector(v.into_boxed_slice())
325 }
326
327 /// Returns true if the value is a String. Returns false otherwise.
328 ///
329 /// For any Value on which `is_string` returns true, `as_str` is guaranteed
330 /// to return the string slice.
331 ///
332 /// ```
333 /// # use lexpr::sexp;
334 /// #
335 /// let v = sexp!(((a . "some string") (b . #f)));
336 ///
337 /// assert!(v["a"].is_string());
338 ///
339 /// // The boolean `false` is not a string.
340 /// assert!(!v["b"].is_string());
341 /// ```
342 pub fn is_string(&self) -> bool {
343 self.as_str().is_some()
344 }
345
346 /// If the value is a String, returns the associated str. Returns `None`
347 /// otherwise.
348 ///
349 /// ```
350 /// # use lexpr::sexp;
351 /// #
352 /// let v = sexp!(((a . "some string") (b . #f)));
353 ///
354 /// assert_eq!(v["a"].as_str(), Some("some string"));
355 ///
356 /// // The boolean `false` is not a string.
357 /// assert_eq!(v["b"].as_str(), None);
358 ///
359 /// // S-expression values are printed in S-expression
360 /// // representation, so strings are in quotes.
361 /// // The value is: "some string"
362 /// println!("The value is: {}", v["a"]);
363 ///
364 /// // Rust strings are printed without quotes.
365 /// //
366 /// // The value is: some string
367 /// println!("The value is: {}", v["a"].as_str().unwrap());
368 /// ```
369 pub fn as_str(&self) -> Option<&str> {
370 match self {
371 Value::String(s) => Some(s),
372 _ => None,
373 }
374 }
375
376 /// Returns true if the value is a symbol. Returns false otherwise.
377 ///
378 /// For any Value on which `is_symbol` returns true, `as_symbol` is guaranteed
379 /// to return the string slice.
380 ///
381 /// ```
382 /// # use lexpr::sexp;
383 /// #
384 /// let v = sexp!((#:foo bar "baz"));
385 ///
386 /// assert!(v[1].is_symbol());
387 ///
388 /// // Keywords and strings are not symbols.
389 /// assert!(!v[0].is_symbol());
390 /// assert!(!v[2].is_symbol());
391 /// ```
392 pub fn is_symbol(&self) -> bool {
393 self.as_symbol().is_some()
394 }
395
396 /// If the value is a symbol, returns the associated str. Returns `None`
397 /// otherwise.
398 ///
399 /// ```
400 /// # use lexpr::sexp;
401 /// #
402 /// let v = sexp!(foo);
403 ///
404 /// assert_eq!(v.as_symbol(), Some("foo"));
405 /// ```
406 pub fn as_symbol(&self) -> Option<&str> {
407 match self {
408 Value::Symbol(s) => Some(s),
409 _ => None,
410 }
411 }
412
413 /// Returns true if the value is a keyword. Returns false otherwise.
414 ///
415 /// For any Value on which `is_keyword` returns true, `as_keyword` is guaranteed
416 /// to return the string slice.
417 ///
418 /// ```
419 /// # use lexpr::sexp;
420 /// #
421 /// let v = sexp!((#:foo bar "baz"));
422 ///
423 /// assert!(v[0].is_keyword());
424 ///
425 /// // Symbols and strings are not keywords.
426 /// assert!(!v[1].is_keyword());
427 /// assert!(!v[2].is_keyword());
428 /// ```
429 pub fn is_keyword(&self) -> bool {
430 self.as_keyword().is_some()
431 }
432
433 /// If the value is a keyword, returns the associated str. Returns `None`
434 /// otherwise.
435 ///
436 /// ```
437 /// # use lexpr::sexp;
438 /// #
439 /// let v = sexp!(#:foo);
440 ///
441 /// assert_eq!(v.as_keyword(), Some("foo"));
442 /// ```
443 pub fn as_keyword(&self) -> Option<&str> {
444 match self {
445 Value::Keyword(s) => Some(s),
446 _ => None,
447 }
448 }
449
450 /// Get the name of a symbol or keyword, or the value of a string.
451 ///
452 /// This is useful if symbols, keywords and strings need to be treated
453 /// equivalently in some context.
454 ///
455 /// ```
456 /// # use lexpr::sexp;
457 /// #
458 /// let kw = sexp!(#:foo);
459 /// assert_eq!(kw.as_name(), Some("foo"));
460 ///
461 /// let sym = sexp!(bar);
462 /// assert_eq!(sym.as_name(), Some("bar"));
463 ///
464 /// let s = sexp!("baz");
465 /// assert_eq!(s.as_name(), Some("baz"));
466 /// ```
467 pub fn as_name(&self) -> Option<&str> {
468 match self {
469 Value::Symbol(s) => Some(s),
470 Value::Keyword(s) => Some(s),
471 Value::String(s) => Some(s),
472 _ => None,
473 }
474 }
475
476 /// Returns true if the value is a byte vector. Returns false otherwise.
477 ///
478 /// For any Value on which `is_bytes` returns true, `as_bytes` is guaranteed
479 /// to return the byte slice.
480 ///
481 /// ```
482 /// # use lexpr::sexp;
483 /// #
484 /// let v = sexp!(((a . ,(b"some bytes" as &[u8])) (b . "string")));
485 ///
486 /// assert!(v["a"].is_bytes());
487 ///
488 /// // A string is not a byte vector.
489 /// assert!(!v["b"].is_bytes());
490 /// ```
491 pub fn is_bytes(&self) -> bool {
492 self.as_bytes().is_some()
493 }
494
495 /// If the value is a byte vector, returns the associated byte
496 /// slice. Returns `None` otherwise.
497 ///
498 /// ```
499 /// # use lexpr::sexp;
500 /// #
501 /// let v = sexp!(((a . ,(b"some bytes" as &[u8])) (b . "string")));
502 ///
503 /// assert_eq!(v["a"].as_bytes(), Some(b"some bytes" as &[u8]));
504 ///
505 /// // A string is not a byte vector.
506 /// assert_eq!(v["b"].as_bytes(), None);
507 /// ```
508 pub fn as_bytes(&self) -> Option<&[u8]> {
509 match self {
510 Value::Bytes(s) => Some(s),
511 _ => None,
512 }
513 }
514
515 /// Return `true` if the value is a number.
516 pub fn is_number(&self) -> bool {
517 self.as_number().is_some()
518 }
519
520 /// For numbers, return a reference to them. For other values, return
521 /// `None`.
522 pub fn as_number(&self) -> Option<&Number> {
523 match self {
524 Value::Number(n) => Some(n),
525 _ => None,
526 }
527 }
528
529 /// Returns true if the value is an integer between `i64::MIN` and
530 /// `i64::MAX`.
531 ///
532 /// For any Value on which `is_i64` returns true, `as_i64` is guaranteed to
533 /// return the integer value.
534 ///
535 /// ```
536 /// # use lexpr::sexp;
537 /// #
538 /// let big = i64::max_value() as u64 + 10;
539 /// let v = sexp!(((a . 64) (b . ,big) (c . 256.0)));
540 ///
541 /// assert!(v["a"].is_i64());
542 ///
543 /// // Greater than i64::MAX.
544 /// assert!(!v["b"].is_i64());
545 ///
546 /// // Numbers with a decimal point are not considered integers.
547 /// assert!(!v["c"].is_i64());
548 /// ```
549 pub fn is_i64(&self) -> bool {
550 match self.as_number() {
551 Some(n) => n.is_i64(),
552 _ => false,
553 }
554 }
555
556 /// Returns true if the value is an integer between zero and `u64::MAX`.
557 ///
558 /// For any Value on which `is_u64` returns true, `as_u64` is guaranteed to
559 /// return the integer value.
560 ///
561 /// ```
562 /// # use lexpr::sexp;
563 /// #
564 /// let v = sexp!(((a . 64) (b . -64) (c . 256.0)));
565 ///
566 /// assert!(v["a"].is_u64());
567 ///
568 /// // Negative integer.
569 /// assert!(!v["b"].is_u64());
570 ///
571 /// // Numbers with a decimal point are not considered integers.
572 /// assert!(!v["c"].is_u64());
573 /// ```
574 pub fn is_u64(&self) -> bool {
575 match self.as_number() {
576 Some(n) => n.is_u64(),
577 _ => false,
578 }
579 }
580
581 /// Returns true if the value is a number that can be represented by f64.
582 ///
583 /// For any Value on which `is_f64` returns true, `as_f64` is guaranteed to
584 /// return the floating point value.
585 ///
586 /// Currently this function returns true if and only if both `is_i64` and
587 /// `is_u64` return false but this is not a guarantee in the future.
588 ///
589 /// ```
590 /// # use lexpr::sexp;
591 /// #
592 /// let v = sexp!(((a . 256.0) (b . 64) (c . -64)));
593 ///
594 /// assert!(v["a"].is_f64());
595 ///
596 /// // Integers.
597 /// assert!(!v["b"].is_f64());
598 /// assert!(!v["c"].is_f64());
599 /// ```
600 #[inline]
601 pub fn is_f64(&self) -> bool {
602 match self.as_number() {
603 Some(n) => n.is_f64(),
604 _ => false,
605 }
606 }
607
608 /// If the value is an integer, represent it as i64 if possible. Returns
609 /// None otherwise.
610 ///
611 /// ```
612 /// # use lexpr::sexp;
613 /// #
614 /// let big = i64::max_value() as u64 + 10;
615 /// let v = sexp!(((a . 64) (b . ,big) (c . 256.0)));
616 ///
617 /// assert_eq!(v["a"].as_i64(), Some(64));
618 /// assert_eq!(v["b"].as_i64(), None);
619 /// assert_eq!(v["c"].as_i64(), None);
620 /// ```
621 #[inline]
622 pub fn as_i64(&self) -> Option<i64> {
623 self.as_number().and_then(Number::as_i64)
624 }
625
626 /// If the value is an integer, represent it as u64 if possible. Returns
627 /// None otherwise.
628 ///
629 /// ```
630 /// # use lexpr::sexp;
631 /// #
632 /// let v = sexp!(((a . 64) (b . -64) (c . 256.0)));
633 ///
634 /// assert_eq!(v["a"].as_u64(), Some(64));
635 /// assert_eq!(v["b"].as_u64(), None);
636 /// assert_eq!(v["c"].as_u64(), None);
637 /// ```
638 pub fn as_u64(&self) -> Option<u64> {
639 self.as_number().and_then(Number::as_u64)
640 }
641
642 /// If the value is a number, represent it as f64 if possible. Returns
643 /// None otherwise.
644 ///
645 /// ```
646 /// # use lexpr::sexp;
647 /// #
648 /// let v = sexp!(((a . 256.0) (b . 64) (c . -64)));
649 ///
650 /// assert_eq!(v["a"].as_f64(), Some(256.0));
651 /// assert_eq!(v["b"].as_f64(), Some(64.0));
652 /// assert_eq!(v["c"].as_f64(), Some(-64.0));
653 /// ```
654 pub fn as_f64(&self) -> Option<f64> {
655 self.as_number().and_then(Number::as_f64)
656 }
657
658 /// Returns true if the value is a Boolean. Returns false otherwise.
659 ///
660 /// For any Value on which `is_boolean` returns true, `as_bool` is
661 /// guaranteed to return the boolean value.
662 ///
663 /// ```
664 /// # use lexpr::sexp;
665 /// #
666 /// let v = sexp!(((a . #f) (b . #nil)));
667 ///
668 /// assert!(v["a"].is_boolean());
669 ///
670 /// // The nil value is special, and not a boolean.
671 /// assert!(!v["b"].is_boolean());
672 /// ```
673 pub fn is_boolean(&self) -> bool {
674 self.as_bool().is_some()
675 }
676
677 /// If the value is a `Boolean`, returns the associated bool. Returns None
678 /// otherwise.
679 ///
680 /// ```
681 /// # use lexpr::sexp;
682 /// #
683 /// let v = sexp!(((a . #f) (b . "false")));
684 ///
685 /// assert_eq!(v["a"].as_bool(), Some(false));
686 ///
687 /// // The string `"false"` is a string, not a boolean.
688 /// assert_eq!(v["b"].as_bool(), None);
689 /// ```
690 pub fn as_bool(&self) -> Option<bool> {
691 match self {
692 Value::Bool(b) => Some(*b),
693 _ => None,
694 }
695 }
696
697 /// Returns true if the value is a character. Returns false otherwise.
698 pub fn is_char(&self) -> bool {
699 self.as_char().is_some()
700 }
701
702 /// If the value is a character, returns the associated `char`. Returns None
703 /// otherwise.
704 ///
705 /// ```
706 /// # use lexpr::sexp;
707 /// #
708 /// let v = sexp!(((a . 'c') (b . "c")));
709 ///
710 /// assert_eq!(v["a"].as_char(), Some('c'));
711 ///
712 /// // The string `"c"` is a single-character string, not a character.
713 /// assert_eq!(v["b"].as_char(), None);
714 /// ```
715 pub fn as_char(&self) -> Option<char> {
716 match self {
717 Value::Char(c) => Some(*c),
718 _ => None,
719 }
720 }
721
722 /// Returns true if the value is `Nil`. Returns false otherwise.
723 ///
724 /// For any Value on which `is_nil` returns true, `as_nil` is guaranteed
725 /// to return `Some(())`.
726 ///
727 /// ```
728 /// # use lexpr::sexp;
729 /// #
730 /// let v = sexp!(((a . #nil) (b . #f)));
731 ///
732 /// assert!(v["a"].is_nil());
733 ///
734 /// // The boolean `false` is not nil.
735 /// assert!(!v["b"].is_nil());
736 /// ```
737 pub fn is_nil(&self) -> bool {
738 self.as_nil().is_some()
739 }
740
741 /// If the value is `Nil`, returns `()`. Returns `None` otherwise.
742 ///
743 /// ```
744 /// # use lexpr::sexp;
745 /// #
746 /// let v = sexp!(((a . #nil) (b . #f) (c . ())));
747 ///
748 /// assert_eq!(v["a"].as_nil(), Some(()));
749 ///
750 /// // The boolean `false` is not nil.
751 /// assert_eq!(v["b"].as_nil(), None);
752 /// // Neither is the empty list.
753 /// assert_eq!(v["c"].as_nil(), None);
754 /// ```
755 pub fn as_nil(&self) -> Option<()> {
756 match self {
757 Value::Nil => Some(()),
758 _ => None,
759 }
760 }
761
762 /// Returns true if the value is `Null`. Returns false otherwise.
763 pub fn is_null(&self) -> bool {
764 self.as_null().is_some()
765 }
766
767 /// If the value is `Null`, returns `()`. Returns `None` otherwise.
768 pub fn as_null(&self) -> Option<()> {
769 match self {
770 Value::Null => Some(()),
771 _ => None,
772 }
773 }
774
775 /// Returns true if the value is a cons cell. Returns `False` otherwise.
776 pub fn is_cons(&self) -> bool {
777 matches!(self, Value::Cons(_))
778 }
779
780 /// If the value is a cons cell, returns a reference to it. Returns `None`
781 /// otherwise.
782 pub fn as_cons(&self) -> Option<&Cons> {
783 match self {
784 Value::Cons(pair) => Some(pair),
785 _ => None,
786 }
787 }
788
789 /// If the value is a cons cell, returns a mutable reference to it. Returns
790 /// `None` otherwise.
791 pub fn as_cons_mut(&mut self) -> Option<&mut Cons> {
792 match self {
793 Value::Cons(pair) => Some(pair),
794 _ => None,
795 }
796 }
797
798 /// If the value is a cons cell, return references to its `car` and `cdr`
799 /// fields.
800 ///
801 /// ```
802 /// # use lexpr::sexp;
803 /// let cell = sexp!((foo . bar));
804 /// assert_eq!(cell.as_pair(), Some((&sexp!(foo), &sexp!(bar))));
805 /// assert_eq!(sexp!("not-a-pair").as_pair(), None);
806 /// ```
807 pub fn as_pair(&self) -> Option<(&Value, &Value)> {
808 self.as_cons().map(Cons::as_pair)
809 }
810
811 /// Returns true if the value is a vector.
812 pub fn is_vector(&self) -> bool {
813 matches!(self, Value::Vector(_))
814 }
815
816 /// If the value is a vector, return a reference to its elements.
817 ///
818 /// ```
819 /// # use lexpr::{sexp, Value};
820 /// let v = sexp!(#(1 2 "three"));
821 /// let slice: &[Value] = &[sexp!(1), sexp!(2), sexp!("three")];
822 /// assert_eq!(v.as_slice(), Some(slice));
823 /// ```
824 pub fn as_slice(&self) -> Option<&[Value]> {
825 match self {
826 Value::Vector(elements) => Some(elements),
827 _ => None,
828 }
829 }
830
831 /// If the value is a vector, return a mutable reference to its elements.
832 ///
833 /// ```
834 /// # use lexpr::{sexp, Value};
835 /// let mut v = sexp!(#(1 2 "three"));
836 /// v.as_slice_mut().unwrap()[2] = sexp!(3);
837 /// let slice: &[Value] = &[sexp!(1), sexp!(2), sexp!(3)];
838 /// assert_eq!(v.as_slice(), Some(slice));
839 /// ```
840 pub fn as_slice_mut(&mut self) -> Option<&mut [Value]> {
841 match self {
842 Value::Vector(elements) => Some(elements),
843 _ => None,
844 }
845 }
846
847 /// If the value is a list, return an iterator over the list elements.
848 ///
849 /// If the value is not either a cons cell or `Null`, `None` is returned.
850 ////
851 /// Note that the returned iterator has special behavior for improper lists, yielding the
852 /// element after the dot after returning `None` the first time.
853 ///
854 /// ```
855 /// use lexpr::sexp;
856 ///
857 /// let value = lexpr::from_str("(1 2 . 3)").unwrap();
858 /// let mut iter = value.list_iter().unwrap();
859 /// assert_eq!(iter.next(), Some(&sexp!(1)));
860 /// assert_eq!(iter.next(), Some(&sexp!(2)));
861 /// assert_eq!(iter.next(), None);
862 /// assert_eq!(iter.next(), Some(&sexp!(3)));
863 /// assert_eq!(iter.next(), None);
864 /// ```
865 pub fn list_iter(&self) -> Option<cons::ListIter<'_>> {
866 match self {
867 Value::Cons(cell) => Some(cons::ListIter::cons(cell)),
868 Value::Null => Some(cons::ListIter::empty()),
869 _ => None,
870 }
871 }
872
873 /// Attempts conversion to a vector, cloning the values.
874 ///
875 /// For proper lists (including `Value::Null`), this returns a vector of
876 /// values. If you want to handle improper list in a similar way, combine
877 /// [`as_cons`] and the [`Cons::to_vec`] method.
878 ///
879 /// ```
880 /// # use lexpr::{sexp, Value};
881 /// assert_eq!(sexp!((1 2 3)).to_vec(), Some(vec![sexp!(1), sexp!(2), sexp!(3)]));
882 /// assert_eq!(sexp!(()).to_vec(), Some(vec![]));
883 /// assert_eq!(sexp!((1 2 . 3)).to_vec(), None);
884 /// ```
885 /// [`as_cons`]: Value::as_cons
886 pub fn to_vec(&self) -> Option<Vec<Value>> {
887 match self {
888 Value::Null => Some(Vec::new()),
889 Value::Cons(pair) => {
890 let (vec, rest) = pair.to_ref_vec();
891 if rest.is_null() {
892 Some(vec.into_iter().cloned().collect())
893 } else {
894 None
895 }
896 }
897 _ => None,
898 }
899 }
900
901 /// Attempts conversion to a vector, taking references to the values.
902 ///
903 /// For proper lists (including `Value::Null`), this returns a vector of
904 /// value references. If you want to handle improper list in a similar way,
905 /// combine [`as_cons`] and the [`Cons::to_ref_vec`] method.
906 ///
907 /// ```
908 /// # use lexpr::{sexp, Value};
909 /// assert_eq!(sexp!((1 2 3)).to_ref_vec(), Some(vec![&sexp!(1), &sexp!(2), &sexp!(3)]));
910 /// assert_eq!(sexp!(()).to_ref_vec(), Some(vec![]));
911 /// assert_eq!(sexp!((1 2 . 3)).to_ref_vec(), None);
912 /// ```
913 ///
914 /// [`as_cons`]: Value::as_cons
915 pub fn to_ref_vec(&self) -> Option<Vec<&Value>> {
916 match self {
917 Value::Null => Some(Vec::new()),
918 Value::Cons(pair) => {
919 let (vec, rest) = pair.to_ref_vec();
920 if rest.is_null() {
921 Some(vec)
922 } else {
923 None
924 }
925 }
926 _ => None,
927 }
928 }
929
930 /// Index into a S-expression list. A string or `Value` value can
931 /// be used to access a value in an association list, and a usize
932 /// index can be used to access the n-th element of a list.
933 ///
934 /// For indexing into association lists, the given string will
935 /// match strings, symbols and keywords.
936 ///
937 /// Returns `None` if the type of `self` does not match the type
938 /// of the index, for example if the index is a string and `self`
939 /// is not an association list. Also returns `None` if the given
940 /// key does not exist in the map or the given index is not within
941 /// the bounds of the list; note that the tail of an improper list
942 /// is also considered out-of-bounds.
943 ///
944 /// In Scheme terms, this method can be thought of a combination
945 /// of `assoc-ref` and `list-ref`, depending on the argument type. If
946 /// you want to look up a number in an association list, use an
947 /// `Value` value containing that number.
948 ///
949 /// ```
950 /// # use lexpr::sexp;
951 /// #
952 /// let alist = sexp!((("A" . 65) (B . 66) (#:C . 67) (42 . "The answer")));
953 /// assert_eq!(alist.get("A").unwrap(), &sexp!(65));
954 /// assert_eq!(alist.get("B").unwrap(), &sexp!(66));
955 /// assert_eq!(alist.get("C").unwrap(), &sexp!(67));
956 /// assert_eq!(alist.get(sexp!(42)).unwrap(), &sexp!("The answer"));
957 ///
958 /// let list = sexp!(("A" "B" "C"));
959 /// assert_eq!(*list.get(2).unwrap(), sexp!("C"));
960 ///
961 /// assert_eq!(list.get("A"), None);
962 /// ```
963 ///
964 /// Square brackets can also be used to index into a value in a
965 /// more concise way. This returns the nil value in cases where
966 /// `get` would have returned `None`. See [`Index`] for details.
967 ///
968 /// ```
969 /// # use lexpr::sexp;
970 /// #
971 /// let alist = sexp!((
972 /// ("A" . ("a" "á" "à"))
973 /// ("B" . ((b . 42) (c . 23)))
974 /// ("C" . ("c" "ć" "ć̣" "ḉ"))
975 /// ));
976 /// assert_eq!(alist["B"][0], sexp!((b . 42)));
977 /// assert_eq!(alist["C"][1], sexp!("ć"));
978 ///
979 /// assert_eq!(alist["D"], sexp!(#nil));
980 /// assert_eq!(alist[0]["x"]["y"]["z"], sexp!(#nil));
981 /// ```
982 ///
983 /// [`Index`]: trait.Index.html
984 pub fn get<I: Index>(&self, index: I) -> Option<&Value> {
985 index.index_into(self)
986 }
987}
988
989struct WriterFormatter<'a, 'b> {
990 inner: &'a mut fmt::Formatter<'b>,
991}
992
993impl<'a, 'b> io::Write for WriterFormatter<'a, 'b> {
994 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
995 fn io_error<E>(_: E) -> io::Error {
996 // Sexp does not matter because fmt::Debug and fmt::Display impls
997 // below just map it to fmt::Error
998 io::Error::new(io::ErrorKind::Other, "fmt error")
999 }
1000 let s = str::from_utf8(buf).map_err(io_error)?;
1001 self.inner.write_str(s).map_err(io_error)?;
1002 Ok(buf.len())
1003 }
1004
1005 fn flush(&mut self) -> io::Result<()> {
1006 Ok(())
1007 }
1008}
1009
1010impl fmt::Display for Value {
1011 /// Display an S-expression value as a string.
1012 ///
1013 /// ```
1014 /// # use lexpr::sexp;
1015 /// #
1016 /// let value = sexp!(((city "London") (street "10 Downing Street")));
1017 ///
1018 /// // Compact format:
1019 /// //
1020 /// // ((city "London") (street "10 Downing Street"))
1021 /// let compact = format!("{}", value);
1022 /// assert_eq!(compact,
1023 /// r#"((city "London") (street "10 Downing Street"))"#);
1024 /// ```
1025 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1026 let mut wr = WriterFormatter { inner: f };
1027 crate::print::to_writer(&mut wr, self).map_err(|_| fmt::Error)
1028 }
1029}
1030
1031impl str::FromStr for Value {
1032 /// Parse an S-expression value from a string.
1033 type Err = crate::parse::Error;
1034
1035 fn from_str(s: &str) -> Result<Self, Self::Err> {
1036 crate::parse::from_str(s)
1037 }
1038}
1039
1040mod from;
1041mod index;
1042mod partial_eq;
1043
1044#[cfg(test)]
1045mod tests;