Skip to main content

ocaml_sexplib/
lib.rs

1// I don't like this rule because it changes the semantic
2// structure of the code.
3#![allow(clippy::collapsible_else_if)]
4// Sometimes "x >= y + 1" is semantically clearer than "x > y"
5#![allow(clippy::int_plus_one)]
6// `is_empty` sometimes makes something too much like a collection.
7#![allow(clippy::len_zero)]
8
9use std::ops::{Deref, Range};
10
11pub mod atom;
12pub mod de;
13pub mod error;
14pub mod input;
15pub mod ser;
16pub mod sexp;
17pub mod token_writer;
18pub mod tokenizer;
19
20pub use sexp::Sexp;
21
22pub use de::{
23    from_slice, from_str, iter_from_slice, iter_from_str, many_from_slice, many_from_str,
24    Deserializer,
25};
26pub use error::{Error, Result};
27pub use ser::{to_string, to_string_mach, to_writer, to_writer_mach, Serializer};
28pub use sexp::de::from_sexp;
29pub use sexp::ser::to_sexp;
30
31// Can't name a module "ref", so I guess we'll just put this as the top-level.
32
33/// A fundamental wrapper type that provides a building block for zero-copy deserialization. Similar
34/// to how [`std::borrow::Cow`] represents borrowed or owned data, [`Ref`] represents borrowed data
35/// or "transient" data that isn't as long lived, e.g. a scratch buffer.
36#[derive(Debug)]
37pub enum Ref<'de, 't, T>
38where
39    T: ?Sized,
40{
41    Borrowed(&'de T),
42    Transient(&'t T),
43}
44
45impl<'de, 't, T> Deref for Ref<'de, 't, T>
46where
47    T: ?Sized,
48{
49    type Target = T;
50
51    fn deref(&self) -> &T {
52        match *self {
53            Ref::Borrowed(de) => de,
54            Ref::Transient(t) => t,
55        }
56    }
57}
58
59impl<'de, 't> Ref<'de, 't, [u8]> {
60    pub fn index(&self, range: Range<usize>) -> Ref<'de, 't, [u8]> {
61        match self {
62            Ref::Borrowed(bytes) => Ref::Borrowed(&bytes[range]),
63            Ref::Transient(bytes) => Ref::Transient(&bytes[range]),
64        }
65    }
66}