[][src]Crate shoebill

Pretty-printer with the following notable points (which may be good or bad depending on what you want) :

(1) Uses a trait Doclike to allow insertion of different string types (and already-allocated docs) inline. IE "a".concat(format!("c"), printer).concat(d, printer) where d is some doc that was previously allocated. "a" gets allocated as a &str, and format!("c") as an owned string automatically.

(2) Allows use of borrowed or owned strings (using Cow<'_, str>) by default

(3) Allows rendering to be done with format/write macros, instead of exclusively to a target string.

(4) Includes macros allowing users to cut down on syntactic noise when composing docs.

(5) Uses an explicit allocator IndexSet for efficiency.

(6) Has explicit support for Rust Object Notation items. The motivating use case for this crate was writing debug implementations for types that have some degree of indirection (like index pointers) keeping them from using the #[derive(Debug)] macro effectively.

Taking the printer as the last argument instead of being the self item both allows for more idiomatic dot composition and plays nicer with the idea that the items of interest are Docs, and the Printer is just a thing we have to eventually tether our docs/text to.


There's no unsafe in this crate, but users should be aware of the following two safety points with respect to runtime errors:

  1. This crate uses u32 to keep track of Doc elements the length of documents. Attempting to allocate more than u32::MAX unique docs, or attempting to render a string with a length greater than u32::MAX will cause a runtime error. When I have some free time I'll make the use of u64 in those positions an opt-in feature.

  2. the API presented by this crate is safe with respect to memory lifetimes; you won't be able to create a situation where you have a DocPtr to a dropped arena/bad memory, but there's no guard rail to prevent you from creating multiple printers and accidentally trying to render a Doc with some printer A when it was actually allocated in printer B. If you happen to do this, you'll get a runtime error (panic).



Tools for managing bracketing during pretty-printing based.


Types for formatting items using Rust Object Notation (the format you see when you debug format Rust items with the {:#?} formatter).



Macro for allowing more pleasant composition items that implement Doclike using more familiar operators. The infix operators (which are all left-associtive, but allow for grouping w/ parentheses)




Intercalate, adding a trailing sep chracter as well.



A cheap (copy-able) pointer to an allocated Doc.


The actual thing what holds the information used in composing and printing documents. The Cow strings are held in strings, and Holds CowStr elements and Doc elements in separate IndexSets.


Renderable is a separate thing so that we can use it with format! and write! style macros. This has two lifetimes so that you can have multiple Renderable structs in one scope as long as their lifetimes don't overlap. If we ONLY had the <'p> lifetime, we wouldn't be able to do something like:


A pointer to an allocated string or string slice. You should never have to deal with this. It's only public since Doc would leak it otherwise.



The inner document type. Newline gives you the option of specifying an alternate representation (as an Option) in cases where the renderer is in flat mode, where being in flat mode means you've either elected to specifically render something as flat, or you elected to group elements together (as a Group node), and all of the grouped elements will fit onto the current line without exceeding the line width specified for rendering.


A tagged union of either a Cow string, or a DocPtr. By using this type in conjuction with the Doclike trait, we get a pretty large amount of code reuse while cutting down on syntax noise since in many cases we can treat string slices, owned strings, and DocPtr items in the exact same way with the only overhead being that of dealing with the enum (IE there are no extra allocations or clones).



Trait that defines items we can treat as Doc elements. We can use methods like alloc, concat, group, nest, etc. directly on types implementing Doclike.


Trait that allows types to allocate and render Docs. See the trait documentation for more details.