# char-list A persistent string type with the same API as a linked-list of characters. ## Contents ### `FiniteCharList` The `FiniteCharList` type is probably what you want to use. It behaves just like a linked list of characters but with better (TODO: verify) performance. ## `CharList` The `CharList` type allows customization of the data structure by allowing a custom tail. I'm using this to emulate Prolog's open-ended lists where the tail of the list may be an uninstantiated Prolog variable. A `FiniteCharList` is just a type alias for `CharList<()>`. Generic `CharList`s have much fewer abilities provided by this crate because the nature of the tail is unknown. For instance, `CharList` does *not* implement `AsRef` or even `PartialEq`! The intention is that you will wrap a `CharList` in a newtype and implement those traits if it makes sense for your problem space. For example, I (plan to) use a `CharList` which *will* implement `PartialEq` because I want syntactic equality. ## Docs See the [docs](https://docs.rs/char-list/latest/char_list/) for memory-layout ***diagrams*** and explanations of how it all works. ## DISCLAIMER: `unsafe` This crate is a work in progress. Specifically ***Not all uses of `unsafe` have been validated!*** Please don't use this for anything serious yet. Safety audits are welcome and appreciated! I'm still quite new to writing `unsafe` code. Also, this crate depends on [`front-vec`](https://crates.io/crates/front-vec) which is also badly in need of auditing. ## Example ```rust use assert2::assert; // For nicer assertions. let icon = FiniteCharList::from("icon"); let nomicon = icon.cons_str("nom"); let rustonomicon = nomicon.cons_str("rusto"); // Cloning requires // 1) copying two words, and // 2) performing one BTreeMap lookup. let rustonomicon2 = rustonomicon.clone(); assert!(icon == "icon"); assert!(nomicon == "nomicon"); assert!(rustonomicon == "rustonomicon"); assert!(rustonomicon == rustonomicon2); // No new allocations required (if underlying buffer capacity allows). // Mutably prepends the `&str` to the buffer without shifting memory. let the_book = rustonomicon.cons_str("the "); assert!(the_book == "the rustonomicon"); // Drop to mutably resize underlying buffer and drop(rustonomicon); drop(the_book); drop(rustonomicon2); let janelle_monae = icon.cons('b'); // Duplication required now. assert!(janelle_monae == "bicon"); ```