diff --git a/crates/iddqd/README.md b/crates/iddqd/README.md index 4cd043b..7c39e00 100644 --- a/crates/iddqd/README.md +++ b/crates/iddqd/README.md @@ -12,18 +12,18 @@ Maps where keys are borrowed from values. This crate consists of several map types, collectively called **ID maps**: -* [`IdOrdMap`](https://docs.rs/iddqd/0.4.6/iddqd/id_ord_map/imp/struct.IdOrdMap.html): A B-Tree based map where keys are borrowed from values. -* [`IdHashMap`](https://docs.rs/iddqd/0.4.6/iddqd/id_hash_map/imp/struct.IdHashMap.html): A hash map where keys are borrowed from values. -* [`BiHashMap`](https://docs.rs/iddqd/0.4.6/iddqd/bi_hash_map/imp/struct.BiHashMap.html): A bijective (1:1) hash map with two keys, borrowed from +* [`IdOrdMap`]: A B-Tree based map where keys are borrowed from values. +* [`IdHashMap`]: A hash map where keys are borrowed from values. +* [`BiHashMap`]: A bijective (1:1) hash map with two keys, borrowed from values. -* [`TriHashMap`](https://docs.rs/iddqd/0.4.6/iddqd/tri_hash_map/imp/struct.TriHashMap.html): A trijective (1:1:1) hash map with three keys, borrowed +* [`TriHashMap`]: A trijective (1:1:1) hash map with three keys, borrowed from values. ## Usage * Pick your ID map type. -* Depending on the ID map type, implement [`IdOrdItem`](https://docs.rs/iddqd/0.4.6/iddqd/id_ord_map/trait_defs/trait.IdOrdItem.html), [`IdHashItem`](https://docs.rs/iddqd/0.4.6/iddqd/id_hash_map/trait_defs/trait.IdHashItem.html), - [`BiHashItem`](https://docs.rs/iddqd/0.4.6/iddqd/bi_hash_map/trait_defs/trait.BiHashItem.html), or [`TriHashItem`](https://docs.rs/iddqd/0.4.6/iddqd/tri_hash_map/trait_defs/trait.TriHashItem.html) for your value type. +* Depending on the ID map type, implement [`IdOrdItem`], [`IdHashItem`], + [`BiHashItem`], or [`TriHashItem`] for your value type. * Store values in the ID map type. ### Features @@ -40,7 +40,7 @@ issues encountered using Rust’s default map types in practice at Oxide. * There’s no `insert` method; insertion must be through either `insert_overwrite` or `insert_unique`. You must pick an insertion behavior. -* For hash maps, the default hasher is [`foldhash`](https://docs.rs/foldhash/0.2.0/foldhash/index.html), which is much faster +* For hash maps, the default hasher is [`foldhash`], which is much faster than SipHash. However, foldhash does *not provide the same level of HashDoS resistance* as SipHash. If that is important to you, you can use a different hasher. (Disable the `default-hasher` feature to require a hash @@ -49,11 +49,11 @@ issues encountered using Rust’s default map types in practice at Oxide. We’ve also sometimes needed to index a set of data by more than one key, or perhaps map one key to another. For that purpose, this crate provides -[`BiHashMap`](https://docs.rs/iddqd/0.4.6/iddqd/bi_hash_map/imp/struct.BiHashMap.html) and [`TriHashMap`](https://docs.rs/iddqd/0.4.6/iddqd/tri_hash_map/imp/struct.TriHashMap.html). +[`BiHashMap`] and [`TriHashMap`]. -* [`BiHashMap`](https://docs.rs/iddqd/0.4.6/iddqd/bi_hash_map/imp/struct.BiHashMap.html) has two keys, and provides a bijection (1:1 relationship) +* [`BiHashMap`] has two keys, and provides a bijection (1:1 relationship) between the keys. -* [`TriHashMap`](https://docs.rs/iddqd/0.4.6/iddqd/tri_hash_map/imp/struct.TriHashMap.html) has three keys, and provides a trijection (1:1:1 +* [`TriHashMap`] has three keys, and provides a trijection (1:1:1 relationship) between the keys. As a consequence of the general API structure, maps can have arbitrary @@ -61,7 +61,7 @@ non-key data associated with them as well. ### Examples -An example for [`IdOrdMap`](https://docs.rs/iddqd/0.4.6/iddqd/id_ord_map/imp/struct.IdOrdMap.html): +An example for [`IdOrdMap`]: ````rust use iddqd::{IdOrdItem, IdOrdMap, id_upcast}; @@ -103,7 +103,7 @@ for user in &users { Keys don’t have to be borrowed from the value. For smaller `Copy` types, it’s recommended that you use owned keys. Here’s an example of using -[`IdOrdMap`](https://docs.rs/iddqd/0.4.6/iddqd/id_ord_map/imp/struct.IdOrdMap.html) with a small integer key: +[`IdOrdMap`] with a small integer key: ````rust struct Record { @@ -125,7 +125,7 @@ impl IdOrdItem for Record { // ... ```` -An example for [`IdHashMap`](https://docs.rs/iddqd/0.4.6/iddqd/id_hash_map/imp/struct.IdHashMap.html), showing a complex borrowed key. Here, +An example for [`IdHashMap`], showing a complex borrowed key. Here, “complex” means that the key is not a reference itself, but a struct that returns references to more than one field from the value. @@ -199,8 +199,8 @@ through the [`Borrow`] trait. But the [`Borrow`] trait is a bit too restrictive for complex keys such as `ArtifactKey` above, requiring workarounds such as [dynamic dispatch](https://github.com/sunshowers-code/borrow-complex-key-example). To -address this, the crates.io ecosystem has standardized on the [`Equivalent`](https://docs.rs/equivalent/1.0.2/equivalent/trait.Equivalent.html) -and [`Comparable`](https://docs.rs/equivalent/1.0.2/equivalent/trait.Comparable.html) traits as generalizations of `Borrow`. The map types in +address this, the crates.io ecosystem has standardized on the [`Equivalent`] +and [`Comparable`] traits as generalizations of `Borrow`. The map types in this crate require these traits. For a key type `T::Key<'_>` and a query type `Q`: @@ -209,7 +209,7 @@ For a key type `T::Key<'_>` and a query type `Q`: must hash in the same way as `T::Key<'_>`. Typically, this is done by ensuring that enum variants and struct fields are in the same order[^proptest]. -* [`IdOrdMap`](https://docs.rs/iddqd/0.4.6/iddqd/id_ord_map/imp/struct.IdOrdMap.html) requires `Q: Comparable>`, which in turn requires +* [`IdOrdMap`] requires `Q: Comparable>`, which in turn requires `Equivalent>`. (There’s no need for `Q` to implement `Ord` or `Eq` itself.) @@ -245,7 +245,7 @@ let owned_key = OwnedArtifactKey { assert_eq!(artifacts.get(&owned_key).unwrap().data, b"data1",); ```` -There’s a blanket implementation of [`Equivalent`](https://docs.rs/equivalent/1.0.2/equivalent/trait.Equivalent.html) and [`Comparable`](https://docs.rs/equivalent/1.0.2/equivalent/trait.Comparable.html) for +There’s a blanket implementation of [`Equivalent`] and [`Comparable`] for [`Borrow`], so if your type already implements [`Borrow`], there aren’t any extra steps to take. @@ -277,26 +277,26 @@ tests depend on nextest’s process-per-test model. ## No-std compatibility -Most of this crate is no-std compatible, though [`alloc`](https://doc.rust-lang.org/nightly/alloc/index.html) is required. +Most of this crate is no-std compatible, though [`alloc`] is required. -The [`IdOrdMap`](https://docs.rs/iddqd/0.4.6/iddqd/id_ord_map/imp/struct.IdOrdMap.html) type is not currently no-std compatible due to its use of a +The [`IdOrdMap`] type is not currently no-std compatible due to its use of a thread-local. This thread-local is just a way to work around a limitation in std’s `BTreeMap` API, though. Either a custom B-Tree implementation, or a platform-specific notion of thread locals, would suffice to make -[`IdOrdMap`](https://docs.rs/iddqd/0.4.6/iddqd/id_ord_map/imp/struct.IdOrdMap.html) no-std compatible. +[`IdOrdMap`] no-std compatible. ## Optional features * `allocator-api2`: Enables support for custom allocators via the - [`allocator_api2`](https://docs.rs/allocator-api2/0.2.21/allocator_api2/index.html) crate. Both global and scoped/arena allocators + [`allocator_api2`] crate. Both global and scoped/arena allocators (such as `bumpalo`) are supported. Custom allocators are not currently supported by `IdOrdMap`. -* `daft`: Enables [`daft`](https://docs.rs/daft/0.1.5/daft/index.html) support for all ID map types. *Not enabled by +* `daft`: Enables [`daft`] support for all ID map types. *Not enabled by default.* * `default-hasher`: Enables the `DefaultHashBuilder` type. Disable this feature to require a hash builder type parameter to be passed into - [`IdHashMap`](https://docs.rs/iddqd/0.4.6/iddqd/id_hash_map/imp/struct.IdHashMap.html), [`BiHashMap`](https://docs.rs/iddqd/0.4.6/iddqd/bi_hash_map/imp/struct.BiHashMap.html), and [`TriHashMap`](https://docs.rs/iddqd/0.4.6/iddqd/tri_hash_map/imp/struct.TriHashMap.html). *Enabled by default.* -* `proptest`: Enables [`proptest`](https://docs.rs/proptest/1.7.0/proptest/index.html) support for all ID map types, providing + [`IdHashMap`], [`BiHashMap`], and [`TriHashMap`]. *Enabled by default.* +* `proptest`: Enables [`proptest`] support for all ID map types, providing [`Arbitrary`] implementations and strategies for property-based testing. *Not enabled by default.* * `schemars08`: Enables [`schemars`] support for all ID map types, @@ -335,8 +335,23 @@ The name `iddqd` is a reference to [a cheat code](https://doomwiki.org/wiki/Doom_cheat_codes) in the classic video game *Doom*. It has `id` in the name, and is short and memorable. -[`Borrow`]: https://doc.rust-lang.org/nightly/core/borrow/trait.Borrow.html -[`Arbitrary`]: https://docs.rs/proptest/1.7.0/proptest/arbitrary/traits/trait.Arbitrary.html +[`IdOrdMap`]: https://docs.rs/iddqd/0.4.6/iddqd/id_ord_map/imp/struct.IdOrdMap.html "struct iddqd::id_ord_map::imp::IdOrdMap" +[`IdHashMap`]: https://docs.rs/iddqd/0.4.6/iddqd/id_hash_map/imp/struct.IdHashMap.html "struct iddqd::id_hash_map::imp::IdHashMap" +[`BiHashMap`]: https://docs.rs/iddqd/0.4.6/iddqd/bi_hash_map/imp/struct.BiHashMap.html "struct iddqd::bi_hash_map::imp::BiHashMap" +[`TriHashMap`]: https://docs.rs/iddqd/0.4.6/iddqd/tri_hash_map/imp/struct.TriHashMap.html "struct iddqd::tri_hash_map::imp::TriHashMap" +[`IdOrdItem`]: https://docs.rs/iddqd/0.4.6/iddqd/id_ord_map/trait_defs/trait.IdOrdItem.html "trait iddqd::id_ord_map::trait_defs::IdOrdItem" +[`IdHashItem`]: https://docs.rs/iddqd/0.4.6/iddqd/id_hash_map/trait_defs/trait.IdHashItem.html "trait iddqd::id_hash_map::trait_defs::IdHashItem" +[`BiHashItem`]: https://docs.rs/iddqd/0.4.6/iddqd/bi_hash_map/trait_defs/trait.BiHashItem.html "trait iddqd::bi_hash_map::trait_defs::BiHashItem" +[`TriHashItem`]: https://docs.rs/iddqd/0.4.6/iddqd/tri_hash_map/trait_defs/trait.TriHashItem.html "trait iddqd::tri_hash_map::trait_defs::TriHashItem" +[`foldhash`]: https://docs.rs/foldhash/0.2.0/foldhash/index.html "module foldhash" +[`Borrow`]: https://doc.rust-lang.org/nightly/core/borrow/trait.Borrow.html "trait core::borrow::Borrow" +[`Equivalent`]: https://docs.rs/equivalent/1.0.2/equivalent/trait.Equivalent.html "trait equivalent::Equivalent" +[`Comparable`]: https://docs.rs/equivalent/1.0.2/equivalent/trait.Comparable.html "trait equivalent::Comparable" +[`alloc`]: https://doc.rust-lang.org/nightly/alloc/index.html "module alloc" +[`allocator_api2`]: https://docs.rs/allocator-api2/0.2.21/allocator_api2/index.html "module allocator_api2" +[`daft`]: https://docs.rs/daft/0.1.5/daft/index.html "module daft" +[`proptest`]: https://docs.rs/proptest/1.7.0/proptest/index.html "module proptest" +[`Arbitrary`]: https://docs.rs/proptest/1.7.0/proptest/arbitrary/traits/trait.Arbitrary.html "trait proptest::arbitrary::traits::Arbitrary" [`schemars`]: https://crates.io/crates/schemars [automatic replacement]: https://github.com/oxidecomputer/iddqd/blob/main/crates/iddqd-extended-examples/examples/typify-types.rs [`typify`]: https://crates.io/crates/typify