Import intrusive-collections from crates.io

This is generated with get_rust_pkg.py, plus Android.bp,
TEST_MAPPING and patches/Android.bp.patch.

Test is not generated due to API changes in rand* crates. Android's
version is already newer, so it requires to fix this library to make the
test build.

Bug: 174797066
Test: mma
Test: tools/external_updater/updater.sh update --refresh --keep_date
      rust/crates/intrusive-collections
Change-Id: If027f439d88ca585e57f2efa05ad6ac88130e8e5
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
new file mode 100644
index 0000000..c5f55b1
--- /dev/null
+++ b/.cargo_vcs_info.json
@@ -0,0 +1,5 @@
+{
+  "git": {
+    "sha1": "1cc39624ea4e69f4741f9179e780eecc763423d6"
+  }
+}
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..a9d37c5
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+target
+Cargo.lock
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..1ebea6e
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,36 @@
+language: rust
+sudo: false
+addons:
+  apt:
+    packages:
+    - libcurl4-openssl-dev
+    - libelf-dev
+    - libdw-dev
+    - binutils-dev
+
+rust:
+- nightly
+- beta
+- stable
+- 1.36.0
+
+before_script:
+- |
+  pip install 'travis-cargo<0.2' --user &&
+  export PATH=$HOME/.local/bin:$PATH
+
+script:
+- travis-cargo build
+- travis-cargo test
+- travis-cargo doc
+
+after_success:
+- travis-cargo --only nightly doc-upload
+- travis-cargo --only nightly coveralls --no-sudo --verify
+
+env:
+  global:
+  - TRAVIS_CARGO_NIGHTLY_FEATURE=nightly
+
+notifications:
+  email: false
diff --git a/Android.bp b/Android.bp
new file mode 100644
index 0000000..119bd2d
--- /dev/null
+++ b/Android.bp
@@ -0,0 +1,26 @@
+// This file is generated by cargo2android.py --run --device --dependencies --patch=patches/Android.bp.patch.
+// TODO(victorhsieh): Add --test. The test in the current version depends on an older rand crate
+// (pre 0.8) to compile due to several API changes. However, Android's rand is already newer.
+
+rust_library {
+    name: "libintrusive_collections",
+    host_supported: true,
+    crate_name: "intrusive_collections",
+    srcs: ["src/lib.rs"],
+    edition: "2018",
+    features: [
+        "alloc",
+        "default",
+    ],
+    rustlibs: [
+        "libmemoffset",
+    ],
+    apex_available: [
+        "//apex_available:platform",
+        "com.android.virt",
+    ],
+}
+
+// dependent_library ["feature_list"]
+//   autocfg-1.0.1
+//   memoffset-0.5.6 "default"
diff --git a/Cargo.toml b/Cargo.toml
new file mode 100644
index 0000000..08ed56d
--- /dev/null
+++ b/Cargo.toml
@@ -0,0 +1,39 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g., crates.io) dependencies
+#
+# If you believe there's an error in this file please file an
+# issue against the rust-lang/cargo repository. If you're
+# editing this file be aware that the upstream Cargo.toml
+# will likely look very different (and much more reasonable)
+
+[package]
+edition = "2018"
+name = "intrusive-collections"
+version = "0.9.0"
+authors = ["Amanieu d'Antras <amanieu@gmail.com>"]
+description = "Intrusive collections for Rust (linked list and red-black tree)"
+documentation = "https://docs.rs/intrusive-collections"
+readme = "README.md"
+keywords = ["intrusive", "no_std", "list", "rbtree"]
+categories = ["data-structures", "no-std"]
+license = "Apache-2.0/MIT"
+repository = "https://github.com/Amanieu/intrusive-rs"
+[dependencies.memoffset]
+version = "0.5.4"
+[dev-dependencies.rand]
+version = "0.7.3"
+
+[dev-dependencies.rand_xorshift]
+version = "0.2.0"
+
+[dev-dependencies.typed-arena]
+version = "2.0.1"
+
+[features]
+alloc = []
+default = ["alloc"]
+nightly = []
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
new file mode 100644
index 0000000..ffa9b83
--- /dev/null
+++ b/Cargo.toml.orig
@@ -0,0 +1,25 @@
+[package]
+name = "intrusive-collections"
+version = "0.9.0"
+authors = ["Amanieu d'Antras <amanieu@gmail.com>"]
+description = "Intrusive collections for Rust (linked list and red-black tree)"
+documentation = "https://docs.rs/intrusive-collections"
+license = "Apache-2.0/MIT"
+repository = "https://github.com/Amanieu/intrusive-rs"
+readme = "README.md"
+keywords = ["intrusive", "no_std", "list", "rbtree"]
+categories = ["data-structures", "no-std"]
+edition = "2018"
+
+[features]
+nightly = []
+alloc = []
+default = ["alloc"]
+
+[dependencies]
+memoffset = "0.5.4"
+
+[dev-dependencies]
+rand = "0.7.3"
+typed-arena = "2.0.1"
+rand_xorshift = "0.2.0"
diff --git a/DESIGN.md b/DESIGN.md
new file mode 100644
index 0000000..a667069
--- /dev/null
+++ b/DESIGN.md
@@ -0,0 +1,33 @@
+# Design rationale
+
+> I always hear that intrusive collections can't be done in Rust (either "can't be done safely" or "can't be done as performantly as C++"). Can you elaborate on this?
+
+I would say that it is a combination of both "can't be done safely" and "can't be done as performantly as C++". You should keep in mind that C++ libraries such as [Boost.Intrusive](http://www.boost.org/doc/libs/release/doc/html/intrusive.html) don't exactly have a safe API and instead place a bunch of [requirements on the user](http://www.boost.org/doc/libs/1_53_0/doc/html/intrusive/usage.html#intrusive.usage.usage_lifetime) regarding object lifetimes.
+
+There are several factor that a Rust implementation of intrusive collections must take into account:
+
+1. Elements in a collection can't have a pointer back to the collection itself since these would become invalid if the collection is moved. C++ doesn't suffer from this limitation because it can adjust these pointers in the move constructor.
+
+   (Not that I'm complaining about Rust's lack of move constructors. Having to deal with move constructors introduces *a lot* of complexity for collection code due to exception safety issues.)
+
+    This basically means that we have to use NULL-terminated linked lists instead of circular linked lists. It's very slightly slower (depending on who you ask), but generally not a big deal. This same restriction also applies to normal collection types in Rust.
+
+2. Rust doesn't have any equivalent to C++'s "pointer to member" type to tell a collection type which struct field to use for the intrusive `Link` (basically the prev/next pointers in a linked list). Instead, we use an unsafe `Adapter` trait which describes how to convert between a `*const T` and `*const Link`.
+
+   The `intrusive_adapter!` macro provides a safe and easy way of creating and adapter type. It uses `offset_of!` and `container_of!` internally in a way that is guaranteed to be safe. This macro only supports the case where the link is a direct field of the object type; more complicated scenarios (such as nested fields) require a manual implementation of `Adapter`.
+
+3. You can't safely give out `&mut` references to elements in a collection due to the aliasing rules (an object may be part of multiple intrusive collections at once) and because it allows the user to "break" the links in a collection with code like `mem::replace(&mut obj.link, Link::new())`.
+
+   Since we can only give out `&` references to collection elements, any mutability must be done through `Cell` / `RefCell` / `UnsafeCell`.
+
+4. Objects must not be moved or destroyed while they are still linked into an intrusive collection. While this basically sounds like having the collection take a shared borrow of an object when inserting it, lifetimes aren't ideal for this since they effectively restrict the lifetime of the collection to a single function.
+
+   The basic approach that `intrusive-collections` takes is that a collection *takes ownership* of an object, usually in the form of an owned pointer (`Box<T>`, `Rc<T>`, etc), and then returns the owned pointer back to the user when the object is removed from the collection. The owned pointer type is a generic parameter of the collection (through the `Adapter` trait).
+
+   The case of `Box<T>` is the simplest, since the collection becomes the sole owner of the object. `Rc<T>` is more interesting since the ownership is shared. This enables inserting an object into multiple intrusive collections (with multiple `Link`s in the object) without needing to worry about the object moving or dropping while still in use.
+
+   `intrusive-collection` also supports using `&'a T` as the owned pointer type. This allows shared ownership (you can keep accessing variables that have been inserted in the collection) without the need for reference counting. Safety is ensure by restricting the lifetime of the collection such that it does not outlive any objects that have been inserted into it. As a bonus, this also works with [arenas](https://crates.io/crates/typed-arena) which give out `&'a T` references to allocated objects.
+
+   Finally, if you really need to avoid the overhead of `Rc`, the crate also provides an `UnsafeRef` type which acts like an `Rc` but without the reference count: you are expected to free the object yourself once you are sure it is no longer in use.
+
+So basically, `intrusive-collections` is almost as performant as C++ intrusive collections. If you want every last bit of performance, you can use `UnsafeRef` instead of `Rc` for the owned pointer and `UnsafeCell` instead of `RefCell` for the object data. However I would expect the gains to be relatively minor compared to the added unsafety.
diff --git a/LICENSE b/LICENSE
new file mode 120000
index 0000000..6b579aa
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1 @@
+LICENSE-APACHE
\ No newline at end of file
diff --git a/LICENSE-APACHE b/LICENSE-APACHE
new file mode 100644
index 0000000..16fe87b
--- /dev/null
+++ b/LICENSE-APACHE
@@ -0,0 +1,201 @@
+                              Apache License
+                        Version 2.0, January 2004
+                     http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+   "License" shall mean the terms and conditions for use, reproduction,
+   and distribution as defined by Sections 1 through 9 of this document.
+
+   "Licensor" shall mean the copyright owner or entity authorized by
+   the copyright owner that is granting the License.
+
+   "Legal Entity" shall mean the union of the acting entity and all
+   other entities that control, are controlled by, or are under common
+   control with that entity. For the purposes of this definition,
+   "control" means (i) the power, direct or indirect, to cause the
+   direction or management of such entity, whether by contract or
+   otherwise, or (ii) ownership of fifty percent (50%) or more of the
+   outstanding shares, or (iii) beneficial ownership of such entity.
+
+   "You" (or "Your") shall mean an individual or Legal Entity
+   exercising permissions granted by this License.
+
+   "Source" form shall mean the preferred form for making modifications,
+   including but not limited to software source code, documentation
+   source, and configuration files.
+
+   "Object" form shall mean any form resulting from mechanical
+   transformation or translation of a Source form, including but
+   not limited to compiled object code, generated documentation,
+   and conversions to other media types.
+
+   "Work" shall mean the work of authorship, whether in Source or
+   Object form, made available under the License, as indicated by a
+   copyright notice that is included in or attached to the work
+   (an example is provided in the Appendix below).
+
+   "Derivative Works" shall mean any work, whether in Source or Object
+   form, that is based on (or derived from) the Work and for which the
+   editorial revisions, annotations, elaborations, or other modifications
+   represent, as a whole, an original work of authorship. For the purposes
+   of this License, Derivative Works shall not include works that remain
+   separable from, or merely link (or bind by name) to the interfaces of,
+   the Work and Derivative Works thereof.
+
+   "Contribution" shall mean any work of authorship, including
+   the original version of the Work and any modifications or additions
+   to that Work or Derivative Works thereof, that is intentionally
+   submitted to Licensor for inclusion in the Work by the copyright owner
+   or by an individual or Legal Entity authorized to submit on behalf of
+   the copyright owner. For the purposes of this definition, "submitted"
+   means any form of electronic, verbal, or written communication sent
+   to the Licensor or its representatives, including but not limited to
+   communication on electronic mailing lists, source code control systems,
+   and issue tracking systems that are managed by, or on behalf of, the
+   Licensor for the purpose of discussing and improving the Work, but
+   excluding communication that is conspicuously marked or otherwise
+   designated in writing by the copyright owner as "Not a Contribution."
+
+   "Contributor" shall mean Licensor and any individual or Legal Entity
+   on behalf of whom a Contribution has been received by Licensor and
+   subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of
+   this License, each Contributor hereby grants to You a perpetual,
+   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+   copyright license to reproduce, prepare Derivative Works of,
+   publicly display, publicly perform, sublicense, and distribute the
+   Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of
+   this License, each Contributor hereby grants to You a perpetual,
+   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+   (except as stated in this section) patent license to make, have made,
+   use, offer to sell, sell, import, and otherwise transfer the Work,
+   where such license applies only to those patent claims licensable
+   by such Contributor that are necessarily infringed by their
+   Contribution(s) alone or by combination of their Contribution(s)
+   with the Work to which such Contribution(s) was submitted. If You
+   institute patent litigation against any entity (including a
+   cross-claim or counterclaim in a lawsuit) alleging that the Work
+   or a Contribution incorporated within the Work constitutes direct
+   or contributory patent infringement, then any patent licenses
+   granted to You under this License for that Work shall terminate
+   as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the
+   Work or Derivative Works thereof in any medium, with or without
+   modifications, and in Source or Object form, provided that You
+   meet the following conditions:
+
+   (a) You must give any other recipients of the Work or
+       Derivative Works a copy of this License; and
+
+   (b) You must cause any modified files to carry prominent notices
+       stating that You changed the files; and
+
+   (c) You must retain, in the Source form of any Derivative Works
+       that You distribute, all copyright, patent, trademark, and
+       attribution notices from the Source form of the Work,
+       excluding those notices that do not pertain to any part of
+       the Derivative Works; and
+
+   (d) If the Work includes a "NOTICE" text file as part of its
+       distribution, then any Derivative Works that You distribute must
+       include a readable copy of the attribution notices contained
+       within such NOTICE file, excluding those notices that do not
+       pertain to any part of the Derivative Works, in at least one
+       of the following places: within a NOTICE text file distributed
+       as part of the Derivative Works; within the Source form or
+       documentation, if provided along with the Derivative Works; or,
+       within a display generated by the Derivative Works, if and
+       wherever such third-party notices normally appear. The contents
+       of the NOTICE file are for informational purposes only and
+       do not modify the License. You may add Your own attribution
+       notices within Derivative Works that You distribute, alongside
+       or as an addendum to the NOTICE text from the Work, provided
+       that such additional attribution notices cannot be construed
+       as modifying the License.
+
+   You may add Your own copyright statement to Your modifications and
+   may provide additional or different license terms and conditions
+   for use, reproduction, or distribution of Your modifications, or
+   for any such Derivative Works as a whole, provided Your use,
+   reproduction, and distribution of the Work otherwise complies with
+   the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise,
+   any Contribution intentionally submitted for inclusion in the Work
+   by You to the Licensor shall be under the terms and conditions of
+   this License, without any additional terms or conditions.
+   Notwithstanding the above, nothing herein shall supersede or modify
+   the terms of any separate license agreement you may have executed
+   with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade
+   names, trademarks, service marks, or product names of the Licensor,
+   except as required for reasonable and customary use in describing the
+   origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or
+   agreed to in writing, Licensor provides the Work (and each
+   Contributor provides its Contributions) on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+   implied, including, without limitation, any warranties or conditions
+   of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+   PARTICULAR PURPOSE. You are solely responsible for determining the
+   appropriateness of using or redistributing the Work and assume any
+   risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory,
+   whether in tort (including negligence), contract, or otherwise,
+   unless required by applicable law (such as deliberate and grossly
+   negligent acts) or agreed to in writing, shall any Contributor be
+   liable to You for damages, including any direct, indirect, special,
+   incidental, or consequential damages of any character arising as a
+   result of this License or out of the use or inability to use the
+   Work (including but not limited to damages for loss of goodwill,
+   work stoppage, computer failure or malfunction, or any and all
+   other commercial damages or losses), even if such Contributor
+   has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing
+   the Work or Derivative Works thereof, You may choose to offer,
+   and charge a fee for, acceptance of support, warranty, indemnity,
+   or other liability obligations and/or rights consistent with this
+   License. However, in accepting such obligations, You may act only
+   on Your own behalf and on Your sole responsibility, not on behalf
+   of any other Contributor, and only if You agree to indemnify,
+   defend, and hold each Contributor harmless for any liability
+   incurred by, or claims asserted against, such Contributor by reason
+   of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work.
+
+   To apply the Apache License to your work, attach the following
+   boilerplate notice, with the fields enclosed by brackets "[]"
+   replaced with your own identifying information. (Don't include
+   the brackets!)  The text should be enclosed in the appropriate
+   comment syntax for the file format. We also recommend that a
+   file or class name and description of purpose be included on the
+   same "printed page" as the copyright notice for easier
+   identification within third-party archives.
+
+Copyright [yyyy] [name of copyright owner]
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+	http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
diff --git a/LICENSE-MIT b/LICENSE-MIT
new file mode 100644
index 0000000..5afc2a7
--- /dev/null
+++ b/LICENSE-MIT
@@ -0,0 +1,25 @@
+Copyright (c) 2016 Amanieu d'Antras
+
+Permission is hereby granted, free of charge, to any
+person obtaining a copy of this software and associated
+documentation files (the "Software"), to deal in the
+Software without restriction, including without
+limitation the rights to use, copy, modify, merge,
+publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software
+is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice
+shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
diff --git a/METADATA b/METADATA
new file mode 100644
index 0000000..ffc6a09
--- /dev/null
+++ b/METADATA
@@ -0,0 +1,19 @@
+name: "intrusive-collections"
+description: "Intrusive collections for Rust (linked list and red-black tree)"
+third_party {
+  url {
+    type: HOMEPAGE
+    value: "https://crates.io/crates/intrusive-collections"
+  }
+  url {
+    type: ARCHIVE
+    value: "https://static.crates.io/crates/intrusive-collections/intrusive-collections-0.9.0.crate"
+  }
+  version: "0.9.0"
+  license_type: NOTICE
+  last_upgrade_date {
+    year: 2020
+    month: 12
+    day: 15
+  }
+}
diff --git a/MODULE_LICENSE_APACHE2 b/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/MODULE_LICENSE_APACHE2
diff --git a/OWNERS b/OWNERS
new file mode 100644
index 0000000..46fc303
--- /dev/null
+++ b/OWNERS
@@ -0,0 +1 @@
+include platform/prebuilts/rust:/OWNERS
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..271d304
--- /dev/null
+++ b/README.md
@@ -0,0 +1,45 @@
+intrusive-collections
+=====================
+
+[![Build Status](https://travis-ci.org/Amanieu/intrusive-rs.svg?branch=master)](https://travis-ci.org/Amanieu/intrusive-rs) [![Coverage Status](https://coveralls.io/repos/github/Amanieu/intrusive-rs/badge.svg?branch=master)](https://coveralls.io/github/Amanieu/intrusive-rs?branch=master) [![Crates.io](https://img.shields.io/crates/v/intrusive-collections.svg)](https://crates.io/crates/intrusive-collections)
+
+A Rust library for creating intrusive collections. Currently supports singly-linked and doubly-linked lists, as well as red-black trees.
+
+## Features
+
+- Compatible with `#[no_std]`.
+- Intrusive collections don't require any dynamic memory allocation since they simply keep track of existing objects rather than allocating new ones.
+- You can safely manipulate intrusive collections without any unsafe code.
+- A single object can be a member of multiple intrusive collections simultaneously.
+- Intrusive collections provide a `Cursor`-based interface, which allows safe mutation while iterating.
+
+For examples and more information, see the documentation ([crates.io](https://docs.rs/intrusive-collections), [master](https://amanieu.github.io/intrusive-rs/intrusive_collections/index.html)).
+
+## Usage
+
+Add this to your `Cargo.toml`:
+
+```toml
+[dependencies]
+intrusive-collections = "0.9"
+```
+
+This crate has two Cargo features:
+
+- `nightly`: Enables nightly-only features: `const fn` constructors for collections (`Link` constructors are always `const fn`)
+- `alloc` (enabled by default): Implements `IntrusivePointer` for `Box`, `Rc` and `Arc`.
+
+## License
+
+Licensed under either of
+
+ * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
+ * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
+
+at your option.
+
+### Contribution
+
+Unless you explicitly state otherwise, any contribution intentionally submitted
+for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any
+additional terms or conditions.
diff --git a/TEST_MAPPING b/TEST_MAPPING
new file mode 100644
index 0000000..5fcbe3a
--- /dev/null
+++ b/TEST_MAPPING
@@ -0,0 +1,12 @@
+// Generated by cargo2android.py for tests in Android.bp
+{
+  "presubmit": [
+    {
+      "host": true,
+      "name": "intrusive-collections_host_test_src_lib"
+    },
+    {
+      "name": "intrusive-collections_device_test_src_lib"
+    }
+  ]
+}
diff --git a/patches/Android.bp.patch b/patches/Android.bp.patch
new file mode 100644
index 0000000..15d6516
--- /dev/null
+++ b/patches/Android.bp.patch
@@ -0,0 +1,22 @@
+diff --git a/Android.bp b/Android.bp
+index 9e3c084..d4334b6 100644
+--- a/Android.bp
++++ b/Android.bp
+@@ -1,4 +1,6 @@
+ // This file is generated by cargo2android.py --run --device --dependencies --patch=patches/Android.bp.patch.
++// TODO(victorhsieh): Add --test. The test in the current version depends on an older rand crate
++// (pre 0.8) to compile due to several API changes. However, Android's rand is already newer.
+ 
+ rust_library {
+     name: "libintrusive_collections",
+@@ -13,6 +15,10 @@ rust_library {
+     rustlibs: [
+         "libmemoffset",
+     ],
++    apex_available: [
++        "//apex_available:platform",
++        "com.android.virt",
++    ],
+ }
+ 
+ // dependent_library ["feature_list"]
diff --git a/src/adapter.rs b/src/adapter.rs
new file mode 100644
index 0000000..3a146e9
--- /dev/null
+++ b/src/adapter.rs
@@ -0,0 +1,286 @@
+// Copyright 2016 Amanieu d'Antras
+// Copyright 2020 Amari Robinson
+//
+// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
+// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
+// http://opensource.org/licenses/MIT>, at your option. This file may not be
+// copied, modified, or distributed except according to those terms.
+
+use crate::link_ops::LinkOps;
+use crate::pointer_ops::PointerOps;
+
+/// Trait for a adapter which allows a type to be inserted into an intrusive
+/// collection.
+///
+/// `LinkOps` implements the collection-specific operations which
+/// allows an object to be inserted into an intrusive collection. This type
+/// needs to implement the appropriate trait for the collection type
+/// (eg. `LinkedListOps` for inserting into a `LinkedList`).
+/// `LinkOps` type may be stateful, allowing custom link types.
+///
+/// `PointerOps` implements the collection-specific pointer conversions which
+/// allow an object to be inserted into an intrusive collection.
+/// `PointerOps` type may be stateful, allowing custom pointer types.
+///
+/// A single object type may have multiple adapters, which allows it to be part
+/// of multiple intrusive collections simultaneously.
+///
+/// In most cases you do not need to implement this trait manually: the
+/// `intrusive_adapter!` macro will generate the necessary implementation for a
+/// given type and its link field. However it is possible to implement it
+/// manually if the intrusive link is not a direct field of the object type.
+///
+/// It is also possible to create stateful adapters.
+/// This allows links and containers to be separated and avoids the need for objects to be modified to
+/// contain a link.
+///
+/// # Safety
+///
+/// It must be possible to get back a reference to the container by passing a
+/// pointer returned by `get_link` to `get_container`.
+pub unsafe trait Adapter {
+    /// Collection-specific link operations which allow an object to be inserted in
+    /// an intrusive collection.
+    type LinkOps: LinkOps;
+
+    /// Collection-specific pointer conversions which allow an object to
+    /// be inserted in an intrusive collection.
+    type PointerOps: PointerOps;
+
+    /// Gets a reference to an object from a reference to a link in that object.
+    ///
+    /// # Safety
+    ///
+    /// `link` must be a valid pointer previously returned by `get_link`.
+    unsafe fn get_value(
+        &self,
+        link: <Self::LinkOps as LinkOps>::LinkPtr,
+    ) -> *const <Self::PointerOps as PointerOps>::Value;
+
+    /// Gets a reference to the link for the given object.
+    ///
+    /// # Safety
+    ///
+    /// `value` must be a valid pointer.
+    unsafe fn get_link(
+        &self,
+        value: *const <Self::PointerOps as PointerOps>::Value,
+    ) -> <Self::LinkOps as LinkOps>::LinkPtr;
+
+    /// Returns a reference to the link operations.
+    fn link_ops(&self) -> &Self::LinkOps;
+
+    /// Returns a reference to the mutable link operations.
+    fn link_ops_mut(&mut self) -> &mut Self::LinkOps;
+
+    /// Returns a reference to the pointer converter.
+    fn pointer_ops(&self) -> &Self::PointerOps;
+}
+
+/// Unsafe macro to get a raw pointer to an outer object from a pointer to one
+/// of its fields.
+///
+/// # Examples
+///
+/// ```
+/// use intrusive_collections::container_of;
+///
+/// struct S { x: u32, y: u32 };
+/// let container = S { x: 1, y: 2 };
+/// let field = &container.x;
+/// let container2: *const S = unsafe { container_of!(field, S, x) };
+/// assert_eq!(&container as *const S, container2);
+/// ```
+///
+/// # Safety
+///
+/// This is unsafe because it assumes that the given expression is a valid
+/// pointer to the specified field of some container type.
+#[macro_export]
+macro_rules! container_of {
+    ($ptr:expr, $container:path, $field:ident) => {
+        #[allow(clippy::cast_ptr_alignment)]
+        {
+            ($ptr as *const _ as *const u8).sub($crate::offset_of!($container, $field))
+                as *const $container
+        }
+    };
+}
+
+/// Macro to generate an implementation of `Adapter` for a given set of types.
+/// In particular this will automatically generate implementations of the
+/// `get_value` and `get_link` methods for a given named field in a struct.
+///
+/// The basic syntax to create an adapter is:
+///
+/// ```rust,ignore
+/// intrusive_adapter!(Adapter = Pointer: Value { link_field: LinkType });
+/// ```
+///
+/// You can create a new instance of an adapter using the `new` method or the
+/// `NEW` associated constant. The adapter also implements the `Default` trait.
+///
+/// # Generics
+///
+/// This macro supports generic arguments:
+///
+/// ```rust,ignore
+/// intrusive_adapter!(
+///     Adapter<'lifetime, Type, Type2> =
+///         Pointer: Value {
+///             link_field: LinkType
+///         }
+///         where
+///             Type: Copy,
+///             Type2: ?Sized + 'lifetime
+///     );
+/// ```
+///
+/// Note that due to macro parsing limitations, `T: Trait` bounds are not
+/// supported in the generic argument list. You must list any trait bounds in
+/// a separate `where` clause at the end of the macro.
+///
+/// # Examples
+///
+/// ```
+/// use intrusive_collections::{LinkedListLink, RBTreeLink};
+/// use intrusive_collections::intrusive_adapter;
+///
+/// pub struct Test {
+///     link: LinkedListLink,
+///     link2: RBTreeLink,
+/// }
+/// intrusive_adapter!(MyAdapter = Box<Test>: Test { link: LinkedListLink });
+/// intrusive_adapter!(pub MyAdapter2 = Box<Test>: Test { link2: RBTreeLink });
+///
+/// pub struct Test2<T>
+///     where T: Clone + ?Sized
+/// {
+///     link: LinkedListLink,
+///     val: T,
+/// }
+/// intrusive_adapter!(MyAdapter3<'a, T> = &'a Test2<T>: Test2<T> { link: LinkedListLink } where T: ?Sized + Clone + 'a);
+/// ```
+#[macro_export]
+macro_rules! intrusive_adapter {
+    (@impl
+        $(#[$attr:meta])* ($($privacy:tt)*) $name:ident ($($args:tt),*)
+        = $pointer:ty: $value:path { $field:ident: $link:ty } $($where_:tt)*
+    ) => {
+        #[allow(explicit_outlives_requirements)]
+        $(#[$attr])*
+        $($privacy)* struct $name<$($args),*> $($where_)* {
+            link_ops: <$link as $crate::DefaultLinkOps>::Ops,
+            pointer_ops: $crate::DefaultPointerOps<$pointer>,
+        }
+        unsafe impl<$($args),*> Send for $name<$($args),*> $($where_)* {}
+        unsafe impl<$($args),*> Sync for $name<$($args),*> $($where_)* {}
+        impl<$($args),*> Copy for $name<$($args),*> $($where_)* {}
+        impl<$($args),*> Clone for $name<$($args),*> $($where_)* {
+            #[inline]
+            fn clone(&self) -> Self {
+                *self
+            }
+        }
+        impl<$($args),*> Default for $name<$($args),*> $($where_)* {
+            #[inline]
+            fn default() -> Self {
+                Self::NEW
+            }
+        }
+        #[allow(dead_code)]
+        impl<$($args),*> $name<$($args),*> $($where_)* {
+            pub const NEW: Self = $name {
+                link_ops: <$link as $crate::DefaultLinkOps>::NEW,
+                pointer_ops: $crate::DefaultPointerOps::<$pointer>::new(),
+            };
+            #[inline]
+            pub fn new() -> Self {
+                Self::NEW
+            }
+        }
+        #[allow(dead_code, unsafe_code)]
+        unsafe impl<$($args),*> $crate::Adapter for $name<$($args),*> $($where_)* {
+            type LinkOps = <$link as $crate::DefaultLinkOps>::Ops;
+            type PointerOps = $crate::DefaultPointerOps<$pointer>;
+
+            #[inline]
+            unsafe fn get_value(&self, link: <Self::LinkOps as $crate::LinkOps>::LinkPtr) -> *const <Self::PointerOps as $crate::PointerOps>::Value {
+                $crate::container_of!(link.as_ptr(), $value, $field)
+            }
+            #[inline]
+            unsafe fn get_link(&self, value: *const <Self::PointerOps as $crate::PointerOps>::Value) -> <Self::LinkOps as $crate::LinkOps>::LinkPtr {
+                // We need to do this instead of just accessing the field directly
+                // to strictly follow the stack borrow rules.
+                let ptr = (value as *const u8).add($crate::offset_of!($value, $field));
+                core::ptr::NonNull::new_unchecked(ptr as *mut _)
+            }
+            #[inline]
+            fn link_ops(&self) -> &Self::LinkOps {
+                &self.link_ops
+            }
+            #[inline]
+            fn link_ops_mut(&mut self) -> &mut Self::LinkOps {
+                &mut self.link_ops
+            }
+            #[inline]
+            fn pointer_ops(&self) -> &Self::PointerOps {
+                &self.pointer_ops
+            }
+        }
+    };
+    (@find_generic
+        $(#[$attr:meta])* ($($privacy:tt)*) $name:ident ($($prev:tt)*) > $($rest:tt)*
+    ) => {
+        intrusive_adapter!(@impl
+            $(#[$attr])* ($($privacy)*) $name ($($prev)*) $($rest)*
+        );
+    };
+    (@find_generic
+        $(#[$attr:meta])* ($($privacy:tt)*) $name:ident ($($prev:tt)*) $cur:tt $($rest:tt)*
+    ) => {
+        intrusive_adapter!(@find_generic
+            $(#[$attr])* ($($privacy)*) $name ($($prev)* $cur) $($rest)*
+        );
+    };
+    (@find_if_generic
+        $(#[$attr:meta])* ($($privacy:tt)*) $name:ident < $($rest:tt)*
+    ) => {
+        intrusive_adapter!(@find_generic
+            $(#[$attr])* ($($privacy)*) $name () $($rest)*
+        );
+    };
+    (@find_if_generic
+        $(#[$attr:meta])* ($($privacy:tt)*) $name:ident $($rest:tt)*
+    ) => {
+        intrusive_adapter!(@impl
+            $(#[$attr])* ($($privacy)*) $name () $($rest)*
+        );
+    };
+    ($(#[$attr:meta])* pub $name:ident $($rest:tt)*) => {
+        intrusive_adapter!(@find_if_generic
+            $(#[$attr])* (pub) $name $($rest)*
+        );
+    };
+    ($(#[$attr:meta])* $name:ident $($rest:tt)*) => {
+        intrusive_adapter!(@find_if_generic
+            $(#[$attr])* () $name $($rest)*
+        );
+    };
+}
+
+#[cfg(test)]
+mod tests {
+    use crate::LinkedListLink;
+    use std::rc::Rc;
+
+    struct Obj {
+        link: LinkedListLink,
+    }
+
+    #[deny(missing_docs)]
+    intrusive_adapter! {
+        /// Test doc comment
+        ObjAdapter1 = Rc<Obj>: Obj { link: LinkedListLink }
+    }
+}
diff --git a/src/key_adapter.rs b/src/key_adapter.rs
new file mode 100644
index 0000000..fa5cd2a
--- /dev/null
+++ b/src/key_adapter.rs
@@ -0,0 +1,66 @@
+// Copyright 2016 Amanieu d'Antras
+// Copyright 2020 Amari Robinson
+//
+// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
+// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
+// http://opensource.org/licenses/MIT>, at your option. This file may not be
+// copied, modified, or distributed except according to those terms.
+
+use crate::adapter::Adapter;
+use crate::pointer_ops::PointerOps;
+
+/// Extension of the `Adapter` trait to provide a way of extracting a key from
+/// an object. This key can then be used as an index in certain intrusive
+/// collections (currently only `RBTree` uses this).
+///
+/// The key can be returned either as a value or as a reference, which allows
+/// you to
+///
+/// # Examples
+///
+/// ```
+/// use intrusive_collections::intrusive_adapter;
+/// use intrusive_collections::{RBTreeLink, KeyAdapter};
+///
+/// struct S {
+///     link: RBTreeLink,
+///     key: u32,
+///     value: u64,
+/// }
+///
+/// // Adapter which returns a key by value
+/// intrusive_adapter!(MyAdapter = Box<S>: S { link : RBTreeLink });
+/// impl<'a> KeyAdapter<'a> for MyAdapter {
+///     type Key = u32;
+///     fn get_key(&self, s: &'a S) -> u32 { s.key }
+/// }
+///
+/// // Adapter which returns a key by reference
+/// intrusive_adapter!(MyAdapter2 = Box<S>: S { link : RBTreeLink });
+/// impl<'a> KeyAdapter<'a> for MyAdapter2 {
+///     type Key = &'a u32;
+///     fn get_key(&self, s: &'a S) -> &'a u32 { &s.key }
+/// }
+///
+/// struct U {
+///     link: RBTreeLink,
+///     key1: i32,
+///     key2: String,
+///     key3: f64,
+/// }
+///
+/// // Adapter which returns a tuple as a key. When used in a RBTree, this will
+/// // keep all elements sorted by `key1` first, then `key2` and finally `key3`.
+/// intrusive_adapter!(MyAdapter3 = Box<U>: U { link : RBTreeLink });
+/// impl<'a> KeyAdapter<'a> for MyAdapter3 {
+///     type Key = (i32, &'a str, f64);
+///     fn get_key(&self, u: &'a U) -> Self::Key { (u.key1, &u.key2, u.key3) }
+/// }
+/// ```
+pub trait KeyAdapter<'a>: Adapter {
+    /// Type of the key returned by `get_key`.
+    type Key;
+
+    /// Gets the key for the given object.
+    fn get_key(&self, value: &'a <Self::PointerOps as PointerOps>::Value) -> Self::Key;
+}
diff --git a/src/lib.rs b/src/lib.rs
new file mode 100644
index 0000000..928b337
--- /dev/null
+++ b/src/lib.rs
@@ -0,0 +1,316 @@
+// Copyright 2016 Amanieu d'Antras
+// Copyright 2020 Amari Robinson
+//
+// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
+// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
+// http://opensource.org/licenses/MIT>, at your option. This file may not be
+// copied, modified, or distributed except according to those terms.
+
+//! Intrusive collections for Rust.
+//!
+//! This library provides a set of high-performance intrusive collections which
+//! can offer better performance and more flexibility than standard collections.
+//!
+//! The main difference between an intrusive collection and a normal one is that
+//! while normal collections allocate memory behind your back to keep track of a
+//! set of *values*, intrusive collections never allocate memory themselves and
+//! instead keep track of a set of *objects*. Such collections are called
+//! intrusive because they requires explicit support in objects to allow them to
+//! be inserted into a collection.
+//!
+//! # Example
+//!
+//! ```
+//! use intrusive_collections::intrusive_adapter;
+//! use intrusive_collections::{LinkedList, LinkedListLink};
+//! use std::cell::Cell;
+//!
+//! // A simple struct containing an instrusive link and a value
+//! struct Test {
+//!     link: LinkedListLink,
+//!     value: Cell<i32>,
+//! }
+//!
+//! // The adapter describes how an object can be inserted into an intrusive
+//! // collection. This is automatically generated using a macro.
+//! intrusive_adapter!(TestAdapter = Box<Test>: Test { link: LinkedListLink });
+//!
+//! // Create a list and some objects
+//! let mut list = LinkedList::new(TestAdapter::new());
+//! let a = Box::new(Test {
+//!     link: LinkedListLink::new(),
+//!     value: Cell::new(1),
+//! });
+//! let b = Box::new(Test {
+//!     link: LinkedListLink::new(),
+//!     value: Cell::new(2),
+//! });
+//! let c = Box::new(Test {
+//!     link: LinkedListLink::new(),
+//!     value: Cell::new(3),
+//! });
+//!
+//! // Insert the objects at the front of the list
+//! list.push_front(a);
+//! list.push_front(b);
+//! list.push_front(c);
+//! assert_eq!(list.iter().map(|x| x.value.get()).collect::<Vec<_>>(), [3, 2, 1]);
+//!
+//! // At this point, the objects are owned by the list, and we can modify
+//! // them through the list.
+//! list.front().get().unwrap().value.set(4);
+//! assert_eq!(list.iter().map(|x| x.value.get()).collect::<Vec<_>>(), [4, 2, 1]);
+//!
+//! // Removing an object from an instrusive collection gives us back the
+//! // Box<Test> that we originally inserted into it.
+//! let a = list.pop_front().unwrap();
+//! assert_eq!(a.value.get(), 4);
+//! assert_eq!(list.iter().map(|x| x.value.get()).collect::<Vec<_>>(), [2, 1]);
+//!
+//! // Dropping the collection will automatically free b and c by
+//! // transforming them back into Box<Test> and dropping them.
+//! drop(list);
+//! ```
+//!
+//! # Links and adapters
+//!
+//! Intrusive collections track objects through links which are embedded within
+//! the objects themselves. It also allows a single object to be part of
+//! multiple intrusive collections at once by having multiple links in it.
+//!
+//! The relationship between an object and a link inside it is described by the
+//! `Adapter` trait. Intrusive collections use an implementation of this trait
+//! to determine which link in an object should be used by the collection. In
+//! most cases you do not need to write an implementation manually: the
+//! `intrusive_adapter!` macro will automatically generate the necessary code.
+//!
+//! For red-black trees, the adapter must also implement the `KeyAdapter` trait
+//! which allows a key to be extracted from an object. This key is then used to
+//! keep all elements in the tree in ascending order.
+//!
+//! ```
+//! use intrusive_collections::intrusive_adapter;
+//! use intrusive_collections::{SinglyLinkedListLink, SinglyLinkedList};
+//! use intrusive_collections::{LinkedListLink, LinkedList};
+//! use intrusive_collections::{XorLinkedList, XorLinkedListLink};
+//! use intrusive_collections::{RBTreeLink, RBTree, KeyAdapter};
+//! use std::rc::Rc;
+//!
+//! // This struct can be inside three lists and one tree simultaneously
+//! #[derive(Default)]
+//! struct Test {
+//!     link: LinkedListLink,
+//!     link2: SinglyLinkedListLink,
+//!     link3: XorLinkedListLink,
+//!     link4: RBTreeLink,
+//!     value: i32,
+//! }
+//!
+//! intrusive_adapter!(MyAdapter = Rc<Test>: Test { link: LinkedListLink });
+//! intrusive_adapter!(MyAdapter2 = Rc<Test>: Test { link2: SinglyLinkedListLink });
+//! intrusive_adapter!(MyAdapter3 = Rc<Test>: Test { link3: XorLinkedListLink });
+//! intrusive_adapter!(MyAdapter4 = Rc<Test>: Test { link4: RBTreeLink });
+//! impl<'a> KeyAdapter<'a> for MyAdapter4 {
+//!     type Key = i32;
+//!     fn get_key(&self, x: &'a Test) -> i32 { x.value }
+//! }
+//!
+//! let mut a = LinkedList::new(MyAdapter::new());
+//! let mut b = SinglyLinkedList::new(MyAdapter2::new());
+//! let mut c = XorLinkedList::new(MyAdapter3::new());
+//! let mut d = RBTree::new(MyAdapter4::new());
+//!
+//! let test = Rc::new(Test::default());
+//! a.push_front(test.clone());
+//! b.push_front(test.clone());
+//! c.push_front(test.clone());
+//! d.insert(test);
+//! ```
+//!
+//! # Cursors
+//!
+//! Intrusive collections are manipulated using cursors. A cursor is similar to
+//! an iterator, except that it can freely seek back-and-forth, and can safely
+//! mutate the list during iteration. This is similar to how a C++ iterator
+//! works.
+//!
+//! A cursor views an intrusive collection as a circular list, with a special
+//! null object between the last and first elements of the collection. A cursor
+//! will either point to a valid object in the collection or to this special
+//! null object.
+//!
+//! Cursors come in two forms: `Cursor` and `CursorMut`. A `Cursor` gives a
+//! read-only view of a collection, but you are allowed to use multiple `Cursor`
+//! objects simultaneously on the same collection. On the other hand,
+//! `CursorMut` can be used to mutate the collection, but you may only use one
+//! of them at a time.
+//!
+//! Cursors are a very powerful abstraction since they allow a collection to be
+//! mutated safely while it is being iterated on. For example, here is a
+//! function which removes all values within a given range from a `RBTree`:
+//!
+//! ```
+//! use intrusive_collections::intrusive_adapter;
+//! use intrusive_collections::{RBTreeLink, RBTree, KeyAdapter, Bound};
+//!
+//! struct Element {
+//!     link: RBTreeLink,
+//!     value: i32,
+//! }
+//!
+//! intrusive_adapter!(ElementAdapter = Box<Element>: Element { link: RBTreeLink });
+//! impl<'a> KeyAdapter<'a> for ElementAdapter {
+//!     type Key = i32;
+//!     fn get_key(&self, e: &'a Element) -> i32 { e.value }
+//! }
+//!
+//! fn remove_range(tree: &mut RBTree<ElementAdapter>, min: i32, max: i32) {
+//!     // Find the first element which is greater than or equal to min
+//!     let mut cursor = tree.lower_bound_mut(Bound::Included(&min));
+//!
+//!     // Iterate over all elements in the range [min, max]
+//!     while cursor.get().map_or(false, |e| e.value <= max) {
+//!         // CursorMut::remove will return a Some(<Box<Element>), which we
+//!         // simply drop here. This will also advance the cursor to the next
+//!         // element.
+//!         cursor.remove();
+//!     }
+//! }
+//! ```
+//!
+//! # Scoped collections
+//!
+//! Instead of taking ownership of objects inserted into them, intrusive
+//! collections can also work with borrowed values. This works by using
+//! lifetimes and the borrow checker to ensure that any objects inserted into an
+//! intrusive collection will outlive the collection itself.
+//!
+//! ```
+//! use intrusive_collections::intrusive_adapter;
+//! use intrusive_collections::{LinkedListLink, LinkedList};
+//! use typed_arena::Arena;
+//! use std::cell::Cell;
+//!
+//! struct Value {
+//!     link: LinkedListLink,
+//!     value: Cell<i32>,
+//! }
+//!
+//! // Note that we use a plain reference as the pointer type for the collection.
+//! intrusive_adapter!(ValueAdapter<'a> = &'a Value: Value { link: LinkedListLink });
+//!
+//! // Create an arena and a list. Note that since stack objects are dropped in
+//! // reverse order, the Arena must be created before the LinkedList. This
+//! // ensures that the list is dropped before the values are freed by the
+//! // arena. This is enforced by the Rust lifetime system.
+//! let arena = Arena::new();
+//! let mut list = LinkedList::new(ValueAdapter::new());
+//!
+//! // We can now insert values allocated from the arena into the linked list
+//! list.push_back(arena.alloc(Value {
+//!     link: LinkedListLink::new(),
+//!     value: Cell::new(1),
+//! }));
+//! list.push_back(arena.alloc(Value {
+//!     link: LinkedListLink::new(),
+//!     value: Cell::new(2),
+//! }));
+//! list.push_back(arena.alloc(Value {
+//!     link: LinkedListLink::new(),
+//!     value: Cell::new(3),
+//! }));
+//! assert_eq!(list.iter().map(|x| x.value.get()).collect::<Vec<_>>(), [1, 2, 3]);
+//!
+//! // We can also insert stack allocated values into an intrusive list.
+//! // Again, the values must outlive the LinkedList.
+//! let a = Value {
+//!     link: LinkedListLink::new(),
+//!     value: Cell::new(4),
+//! };
+//! let b = Value {
+//!     link: LinkedListLink::new(),
+//!     value: Cell::new(5),
+//! };
+//! let c = Value {
+//!     link: LinkedListLink::new(),
+//!     value: Cell::new(6),
+//! };
+//! let mut list2 = LinkedList::new(ValueAdapter::new());
+//! list2.push_back(&a);
+//! list2.push_back(&b);
+//! list2.push_back(&c);
+//! assert_eq!(list2.iter().map(|x| x.value.get()).collect::<Vec<_>>(), [4, 5, 6]);
+//!
+//! // Since these are shared references, any changes in the values are reflected in
+//! // the list.
+//! a.value.set(7);
+//! assert_eq!(list2.iter().map(|x| x.value.get()).collect::<Vec<_>>(), [7, 5, 6]);
+//! ```
+//!
+//! # Safety
+//!
+//! While it is possible to use intrusive collections without any unsafe code,
+//! this crate also exposes a few unsafe features.
+//!
+//! The `cursor_from_ptr` and `cursor_mut_from_ptr` allow you to create a
+//! cursor pointing to a specific element in the collection from a pointer to
+//! that element. This is unsafe because it assumes that the objected pointed to
+//! is currently inserted in the collection.
+//!
+//! The `UnsafeRef` type acts like `Rc`, except without the reference count.
+//! Instead, you are responsible for keeping track of the number of active
+//! references to an object and for freeing it once the last reference is
+//! dropped. The advantage of `UnsafeRef` over `Rc` is that it reduces the size
+//! of the allocation by two `usize` and avoids the overhead of maintaining
+//! reference counts.
+
+#![warn(missing_docs)]
+#![warn(rust_2018_idioms)]
+#![no_std]
+#![cfg_attr(feature = "nightly", feature(const_fn))]
+#![allow(clippy::declare_interior_mutable_const, clippy::collapsible_if)]
+
+#[cfg(feature = "alloc")]
+extern crate alloc;
+
+#[cfg(test)]
+extern crate std;
+
+mod unsafe_ref;
+#[macro_use]
+mod adapter;
+mod key_adapter;
+mod link_ops;
+mod pointer_ops;
+mod unchecked_option;
+
+pub mod linked_list;
+pub mod rbtree;
+pub mod singly_linked_list;
+pub mod xor_linked_list;
+
+pub use crate::adapter::Adapter;
+pub use crate::key_adapter::KeyAdapter;
+pub use crate::link_ops::{DefaultLinkOps, LinkOps};
+pub use crate::linked_list::Link as LinkedListLink;
+pub use crate::linked_list::LinkedList;
+pub use crate::pointer_ops::{DefaultPointerOps, PointerOps};
+pub use crate::rbtree::Link as RBTreeLink;
+pub use crate::rbtree::RBTree;
+pub use crate::singly_linked_list::Link as SinglyLinkedListLink;
+pub use crate::singly_linked_list::SinglyLinkedList;
+pub use crate::unsafe_ref::UnsafeRef;
+pub use crate::xor_linked_list::Link as XorLinkedListLink;
+pub use crate::xor_linked_list::XorLinkedList;
+pub use memoffset::offset_of;
+
+/// An endpoint of a range of keys.
+#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
+pub enum Bound<T> {
+    /// An inclusive bound.
+    Included(T),
+    /// An exclusive bound.
+    Excluded(T),
+    /// An infinite endpoint. Indicates that there is no bound in this direction.
+    Unbounded,
+}
diff --git a/src/link_ops.rs b/src/link_ops.rs
new file mode 100644
index 0000000..73851f4
--- /dev/null
+++ b/src/link_ops.rs
@@ -0,0 +1,40 @@
+// Copyright 2020 Amari Robinson
+//
+// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
+// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
+// http://opensource.org/licenses/MIT>, at your option. This file may not be
+// copied, modified, or distributed except according to those terms.
+
+/// Base trait for link operations.
+///
+/// `LinkPtr` is the representation of a link pointer.
+/// Typically this is `NonNull`, but compact representations such
+/// as `u8` or `u16` are possible.
+pub unsafe trait LinkOps {
+    /// The link pointer type.
+    type LinkPtr: Copy + Eq;
+
+    /// Attempts to acquire ownership of a link so that it can be used in an
+    /// intrusive collection.
+    ///
+    /// If this function succeeds then the intrusive collection will have
+    /// exclusive access to the link until `release_link` is called.
+    unsafe fn acquire_link(&mut self, ptr: Self::LinkPtr) -> bool;
+
+    /// Releases ownership of a link that was previously acquired with `acquire_link`.
+    ///
+    /// # Safety
+    /// An implementation of `release_link` must not panic.
+    unsafe fn release_link(&mut self, ptr: Self::LinkPtr);
+}
+
+/// The default implementation of `LinkOps` associated with a link type.
+pub trait DefaultLinkOps {
+    /// The default link operations.
+    type Ops: LinkOps + Default;
+
+    /// The associated constant that represents `Ops::default()`.
+    ///
+    /// This exists because `Default::default()` is not a constant function.
+    const NEW: Self::Ops;
+}
diff --git a/src/linked_list.rs b/src/linked_list.rs
new file mode 100644
index 0000000..efda06a
--- /dev/null
+++ b/src/linked_list.rs
@@ -0,0 +1,1670 @@
+// Copyright 2016 Amanieu d'Antras
+// Copyright 2020 Amari Robinson
+//
+// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
+// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
+// http://opensource.org/licenses/MIT>, at your option. This file may not be
+// copied, modified, or distributed except according to those terms.
+
+//! Intrusive doubly-linked list.
+
+use core::cell::Cell;
+use core::fmt;
+use core::ptr::NonNull;
+
+use crate::link_ops::{self, DefaultLinkOps};
+use crate::pointer_ops::PointerOps;
+use crate::singly_linked_list::SinglyLinkedListOps;
+use crate::unchecked_option::UncheckedOptionExt;
+use crate::xor_linked_list::XorLinkedListOps;
+use crate::Adapter;
+
+// =============================================================================
+// LinkedListOps
+// =============================================================================
+
+/// Link operations for `LinkedList`.
+pub unsafe trait LinkedListOps: link_ops::LinkOps {
+    /// Returns the "next" link pointer of `ptr`.
+    ///
+    /// # Safety
+    /// An implementation of `next` must not panic.
+    unsafe fn next(&self, ptr: Self::LinkPtr) -> Option<Self::LinkPtr>;
+
+    /// Returns the "prev" link pointer of `ptr`.
+    ///
+    /// # Safety
+    /// An implementation of `prev` must not panic.
+    unsafe fn prev(&self, ptr: Self::LinkPtr) -> Option<Self::LinkPtr>;
+
+    /// Sets the "next" link pointer of `ptr`.
+    ///
+    /// # Safety
+    /// An implementation of `set_next` must not panic.
+    unsafe fn set_next(&mut self, ptr: Self::LinkPtr, next: Option<Self::LinkPtr>);
+
+    /// Sets the "prev" link pointer of `ptr`.
+    ///
+    /// # Safety
+    /// An implementation of `set_prev` must not panic.
+    unsafe fn set_prev(&mut self, ptr: Self::LinkPtr, prev: Option<Self::LinkPtr>);
+}
+
+// =============================================================================
+// Link
+// =============================================================================
+
+/// Intrusive link that allows an object to be inserted into a
+/// `LinkedList`.
+#[repr(align(2))]
+pub struct Link {
+    next: Cell<Option<NonNull<Link>>>,
+    prev: Cell<Option<NonNull<Link>>>,
+}
+
+// Use a special value to indicate an unlinked node
+const UNLINKED_MARKER: Option<NonNull<Link>> =
+    unsafe { Some(NonNull::new_unchecked(1 as *mut Link)) };
+
+impl Link {
+    /// Creates a new `Link`.
+    #[inline]
+    pub const fn new() -> Link {
+        Link {
+            next: Cell::new(UNLINKED_MARKER),
+            prev: Cell::new(UNLINKED_MARKER),
+        }
+    }
+
+    /// Checks whether the `Link` is linked into a `LinkedList`.
+    #[inline]
+    pub fn is_linked(&self) -> bool {
+        self.next.get() != UNLINKED_MARKER
+    }
+
+    /// Forcibly unlinks an object from a `LinkedList`.
+    ///
+    /// # Safety
+    ///
+    /// It is undefined behavior to call this function while still linked into a
+    /// `LinkedList`. The only situation where this function is useful is
+    /// after calling `fast_clear` on a `LinkedList`, since this clears
+    /// the collection without marking the nodes as unlinked.
+    #[inline]
+    pub unsafe fn force_unlink(&self) {
+        self.next.set(UNLINKED_MARKER);
+    }
+}
+
+impl DefaultLinkOps for Link {
+    type Ops = LinkOps;
+
+    const NEW: Self::Ops = LinkOps;
+}
+
+// An object containing a link can be sent to another thread if it is unlinked.
+unsafe impl Send for Link {}
+
+// Provide an implementation of Clone which simply initializes the new link as
+// unlinked. This allows structs containing a link to derive Clone.
+impl Clone for Link {
+    #[inline]
+    fn clone(&self) -> Link {
+        Link::new()
+    }
+}
+
+// Same as above
+impl Default for Link {
+    #[inline]
+    fn default() -> Link {
+        Link::new()
+    }
+}
+
+// Provide an implementation of Debug so that structs containing a link can
+// still derive Debug.
+impl fmt::Debug for Link {
+    #[inline]
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        // There isn't anything sensible to print here except whether the link
+        // is currently in a list.
+        if self.is_linked() {
+            write!(f, "linked")
+        } else {
+            write!(f, "unlinked")
+        }
+    }
+}
+
+// =============================================================================
+// LinkOps
+// =============================================================================
+
+/// Default `LinkOps` implementation for `LinkedList`.
+#[derive(Clone, Copy, Default)]
+pub struct LinkOps;
+
+unsafe impl link_ops::LinkOps for LinkOps {
+    type LinkPtr = NonNull<Link>;
+
+    #[inline]
+    unsafe fn acquire_link(&mut self, ptr: Self::LinkPtr) -> bool {
+        if ptr.as_ref().is_linked() {
+            false
+        } else {
+            ptr.as_ref().next.set(None);
+            true
+        }
+    }
+
+    #[inline]
+    unsafe fn release_link(&mut self, ptr: Self::LinkPtr) {
+        ptr.as_ref().next.set(UNLINKED_MARKER);
+    }
+}
+
+unsafe impl LinkedListOps for LinkOps {
+    #[inline]
+    unsafe fn next(&self, ptr: Self::LinkPtr) -> Option<Self::LinkPtr> {
+        ptr.as_ref().next.get()
+    }
+
+    #[inline]
+    unsafe fn prev(&self, ptr: Self::LinkPtr) -> Option<Self::LinkPtr> {
+        ptr.as_ref().prev.get()
+    }
+
+    #[inline]
+    unsafe fn set_next(&mut self, ptr: Self::LinkPtr, next: Option<Self::LinkPtr>) {
+        ptr.as_ref().next.set(next);
+    }
+
+    #[inline]
+    unsafe fn set_prev(&mut self, ptr: Self::LinkPtr, prev: Option<Self::LinkPtr>) {
+        ptr.as_ref().prev.set(prev);
+    }
+}
+
+unsafe impl SinglyLinkedListOps for LinkOps {
+    #[inline]
+    unsafe fn next(&self, ptr: Self::LinkPtr) -> Option<Self::LinkPtr> {
+        ptr.as_ref().next.get()
+    }
+
+    #[inline]
+    unsafe fn set_next(&mut self, ptr: Self::LinkPtr, next: Option<Self::LinkPtr>) {
+        ptr.as_ref().next.set(next);
+    }
+}
+
+unsafe impl XorLinkedListOps for LinkOps {
+    #[inline]
+    unsafe fn next(
+        &self,
+        ptr: Self::LinkPtr,
+        prev: Option<Self::LinkPtr>,
+    ) -> Option<Self::LinkPtr> {
+        let packed = ptr
+            .as_ref()
+            .next
+            .get()
+            .map(|x| x.as_ptr() as usize)
+            .unwrap_or(0);
+        let raw = packed ^ prev.map(|x| x.as_ptr() as usize).unwrap_or(0);
+        NonNull::new(raw as *mut _)
+    }
+
+    #[inline]
+    unsafe fn prev(
+        &self,
+        ptr: Self::LinkPtr,
+        next: Option<Self::LinkPtr>,
+    ) -> Option<Self::LinkPtr> {
+        let packed = ptr
+            .as_ref()
+            .next
+            .get()
+            .map(|x| x.as_ptr() as usize)
+            .unwrap_or(0);
+        let raw = packed ^ next.map(|x| x.as_ptr() as usize).unwrap_or(0);
+        NonNull::new(raw as *mut _)
+    }
+
+    #[inline]
+    unsafe fn set(
+        &mut self,
+        ptr: Self::LinkPtr,
+        prev: Option<Self::LinkPtr>,
+        next: Option<Self::LinkPtr>,
+    ) {
+        let new_packed = prev.map(|x| x.as_ptr() as usize).unwrap_or(0)
+            ^ next.map(|x| x.as_ptr() as usize).unwrap_or(0);
+
+        let new_next = NonNull::new(new_packed as *mut _);
+        ptr.as_ref().next.set(new_next);
+    }
+
+    #[inline]
+    unsafe fn replace_next_or_prev(
+        &mut self,
+        ptr: Self::LinkPtr,
+        old: Option<Self::LinkPtr>,
+        new: Option<Self::LinkPtr>,
+    ) {
+        let packed = ptr
+            .as_ref()
+            .next
+            .get()
+            .map(|x| x.as_ptr() as usize)
+            .unwrap_or(0);
+        let new_packed = packed
+            ^ old.map(|x| x.as_ptr() as usize).unwrap_or(0)
+            ^ new.map(|x| x.as_ptr() as usize).unwrap_or(0);
+
+        let new_next = NonNull::new(new_packed as *mut _);
+        ptr.as_ref().next.set(new_next);
+    }
+}
+
+#[inline]
+unsafe fn link_between<T: LinkedListOps>(
+    link_ops: &mut T,
+    ptr: T::LinkPtr,
+    prev: Option<T::LinkPtr>,
+    next: Option<T::LinkPtr>,
+) {
+    if let Some(prev) = prev {
+        link_ops.set_next(prev, Some(ptr));
+    }
+    if let Some(next) = next {
+        link_ops.set_prev(next, Some(ptr));
+    }
+    link_ops.set_next(ptr, next);
+    link_ops.set_prev(ptr, prev);
+}
+
+#[inline]
+unsafe fn link_after<T: LinkedListOps>(link_ops: &mut T, ptr: T::LinkPtr, prev: T::LinkPtr) {
+    link_between(link_ops, ptr, Some(prev), link_ops.next(prev));
+}
+
+#[inline]
+unsafe fn link_before<T: LinkedListOps>(link_ops: &mut T, ptr: T::LinkPtr, next: T::LinkPtr) {
+    link_between(link_ops, ptr, link_ops.prev(next), Some(next));
+}
+
+#[inline]
+unsafe fn replace_with<T: LinkedListOps>(link_ops: &mut T, ptr: T::LinkPtr, new: T::LinkPtr) {
+    let prev = link_ops.prev(ptr);
+    let next = link_ops.next(ptr);
+
+    if let Some(prev) = prev {
+        link_ops.set_next(prev, Some(new));
+    }
+    if let Some(next) = next {
+        link_ops.set_prev(next, Some(new));
+    }
+    link_ops.set_next(new, next);
+    link_ops.set_prev(new, prev);
+    link_ops.release_link(ptr);
+}
+
+#[inline]
+unsafe fn remove<T: LinkedListOps>(link_ops: &mut T, ptr: T::LinkPtr) {
+    let prev = link_ops.prev(ptr);
+    let next = link_ops.next(ptr);
+
+    if let Some(next) = next {
+        link_ops.set_prev(next, prev);
+    }
+    if let Some(prev) = prev {
+        link_ops.set_next(prev, next);
+    }
+    link_ops.release_link(ptr);
+}
+
+#[inline]
+unsafe fn splice<T: LinkedListOps>(
+    link_ops: &mut T,
+    start: T::LinkPtr,
+    end: T::LinkPtr,
+    prev: Option<T::LinkPtr>,
+    next: Option<T::LinkPtr>,
+) {
+    link_ops.set_prev(start, prev);
+    link_ops.set_next(end, next);
+    if let Some(prev) = prev {
+        link_ops.set_next(prev, Some(start));
+    }
+    if let Some(next) = next {
+        link_ops.set_prev(next, Some(end));
+    }
+}
+
+// =============================================================================
+// Cursor, CursorMut
+// =============================================================================
+
+/// A cursor which provides read-only access to a `LinkedList`.
+pub struct Cursor<'a, A: Adapter>
+where
+    A::LinkOps: LinkedListOps,
+{
+    current: Option<<A::LinkOps as link_ops::LinkOps>::LinkPtr>,
+    list: &'a LinkedList<A>,
+}
+
+impl<'a, A: Adapter> Clone for Cursor<'a, A>
+where
+    A::LinkOps: LinkedListOps,
+{
+    #[inline]
+    fn clone(&self) -> Cursor<'a, A> {
+        Cursor {
+            current: self.current,
+            list: self.list,
+        }
+    }
+}
+
+impl<'a, A: Adapter> Cursor<'a, A>
+where
+    A::LinkOps: LinkedListOps,
+{
+    /// Checks if the cursor is currently pointing to the null object.
+    #[inline]
+    pub fn is_null(&self) -> bool {
+        self.current.is_none()
+    }
+
+    /// Returns a reference to the object that the cursor is currently
+    /// pointing to.
+    ///
+    /// This returns `None` if the cursor is currently pointing to the null
+    /// object.
+    #[inline]
+    pub fn get(&self) -> Option<&'a <A::PointerOps as PointerOps>::Value> {
+        Some(unsafe { &*self.list.adapter.get_value(self.current?) })
+    }
+
+    /// Clones and returns the pointer that points to the element that the
+    /// cursor is referencing.
+    ///
+    /// This returns `None` if the cursor is currently pointing to the null
+    /// object.
+    #[inline]
+    pub fn clone_pointer(&self) -> Option<<A::PointerOps as PointerOps>::Pointer>
+    where
+        <A::PointerOps as PointerOps>::Pointer: Clone,
+    {
+        let raw_pointer = self.get()? as *const <A::PointerOps as PointerOps>::Value;
+        Some(unsafe {
+            crate::pointer_ops::clone_pointer_from_raw(self.list.adapter.pointer_ops(), raw_pointer)
+        })
+    }
+
+    /// Moves the cursor to the next element of the `LinkedList`.
+    ///
+    /// If the cursor is pointer to the null object then this will move it to
+    /// the first element of the `LinkedList`. If it is pointing to the
+    /// last element of the `LinkedList` then this will move it to the
+    /// null object.
+    #[inline]
+    pub fn move_next(&mut self) {
+        if let Some(current) = self.current {
+            self.current = unsafe { self.list.adapter.link_ops().next(current) };
+        } else {
+            self.current = self.list.head;
+        }
+    }
+
+    /// Moves the cursor to the previous element of the `LinkedList`.
+    ///
+    /// If the cursor is pointer to the null object then this will move it to
+    /// the last element of the `LinkedList`. If it is pointing to the first
+    /// element of the `LinkedList` then this will move it to the null object.
+    #[inline]
+    pub fn move_prev(&mut self) {
+        if let Some(current) = self.current {
+            self.current = unsafe { self.list.adapter.link_ops().prev(current) };
+        } else {
+            self.current = self.list.tail;
+        }
+    }
+
+    /// Returns a cursor pointing to the next element of the `LinkedList`.
+    ///
+    /// If the cursor is pointer to the null object then this will return the
+    /// first element of the `LinkedList`. If it is pointing to the last
+    /// element of the `LinkedList` then this will return a null cursor.
+    #[inline]
+    pub fn peek_next(&self) -> Cursor<'_, A> {
+        let mut next = self.clone();
+        next.move_next();
+        next
+    }
+
+    /// Returns a cursor pointing to the previous element of the `LinkedList`.
+    ///
+    /// If the cursor is pointer to the null object then this will return the
+    /// last element of the `LinkedList`. If it is pointing to the first
+    /// element of the `LinkedList` then this will return a null cursor.
+    #[inline]
+    pub fn peek_prev(&self) -> Cursor<'_, A> {
+        let mut prev = self.clone();
+        prev.move_prev();
+        prev
+    }
+}
+
+/// A cursor which provides mutable access to a `LinkedList`.
+pub struct CursorMut<'a, A: Adapter>
+where
+    A::LinkOps: LinkedListOps,
+{
+    current: Option<<A::LinkOps as link_ops::LinkOps>::LinkPtr>,
+    list: &'a mut LinkedList<A>,
+}
+
+impl<'a, A: Adapter> CursorMut<'a, A>
+where
+    A::LinkOps: LinkedListOps,
+{
+    /// Checks if the cursor is currently pointing to the null object.
+    #[inline]
+    pub fn is_null(&self) -> bool {
+        self.current.is_none()
+    }
+
+    /// Returns a reference to the object that the cursor is currently
+    /// pointing to.
+    ///
+    /// This returns None if the cursor is currently pointing to the null
+    /// object.
+    #[inline]
+    pub fn get(&self) -> Option<&<A::PointerOps as PointerOps>::Value> {
+        Some(unsafe { &*self.list.adapter.get_value(self.current?) })
+    }
+
+    /// Returns a read-only cursor pointing to the current element.
+    ///
+    /// The lifetime of the returned `Cursor` is bound to that of the
+    /// `CursorMut`, which means it cannot outlive the `CursorMut` and that the
+    /// `CursorMut` is frozen for the lifetime of the `Cursor`.
+    #[inline]
+    pub fn as_cursor(&self) -> Cursor<'_, A> {
+        Cursor {
+            current: self.current,
+            list: self.list,
+        }
+    }
+
+    /// Moves the cursor to the next element of the `LinkedList`.
+    ///
+    /// If the cursor is pointer to the null object then this will move it to
+    /// the first element of the `LinkedList`. If it is pointing to the
+    /// last element of the `LinkedList` then this will move it to the
+    /// null object.
+    #[inline]
+    pub fn move_next(&mut self) {
+        if let Some(current) = self.current {
+            self.current = unsafe { self.list.adapter.link_ops().next(current) };
+        } else {
+            self.current = self.list.head;
+        }
+    }
+
+    /// Moves the cursor to the previous element of the `LinkedList`.
+    ///
+    /// If the cursor is pointer to the null object then this will move it to
+    /// the last element of the `LinkedList`. If it is pointing to the first
+    /// element of the `LinkedList` then this will move it to the null object.
+    #[inline]
+    pub fn move_prev(&mut self) {
+        if let Some(current) = self.current {
+            self.current = unsafe { self.list.adapter.link_ops().prev(current) };
+        } else {
+            self.current = self.list.tail;
+        }
+    }
+
+    ///Returns a cursor pointing to the next element of the `LinkedList`.
+    ///
+    /// If the cursor is pointer to the null object then this will return the
+    /// first element of the `LinkedList`. If it is pointing to the last
+    /// element of the `LinkedList` then this will return a null cursor.
+    #[inline]
+    pub fn peek_next(&self) -> Cursor<'_, A> {
+        let mut next = self.as_cursor();
+        next.move_next();
+        next
+    }
+
+    /// Returns a cursor pointing to the previous element of the `LinkedList`.
+    ///
+    /// If the cursor is pointer to the null object then this will return the
+    /// last element of the `LinkedList`. If it is pointing to the first
+    /// element of the `LinkedList` then this will return a null cursor.
+    #[inline]
+    pub fn peek_prev(&self) -> Cursor<'_, A> {
+        let mut prev = self.as_cursor();
+        prev.move_prev();
+        prev
+    }
+
+    /// Removes the current element from the `LinkedList`.
+    ///
+    /// A pointer to the element that was removed is returned, and the cursor is
+    /// moved to point to the next element in the `LinkedList`.
+    ///
+    /// If the cursor is currently pointing to the null object then no element
+    /// is removed and `None` is returned.
+    #[inline]
+    pub fn remove(&mut self) -> Option<<A::PointerOps as PointerOps>::Pointer> {
+        unsafe {
+            if let Some(current) = self.current {
+                if self.list.head == self.current {
+                    self.list.head = self.list.adapter.link_ops().next(current);
+                }
+                if self.list.tail == self.current {
+                    self.list.tail = self.list.adapter.link_ops().prev(current);
+                }
+                let next = self.list.adapter.link_ops().next(current);
+                let result = current;
+                remove(self.list.adapter.link_ops_mut(), current);
+                self.current = next;
+                Some(
+                    self.list
+                        .adapter
+                        .pointer_ops()
+                        .from_raw(self.list.adapter.get_value(result)),
+                )
+            } else {
+                None
+            }
+        }
+    }
+
+    /// Removes the current element from the `LinkedList` and inserts another
+    /// object in its place.
+    ///
+    /// A pointer to the element that was removed is returned, and the cursor is
+    /// modified to point to the newly added element.
+    ///
+    /// If the cursor is currently pointing to the null object then an error is
+    /// returned containing the given `val` parameter.
+    ///
+    /// # Panics
+    ///
+    /// Panics if the new element is already linked to a different intrusive
+    /// collection.
+    #[inline]
+    pub fn replace_with(
+        &mut self,
+        val: <A::PointerOps as PointerOps>::Pointer,
+    ) -> Result<<A::PointerOps as PointerOps>::Pointer, <A::PointerOps as PointerOps>::Pointer>
+    {
+        unsafe {
+            if let Some(current) = self.current {
+                let new = self.list.node_from_value(val);
+                if self.list.head == self.current {
+                    self.list.head = Some(new);
+                }
+                if self.list.tail == self.current {
+                    self.list.tail = Some(new);
+                }
+                let result = current;
+                replace_with(self.list.adapter.link_ops_mut(), current, new);
+                self.current = Some(new);
+                Ok(self
+                    .list
+                    .adapter
+                    .pointer_ops()
+                    .from_raw(self.list.adapter.get_value(result)))
+            } else {
+                Err(val)
+            }
+        }
+    }
+
+    /// Inserts a new element into the `LinkedList` after the current one.
+    ///
+    /// If the cursor is pointing at the null object then the new element is
+    /// inserted at the front of the `LinkedList`.
+    ///
+    /// # Panics
+    ///
+    /// Panics if the new element is already linked to a different intrusive
+    /// collection.
+    #[inline]
+    pub fn insert_after(&mut self, val: <A::PointerOps as PointerOps>::Pointer) {
+        unsafe {
+            let new = self.list.node_from_value(val);
+            if let Some(current) = self.current {
+                link_after(self.list.adapter.link_ops_mut(), new, current);
+            } else {
+                link_between(self.list.adapter.link_ops_mut(), new, None, self.list.head);
+                self.list.head = Some(new);
+            }
+            if self.list.tail == self.current {
+                self.list.tail = Some(new);
+            }
+        }
+    }
+
+    /// Inserts a new element into the `LinkedList` before the current one.
+    ///
+    /// If the cursor is pointing at the null object then the new element is
+    /// inserted at the end of the `LinkedList`.
+    ///
+    /// # Panics
+    ///
+    /// Panics if the new element is already linked to a different intrusive
+    /// collection.
+    #[inline]
+    pub fn insert_before(&mut self, val: <A::PointerOps as PointerOps>::Pointer) {
+        unsafe {
+            let new = self.list.node_from_value(val);
+
+            let link_ops = self.list.adapter.link_ops_mut();
+
+            if let Some(current) = self.current {
+                link_before(link_ops, new, current);
+            } else {
+                link_between(link_ops, new, self.list.tail, None);
+                self.list.tail = Some(new);
+            }
+            if self.list.head == self.current {
+                self.list.head = Some(new);
+            }
+        }
+    }
+
+    /// Inserts the elements from the given `LinkedList` after the current one.
+    ///
+    /// If the cursor is pointing at the null object then the new elements are
+    /// inserted at the start of the `LinkedList`.
+    #[inline]
+    pub fn splice_after(&mut self, mut list: LinkedList<A>) {
+        if !list.is_empty() {
+            unsafe {
+                let head = list.head.unwrap_unchecked();
+                let tail = list.tail.unwrap_unchecked();
+
+                let link_ops = self.list.adapter.link_ops_mut();
+
+                if let Some(current) = self.current {
+                    splice(link_ops, head, tail, Some(current), link_ops.next(current));
+                } else {
+                    splice(link_ops, head, tail, None, self.list.head);
+                    self.list.head = list.head;
+                }
+                if self.list.tail == self.current {
+                    self.list.tail = list.tail;
+                }
+                list.head = None;
+                list.tail = None;
+            }
+        }
+    }
+
+    /// Moves all element from the given `LinkedList` before the current one.
+    ///
+    /// If the cursor is pointing at the null object then the new elements are
+    /// inserted at the end of the `LinkedList`.
+    #[inline]
+    pub fn splice_before(&mut self, mut list: LinkedList<A>) {
+        if !list.is_empty() {
+            unsafe {
+                let head = list.head.unwrap_unchecked();
+                let tail = list.tail.unwrap_unchecked();
+
+                let link_ops = self.list.adapter.link_ops_mut();
+
+                if let Some(current) = self.current {
+                    splice(link_ops, head, tail, link_ops.prev(current), Some(current));
+                } else {
+                    splice(link_ops, head, tail, self.list.tail, None);
+                    self.list.tail = list.tail;
+                }
+                if self.list.head == self.current {
+                    self.list.head = list.head;
+                }
+                list.head = None;
+                list.tail = None;
+            }
+        }
+    }
+
+    /// Splits the list into two after the current element. This will return a
+    /// new list consisting of everything after the cursor, with the original
+    /// list retaining everything before.
+    ///
+    /// If the cursor is pointing at the null object then the entire contents
+    /// of the `LinkedList` are moved.
+    #[inline]
+    pub fn split_after(&mut self) -> LinkedList<A>
+    where
+        A: Clone,
+    {
+        if let Some(current) = self.current {
+            unsafe {
+                let mut list = LinkedList {
+                    head: self.list.adapter.link_ops().next(current),
+                    tail: self.list.tail,
+                    adapter: self.list.adapter.clone(),
+                };
+                if let Some(head) = list.head {
+                    self.list.adapter.link_ops_mut().set_prev(head, None);
+                } else {
+                    list.tail = None;
+                }
+                self.list.adapter.link_ops_mut().set_next(current, None);
+                self.list.tail = self.current;
+                list
+            }
+        } else {
+            let list = LinkedList {
+                head: self.list.head,
+                tail: self.list.tail,
+                adapter: self.list.adapter.clone(),
+            };
+            self.list.head = None;
+            self.list.tail = None;
+            list
+        }
+    }
+
+    /// Splits the list into two before the current element. This will return a
+    /// new list consisting of everything before the cursor, with the original
+    /// list retaining everything after.
+    ///
+    /// If the cursor is pointing at the null object then the entire contents
+    /// of the `LinkedList` are moved.
+    #[inline]
+    pub fn split_before(&mut self) -> LinkedList<A>
+    where
+        A: Clone,
+    {
+        if let Some(current) = self.current {
+            unsafe {
+                let mut list = LinkedList {
+                    head: self.list.head,
+                    tail: self.list.adapter.link_ops().prev(current),
+                    adapter: self.list.adapter.clone(),
+                };
+                if let Some(tail) = list.tail {
+                    self.list.adapter.link_ops_mut().set_prev(tail, None);
+                } else {
+                    list.head = None;
+                }
+                self.list.adapter.link_ops_mut().set_prev(current, None);
+                self.list.head = self.current;
+                list
+            }
+        } else {
+            let list = LinkedList {
+                head: self.list.head,
+                tail: self.list.tail,
+                adapter: self.list.adapter.clone(),
+            };
+            self.list.head = None;
+            self.list.tail = None;
+            list
+        }
+    }
+}
+
+// =============================================================================
+// LinkedList
+// =============================================================================
+
+/// An intrusive doubly-linked list.
+///
+/// When this collection is dropped, all elements linked into it will be
+/// converted back to owned pointers and dropped.
+pub struct LinkedList<A: Adapter>
+where
+    A::LinkOps: LinkedListOps,
+{
+    head: Option<<A::LinkOps as link_ops::LinkOps>::LinkPtr>,
+    tail: Option<<A::LinkOps as link_ops::LinkOps>::LinkPtr>,
+    adapter: A,
+}
+
+impl<A: Adapter> LinkedList<A>
+where
+    A::LinkOps: LinkedListOps,
+{
+    #[inline]
+    fn node_from_value(
+        &mut self,
+        val: <A::PointerOps as PointerOps>::Pointer,
+    ) -> <A::LinkOps as link_ops::LinkOps>::LinkPtr {
+        use link_ops::LinkOps;
+
+        unsafe {
+            let raw = self.adapter.pointer_ops().into_raw(val);
+            let link = self.adapter.get_link(raw);
+
+            if !self.adapter.link_ops_mut().acquire_link(link) {
+                // convert the node back into a pointer
+                self.adapter.pointer_ops().from_raw(raw);
+
+                panic!("attempted to insert an object that is already linked");
+            }
+
+            link
+        }
+    }
+
+    /// Creates an empty `LinkedList`.
+    #[cfg(not(feature = "nightly"))]
+    #[inline]
+    pub fn new(adapter: A) -> LinkedList<A> {
+        LinkedList {
+            head: None,
+            tail: None,
+            adapter,
+        }
+    }
+
+    /// Creates an empty `LinkedList`.
+    #[cfg(feature = "nightly")]
+    #[inline]
+    pub const fn new(adapter: A) -> LinkedList<A> {
+        LinkedList {
+            head: None,
+            tail: None,
+            adapter,
+        }
+    }
+
+    /// Returns `true` if the `LinkedList` is empty.
+    #[inline]
+    pub fn is_empty(&self) -> bool {
+        self.head.is_none()
+    }
+
+    /// Returns a null `Cursor` for this list.
+    #[inline]
+    pub fn cursor(&self) -> Cursor<'_, A> {
+        Cursor {
+            current: None,
+            list: self,
+        }
+    }
+
+    /// Returns a null `CursorMut` for this list.
+    #[inline]
+    pub fn cursor_mut(&mut self) -> CursorMut<'_, A> {
+        CursorMut {
+            current: None,
+            list: self,
+        }
+    }
+
+    /// Creates a `Cursor` from a pointer to an element.
+    ///
+    /// # Safety
+    ///
+    /// `ptr` must be a pointer to an object that is part of this list.
+    #[inline]
+    pub unsafe fn cursor_from_ptr(
+        &self,
+        ptr: *const <A::PointerOps as PointerOps>::Value,
+    ) -> Cursor<'_, A> {
+        Cursor {
+            current: Some(self.adapter.get_link(ptr)),
+            list: self,
+        }
+    }
+
+    /// Creates a `CursorMut` from a pointer to an element.
+    ///
+    /// # Safety
+    ///
+    /// `ptr` must be a pointer to an object that is part of this list.
+    #[inline]
+    pub unsafe fn cursor_mut_from_ptr(
+        &mut self,
+        ptr: *const <A::PointerOps as PointerOps>::Value,
+    ) -> CursorMut<'_, A> {
+        CursorMut {
+            current: Some(self.adapter.get_link(ptr)),
+            list: self,
+        }
+    }
+
+    /// Returns a `Cursor` pointing to the first element of the list. If the
+    /// list is empty then a null cursor is returned.
+    #[inline]
+    pub fn front(&self) -> Cursor<'_, A> {
+        let mut cursor = self.cursor();
+        cursor.move_next();
+        cursor
+    }
+
+    /// Returns a `CursorMut` pointing to the first element of the list. If the
+    /// the list is empty then a null cursor is returned.
+    #[inline]
+    pub fn front_mut(&mut self) -> CursorMut<'_, A> {
+        let mut cursor = self.cursor_mut();
+        cursor.move_next();
+        cursor
+    }
+
+    /// Returns a `Cursor` pointing to the last element of the list. If the list
+    /// is empty then a null cursor is returned.
+    #[inline]
+    pub fn back(&self) -> Cursor<'_, A> {
+        let mut cursor = self.cursor();
+        cursor.move_prev();
+        cursor
+    }
+
+    /// Returns a `CursorMut` pointing to the last element of the list. If the
+    /// list is empty then a null cursor is returned.
+    #[inline]
+    pub fn back_mut(&mut self) -> CursorMut<'_, A> {
+        let mut cursor = self.cursor_mut();
+        cursor.move_prev();
+        cursor
+    }
+
+    /// Gets an iterator over the objects in the `LinkedList`.
+    #[inline]
+    pub fn iter(&self) -> Iter<'_, A> {
+        Iter {
+            head: self.head,
+            tail: self.tail,
+            list: self,
+        }
+    }
+
+    /// Removes all elements from the `LinkedList`.
+    ///
+    /// This will unlink all object currently in the list, which requires
+    /// iterating through all elements in the `LinkedList`. Each element is
+    /// converted back to an owned pointer and then dropped.
+    #[inline]
+    pub fn clear(&mut self) {
+        use link_ops::LinkOps;
+
+        let mut current = self.head;
+        self.head = None;
+        self.tail = None;
+        while let Some(x) = current {
+            unsafe {
+                let next = self.adapter.link_ops().next(x);
+                self.adapter.link_ops_mut().release_link(x);
+                self.adapter
+                    .pointer_ops()
+                    .from_raw(self.adapter.get_value(x));
+                current = next;
+            }
+        }
+    }
+
+    /// Empties the `LinkedList` without unlinking or freeing objects in it.
+    ///
+    /// Since this does not unlink any objects, any attempts to link these
+    /// objects into another `LinkedList` will fail but will not cause any
+    /// memory unsafety. To unlink those objects manually, you must call the
+    /// `force_unlink` function on them.
+    #[inline]
+    pub fn fast_clear(&mut self) {
+        self.head = None;
+        self.tail = None;
+    }
+
+    /// Takes all the elements out of the `LinkedList`, leaving it empty.
+    /// The taken elements are returned as a new `LinkedList`.
+    #[inline]
+    pub fn take(&mut self) -> LinkedList<A>
+    where
+        A: Clone,
+    {
+        let list = LinkedList {
+            head: self.head,
+            tail: self.tail,
+            adapter: self.adapter.clone(),
+        };
+        self.head = None;
+        self.tail = None;
+        list
+    }
+
+    /// Inserts a new element at the start of the `LinkedList`.
+    #[inline]
+    pub fn push_front(&mut self, val: <A::PointerOps as PointerOps>::Pointer) {
+        self.cursor_mut().insert_after(val);
+    }
+
+    /// Inserts a new element at the end of the `LinkedList`.
+    #[inline]
+    pub fn push_back(&mut self, val: <A::PointerOps as PointerOps>::Pointer) {
+        self.cursor_mut().insert_before(val);
+    }
+
+    /// Removes the first element of the `LinkedList`.
+    ///
+    /// This returns `None` if the `LinkedList` is empty.
+    #[inline]
+    pub fn pop_front(&mut self) -> Option<<A::PointerOps as PointerOps>::Pointer> {
+        self.front_mut().remove()
+    }
+
+    /// Removes the last element of the `LinkedList`.
+    ///
+    /// This returns `None` if the `LinkedList` is empty.
+    #[inline]
+    pub fn pop_back(&mut self) -> Option<<A::PointerOps as PointerOps>::Pointer> {
+        self.back_mut().remove()
+    }
+}
+
+// Allow read-only access to values from multiple threads
+unsafe impl<A: Adapter + Sync> Sync for LinkedList<A>
+where
+    <A::PointerOps as PointerOps>::Value: Sync,
+    A::LinkOps: LinkedListOps,
+{
+}
+
+// Allow sending to another thread if the ownership (represented by the <A::PointerOps as PointerOps>::Pointer owned
+// pointer type) can be transferred to another thread.
+unsafe impl<A: Adapter + Send> Send for LinkedList<A>
+where
+    <A::PointerOps as PointerOps>::Pointer: Send,
+    A::LinkOps: LinkedListOps,
+{
+}
+
+// Drop all owned pointers if the collection is dropped
+impl<A: Adapter> Drop for LinkedList<A>
+where
+    A::LinkOps: LinkedListOps,
+{
+    #[inline]
+    fn drop(&mut self) {
+        self.clear();
+    }
+}
+
+impl<A: Adapter> IntoIterator for LinkedList<A>
+where
+    A::LinkOps: LinkedListOps,
+{
+    type Item = <A::PointerOps as PointerOps>::Pointer;
+    type IntoIter = IntoIter<A>;
+
+    #[inline]
+    fn into_iter(self) -> IntoIter<A> {
+        IntoIter { list: self }
+    }
+}
+
+impl<'a, A: Adapter + 'a> IntoIterator for &'a LinkedList<A>
+where
+    A::LinkOps: LinkedListOps,
+{
+    type Item = &'a <A::PointerOps as PointerOps>::Value;
+    type IntoIter = Iter<'a, A>;
+
+    #[inline]
+    fn into_iter(self) -> Iter<'a, A> {
+        self.iter()
+    }
+}
+
+impl<A: Adapter + Default> Default for LinkedList<A>
+where
+    A::LinkOps: LinkedListOps,
+{
+    fn default() -> LinkedList<A> {
+        LinkedList::new(A::default())
+    }
+}
+
+impl<A: Adapter> fmt::Debug for LinkedList<A>
+where
+    A::LinkOps: LinkedListOps,
+    <A::PointerOps as PointerOps>::Value: fmt::Debug,
+{
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_list().entries(self.iter()).finish()
+    }
+}
+
+// =============================================================================
+// Iter
+// =============================================================================
+
+/// An iterator over references to the items of a `LinkedList`.
+pub struct Iter<'a, A: Adapter>
+where
+    A::LinkOps: LinkedListOps,
+{
+    head: Option<<A::LinkOps as link_ops::LinkOps>::LinkPtr>,
+    tail: Option<<A::LinkOps as link_ops::LinkOps>::LinkPtr>,
+    list: &'a LinkedList<A>,
+}
+impl<'a, A: Adapter + 'a> Iterator for Iter<'a, A>
+where
+    A::LinkOps: LinkedListOps,
+{
+    type Item = &'a <A::PointerOps as PointerOps>::Value;
+
+    #[inline]
+    fn next(&mut self) -> Option<&'a <A::PointerOps as PointerOps>::Value> {
+        let head = self.head?;
+
+        if Some(head) == self.tail {
+            self.head = None;
+            self.tail = None;
+        } else {
+            self.head = unsafe { self.list.adapter.link_ops().next(head) };
+        }
+        Some(unsafe { &*self.list.adapter.get_value(head) })
+    }
+}
+impl<'a, A: Adapter + 'a> DoubleEndedIterator for Iter<'a, A>
+where
+    A::LinkOps: LinkedListOps,
+{
+    #[inline]
+    fn next_back(&mut self) -> Option<&'a <A::PointerOps as PointerOps>::Value> {
+        let tail = self.tail?;
+
+        if Some(tail) == self.head {
+            self.head = None;
+            self.tail = None;
+        } else {
+            self.tail = unsafe { self.list.adapter.link_ops().prev(tail) };
+        }
+        Some(unsafe { &*self.list.adapter.get_value(tail) })
+    }
+}
+impl<'a, A: Adapter + 'a> Clone for Iter<'a, A>
+where
+    A::LinkOps: LinkedListOps,
+{
+    #[inline]
+    fn clone(&self) -> Iter<'a, A> {
+        Iter {
+            head: self.head,
+            tail: self.tail,
+            list: self.list,
+        }
+    }
+}
+
+// =============================================================================
+// IntoIter
+// =============================================================================
+
+/// An iterator which consumes a `LinkedList`.
+pub struct IntoIter<A: Adapter>
+where
+    A::LinkOps: LinkedListOps,
+{
+    list: LinkedList<A>,
+}
+impl<A: Adapter> Iterator for IntoIter<A>
+where
+    A::LinkOps: LinkedListOps,
+{
+    type Item = <A::PointerOps as PointerOps>::Pointer;
+
+    #[inline]
+    fn next(&mut self) -> Option<<A::PointerOps as PointerOps>::Pointer> {
+        self.list.pop_front()
+    }
+}
+impl<A: Adapter> DoubleEndedIterator for IntoIter<A>
+where
+    A::LinkOps: LinkedListOps,
+{
+    #[inline]
+    fn next_back(&mut self) -> Option<<A::PointerOps as PointerOps>::Pointer> {
+        self.list.pop_back()
+    }
+}
+
+// =============================================================================
+// Tests
+// =============================================================================
+
+#[cfg(test)]
+mod tests {
+    use super::{Link, LinkedList};
+    use std::fmt;
+    use std::format;
+    use std::rc::Rc;
+    use std::vec::Vec;
+
+    struct Obj {
+        link1: Link,
+        link2: Link,
+        value: u32,
+    }
+    impl fmt::Debug for Obj {
+        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+            write!(f, "{}", self.value)
+        }
+    }
+    intrusive_adapter!(ObjAdapter1 = Rc<Obj>: Obj { link1: Link });
+    intrusive_adapter!(ObjAdapter2 = Rc<Obj>: Obj { link2: Link });
+    fn make_obj(value: u32) -> Rc<Obj> {
+        Rc::new(Obj {
+            link1: Link::new(),
+            link2: Link::default(),
+            value,
+        })
+    }
+
+    #[test]
+    fn test_link() {
+        let a = make_obj(1);
+        assert!(!a.link1.is_linked());
+        assert!(!a.link2.is_linked());
+
+        let mut b = LinkedList::<ObjAdapter1>::default();
+        assert!(b.is_empty());
+
+        b.cursor_mut().insert_after(a.clone());
+        assert!(!b.is_empty());
+        assert!(a.link1.is_linked());
+        assert!(!a.link2.is_linked());
+        assert_eq!(format!("{:?}", a.link1), "linked");
+        assert_eq!(format!("{:?}", a.link2), "unlinked");
+
+        assert_eq!(
+            b.front_mut().remove().unwrap().as_ref() as *const _,
+            a.as_ref() as *const _
+        );
+        assert!(b.is_empty());
+        assert!(!a.link1.is_linked());
+        assert!(!a.link2.is_linked());
+    }
+
+    #[test]
+    fn test_cursor() {
+        let a = make_obj(1);
+        let b = make_obj(2);
+        let c = make_obj(3);
+
+        let mut l = LinkedList::new(ObjAdapter1::new());
+        let mut cur = l.cursor_mut();
+        assert!(cur.is_null());
+        assert!(cur.get().is_none());
+        assert!(cur.remove().is_none());
+        assert_eq!(
+            cur.replace_with(a.clone()).unwrap_err().as_ref() as *const _,
+            a.as_ref() as *const _
+        );
+
+        cur.insert_before(a.clone());
+        cur.insert_before(c.clone());
+        cur.move_prev();
+        cur.insert_before(b.clone());
+        assert!(cur.peek_next().is_null());
+        cur.move_next();
+        assert!(cur.is_null());
+
+        cur.move_next();
+        assert!(cur.peek_prev().is_null());
+        assert!(!cur.is_null());
+        assert_eq!(cur.get().unwrap() as *const _, a.as_ref() as *const _);
+
+        {
+            let mut cur2 = cur.as_cursor();
+            assert_eq!(cur2.get().unwrap() as *const _, a.as_ref() as *const _);
+            assert_eq!(cur2.peek_next().get().unwrap().value, 2);
+            cur2.move_next();
+            assert_eq!(cur2.get().unwrap().value, 2);
+            cur2.move_next();
+            assert_eq!(cur2.peek_prev().get().unwrap().value, 2);
+            assert_eq!(cur2.get().unwrap() as *const _, c.as_ref() as *const _);
+            cur2.move_prev();
+            assert_eq!(cur2.get().unwrap() as *const _, b.as_ref() as *const _);
+            cur2.move_next();
+            assert_eq!(cur2.get().unwrap() as *const _, c.as_ref() as *const _);
+            cur2.move_next();
+            assert!(cur2.is_null());
+            assert!(cur2.clone().get().is_none());
+        }
+        assert_eq!(cur.get().unwrap() as *const _, a.as_ref() as *const _);
+
+        cur.move_next();
+        assert_eq!(
+            cur.remove().unwrap().as_ref() as *const _,
+            b.as_ref() as *const _
+        );
+        assert_eq!(cur.get().unwrap() as *const _, c.as_ref() as *const _);
+        cur.insert_after(b.clone());
+        assert_eq!(cur.get().unwrap() as *const _, c.as_ref() as *const _);
+        cur.move_prev();
+        assert_eq!(cur.get().unwrap() as *const _, a.as_ref() as *const _);
+        assert_eq!(
+            cur.remove().unwrap().as_ref() as *const _,
+            a.as_ref() as *const _
+        );
+        assert!(!a.link1.is_linked());
+        assert!(c.link1.is_linked());
+        assert_eq!(cur.get().unwrap() as *const _, c.as_ref() as *const _);
+        assert_eq!(
+            cur.replace_with(a.clone()).unwrap().as_ref() as *const _,
+            c.as_ref() as *const _
+        );
+        assert!(a.link1.is_linked());
+        assert!(!c.link1.is_linked());
+        assert_eq!(cur.get().unwrap() as *const _, a.as_ref() as *const _);
+        cur.move_next();
+        assert_eq!(
+            cur.replace_with(c.clone()).unwrap().as_ref() as *const _,
+            b.as_ref() as *const _
+        );
+        assert!(a.link1.is_linked());
+        assert!(!b.link1.is_linked());
+        assert!(c.link1.is_linked());
+        assert_eq!(cur.get().unwrap() as *const _, c.as_ref() as *const _);
+    }
+
+    #[test]
+    fn test_push_pop() {
+        let a = make_obj(1);
+        let b = make_obj(2);
+        let c = make_obj(3);
+
+        let mut l = LinkedList::new(ObjAdapter1::new());
+        l.push_front(a);
+        assert_eq!(l.iter().map(|x| x.value).collect::<Vec<_>>(), [1]);
+        l.push_front(b);
+        assert_eq!(l.iter().map(|x| x.value).collect::<Vec<_>>(), [2, 1]);
+        l.push_back(c);
+        assert_eq!(l.iter().map(|x| x.value).collect::<Vec<_>>(), [2, 1, 3]);
+        assert_eq!(l.pop_front().unwrap().value, 2);
+        assert_eq!(l.iter().map(|x| x.value).collect::<Vec<_>>(), [1, 3]);
+        assert_eq!(l.pop_back().unwrap().value, 3);
+        assert_eq!(l.iter().map(|x| x.value).collect::<Vec<_>>(), [1]);
+        assert_eq!(l.pop_front().unwrap().value, 1);
+        assert_eq!(l.iter().map(|x| x.value).collect::<Vec<_>>(), []);
+        assert!(l.pop_front().is_none());
+        assert_eq!(l.iter().map(|x| x.value).collect::<Vec<_>>(), []);
+        assert!(l.pop_back().is_none());
+        assert_eq!(l.iter().map(|x| x.value).collect::<Vec<_>>(), []);
+    }
+
+    #[test]
+    fn test_split_splice() {
+        let mut l1 = LinkedList::new(ObjAdapter1::new());
+        let mut l2 = LinkedList::new(ObjAdapter1::new());
+        let mut l3 = LinkedList::new(ObjAdapter1::new());
+
+        let a = make_obj(1);
+        let b = make_obj(2);
+        let c = make_obj(3);
+        let d = make_obj(4);
+        l1.cursor_mut().insert_before(a);
+        l1.cursor_mut().insert_before(b);
+        l1.cursor_mut().insert_before(c);
+        l1.cursor_mut().insert_before(d);
+        assert_eq!(l1.iter().map(|x| x.value).collect::<Vec<_>>(), [1, 2, 3, 4]);
+        assert_eq!(l2.iter().map(|x| x.value).collect::<Vec<_>>(), []);
+        assert_eq!(l3.iter().map(|x| x.value).collect::<Vec<_>>(), []);
+        {
+            let mut cur = l1.front_mut();
+            cur.move_next();
+            l2 = cur.split_after();
+        }
+        assert_eq!(l1.iter().map(|x| x.value).collect::<Vec<_>>(), [1, 2]);
+        assert_eq!(l2.iter().map(|x| x.value).collect::<Vec<_>>(), [3, 4]);
+        assert_eq!(l3.iter().map(|x| x.value).collect::<Vec<_>>(), []);
+        {
+            let mut cur = l2.back_mut();
+            l3 = cur.split_before();
+        }
+        assert_eq!(l1.iter().map(|x| x.value).collect::<Vec<_>>(), [1, 2]);
+        assert_eq!(l2.iter().map(|x| x.value).collect::<Vec<_>>(), [4]);
+        assert_eq!(l3.iter().map(|x| x.value).collect::<Vec<_>>(), [3]);
+        {
+            let mut cur = l1.front_mut();
+            cur.splice_after(l2.take());
+        }
+        assert_eq!(l1.iter().map(|x| x.value).collect::<Vec<_>>(), [1, 4, 2]);
+        assert_eq!(l2.iter().map(|x| x.value).collect::<Vec<_>>(), []);
+        assert_eq!(l3.iter().map(|x| x.value).collect::<Vec<_>>(), [3]);
+        {
+            let mut cur = l1.front_mut();
+            cur.move_next();
+            cur.splice_before(l3.take());
+        }
+        assert_eq!(l1.iter().map(|x| x.value).collect::<Vec<_>>(), [1, 3, 4, 2]);
+        assert_eq!(l2.iter().map(|x| x.value).collect::<Vec<_>>(), []);
+        assert_eq!(l3.iter().map(|x| x.value).collect::<Vec<_>>(), []);
+        {
+            let mut cur = l2.cursor_mut();
+            cur.splice_after(l1.take());
+        }
+        assert_eq!(l1.iter().map(|x| x.value).collect::<Vec<_>>(), []);
+        assert_eq!(l2.iter().map(|x| x.value).collect::<Vec<_>>(), [1, 3, 4, 2]);
+        assert_eq!(l3.iter().map(|x| x.value).collect::<Vec<_>>(), []);
+        {
+            let mut cur = l1.cursor_mut();
+            cur.splice_before(l2.take());
+        }
+        assert_eq!(l1.iter().map(|x| x.value).collect::<Vec<_>>(), [1, 3, 4, 2]);
+        assert_eq!(l2.iter().map(|x| x.value).collect::<Vec<_>>(), []);
+        assert_eq!(l3.iter().map(|x| x.value).collect::<Vec<_>>(), []);
+        {
+            let mut cur = l1.cursor_mut();
+            l2 = cur.split_after();
+        }
+        assert_eq!(l1.iter().map(|x| x.value).collect::<Vec<_>>(), []);
+        assert_eq!(l2.iter().map(|x| x.value).collect::<Vec<_>>(), [1, 3, 4, 2]);
+        assert_eq!(l3.iter().map(|x| x.value).collect::<Vec<_>>(), []);
+        {
+            let mut cur = l2.cursor_mut();
+            l1 = cur.split_before();
+        }
+        assert_eq!(l1.iter().map(|x| x.value).collect::<Vec<_>>(), [1, 3, 4, 2]);
+        assert_eq!(l2.iter().map(|x| x.value).collect::<Vec<_>>(), []);
+        assert_eq!(l3.iter().map(|x| x.value).collect::<Vec<_>>(), []);
+        {
+            let mut cur = l1.front_mut();
+            l2 = cur.split_before();
+        }
+        assert_eq!(l1.iter().map(|x| x.value).collect::<Vec<_>>(), [1, 3, 4, 2]);
+        assert_eq!(l2.iter().map(|x| x.value).collect::<Vec<_>>(), []);
+        assert_eq!(l3.iter().map(|x| x.value).collect::<Vec<_>>(), []);
+        {
+            let mut cur = l1.back_mut();
+            l2 = cur.split_after();
+        }
+        assert_eq!(l1.iter().map(|x| x.value).collect::<Vec<_>>(), [1, 3, 4, 2]);
+        assert_eq!(l2.iter().map(|x| x.value).collect::<Vec<_>>(), []);
+        assert_eq!(l3.iter().map(|x| x.value).collect::<Vec<_>>(), []);
+    }
+
+    #[test]
+    fn test_iter() {
+        let mut l = LinkedList::new(ObjAdapter1::new());
+        let a = make_obj(1);
+        let b = make_obj(2);
+        let c = make_obj(3);
+        let d = make_obj(4);
+        l.cursor_mut().insert_before(a.clone());
+        l.cursor_mut().insert_before(b.clone());
+        l.cursor_mut().insert_before(c.clone());
+        l.cursor_mut().insert_before(d.clone());
+
+        assert_eq!(l.front().get().unwrap().value, 1);
+        assert_eq!(l.back().get().unwrap().value, 4);
+        unsafe {
+            assert_eq!(l.cursor_from_ptr(b.as_ref()).get().unwrap().value, 2);
+            assert_eq!(l.cursor_mut_from_ptr(c.as_ref()).get().unwrap().value, 3);
+        }
+
+        let mut v = Vec::new();
+        for x in &l {
+            v.push(x.value);
+        }
+        assert_eq!(v, [1, 2, 3, 4]);
+        assert_eq!(
+            l.iter().clone().map(|x| x.value).collect::<Vec<_>>(),
+            [1, 2, 3, 4]
+        );
+        assert_eq!(
+            l.iter().rev().map(|x| x.value).collect::<Vec<_>>(),
+            [4, 3, 2, 1]
+        );
+        assert_eq!(l.iter().map(|x| x.value).collect::<Vec<_>>(), [1, 2, 3, 4]);
+
+        assert_eq!(format!("{:?}", l), "[1, 2, 3, 4]");
+
+        let mut v = Vec::new();
+        for x in l.take() {
+            v.push(x.value);
+        }
+        assert_eq!(v, [1, 2, 3, 4]);
+        assert!(l.is_empty());
+        assert!(!a.link1.is_linked());
+        assert!(!b.link1.is_linked());
+        assert!(!c.link1.is_linked());
+        assert!(!d.link1.is_linked());
+
+        l.cursor_mut().insert_before(a.clone());
+        l.cursor_mut().insert_before(b.clone());
+        l.cursor_mut().insert_before(c.clone());
+        l.cursor_mut().insert_before(d.clone());
+        l.clear();
+        assert!(l.is_empty());
+        assert!(!a.link1.is_linked());
+        assert!(!b.link1.is_linked());
+        assert!(!c.link1.is_linked());
+        assert!(!d.link1.is_linked());
+
+        v.clear();
+        l.cursor_mut().insert_before(a.clone());
+        l.cursor_mut().insert_before(b.clone());
+        l.cursor_mut().insert_before(c.clone());
+        l.cursor_mut().insert_before(d.clone());
+        for x in l.into_iter().rev() {
+            v.push(x.value);
+        }
+        assert_eq!(v, [4, 3, 2, 1]);
+        assert!(!a.link1.is_linked());
+        assert!(!b.link1.is_linked());
+        assert!(!c.link1.is_linked());
+        assert!(!d.link1.is_linked());
+    }
+
+    #[test]
+    fn test_multi_list() {
+        let mut l1 = LinkedList::new(ObjAdapter1::new());
+        let mut l2 = LinkedList::new(ObjAdapter2::new());
+        let a = make_obj(1);
+        let b = make_obj(2);
+        let c = make_obj(3);
+        let d = make_obj(4);
+        l1.cursor_mut().insert_before(a.clone());
+        l1.cursor_mut().insert_before(b.clone());
+        l1.cursor_mut().insert_before(c.clone());
+        l1.cursor_mut().insert_before(d.clone());
+        l2.cursor_mut().insert_after(a.clone());
+        l2.cursor_mut().insert_after(b.clone());
+        l2.cursor_mut().insert_after(c.clone());
+        l2.cursor_mut().insert_after(d.clone());
+        assert_eq!(l1.iter().map(|x| x.value).collect::<Vec<_>>(), [1, 2, 3, 4]);
+        assert_eq!(l2.iter().map(|x| x.value).collect::<Vec<_>>(), [4, 3, 2, 1]);
+    }
+
+    #[test]
+    fn test_force_unlink() {
+        let mut l = LinkedList::new(ObjAdapter1::new());
+        let a = make_obj(1);
+        let b = make_obj(2);
+        let c = make_obj(3);
+        l.cursor_mut().insert_before(a.clone());
+        l.cursor_mut().insert_before(b.clone());
+        l.cursor_mut().insert_before(c.clone());
+
+        l.fast_clear();
+        assert!(l.is_empty());
+        assert!(a.link1.is_linked());
+        assert!(b.link1.is_linked());
+        assert!(c.link1.is_linked());
+        unsafe {
+            a.link1.force_unlink();
+            b.link1.force_unlink();
+            c.link1.force_unlink();
+        }
+        assert!(l.is_empty());
+        assert!(!a.link1.is_linked());
+        assert!(!b.link1.is_linked());
+        assert!(!c.link1.is_linked());
+    }
+
+    #[test]
+    fn test_non_static() {
+        #[derive(Clone)]
+        struct Obj<'a, T> {
+            link: Link,
+            value: &'a T,
+        }
+        intrusive_adapter!(ObjAdapter<'a, T> = &'a Obj<'a, T>: Obj<'a, T> {link: Link} where T: 'a);
+
+        let v = 5;
+        let a = Obj {
+            link: Link::new(),
+            value: &v,
+        };
+        let b = a.clone();
+        let mut l = LinkedList::new(ObjAdapter::new());
+        l.cursor_mut().insert_before(&a);
+        l.cursor_mut().insert_before(&b);
+        assert_eq!(*l.front().get().unwrap().value, 5);
+        assert_eq!(*l.back().get().unwrap().value, 5);
+    }
+
+    macro_rules! test_clone_pointer {
+        ($ptr: ident, $ptr_import: path) => {
+            use $ptr_import;
+
+            #[derive(Clone)]
+            struct Obj {
+                link: Link,
+                value: usize,
+            }
+            intrusive_adapter!(ObjAdapter = $ptr<Obj>: Obj { link: Link });
+
+            let a = $ptr::new(Obj {
+                link: Link::new(),
+                value: 5,
+            });
+            let mut l = LinkedList::new(ObjAdapter::new());
+            l.cursor_mut().insert_before(a.clone());
+            assert_eq!(2, $ptr::strong_count(&a));
+
+            let pointer = l.front().clone_pointer().unwrap();
+            assert_eq!(pointer.value, 5);
+            assert_eq!(3, $ptr::strong_count(&a));
+
+            l.front_mut().remove();
+            assert!(l.front().clone_pointer().is_none());
+        };
+    }
+
+    #[test]
+    fn test_clone_pointer_rc() {
+        test_clone_pointer!(Rc, std::rc::Rc);
+    }
+
+    #[test]
+    fn test_clone_pointer_arc() {
+        test_clone_pointer!(Arc, std::sync::Arc);
+    }
+}
diff --git a/src/pointer_ops.rs b/src/pointer_ops.rs
new file mode 100644
index 0000000..74285ef
--- /dev/null
+++ b/src/pointer_ops.rs
@@ -0,0 +1,314 @@
+// Copyright 2020 Amari Robinson
+//
+// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
+// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
+// http://opensource.org/licenses/MIT>, at your option. This file may not be
+// copied, modified, or distributed except according to those terms.
+
+#[cfg(feature = "alloc")]
+use crate::alloc::boxed::Box;
+#[cfg(feature = "alloc")]
+use crate::alloc::rc::Rc;
+#[cfg(feature = "alloc")]
+use crate::alloc::sync::Arc;
+use crate::UnsafeRef;
+use core::marker::PhantomData;
+use core::mem::ManuallyDrop;
+use core::ops::Deref;
+
+/// Trait for pointer conversion operations.
+///
+/// `Value` is the actual object type managed by the collection. This type will
+/// typically have a link as a struct field.
+///
+/// `Pointer` is a pointer type which "owns" an object of type `Value`.
+/// Operations which insert an element into an intrusive collection will accept
+/// such a pointer and operations which remove an element will return this type.
+pub unsafe trait PointerOps {
+    /// Object type which is inserted into an intrusive collection.
+    type Value: ?Sized;
+    /// Pointer type which owns an instance of a value.
+    type Pointer;
+
+    /// Constructs an owned pointer from a raw pointer.
+    ///
+    /// # Safety
+    /// The raw pointer must have been previously returned by `into_raw`.
+    ///
+    /// An implementation of `from_raw` must not panic.
+    unsafe fn from_raw(&self, value: *const Self::Value) -> Self::Pointer;
+
+    /// Consumes the owned pointer and returns a raw pointer to the owned object.
+    fn into_raw(&self, ptr: Self::Pointer) -> *const Self::Value;
+}
+
+/// The `PointerOps` type used by an `Adapter` generated by `intrusive_adapter!`.
+pub struct DefaultPointerOps<Pointer>(PhantomData<Pointer>);
+
+impl<Pointer> DefaultPointerOps<Pointer> {
+    /// Constructs an instance of `DefaultPointerOps`.
+    #[inline]
+    pub const fn new() -> DefaultPointerOps<Pointer> {
+        DefaultPointerOps(PhantomData)
+    }
+}
+
+impl<Pointer> Clone for DefaultPointerOps<Pointer> {
+    #[inline]
+    fn clone(&self) -> Self {
+        *self
+    }
+}
+
+impl<Pointer> Copy for DefaultPointerOps<Pointer> {}
+
+impl<Pointer> Default for DefaultPointerOps<Pointer> {
+    #[inline]
+    fn default() -> Self {
+        Self::new()
+    }
+}
+
+unsafe impl<'a, T: ?Sized> PointerOps for DefaultPointerOps<&'a T> {
+    type Value = T;
+    type Pointer = &'a T;
+
+    #[inline]
+    unsafe fn from_raw(&self, raw: *const T) -> &'a T {
+        &*raw
+    }
+
+    #[inline]
+    fn into_raw(&self, ptr: &'a T) -> *const T {
+        ptr
+    }
+}
+
+unsafe impl<T: ?Sized> PointerOps for DefaultPointerOps<UnsafeRef<T>> {
+    type Value = T;
+    type Pointer = UnsafeRef<T>;
+
+    #[inline]
+    unsafe fn from_raw(&self, raw: *const T) -> UnsafeRef<T> {
+        UnsafeRef::from_raw(raw as *mut T)
+    }
+
+    #[inline]
+    fn into_raw(&self, ptr: UnsafeRef<T>) -> *const T {
+        UnsafeRef::into_raw(ptr) as *const T
+    }
+}
+
+#[cfg(feature = "alloc")]
+unsafe impl<T: ?Sized> PointerOps for DefaultPointerOps<Box<T>> {
+    type Value = T;
+    type Pointer = Box<T>;
+
+    #[inline]
+    unsafe fn from_raw(&self, raw: *const T) -> Box<T> {
+        Box::from_raw(raw as *mut T)
+    }
+
+    #[inline]
+    fn into_raw(&self, ptr: Box<T>) -> *const T {
+        Box::into_raw(ptr) as *const T
+    }
+}
+
+#[cfg(feature = "alloc")]
+unsafe impl<T: ?Sized> PointerOps for DefaultPointerOps<Rc<T>> {
+    type Value = T;
+    type Pointer = Rc<T>;
+
+    #[inline]
+    unsafe fn from_raw(&self, raw: *const T) -> Rc<T> {
+        Rc::from_raw(raw)
+    }
+
+    #[inline]
+    fn into_raw(&self, ptr: Rc<T>) -> *const T {
+        Rc::into_raw(ptr)
+    }
+}
+
+#[cfg(feature = "alloc")]
+unsafe impl<T: ?Sized> PointerOps for DefaultPointerOps<Arc<T>> {
+    type Value = T;
+    type Pointer = Arc<T>;
+
+    #[inline]
+    unsafe fn from_raw(&self, raw: *const T) -> Arc<T> {
+        Arc::from_raw(raw)
+    }
+
+    #[inline]
+    fn into_raw(&self, ptr: Arc<T>) -> *const T {
+        Arc::into_raw(ptr)
+    }
+}
+
+/// Clones a `PointerOps::Pointer` from a `*const PointerOps::Value`
+///
+/// This method is only safe to call if the raw pointer is known to be
+/// managed by the provided `PointerOps` type.
+#[inline]
+pub(crate) unsafe fn clone_pointer_from_raw<T: PointerOps>(
+    pointer_ops: &T,
+    ptr: *const T::Value,
+) -> T::Pointer
+where
+    T::Pointer: Clone,
+{
+    /// Guard which converts an pointer back into its raw version
+    /// when it gets dropped. This makes sure we also perform a full
+    /// `from_raw` and `into_raw` round trip - even in the case of panics.
+    struct PointerGuard<'a, T: PointerOps> {
+        pointer: ManuallyDrop<T::Pointer>,
+        pointer_ops: &'a T,
+    }
+
+    impl<'a, T: PointerOps> Drop for PointerGuard<'a, T> {
+        #[inline]
+        fn drop(&mut self) {
+            // Prevent shared pointers from being released by converting them
+            // back into the raw pointers
+            // SAFETY: `pointer` is never dropped. `ManuallyDrop::take` is not stable until 1.42.0.
+            let _ = self
+                .pointer_ops
+                .into_raw(unsafe { core::ptr::read(&*self.pointer) });
+        }
+    }
+
+    let holder = PointerGuard {
+        pointer: ManuallyDrop::new(pointer_ops.from_raw(ptr)),
+        pointer_ops,
+    };
+    holder.pointer.deref().clone()
+}
+
+#[cfg(test)]
+mod tests {
+    use super::{DefaultPointerOps, PointerOps};
+    use std::boxed::Box;
+    use std::fmt::Debug;
+    use std::mem;
+    use std::rc::Rc;
+    use std::sync::Arc;
+
+    #[test]
+    fn test_box() {
+        unsafe {
+            let pointer_ops = DefaultPointerOps::<Box<_>>::new();
+            let p = Box::new(1);
+            let a: *const i32 = &*p;
+            let r = pointer_ops.into_raw(p);
+            assert_eq!(a, r);
+            let p2: Box<i32> = pointer_ops.from_raw(r);
+            let a2: *const i32 = &*p2;
+            assert_eq!(a, a2);
+        }
+    }
+
+    #[test]
+    fn test_rc() {
+        unsafe {
+            let pointer_ops = DefaultPointerOps::<Rc<_>>::new();
+            let p = Rc::new(1);
+            let a: *const i32 = &*p;
+            let r = pointer_ops.into_raw(p);
+            assert_eq!(a, r);
+            let p2: Rc<i32> = pointer_ops.from_raw(r);
+            let a2: *const i32 = &*p2;
+            assert_eq!(a, a2);
+        }
+    }
+
+    #[test]
+    fn test_arc() {
+        unsafe {
+            let pointer_ops = DefaultPointerOps::<Arc<_>>::new();
+            let p = Arc::new(1);
+            let a: *const i32 = &*p;
+            let r = pointer_ops.into_raw(p);
+            assert_eq!(a, r);
+            let p2: Arc<i32> = pointer_ops.from_raw(r);
+            let a2: *const i32 = &*p2;
+            assert_eq!(a, a2);
+        }
+    }
+
+    #[test]
+    fn test_box_unsized() {
+        unsafe {
+            let pointer_ops = DefaultPointerOps::<Box<_>>::new();
+            let p = Box::new(1) as Box<dyn Debug>;
+            let a: *const dyn Debug = &*p;
+            let b: (usize, usize) = mem::transmute(a);
+            let r = pointer_ops.into_raw(p);
+            assert_eq!(a, r);
+            assert_eq!(b, mem::transmute(r));
+            let p2: Box<dyn Debug> = pointer_ops.from_raw(r);
+            let a2: *const dyn Debug = &*p2;
+            assert_eq!(a, a2);
+            assert_eq!(b, mem::transmute(a2));
+        }
+    }
+
+    #[test]
+    fn test_rc_unsized() {
+        unsafe {
+            let pointer_ops = DefaultPointerOps::<Rc<_>>::new();
+            let p = Rc::new(1) as Rc<dyn Debug>;
+            let a: *const dyn Debug = &*p;
+            let b: (usize, usize) = mem::transmute(a);
+            let r = pointer_ops.into_raw(p);
+            assert_eq!(a, r);
+            assert_eq!(b, mem::transmute(r));
+            let p2: Rc<dyn Debug> = pointer_ops.from_raw(r);
+            let a2: *const dyn Debug = &*p2;
+            assert_eq!(a, a2);
+            assert_eq!(b, mem::transmute(a2));
+        }
+    }
+
+    #[test]
+    fn test_arc_unsized() {
+        unsafe {
+            let pointer_ops = DefaultPointerOps::<Arc<_>>::new();
+            let p = Arc::new(1) as Arc<dyn Debug>;
+            let a: *const dyn Debug = &*p;
+            let b: (usize, usize) = mem::transmute(a);
+            let r = pointer_ops.into_raw(p);
+            assert_eq!(a, r);
+            assert_eq!(b, mem::transmute(r));
+            let p2: Arc<dyn Debug> = pointer_ops.from_raw(r);
+            let a2: *const dyn Debug = &*p2;
+            assert_eq!(a, a2);
+            assert_eq!(b, mem::transmute(a2));
+        }
+    }
+
+    #[test]
+    fn clone_arc_from_raw() {
+        use super::clone_pointer_from_raw;
+        unsafe {
+            let pointer_ops = DefaultPointerOps::<Arc<_>>::new();
+            let p = Arc::new(1);
+            let raw = &*p as *const i32;
+            let p2: Arc<i32> = clone_pointer_from_raw(&pointer_ops, raw);
+            assert_eq!(2, Arc::strong_count(&p2));
+        }
+    }
+
+    #[test]
+    fn clone_rc_from_raw() {
+        use super::clone_pointer_from_raw;
+        unsafe {
+            let pointer_ops = DefaultPointerOps::<Rc<_>>::new();
+            let p = Rc::new(1);
+            let raw = &*p as *const i32;
+            let p2: Rc<i32> = clone_pointer_from_raw(&pointer_ops, raw);
+            assert_eq!(2, Rc::strong_count(&p2));
+        }
+    }
+}
diff --git a/src/rbtree.rs b/src/rbtree.rs
new file mode 100644
index 0000000..0eceb81
--- /dev/null
+++ b/src/rbtree.rs
@@ -0,0 +1,2847 @@
+// Copyright 2016 Amanieu d'Antras
+// Copyright 2020 Amari Robinson
+//
+// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
+// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
+// http://opensource.org/licenses/MIT>, at your option. This file may not be
+// copied, modified, or distributed except according to those terms.
+
+//! Intrusive red-black tree.
+
+use core::borrow::Borrow;
+use core::cell::Cell;
+use core::cmp::Ordering;
+use core::fmt;
+use core::mem;
+use core::ptr::NonNull;
+
+use crate::Bound::{self, Excluded, Included, Unbounded};
+
+use crate::link_ops::{self, DefaultLinkOps};
+use crate::linked_list::LinkedListOps;
+use crate::pointer_ops::PointerOps;
+use crate::singly_linked_list::SinglyLinkedListOps;
+use crate::unchecked_option::UncheckedOptionExt;
+use crate::xor_linked_list::XorLinkedListOps;
+use crate::Adapter;
+use crate::KeyAdapter;
+
+// =============================================================================
+// RBTreeOps
+// =============================================================================
+
+/// The color of a red-black tree node.
+#[derive(Copy, Clone, PartialEq, Eq, Debug)]
+#[allow(missing_docs)]
+pub enum Color {
+    Red,
+    Black,
+}
+
+/// Link operations for `RBTree`.
+pub unsafe trait RBTreeOps: link_ops::LinkOps {
+    /// Returns the left child of `ptr`.
+    ///
+    /// # Safety
+    /// An implementation of `left` must not panic.
+    unsafe fn left(&self, ptr: Self::LinkPtr) -> Option<Self::LinkPtr>;
+
+    /// Returns the right child of `ptr`.
+    ///
+    /// # Safety
+    /// An implementation of `right` must not panic.
+    unsafe fn right(&self, ptr: Self::LinkPtr) -> Option<Self::LinkPtr>;
+
+    /// Returns the parent of `ptr`.
+    ///
+    /// # Safety
+    /// An implementation of `parent` must not panic.
+    unsafe fn parent(&self, ptr: Self::LinkPtr) -> Option<Self::LinkPtr>;
+
+    /// Returns the color of `ptr`.
+    ///
+    /// # Safety
+    /// An implementation of `color` must not panic.
+    unsafe fn color(&self, ptr: Self::LinkPtr) -> Color;
+
+    /// Sets the left child of `ptr`.
+    ///
+    /// # Safety
+    /// An implementation of `set_left` must not panic.
+    unsafe fn set_left(&mut self, ptr: Self::LinkPtr, left: Option<Self::LinkPtr>);
+
+    /// Sets the right child of `ptr`.
+    ///
+    /// # Safety
+    /// An implementation of `set_right` must not panic.
+    unsafe fn set_right(&mut self, ptr: Self::LinkPtr, right: Option<Self::LinkPtr>);
+
+    /// Sets the parent of `ptr`.
+    ///
+    /// # Safety
+    /// An implementation of `set_parent` must not panic.
+    unsafe fn set_parent(&mut self, ptr: Self::LinkPtr, parent: Option<Self::LinkPtr>);
+
+    /// Sets the color of `ptr`.
+    ///
+    /// # Safety
+    /// An implementation of `set_color` must not panic.
+    unsafe fn set_color(&mut self, ptr: Self::LinkPtr, color: Color);
+}
+
+// =============================================================================
+// Link
+// =============================================================================
+
+/// Intrusive link that allows an object to be inserted into a
+/// `RBTree`.
+#[repr(align(2))]
+pub struct Link {
+    left: Cell<Option<NonNull<Link>>>,
+    right: Cell<Option<NonNull<Link>>>,
+    parent_color: Cell<usize>,
+}
+
+// Use a special value to indicate an unlinked node. This value represents a
+// red root node, which is impossible in a valid red-black tree.
+const UNLINKED_MARKER: usize = 0;
+
+impl Link {
+    /// Creates a new `Link`.
+    #[inline]
+    pub const fn new() -> Link {
+        Link {
+            left: Cell::new(None),
+            right: Cell::new(None),
+            parent_color: Cell::new(UNLINKED_MARKER),
+        }
+    }
+
+    /// Checks whether the `Link` is linked into a `RBTree`.
+    #[inline]
+    pub fn is_linked(&self) -> bool {
+        self.parent_color.get() != UNLINKED_MARKER
+    }
+
+    /// Forcibly unlinks an object from a `RBTree`.
+    ///
+    /// # Safety
+    ///
+    /// It is undefined behavior to call this function while still linked into a
+    /// `RBTree`. The only situation where this function is useful is
+    /// after calling `fast_clear` on a `RBTree`, since this clears
+    /// the collection without marking the nodes as unlinked.
+    #[inline]
+    pub unsafe fn force_unlink(&self) {
+        self.parent_color.set(UNLINKED_MARKER);
+    }
+}
+
+impl DefaultLinkOps for Link {
+    type Ops = LinkOps;
+
+    const NEW: Self::Ops = LinkOps;
+}
+
+// An object containing a link can be sent to another thread if it is unlinked.
+unsafe impl Send for Link {}
+
+// Provide an implementation of Clone which simply initializes the new link as
+// unlinked. This allows structs containing a link to derive Clone.
+impl Clone for Link {
+    #[inline]
+    fn clone(&self) -> Link {
+        Link::new()
+    }
+}
+
+// Same as above
+impl Default for Link {
+    #[inline]
+    fn default() -> Link {
+        Link::new()
+    }
+}
+
+// Provide an implementation of Debug so that structs containing a link can
+// still derive Debug.
+impl fmt::Debug for Link {
+    #[inline]
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        // There isn't anything sensible to print here except whether the link
+        // is currently in a tree.
+        if self.is_linked() {
+            write!(f, "linked")
+        } else {
+            write!(f, "unlinked")
+        }
+    }
+}
+
+// =============================================================================
+// LinkOps
+// =============================================================================
+
+/// Default `LinkOps` implementation for `RBTree`.
+#[derive(Clone, Copy, Default)]
+pub struct LinkOps;
+
+impl LinkOps {
+    #[inline]
+    unsafe fn set_parent_color(
+        self,
+        ptr: <Self as link_ops::LinkOps>::LinkPtr,
+        parent: Option<<Self as link_ops::LinkOps>::LinkPtr>,
+        color: Color,
+    ) {
+        assert!(mem::align_of::<Link>() >= 2);
+        let bit = match color {
+            Color::Red => 0,
+            Color::Black => 1,
+        };
+        let parent_usize = parent.map(|x| x.as_ptr() as usize).unwrap_or(0);
+        ptr.as_ref().parent_color.set((parent_usize & !1) | bit);
+    }
+}
+
+unsafe impl link_ops::LinkOps for LinkOps {
+    type LinkPtr = NonNull<Link>;
+
+    #[inline]
+    unsafe fn acquire_link(&mut self, ptr: Self::LinkPtr) -> bool {
+        if ptr.as_ref().is_linked() {
+            false
+        } else {
+            self.set_parent_color(ptr, None, Color::Black);
+            true
+        }
+    }
+
+    #[inline]
+    unsafe fn release_link(&mut self, ptr: Self::LinkPtr) {
+        ptr.as_ref().parent_color.set(UNLINKED_MARKER);
+    }
+}
+
+unsafe impl RBTreeOps for LinkOps {
+    #[inline]
+    unsafe fn left(&self, ptr: Self::LinkPtr) -> Option<Self::LinkPtr> {
+        ptr.as_ref().left.get()
+    }
+
+    #[inline]
+    unsafe fn right(&self, ptr: Self::LinkPtr) -> Option<Self::LinkPtr> {
+        ptr.as_ref().right.get()
+    }
+
+    #[inline]
+    unsafe fn parent(&self, ptr: Self::LinkPtr) -> Option<Self::LinkPtr> {
+        let parent_usize = ptr.as_ref().parent_color.get() & !1;
+        NonNull::new(parent_usize as *mut Link)
+    }
+
+    #[inline]
+    unsafe fn color(&self, ptr: Self::LinkPtr) -> Color {
+        if ptr.as_ref().parent_color.get() & 1 == 1 {
+            Color::Black
+        } else {
+            Color::Red
+        }
+    }
+
+    #[inline]
+    unsafe fn set_left(&mut self, ptr: Self::LinkPtr, left: Option<Self::LinkPtr>) {
+        ptr.as_ref().left.set(left);
+    }
+
+    #[inline]
+    unsafe fn set_right(&mut self, ptr: Self::LinkPtr, right: Option<Self::LinkPtr>) {
+        ptr.as_ref().right.set(right);
+    }
+
+    #[inline]
+    unsafe fn set_parent(&mut self, ptr: Self::LinkPtr, parent: Option<Self::LinkPtr>) {
+        self.set_parent_color(ptr, parent, self.color(ptr));
+    }
+
+    #[inline]
+    unsafe fn set_color(&mut self, ptr: Self::LinkPtr, color: Color) {
+        self.set_parent_color(ptr, self.parent(ptr), color);
+    }
+}
+
+unsafe impl SinglyLinkedListOps for LinkOps {
+    #[inline]
+    unsafe fn next(&self, ptr: Self::LinkPtr) -> Option<Self::LinkPtr> {
+        self.right(ptr)
+    }
+
+    #[inline]
+    unsafe fn set_next(&mut self, ptr: Self::LinkPtr, next: Option<Self::LinkPtr>) {
+        self.set_right(ptr, next);
+    }
+}
+
+unsafe impl LinkedListOps for LinkOps {
+    #[inline]
+    unsafe fn next(&self, ptr: Self::LinkPtr) -> Option<Self::LinkPtr> {
+        self.right(ptr)
+    }
+
+    #[inline]
+    unsafe fn prev(&self, ptr: Self::LinkPtr) -> Option<Self::LinkPtr> {
+        self.left(ptr)
+    }
+
+    #[inline]
+    unsafe fn set_next(&mut self, ptr: Self::LinkPtr, next: Option<Self::LinkPtr>) {
+        self.set_right(ptr, next);
+    }
+
+    #[inline]
+    unsafe fn set_prev(&mut self, ptr: Self::LinkPtr, prev: Option<Self::LinkPtr>) {
+        self.set_left(ptr, prev);
+    }
+}
+
+unsafe impl XorLinkedListOps for LinkOps {
+    #[inline]
+    unsafe fn next(
+        &self,
+        ptr: Self::LinkPtr,
+        prev: Option<Self::LinkPtr>,
+    ) -> Option<Self::LinkPtr> {
+        let packed = self.right(ptr).map(|x| x.as_ptr() as usize).unwrap_or(0);
+        let raw = packed ^ prev.map(|x| x.as_ptr() as usize).unwrap_or(0);
+        NonNull::new(raw as *mut _)
+    }
+
+    #[inline]
+    unsafe fn prev(
+        &self,
+        ptr: Self::LinkPtr,
+        next: Option<Self::LinkPtr>,
+    ) -> Option<Self::LinkPtr> {
+        let packed = self.right(ptr).map(|x| x.as_ptr() as usize).unwrap_or(0);
+        let raw = packed ^ next.map(|x| x.as_ptr() as usize).unwrap_or(0);
+        NonNull::new(raw as *mut _)
+    }
+
+    #[inline]
+    unsafe fn set(
+        &mut self,
+        ptr: Self::LinkPtr,
+        prev: Option<Self::LinkPtr>,
+        next: Option<Self::LinkPtr>,
+    ) {
+        let new_packed = prev.map(|x| x.as_ptr() as usize).unwrap_or(0)
+            ^ next.map(|x| x.as_ptr() as usize).unwrap_or(0);
+
+        let new_next = NonNull::new(new_packed as *mut _);
+        self.set_right(ptr, new_next);
+    }
+
+    #[inline]
+    unsafe fn replace_next_or_prev(
+        &mut self,
+        ptr: Self::LinkPtr,
+        old: Option<Self::LinkPtr>,
+        new: Option<Self::LinkPtr>,
+    ) {
+        let packed = self.right(ptr).map(|x| x.as_ptr() as usize).unwrap_or(0);
+        let new_packed = packed
+            ^ old.map(|x| x.as_ptr() as usize).unwrap_or(0)
+            ^ new.map(|x| x.as_ptr() as usize).unwrap_or(0);
+
+        let new_next = NonNull::new(new_packed as *mut _);
+        self.set_right(ptr, new_next);
+    }
+}
+
+#[inline]
+unsafe fn is_left_child<T: RBTreeOps>(link_ops: &T, ptr: T::LinkPtr, parent: T::LinkPtr) -> bool {
+    link_ops.left(parent) == Some(ptr)
+}
+
+#[inline]
+unsafe fn first_child<T: RBTreeOps>(link_ops: &T, ptr: T::LinkPtr) -> T::LinkPtr {
+    let mut x = ptr;
+    while let Some(y) = link_ops.left(x) {
+        x = y;
+    }
+    x
+}
+
+#[inline]
+unsafe fn last_child<T: RBTreeOps>(link_ops: &T, ptr: T::LinkPtr) -> T::LinkPtr {
+    let mut x = ptr;
+    while let Some(y) = link_ops.right(x) {
+        x = y;
+    }
+    x
+}
+
+#[inline]
+unsafe fn next<T: RBTreeOps>(link_ops: &T, ptr: T::LinkPtr) -> Option<T::LinkPtr> {
+    if let Some(right) = link_ops.right(ptr) {
+        Some(first_child(link_ops, right))
+    } else {
+        let mut x = ptr;
+        loop {
+            if let Some(parent) = link_ops.parent(x) {
+                if is_left_child(link_ops, x, parent) {
+                    return Some(parent);
+                }
+
+                x = parent;
+            } else {
+                return None;
+            }
+        }
+    }
+}
+
+#[inline]
+unsafe fn prev<T: RBTreeOps>(link_ops: &T, ptr: T::LinkPtr) -> Option<T::LinkPtr> {
+    if let Some(left) = link_ops.left(ptr) {
+        Some(last_child(link_ops, left))
+    } else {
+        let mut x = ptr;
+        loop {
+            if let Some(parent) = link_ops.parent(x) {
+                if !is_left_child(link_ops, x, parent) {
+                    return Some(parent);
+                }
+
+                x = parent;
+            } else {
+                return None;
+            }
+        }
+    }
+}
+
+#[inline]
+unsafe fn replace_with<T: RBTreeOps>(
+    link_ops: &mut T,
+    ptr: T::LinkPtr,
+    new: T::LinkPtr,
+    root: &mut Option<T::LinkPtr>,
+) {
+    if let Some(parent) = link_ops.parent(ptr) {
+        if is_left_child(link_ops, ptr, parent) {
+            link_ops.set_left(parent, Some(new));
+        } else {
+            link_ops.set_right(parent, Some(new));
+        }
+    } else {
+        *root = Some(new);
+    }
+    if let Some(left) = link_ops.left(ptr) {
+        link_ops.set_parent(left, Some(new));
+    }
+    if let Some(right) = link_ops.right(ptr) {
+        link_ops.set_parent(right, Some(new));
+    }
+    link_ops.set_left(new, link_ops.left(ptr));
+    link_ops.set_right(new, link_ops.right(ptr));
+    link_ops.set_parent(new, link_ops.parent(ptr));
+    link_ops.set_color(new, link_ops.color(ptr));
+    link_ops.release_link(ptr);
+}
+
+#[inline]
+unsafe fn insert_left<T: RBTreeOps>(
+    link_ops: &mut T,
+    ptr: T::LinkPtr,
+    new: T::LinkPtr,
+    root: &mut Option<T::LinkPtr>,
+) {
+    link_ops.set_parent(new, Some(ptr));
+    link_ops.set_color(new, Color::Red);
+    link_ops.set_left(new, None);
+    link_ops.set_right(new, None);
+    link_ops.set_left(ptr, Some(new));
+    post_insert(link_ops, new, root);
+}
+
+#[inline]
+unsafe fn insert_right<T: RBTreeOps>(
+    link_ops: &mut T,
+    ptr: T::LinkPtr,
+    new: T::LinkPtr,
+    root: &mut Option<T::LinkPtr>,
+) {
+    link_ops.set_parent(new, Some(ptr));
+    link_ops.set_color(new, Color::Red);
+    link_ops.set_left(new, None);
+    link_ops.set_right(new, None);
+    link_ops.set_right(ptr, Some(new));
+    post_insert(link_ops, new, root);
+}
+
+unsafe fn rotate_left<T: RBTreeOps>(
+    link_ops: &mut T,
+    ptr: T::LinkPtr,
+    root: &mut Option<T::LinkPtr>,
+) {
+    let y = link_ops.right(ptr).unwrap_unchecked();
+    link_ops.set_right(ptr, link_ops.left(y));
+    if let Some(right) = link_ops.right(ptr) {
+        link_ops.set_parent(right, Some(ptr));
+    }
+    link_ops.set_parent(y, link_ops.parent(ptr));
+    if let Some(parent) = link_ops.parent(ptr) {
+        if is_left_child(link_ops, ptr, parent) {
+            link_ops.set_left(parent, Some(y));
+        } else {
+            link_ops.set_right(parent, Some(y));
+        }
+    } else {
+        *root = Some(y);
+    }
+    link_ops.set_left(y, Some(ptr));
+    link_ops.set_parent(ptr, Some(y));
+}
+
+unsafe fn rotate_right<T: RBTreeOps>(
+    link_ops: &mut T,
+    ptr: T::LinkPtr,
+    root: &mut Option<T::LinkPtr>,
+) {
+    let y = link_ops.left(ptr).unwrap_unchecked();
+    link_ops.set_left(ptr, link_ops.right(y));
+    if let Some(left) = link_ops.left(ptr) {
+        link_ops.set_parent(left, Some(ptr));
+    }
+    link_ops.set_parent(y, link_ops.parent(ptr));
+    if let Some(parent) = link_ops.parent(ptr) {
+        if is_left_child(link_ops, ptr, parent) {
+            link_ops.set_left(parent, Some(y));
+        } else {
+            link_ops.set_right(parent, Some(y));
+        }
+    } else {
+        *root = Some(y);
+    }
+    link_ops.set_right(y, Some(ptr));
+    link_ops.set_parent(ptr, Some(y));
+}
+
+// This code is based on the red-black tree implementation in libc++
+unsafe fn post_insert<T: RBTreeOps>(
+    link_ops: &mut T,
+    ptr: T::LinkPtr,
+    root: &mut Option<T::LinkPtr>,
+) {
+    let mut x = ptr;
+    while let Some(parent) = link_ops.parent(x) {
+        if link_ops.color(parent) != Color::Red {
+            break;
+        }
+        // SAFETY: The root of the tree must be black, and `parent` cannot be the root if it is red.
+        let grandparent = link_ops.parent(parent).unwrap_unchecked();
+
+        if is_left_child(link_ops, parent, grandparent) {
+            let y = link_ops.right(grandparent);
+            if let Some(y) = y {
+                if link_ops.color(y) == Color::Red {
+                    x = parent;
+                    link_ops.set_color(x, Color::Black);
+                    x = grandparent;
+
+                    if link_ops.parent(x).is_none() {
+                        link_ops.set_color(x, Color::Black);
+                    } else {
+                        link_ops.set_color(x, Color::Red);
+                    }
+                    link_ops.set_color(y, Color::Black);
+                    continue;
+                }
+            }
+            if !is_left_child(link_ops, x, parent) {
+                x = parent;
+                rotate_left(link_ops, x, root);
+            }
+            x = link_ops.parent(x).unwrap_unchecked();
+            link_ops.set_color(x, Color::Black);
+            x = link_ops.parent(x).unwrap_unchecked();
+            link_ops.set_color(x, Color::Red);
+            rotate_right(link_ops, x, root);
+            break;
+        } else {
+            let y = link_ops.left(grandparent);
+            if let Some(y) = y {
+                if link_ops.color(y) == Color::Red {
+                    x = parent;
+                    link_ops.set_color(x, Color::Black);
+                    x = grandparent;
+                    if link_ops.parent(x).is_none() {
+                        link_ops.set_color(x, Color::Black);
+                    } else {
+                        link_ops.set_color(x, Color::Red);
+                    }
+                    link_ops.set_color(y, Color::Black);
+                    continue;
+                }
+            }
+            if is_left_child(link_ops, x, parent) {
+                x = parent;
+                rotate_right(link_ops, x, root);
+            }
+            x = link_ops.parent(x).unwrap_unchecked();
+            link_ops.set_color(x, Color::Black);
+            x = link_ops.parent(x).unwrap_unchecked();
+            link_ops.set_color(x, Color::Red);
+            rotate_left(link_ops, x, root);
+            break;
+        }
+    }
+}
+
+// This code is based on the red-black tree implementation in libc++
+unsafe fn remove<T: RBTreeOps>(link_ops: &mut T, ptr: T::LinkPtr, root: &mut Option<T::LinkPtr>) {
+    let y = if link_ops.left(ptr).is_none() || link_ops.right(ptr).is_none() {
+        ptr
+    } else {
+        next(link_ops, ptr).unwrap_unchecked()
+    };
+    let x = if link_ops.left(y).is_some() {
+        link_ops.left(y)
+    } else {
+        link_ops.right(y)
+    };
+    let mut w = None;
+    if let Some(x) = x {
+        link_ops.set_parent(x, link_ops.parent(y));
+    }
+    if let Some(y_parent) = link_ops.parent(y) {
+        if is_left_child(link_ops, y, y_parent) {
+            link_ops.set_left(y_parent, x);
+            w = link_ops.right(y_parent);
+        } else {
+            link_ops.set_right(y_parent, x);
+            w = link_ops.left(y_parent);
+        }
+    } else {
+        *root = x;
+    }
+    let removed_black = link_ops.color(y) == Color::Black;
+    if y != ptr {
+        if let Some(parent) = link_ops.parent(ptr) {
+            link_ops.set_parent(y, Some(parent));
+            if is_left_child(link_ops, ptr, parent) {
+                link_ops.set_left(parent, Some(y));
+            } else {
+                link_ops.set_right(parent, Some(y));
+            }
+        } else {
+            link_ops.set_parent(y, None);
+            *root = Some(y);
+        }
+        link_ops.set_left(y, link_ops.left(ptr));
+        link_ops.set_parent(link_ops.left(y).unwrap_unchecked(), Some(y));
+        link_ops.set_right(y, link_ops.right(ptr));
+        if let Some(y_right) = link_ops.right(y) {
+            link_ops.set_parent(y_right, Some(y));
+        }
+        link_ops.set_color(y, link_ops.color(ptr));
+    }
+    if removed_black && !root.is_none() {
+        if let Some(x) = x {
+            link_ops.set_color(x, Color::Black);
+        } else {
+            let mut w = w.unwrap_unchecked();
+            loop {
+                let mut w_parent = link_ops.parent(w).unwrap_unchecked();
+                if !is_left_child(link_ops, w, w_parent) {
+                    if link_ops.color(w) == Color::Red {
+                        link_ops.set_color(w, Color::Black);
+                        link_ops.set_color(w_parent, Color::Red);
+                        rotate_left(link_ops, w_parent, root);
+                        w = link_ops
+                            .right(link_ops.left(w).unwrap_unchecked())
+                            .unwrap_unchecked();
+                        w_parent = link_ops.parent(w).unwrap_unchecked();
+                    }
+
+                    let left_color = link_ops.left(w).map(|x| link_ops.color(x));
+                    let right_color = link_ops.right(w).map(|x| link_ops.color(x));
+                    if (left_color != Some(Color::Red)) && (right_color != Some(Color::Red)) {
+                        link_ops.set_color(w, Color::Red);
+                        if link_ops.parent(w_parent).is_none()
+                            || link_ops.color(w_parent) == Color::Red
+                        {
+                            link_ops.set_color(w_parent, Color::Black);
+                            break;
+                        }
+                        let w_grandparent = link_ops.parent(w_parent).unwrap_unchecked();
+                        w = if is_left_child(link_ops, w_parent, w_grandparent) {
+                            link_ops.right(w_grandparent).unwrap_unchecked()
+                        } else {
+                            link_ops.left(w_grandparent).unwrap_unchecked()
+                        };
+                    } else {
+                        if link_ops.right(w).map(|x| link_ops.color(x)) != Some(Color::Red) {
+                            link_ops.set_color(link_ops.left(w).unwrap_unchecked(), Color::Black);
+                            link_ops.set_color(w, Color::Red);
+                            rotate_right(link_ops, w, root);
+                            w = link_ops.parent(w).unwrap_unchecked();
+                            w_parent = link_ops.parent(w).unwrap_unchecked();
+                        }
+                        link_ops.set_color(w, link_ops.color(w_parent));
+                        link_ops.set_color(w_parent, Color::Black);
+                        link_ops.set_color(link_ops.right(w).unwrap_unchecked(), Color::Black);
+                        rotate_left(link_ops, w_parent, root);
+                        break;
+                    }
+                } else {
+                    if link_ops.color(w) == Color::Red {
+                        link_ops.set_color(w, Color::Black);
+                        link_ops.set_color(w_parent, Color::Red);
+                        rotate_right(link_ops, w_parent, root);
+                        w = link_ops
+                            .left(link_ops.right(w).unwrap_unchecked())
+                            .unwrap_unchecked();
+                        w_parent = link_ops.parent(w).unwrap_unchecked();
+                    }
+                    let left_color = link_ops.left(w).map(|x| link_ops.color(x));
+                    let right_color = link_ops.right(w).map(|x| link_ops.color(x));
+                    if (left_color != Some(Color::Red)) && (right_color != Some(Color::Red)) {
+                        link_ops.set_color(w, Color::Red);
+                        if link_ops.parent(w_parent).is_none()
+                            || link_ops.color(w_parent) == Color::Red
+                        {
+                            link_ops.set_color(w_parent, Color::Black);
+                            break;
+                        }
+                        w = if is_left_child(
+                            link_ops,
+                            w_parent,
+                            link_ops.parent(w_parent).unwrap_unchecked(),
+                        ) {
+                            link_ops
+                                .right(link_ops.parent(w_parent).unwrap_unchecked())
+                                .unwrap_unchecked()
+                        } else {
+                            link_ops
+                                .left(link_ops.parent(w_parent).unwrap_unchecked())
+                                .unwrap_unchecked()
+                        };
+                    } else {
+                        if link_ops.left(w).map(|x| link_ops.color(x)) != Some(Color::Red) {
+                            link_ops.set_color(link_ops.right(w).unwrap_unchecked(), Color::Black);
+                            link_ops.set_color(w, Color::Red);
+                            rotate_left(link_ops, w, root);
+                            w = link_ops.parent(w).unwrap_unchecked();
+                            w_parent = link_ops.parent(w).unwrap_unchecked();
+                        }
+                        link_ops.set_color(w, link_ops.color(w_parent));
+                        link_ops.set_color(w_parent, Color::Black);
+                        link_ops.set_color(link_ops.left(w).unwrap_unchecked(), Color::Black);
+                        rotate_right(link_ops, w_parent, root);
+                        break;
+                    }
+                }
+            }
+        }
+    }
+    link_ops.release_link(ptr);
+}
+
+// =============================================================================
+// Cursor, CursorMut
+// =============================================================================
+
+/// A cursor which provides read-only access to a `RBTree`.
+pub struct Cursor<'a, A: Adapter>
+where
+    A::LinkOps: RBTreeOps,
+{
+    current: Option<<A::LinkOps as link_ops::LinkOps>::LinkPtr>,
+    tree: &'a RBTree<A>,
+}
+
+impl<'a, A: Adapter> Clone for Cursor<'a, A>
+where
+    A::LinkOps: RBTreeOps,
+{
+    #[inline]
+    fn clone(&self) -> Cursor<'a, A> {
+        Cursor {
+            current: self.current,
+            tree: self.tree,
+        }
+    }
+}
+
+impl<'a, A: Adapter> Cursor<'a, A>
+where
+    A::LinkOps: RBTreeOps,
+{
+    /// Checks if the cursor is currently pointing to the null object.
+    #[inline]
+    pub fn is_null(&self) -> bool {
+        self.current.is_none()
+    }
+
+    /// Returns a reference to the object that the cursor is currently
+    /// pointing to.
+    ///
+    /// This returns `None` if the cursor is currently pointing to the null
+    /// object.
+    #[inline]
+    pub fn get(&self) -> Option<&'a <A::PointerOps as PointerOps>::Value> {
+        Some(unsafe { &*self.tree.adapter.get_value(self.current?) })
+    }
+
+    /// Clones and returns the pointer that points to the element that the
+    /// cursor is referencing.
+    ///
+    /// This returns `None` if the cursor is currently pointing to the null
+    /// object.
+    #[inline]
+    pub fn clone_pointer(&self) -> Option<<A::PointerOps as PointerOps>::Pointer>
+    where
+        <A::PointerOps as PointerOps>::Pointer: Clone,
+    {
+        let raw_pointer = self.get()? as *const <A::PointerOps as PointerOps>::Value;
+        Some(unsafe {
+            crate::pointer_ops::clone_pointer_from_raw(self.tree.adapter.pointer_ops(), raw_pointer)
+        })
+    }
+
+    /// Moves the cursor to the next element of the `RBTree`.
+    ///
+    /// If the cursor is pointer to the null object then this will move it to
+    /// the first element of the `RBTree`. If it is pointing to the last
+    /// element of the `RBTree` then this will move it to the null object.
+    #[inline]
+    pub fn move_next(&mut self) {
+        if let Some(current) = self.current {
+            self.current = unsafe { next(self.tree.adapter.link_ops(), current) };
+        } else if let Some(root) = self.tree.root {
+            self.current = Some(unsafe { first_child(self.tree.adapter.link_ops(), root) });
+        } else {
+            self.current = None;
+        }
+    }
+
+    /// Moves the cursor to the previous element of the `RBTree`.
+    ///
+    /// If the cursor is pointer to the null object then this will move it to
+    /// the last element of the `RBTree`. If it is pointing to the first
+    /// element of the `RBTree` then this will move it to the null object.
+    #[inline]
+    pub fn move_prev(&mut self) {
+        if let Some(current) = self.current {
+            self.current = unsafe { prev(self.tree.adapter.link_ops(), current) };
+        } else if let Some(root) = self.tree.root {
+            self.current = Some(unsafe { last_child(self.tree.adapter.link_ops(), root) });
+        } else {
+            self.current = None;
+        }
+    }
+
+    /// Returns a cursor pointing to the next element of the `RBTree`.
+    ///
+    /// If the cursor is pointer to the null object then this will return the
+    /// first element of the `RBTree`. If it is pointing to the last
+    /// element of the `RBTree` then this will return a null cursor.
+    #[inline]
+    pub fn peek_next(&self) -> Cursor<'_, A> {
+        let mut next = self.clone();
+        next.move_next();
+        next
+    }
+
+    /// Returns a cursor pointing to the previous element of the `RBTree`.
+    ///
+    /// If the cursor is pointer to the null object then this will return the
+    /// last element of the `RBTree`. If it is pointing to the first
+    /// element of the `RBTree` then this will return a null cursor.
+    #[inline]
+    pub fn peek_prev(&self) -> Cursor<'_, A> {
+        let mut prev = self.clone();
+        prev.move_prev();
+        prev
+    }
+}
+
+/// A cursor which provides mutable access to a `RBTree`.
+pub struct CursorMut<'a, A: Adapter>
+where
+    A::LinkOps: RBTreeOps,
+{
+    current: Option<<A::LinkOps as link_ops::LinkOps>::LinkPtr>,
+    tree: &'a mut RBTree<A>,
+}
+
+impl<'a, A: Adapter> CursorMut<'a, A>
+where
+    A::LinkOps: RBTreeOps,
+{
+    /// Checks if the cursor is currently pointing to the null object.
+    #[inline]
+    pub fn is_null(&self) -> bool {
+        self.current.is_none()
+    }
+
+    /// Returns a reference to the object that the cursor is currently
+    /// pointing to.
+    ///
+    /// This returns None if the cursor is currently pointing to the null
+    /// object.
+    #[inline]
+    pub fn get(&self) -> Option<&<A::PointerOps as PointerOps>::Value> {
+        Some(unsafe { &*self.tree.adapter.get_value(self.current?) })
+    }
+
+    /// Returns a read-only cursor pointing to the current element.
+    ///
+    /// The lifetime of the returned `Cursor` is bound to that of the
+    /// `CursorMut`, which means it cannot outlive the `CursorMut` and that the
+    /// `CursorMut` is frozen for the lifetime of the `Cursor`.
+    #[inline]
+    pub fn as_cursor(&self) -> Cursor<'_, A> {
+        Cursor {
+            current: self.current,
+            tree: self.tree,
+        }
+    }
+
+    /// Moves the cursor to the next element of the `RBTree`.
+    ///
+    /// If the cursor is pointer to the null object then this will move it to
+    /// the first element of the `RBTree`. If it is pointing to the last
+    /// element of the `RBTree` then this will move it to the null object.
+    #[inline]
+    pub fn move_next(&mut self) {
+        if let Some(current) = self.current {
+            self.current = unsafe { next(self.tree.adapter.link_ops(), current) };
+        } else if let Some(root) = self.tree.root {
+            self.current = Some(unsafe { first_child(self.tree.adapter.link_ops(), root) });
+        } else {
+            self.current = None;
+        }
+    }
+
+    /// Moves the cursor to the previous element of the `RBTree`.
+    ///
+    /// If the cursor is pointer to the null object then this will move it to
+    /// the last element of the `RBTree`. If it is pointing to the first
+    /// element of the `RBTree` then this will move it to the null object.
+    #[inline]
+    pub fn move_prev(&mut self) {
+        if let Some(current) = self.current {
+            self.current = unsafe { prev(self.tree.adapter.link_ops(), current) };
+        } else if let Some(root) = self.tree.root {
+            self.current = Some(unsafe { last_child(self.tree.adapter.link_ops(), root) });
+        } else {
+            self.current = None;
+        }
+    }
+
+    /// Returns a cursor pointing to the next element of the `RBTree`.
+    ///
+    /// If the cursor is pointer to the null object then this will return the
+    /// first element of the `RBTree`. If it is pointing to the last
+    /// element of the `RBTree` then this will return a null cursor.
+    #[inline]
+    pub fn peek_next(&self) -> Cursor<'_, A> {
+        let mut next = self.as_cursor();
+        next.move_next();
+        next
+    }
+
+    /// Returns a cursor pointing to the previous element of the `RBTree`.
+    ///
+    /// If the cursor is pointer to the null object then this will return the
+    /// last element of the `RBTree`. If it is pointing to the first
+    /// element of the `RBTree` then this will return a null cursor.
+    #[inline]
+    pub fn peek_prev(&self) -> Cursor<'_, A> {
+        let mut prev = self.as_cursor();
+        prev.move_prev();
+        prev
+    }
+
+    /// Removes the current element from the `RBTree`.
+    ///
+    /// A pointer to the element that was removed is returned, and the cursor is
+    /// moved to point to the next element in the `RBTree`.
+    ///
+    /// If the cursor is currently pointing to the null object then no element
+    /// is removed and `None` is returned.
+    #[inline]
+    pub fn remove(&mut self) -> Option<<A::PointerOps as PointerOps>::Pointer> {
+        unsafe {
+            if let Some(current) = self.current {
+                let next = next(self.tree.adapter.link_ops(), current);
+                let result = current;
+                remove(
+                    self.tree.adapter.link_ops_mut(),
+                    current,
+                    &mut self.tree.root,
+                );
+                self.current = next;
+                Some(
+                    self.tree
+                        .adapter
+                        .pointer_ops()
+                        .from_raw(self.tree.adapter.get_value(result)),
+                )
+            } else {
+                None
+            }
+        }
+    }
+
+    /// Removes the current element from the `RBTree` and inserts another
+    /// object in its place.
+    ///
+    /// A pointer to the element that was removed is returned, and the cursor is
+    /// modified to point to the newly added element.
+    ///
+    /// When using this function you must ensure that the elements in the
+    /// collection are maintained in increasing order. Failure to do this may
+    /// lead to `find`, `upper_bound`, `lower_bound` and `range` returning
+    /// incorrect results.
+    ///
+    /// If the cursor is currently pointing to the null object then an error is
+    /// returned containing the given `val` parameter.
+    ///
+    /// # Panics
+    ///
+    /// Panics if the new element is already linked to a different intrusive
+    /// collection.
+    #[inline]
+    pub fn replace_with(
+        &mut self,
+        val: <A::PointerOps as PointerOps>::Pointer,
+    ) -> Result<<A::PointerOps as PointerOps>::Pointer, <A::PointerOps as PointerOps>::Pointer>
+    {
+        unsafe {
+            if let Some(current) = self.current {
+                let new = self.tree.node_from_value(val);
+                let result = current;
+                replace_with(
+                    self.tree.adapter.link_ops_mut(),
+                    current,
+                    new,
+                    &mut self.tree.root,
+                );
+                self.current = Some(new);
+                Ok(self
+                    .tree
+                    .adapter
+                    .pointer_ops()
+                    .from_raw(self.tree.adapter.get_value(result)))
+            } else {
+                Err(val)
+            }
+        }
+    }
+
+    /// Inserts a new element into the `RBTree` after the current one.
+    ///
+    /// When using this function you must ensure that the elements in the
+    /// collection are maintained in increasing order. Failure to do this may
+    /// lead to `find`, `upper_bound`, `lower_bound` and `range` returning
+    /// incorrect results.
+    ///
+    /// If the cursor is pointing at the null object then the new element is
+    /// inserted at the start of the `RBTree`.
+    ///
+    /// # Panics
+    ///
+    /// Panics if the new element is already linked to a different intrusive
+    /// collection.
+    #[inline]
+    pub fn insert_after(&mut self, val: <A::PointerOps as PointerOps>::Pointer) {
+        unsafe {
+            let new = self.tree.node_from_value(val);
+            let link_ops = self.tree.adapter.link_ops_mut();
+
+            if let Some(root) = self.tree.root {
+                if let Some(current) = self.current {
+                    if link_ops.right(current).is_some() {
+                        let next = next(link_ops, current).unwrap_unchecked();
+                        insert_left(link_ops, next, new, &mut self.tree.root);
+                    } else {
+                        insert_right(link_ops, current, new, &mut self.tree.root);
+                    }
+                } else {
+                    insert_left(
+                        link_ops,
+                        first_child(link_ops, root),
+                        new,
+                        &mut self.tree.root,
+                    );
+                }
+            } else {
+                self.tree.insert_root(new);
+            }
+        }
+    }
+
+    /// Inserts a new element into the `RBTree` before the current one.
+    ///
+    /// When using this function you must ensure that the elements in the
+    /// collection are maintained in increasing order. Failure to do this may
+    /// lead to `find`, `upper_bound`, `lower_bound` and `range` returning
+    /// incorrect results.
+    ///
+    /// If the cursor is pointing at the null object then the new element is
+    /// inserted at the end of the `RBTree`.
+    ///
+    /// # Panics
+    ///
+    /// Panics if the new element is already linked to a different intrusive
+    /// collection.
+    #[inline]
+    pub fn insert_before(&mut self, val: <A::PointerOps as PointerOps>::Pointer) {
+        unsafe {
+            let new = self.tree.node_from_value(val);
+            let link_ops = self.tree.adapter.link_ops_mut();
+
+            if let Some(root) = self.tree.root {
+                if let Some(current) = self.current {
+                    if link_ops.left(current).is_some() {
+                        let prev = prev(link_ops, current).unwrap_unchecked();
+                        insert_right(link_ops, prev, new, &mut self.tree.root);
+                    } else {
+                        insert_left(link_ops, current, new, &mut self.tree.root);
+                    }
+                } else {
+                    insert_right(
+                        link_ops,
+                        last_child(link_ops, root),
+                        new,
+                        &mut self.tree.root,
+                    );
+                }
+            } else {
+                self.tree.insert_root(new);
+            }
+        }
+    }
+}
+
+impl<'a, A: for<'b> KeyAdapter<'b>> CursorMut<'a, A>
+where
+    <A as Adapter>::LinkOps: RBTreeOps,
+{
+    /// Inserts a new element into the `RBTree`.
+    ///
+    /// The new element will be inserted at the correct position in the tree
+    /// based on its key, regardless of the current cursor position.
+    ///
+    /// # Panics
+    ///
+    /// Panics if the new element is already linked to a different intrusive
+    /// collection.
+    #[inline]
+    pub fn insert<'c>(&'c mut self, val: <A::PointerOps as PointerOps>::Pointer)
+    where
+        <A as KeyAdapter<'c>>::Key: Ord,
+    {
+        // We explicitly drop the returned CursorMut here, otherwise we would
+        // end up with multiple CursorMut in the same collection.
+        self.tree.insert(val);
+    }
+}
+
+// =============================================================================
+// RBTree
+// =============================================================================
+
+/// An intrusive red-black tree.
+///
+/// When this collection is dropped, all elements linked into it will be
+/// converted back to owned pointers and dropped.
+///
+/// Note that you are responsible for ensuring that the elements in a `RBTree`
+/// remain in ascending key order. This property can be violated, either because
+/// the key of an element was modified, or because the
+/// `insert_before`/`insert_after` methods of `CursorMut` were incorrectly used.
+/// If this situation occurs, memory safety will not be violated but the `find`,
+/// `upper_bound`, `lower_bound` and `range` may return incorrect results.
+pub struct RBTree<A: Adapter>
+where
+    A::LinkOps: RBTreeOps,
+{
+    root: Option<<A::LinkOps as link_ops::LinkOps>::LinkPtr>,
+    adapter: A,
+}
+
+impl<A: Adapter> RBTree<A>
+where
+    A::LinkOps: RBTreeOps,
+{
+    #[inline]
+    fn node_from_value(
+        &mut self,
+        val: <A::PointerOps as PointerOps>::Pointer,
+    ) -> <A::LinkOps as link_ops::LinkOps>::LinkPtr {
+        use link_ops::LinkOps;
+
+        unsafe {
+            let raw = self.adapter.pointer_ops().into_raw(val);
+            let link = self.adapter.get_link(raw);
+
+            if !self.adapter.link_ops_mut().acquire_link(link) {
+                // convert the node back into a pointer
+                self.adapter.pointer_ops().from_raw(raw);
+
+                panic!("attempted to insert an object that is already linked");
+            }
+
+            link
+        }
+    }
+
+    /// Creates an empty `RBTree`.
+    #[cfg(not(feature = "nightly"))]
+    #[inline]
+    pub fn new(adapter: A) -> RBTree<A> {
+        RBTree {
+            root: None,
+            adapter,
+        }
+    }
+
+    /// Creates an empty `RBTree`.
+    #[cfg(feature = "nightly")]
+    #[inline]
+    pub const fn new(adapter: A) -> RBTree<A> {
+        RBTree {
+            root: None,
+            adapter,
+        }
+    }
+
+    /// Returns `true` if the `RBTree` is empty.
+    #[inline]
+    pub fn is_empty(&self) -> bool {
+        self.root.is_none()
+    }
+
+    /// Returns a null `Cursor` for this tree.
+    #[inline]
+    pub fn cursor(&self) -> Cursor<'_, A> {
+        Cursor {
+            current: None,
+            tree: self,
+        }
+    }
+
+    /// Returns a null `CursorMut` for this tree.
+    #[inline]
+    pub fn cursor_mut(&mut self) -> CursorMut<'_, A> {
+        CursorMut {
+            current: None,
+            tree: self,
+        }
+    }
+
+    /// Creates a `Cursor` from a pointer to an element.
+    ///
+    /// # Safety
+    ///
+    /// `ptr` must be a pointer to an object that is part of this tree.
+    #[inline]
+    pub unsafe fn cursor_from_ptr(
+        &self,
+        ptr: *const <A::PointerOps as PointerOps>::Value,
+    ) -> Cursor<'_, A> {
+        Cursor {
+            current: Some(self.adapter.get_link(ptr)),
+            tree: self,
+        }
+    }
+
+    /// Creates a `CursorMut` from a pointer to an element.
+    ///
+    /// # Safety
+    ///
+    /// `ptr` must be a pointer to an object that is part of this tree.
+    #[inline]
+    pub unsafe fn cursor_mut_from_ptr(
+        &mut self,
+        ptr: *const <A::PointerOps as PointerOps>::Value,
+    ) -> CursorMut<'_, A> {
+        CursorMut {
+            current: Some(self.adapter.get_link(ptr)),
+            tree: self,
+        }
+    }
+
+    /// Returns a `Cursor` pointing to the first element of the tree. If the
+    /// tree is empty then a null cursor is returned.
+    #[inline]
+    pub fn front(&self) -> Cursor<'_, A> {
+        let mut cursor = self.cursor();
+        cursor.move_next();
+        cursor
+    }
+
+    /// Returns a `CursorMut` pointing to the first element of the tree. If the
+    /// the tree is empty then a null cursor is returned.
+    #[inline]
+    pub fn front_mut(&mut self) -> CursorMut<'_, A> {
+        let mut cursor = self.cursor_mut();
+        cursor.move_next();
+        cursor
+    }
+
+    /// Returns a `Cursor` pointing to the last element of the tree. If the tree
+    /// is empty then a null cursor is returned.
+    #[inline]
+    pub fn back(&self) -> Cursor<'_, A> {
+        let mut cursor = self.cursor();
+        cursor.move_prev();
+        cursor
+    }
+
+    /// Returns a `CursorMut` pointing to the last element of the tree. If the
+    /// tree is empty then a null cursor is returned.
+    #[inline]
+    pub fn back_mut(&mut self) -> CursorMut<'_, A> {
+        let mut cursor = self.cursor_mut();
+        cursor.move_prev();
+        cursor
+    }
+
+    #[inline]
+    unsafe fn insert_root(&mut self, node: <A::LinkOps as link_ops::LinkOps>::LinkPtr) {
+        self.adapter.link_ops_mut().set_parent(node, None);
+        self.adapter.link_ops_mut().set_color(node, Color::Black);
+        self.adapter.link_ops_mut().set_left(node, None);
+        self.adapter.link_ops_mut().set_right(node, None);
+        self.root = Some(node);
+    }
+
+    /// Gets an iterator over the objects in the `RBTree`.
+    #[inline]
+    pub fn iter(&self) -> Iter<'_, A> {
+        let link_ops = self.adapter.link_ops();
+
+        if let Some(root) = self.root {
+            Iter {
+                head: Some(unsafe { first_child(link_ops, root) }),
+                tail: Some(unsafe { last_child(link_ops, root) }),
+                tree: self,
+            }
+        } else {
+            Iter {
+                head: None,
+                tail: None,
+                tree: self,
+            }
+        }
+    }
+
+    #[inline]
+    fn clear_recurse(&mut self, current: Option<<A::LinkOps as link_ops::LinkOps>::LinkPtr>) {
+        use link_ops::LinkOps;
+        // If adapter.get_value or Pointer::from_raw panic here, it will leak
+        // the nodes and keep them linked. However this is harmless since there
+        // is nothing you can do with just a Link.
+        if let Some(current) = current {
+            unsafe {
+                let left = self.adapter.link_ops_mut().left(current);
+                let right = self.adapter.link_ops_mut().right(current);
+                self.clear_recurse(left);
+                self.clear_recurse(right);
+                self.adapter.link_ops_mut().release_link(current);
+                self.adapter
+                    .pointer_ops()
+                    .from_raw(self.adapter.get_value(current));
+            }
+        }
+    }
+
+    /// Removes all elements from the `RBTree`.
+    ///
+    /// This will unlink all object currently in the tree, which requires
+    /// iterating through all elements in the `RBTree`. Each element is
+    /// converted back to an owned pointer and then dropped.
+    #[inline]
+    pub fn clear(&mut self) {
+        let root = self.root.take();
+        self.clear_recurse(root);
+    }
+
+    /// Empties the `RBTree` without unlinking or freeing objects in it.
+    ///
+    /// Since this does not unlink any objects, any attempts to link these
+    /// objects into another `RBTree` will fail but will not cause any
+    /// memory unsafety. To unlink those objects manually, you must call the
+    /// `force_unlink` function on them.
+    #[inline]
+    pub fn fast_clear(&mut self) {
+        self.root = None;
+    }
+
+    /// Takes all the elements out of the `RBTree`, leaving it empty. The
+    /// taken elements are returned as a new `RBTree`.
+    #[inline]
+    pub fn take(&mut self) -> RBTree<A>
+    where
+        A: Clone,
+    {
+        let tree = RBTree {
+            root: self.root,
+            adapter: self.adapter.clone(),
+        };
+        self.root = None;
+        tree
+    }
+}
+
+impl<A: for<'a> KeyAdapter<'a>> RBTree<A>
+where
+    <A as Adapter>::LinkOps: RBTreeOps,
+{
+    #[inline]
+    fn find_internal<'a, Q: ?Sized + Ord>(
+        &self,
+        key: &Q,
+    ) -> Option<<A::LinkOps as link_ops::LinkOps>::LinkPtr>
+    where
+        <A as KeyAdapter<'a>>::Key: Borrow<Q>,
+        <A::PointerOps as PointerOps>::Value: 'a,
+    {
+        let link_ops = self.adapter.link_ops();
+
+        let mut tree = self.root;
+        while let Some(x) = tree {
+            let current = unsafe { &*self.adapter.get_value(x) };
+            match key.cmp(self.adapter.get_key(current).borrow()) {
+                Ordering::Less => tree = unsafe { link_ops.left(x) },
+                Ordering::Equal => return tree,
+                Ordering::Greater => tree = unsafe { link_ops.right(x) },
+            }
+        }
+        None
+    }
+
+    /// Returns a `Cursor` pointing to an element with the given key. If no such
+    /// element is found then a null cursor is returned.
+    ///
+    /// If multiple elements with an identical key are found then an arbitrary
+    /// one is returned.
+    #[inline]
+    pub fn find<'a, Q: ?Sized + Ord>(&'a self, key: &Q) -> Cursor<'a, A>
+    where
+        <A as KeyAdapter<'a>>::Key: Borrow<Q>,
+    {
+        Cursor {
+            current: self.find_internal(key),
+            tree: self,
+        }
+    }
+
+    /// Returns a `CursorMut` pointing to an element with the given key. If no
+    /// such element is found then a null cursor is returned.
+    ///
+    /// If multiple elements with an identical key are found then an arbitrary
+    /// one is returned.
+    #[inline]
+    pub fn find_mut<'a, Q: ?Sized + Ord>(&'a mut self, key: &Q) -> CursorMut<'a, A>
+    where
+        <A as KeyAdapter<'a>>::Key: Borrow<Q>,
+    {
+        CursorMut {
+            current: self.find_internal(key),
+            tree: self,
+        }
+    }
+
+    #[inline]
+    fn lower_bound_internal<'a, Q: ?Sized + Ord>(
+        &self,
+        bound: Bound<&Q>,
+    ) -> Option<<A::LinkOps as link_ops::LinkOps>::LinkPtr>
+    where
+        <A as KeyAdapter<'a>>::Key: Borrow<Q>,
+        <A::PointerOps as PointerOps>::Value: 'a,
+    {
+        let link_ops = self.adapter.link_ops();
+
+        let mut tree = self.root;
+        let mut result = None;
+        while let Some(x) = tree {
+            let current = unsafe { &*self.adapter.get_value(x) };
+            let cond = match bound {
+                Unbounded => true,
+                Included(key) => key <= self.adapter.get_key(current).borrow(),
+                Excluded(key) => key < self.adapter.get_key(current).borrow(),
+            };
+            if cond {
+                result = tree;
+                tree = unsafe { link_ops.left(x) };
+            } else {
+                tree = unsafe { link_ops.right(x) };
+            }
+        }
+        result
+    }
+
+    /// Returns a `Cursor` pointing to the lowest element whose key is above
+    /// the given bound. If no such element is found then a null cursor is
+    /// returned.
+    #[inline]
+    pub fn lower_bound<'a, Q: ?Sized + Ord>(&'a self, bound: Bound<&Q>) -> Cursor<'a, A>
+    where
+        <A as KeyAdapter<'a>>::Key: Borrow<Q>,
+    {
+        Cursor {
+            current: self.lower_bound_internal(bound),
+            tree: self,
+        }
+    }
+
+    /// Returns a `CursorMut` pointing to the first element whose key is
+    /// above the given bound. If no such element is found then a null
+    /// cursor is returned.
+    #[inline]
+    pub fn lower_bound_mut<'a, Q: ?Sized + Ord>(&'a mut self, bound: Bound<&Q>) -> CursorMut<'a, A>
+    where
+        <A as KeyAdapter<'a>>::Key: Borrow<Q>,
+    {
+        CursorMut {
+            current: self.lower_bound_internal(bound),
+            tree: self,
+        }
+    }
+
+    #[inline]
+    fn upper_bound_internal<'a, Q: ?Sized + Ord>(
+        &self,
+        bound: Bound<&Q>,
+    ) -> Option<<A::LinkOps as link_ops::LinkOps>::LinkPtr>
+    where
+        <A as KeyAdapter<'a>>::Key: Borrow<Q>,
+        <A::PointerOps as PointerOps>::Value: 'a,
+    {
+        let link_ops = self.adapter.link_ops();
+
+        let mut tree = self.root;
+        let mut result = None;
+        while let Some(x) = tree {
+            let current = unsafe { &*self.adapter.get_value(x) };
+            let cond = match bound {
+                Unbounded => false,
+                Included(key) => key < self.adapter.get_key(current).borrow(),
+                Excluded(key) => key <= self.adapter.get_key(current).borrow(),
+            };
+            if cond {
+                tree = unsafe { link_ops.left(x) };
+            } else {
+                result = tree;
+                tree = unsafe { link_ops.right(x) };
+            }
+        }
+        result
+    }
+
+    /// Returns a `Cursor` pointing to the last element whose key is below
+    /// the given bound. If no such element is found then a null cursor is
+    /// returned.
+    #[inline]
+    pub fn upper_bound<'a, Q: ?Sized + Ord>(&'a self, bound: Bound<&Q>) -> Cursor<'a, A>
+    where
+        <A as KeyAdapter<'a>>::Key: Borrow<Q>,
+    {
+        Cursor {
+            current: self.upper_bound_internal(bound),
+            tree: self,
+        }
+    }
+
+    /// Returns a `CursorMut` pointing to the last element whose key is
+    /// below the given bound. If no such element is found then a null
+    /// cursor is returned.
+    #[inline]
+    pub fn upper_bound_mut<'a, Q: ?Sized + Ord>(&'a mut self, bound: Bound<&Q>) -> CursorMut<'a, A>
+    where
+        <A as KeyAdapter<'a>>::Key: Borrow<Q>,
+    {
+        CursorMut {
+            current: self.upper_bound_internal(bound),
+            tree: self,
+        }
+    }
+
+    /// Inserts a new element into the `RBTree`.
+    ///
+    /// The new element will be inserted at the correct position in the tree
+    /// based on its key.
+    ///
+    /// Returns a mutable cursor pointing to the newly added element.
+    ///
+    /// # Panics
+    ///
+    /// Panics if the new element is already linked to a different intrusive
+    /// collection.
+    #[inline]
+    pub fn insert<'a>(&'a mut self, val: <A::PointerOps as PointerOps>::Pointer) -> CursorMut<'_, A>
+    where
+        <A as KeyAdapter<'a>>::Key: Ord,
+    {
+        unsafe {
+            let new = self.node_from_value(val);
+            let raw = self.adapter.get_value(new);
+            if let Some(root) = self.root {
+                let key = self.adapter.get_key(&*raw);
+                let mut tree = root;
+                loop {
+                    let current = &*self.adapter.get_value(tree);
+                    if key < self.adapter.get_key(current) {
+                        if let Some(left) = self.adapter.link_ops().left(tree) {
+                            tree = left;
+                        } else {
+                            insert_left(self.adapter.link_ops_mut(), tree, new, &mut self.root);
+                            break;
+                        }
+                    } else {
+                        if let Some(right) = self.adapter.link_ops().right(tree) {
+                            tree = right;
+                        } else {
+                            insert_right(self.adapter.link_ops_mut(), tree, new, &mut self.root);
+                            break;
+                        }
+                    }
+                }
+            } else {
+                self.insert_root(new);
+            }
+            CursorMut {
+                current: Some(new),
+                tree: self,
+            }
+        }
+    }
+
+    /// Returns an `Entry` for the given key which contains a `CursorMut` to an
+    /// element with the given key or an `InsertCursor` which points to a place
+    /// in which to insert a new element with the given key.
+    ///
+    /// This is more efficient than calling `find` followed by `insert` since
+    /// the tree does not have to be searched a second time to find a place to
+    /// insert the new element.
+    ///
+    /// If multiple elements with an identical key are found then an arbitrary
+    /// one is returned.
+    #[inline]
+    pub fn entry<'a, Q: ?Sized + Ord>(&'a mut self, key: &Q) -> Entry<'a, A>
+    where
+        <A as KeyAdapter<'a>>::Key: Borrow<Q>,
+    {
+        unsafe {
+            if let Some(root) = self.root {
+                let mut tree = root;
+                loop {
+                    let current = &*self.adapter.get_value(tree);
+                    match key.cmp(self.adapter.get_key(current).borrow()) {
+                        Ordering::Less => {
+                            if let Some(left) = self.adapter.link_ops().left(tree) {
+                                tree = left;
+                            } else {
+                                return Entry::Vacant(InsertCursor {
+                                    parent: Some(tree),
+                                    insert_left: true,
+                                    tree: self,
+                                });
+                            }
+                        }
+                        Ordering::Equal => {
+                            return Entry::Occupied(CursorMut {
+                                current: Some(tree),
+                                tree: self,
+                            });
+                        }
+                        Ordering::Greater => {
+                            if let Some(right) = self.adapter.link_ops().right(tree) {
+                                tree = right;
+                            } else {
+                                return Entry::Vacant(InsertCursor {
+                                    parent: Some(tree),
+                                    insert_left: false,
+                                    tree: self,
+                                });
+                            }
+                        }
+                    }
+                }
+            } else {
+                Entry::Vacant(InsertCursor {
+                    parent: None,
+                    insert_left: false,
+                    tree: self,
+                })
+            }
+        }
+    }
+
+    /// Constructs a double-ended iterator over a sub-range of elements in the
+    /// tree, starting at min, and ending at max. If min is `Unbounded`, then it
+    /// will be treated as "negative infinity", and if max is `Unbounded`, then
+    /// it will be treated as "positive infinity". Thus
+    /// `range(Unbounded, Unbounded)` will yield the whole collection.
+    #[inline]
+    pub fn range<'a, Min: ?Sized + Ord, Max: ?Sized + Ord>(
+        &'a self,
+        min: Bound<&Min>,
+        max: Bound<&Max>,
+    ) -> Iter<'a, A>
+    where
+        <A as KeyAdapter<'a>>::Key: Borrow<Min> + Borrow<Max>,
+        <A as KeyAdapter<'a>>::Key: Ord,
+    {
+        let lower = self.lower_bound_internal(min);
+        let upper = self.upper_bound_internal(max);
+
+        if let (Some(lower), Some(upper)) = (lower, upper) {
+            let lower_key = unsafe { self.adapter.get_key(&*self.adapter.get_value(lower)) };
+            let upper_key = unsafe { self.adapter.get_key(&*self.adapter.get_value(upper)) };
+            if upper_key >= lower_key {
+                return Iter {
+                    head: Some(lower),
+                    tail: Some(upper),
+                    tree: self,
+                };
+            }
+        }
+        Iter {
+            head: None,
+            tail: None,
+            tree: self,
+        }
+    }
+}
+
+// Allow read-only access to values from multiple threads
+unsafe impl<A: Adapter + Sync> Sync for RBTree<A>
+where
+    <A::PointerOps as PointerOps>::Value: Sync,
+    A::LinkOps: RBTreeOps,
+{
+}
+
+// Allow sending to another thread if the ownership (represented by the <A::PointerOps as PointerOps>::Pointer owned
+// pointer type) can be transferred to another thread.
+unsafe impl<A: Adapter + Send> Send for RBTree<A>
+where
+    <A::PointerOps as PointerOps>::Pointer: Send,
+    A::LinkOps: RBTreeOps,
+{
+}
+
+// Drop all owned pointers if the collection is dropped
+impl<A: Adapter> Drop for RBTree<A>
+where
+    A::LinkOps: RBTreeOps,
+{
+    #[inline]
+    fn drop(&mut self) {
+        self.clear();
+    }
+}
+
+impl<A: Adapter> IntoIterator for RBTree<A>
+where
+    A::LinkOps: RBTreeOps,
+{
+    type Item = <A::PointerOps as PointerOps>::Pointer;
+    type IntoIter = IntoIter<A>;
+
+    #[inline]
+    fn into_iter(self) -> IntoIter<A> {
+        let link_ops = self.adapter.link_ops();
+
+        if let Some(root) = self.root {
+            IntoIter {
+                head: Some(unsafe { first_child(link_ops, root) }),
+                tail: Some(unsafe { last_child(link_ops, root) }),
+                tree: self,
+            }
+        } else {
+            IntoIter {
+                head: None,
+                tail: None,
+                tree: self,
+            }
+        }
+    }
+}
+
+impl<'a, A: Adapter + 'a> IntoIterator for &'a RBTree<A>
+where
+    A::LinkOps: RBTreeOps,
+{
+    type Item = &'a <A::PointerOps as PointerOps>::Value;
+    type IntoIter = Iter<'a, A>;
+
+    #[inline]
+    fn into_iter(self) -> Iter<'a, A> {
+        self.iter()
+    }
+}
+
+impl<A: Adapter + Default> Default for RBTree<A>
+where
+    A::LinkOps: RBTreeOps,
+{
+    fn default() -> RBTree<A> {
+        RBTree::new(A::default())
+    }
+}
+
+impl<A: Adapter> fmt::Debug for RBTree<A>
+where
+    A::LinkOps: RBTreeOps,
+    <A::PointerOps as PointerOps>::Value: fmt::Debug,
+{
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_set().entries(self.iter()).finish()
+    }
+}
+
+// =============================================================================
+// InsertCursor, Entry
+// =============================================================================
+
+/// A cursor pointing to a slot in which an element can be inserted into a
+/// `RBTree`.
+pub struct InsertCursor<'a, A: Adapter>
+where
+    A::LinkOps: RBTreeOps,
+{
+    parent: Option<<A::LinkOps as link_ops::LinkOps>::LinkPtr>,
+    insert_left: bool,
+    tree: &'a mut RBTree<A>,
+}
+
+impl<'a, A: Adapter + 'a> InsertCursor<'a, A>
+where
+    A::LinkOps: RBTreeOps,
+{
+    /// Inserts a new element into the `RBTree` at the location indicated by
+    /// this `InsertCursor`.
+    ///
+    /// # Panics
+    ///
+    /// Panics if the new element is already linked to a different intrusive
+    /// collection.
+    pub fn insert(self, val: <A::PointerOps as PointerOps>::Pointer) -> CursorMut<'a, A> {
+        unsafe {
+            let new = self.tree.node_from_value(val);
+            let link_ops = self.tree.adapter.link_ops_mut();
+            if let Some(parent) = self.parent {
+                if self.insert_left {
+                    insert_left(link_ops, parent, new, &mut self.tree.root);
+                } else {
+                    insert_right(link_ops, parent, new, &mut self.tree.root);
+                }
+            } else {
+                self.tree.insert_root(new);
+            }
+            CursorMut {
+                current: Some(new),
+                tree: self.tree,
+            }
+        }
+    }
+}
+
+/// An entry in a `RBTree`.
+///
+/// See the documentation for `RBTree::entry`.
+pub enum Entry<'a, A: Adapter>
+where
+    A::LinkOps: RBTreeOps,
+{
+    /// An occupied entry.
+    Occupied(CursorMut<'a, A>),
+
+    /// A vacant entry.
+    Vacant(InsertCursor<'a, A>),
+}
+
+impl<'a, A: Adapter + 'a> Entry<'a, A>
+where
+    A::LinkOps: RBTreeOps,
+{
+    /// Inserts an element into the `RBTree` if the entry is vacant, returning
+    /// a `CursorMut` to the resulting value. If the entry is occupied then a
+    /// `CursorMut` pointing to the element is returned.
+    ///
+    /// # Panics
+    ///
+    /// Panics if the `Entry` is vacant and the new element is already linked to
+    /// a different intrusive collection.
+    pub fn or_insert(self, val: <A::PointerOps as PointerOps>::Pointer) -> CursorMut<'a, A> {
+        match self {
+            Entry::Occupied(entry) => entry,
+            Entry::Vacant(entry) => entry.insert(val),
+        }
+    }
+
+    /// Calls the given function and inserts the result into the `RBTree` if the
+    /// entry is vacant, returning a `CursorMut` to the resulting value. If the
+    /// entry is occupied then a `CursorMut` pointing to the element is
+    /// returned and the function is not executed.
+    ///
+    /// # Panics
+    ///
+    /// Panics if the `Entry` is vacant and the new element is already linked to
+    /// a different intrusive collection.
+    pub fn or_insert_with<F>(self, default: F) -> CursorMut<'a, A>
+    where
+        F: FnOnce() -> <A::PointerOps as PointerOps>::Pointer,
+    {
+        match self {
+            Entry::Occupied(entry) => entry,
+            Entry::Vacant(entry) => entry.insert(default()),
+        }
+    }
+}
+
+// =============================================================================
+// Iter
+// =============================================================================
+
+/// An iterator over references to the items of a `RBTree`.
+pub struct Iter<'a, A: Adapter>
+where
+    A::LinkOps: RBTreeOps,
+{
+    head: Option<<A::LinkOps as link_ops::LinkOps>::LinkPtr>,
+    tail: Option<<A::LinkOps as link_ops::LinkOps>::LinkPtr>,
+    tree: &'a RBTree<A>,
+}
+impl<'a, A: Adapter + 'a> Iterator for Iter<'a, A>
+where
+    A::LinkOps: RBTreeOps,
+{
+    type Item = &'a <A::PointerOps as PointerOps>::Value;
+
+    #[inline]
+    fn next(&mut self) -> Option<&'a <A::PointerOps as PointerOps>::Value> {
+        let head = self.head?;
+
+        if Some(head) == self.tail {
+            self.head = None;
+            self.tail = None;
+        } else {
+            self.head = unsafe { next(self.tree.adapter.link_ops(), head) };
+        }
+        Some(unsafe { &*self.tree.adapter.get_value(head) })
+    }
+}
+impl<'a, A: Adapter + 'a> DoubleEndedIterator for Iter<'a, A>
+where
+    A::LinkOps: RBTreeOps,
+{
+    #[inline]
+    fn next_back(&mut self) -> Option<&'a <A::PointerOps as PointerOps>::Value> {
+        let tail = self.tail?;
+
+        if Some(tail) == self.head {
+            self.head = None;
+            self.tail = None;
+        } else {
+            self.tail = unsafe { prev(self.tree.adapter.link_ops(), tail) };
+        }
+        Some(unsafe { &*self.tree.adapter.get_value(tail) })
+    }
+}
+impl<'a, A: Adapter + 'a> Clone for Iter<'a, A>
+where
+    A::LinkOps: RBTreeOps,
+{
+    #[inline]
+    fn clone(&self) -> Iter<'a, A> {
+        Iter {
+            head: self.head,
+            tail: self.tail,
+            tree: self.tree,
+        }
+    }
+}
+
+// =============================================================================
+// IntoIter
+// =============================================================================
+
+/// An iterator which consumes a `RBTree`.
+pub struct IntoIter<A: Adapter>
+where
+    A::LinkOps: RBTreeOps,
+{
+    head: Option<<A::LinkOps as link_ops::LinkOps>::LinkPtr>,
+    tail: Option<<A::LinkOps as link_ops::LinkOps>::LinkPtr>,
+    tree: RBTree<A>,
+}
+impl<A: Adapter> Iterator for IntoIter<A>
+where
+    A::LinkOps: RBTreeOps,
+{
+    type Item = <A::PointerOps as PointerOps>::Pointer;
+
+    #[inline]
+    fn next(&mut self) -> Option<<A::PointerOps as PointerOps>::Pointer> {
+        use link_ops::LinkOps;
+
+        let head = self.head?;
+        let link_ops = self.tree.adapter.link_ops_mut();
+        unsafe {
+            // Remove the node from the tree. Since head is always the
+            // left-most node, we can infer the following:
+            // - head.left is null.
+            // - head is a left child of its parent (or the root node).
+            if let Some(parent) = link_ops.parent(head) {
+                link_ops.set_left(parent, link_ops.right(head));
+            } else {
+                self.tree.root = link_ops.right(head);
+                if link_ops.right(head).is_none() {
+                    self.tail = None;
+                }
+            }
+            if let Some(right) = link_ops.right(head) {
+                link_ops.set_parent(right, link_ops.parent(head));
+                self.head = Some(first_child(link_ops, right));
+            } else {
+                self.head = link_ops.parent(head);
+            }
+            link_ops.release_link(head);
+            Some(
+                self.tree
+                    .adapter
+                    .pointer_ops()
+                    .from_raw(self.tree.adapter.get_value(head)),
+            )
+        }
+    }
+}
+impl<A: Adapter> DoubleEndedIterator for IntoIter<A>
+where
+    A::LinkOps: RBTreeOps,
+{
+    #[inline]
+    fn next_back(&mut self) -> Option<<A::PointerOps as PointerOps>::Pointer> {
+        use link_ops::LinkOps;
+
+        let tail = self.tail?;
+        let link_ops = self.tree.adapter.link_ops_mut();
+        unsafe {
+            // Remove the node from the tree. Since tail is always the
+            // right-most node, we can infer the following:
+            // - tail.right is null.
+            // - tail is a right child of its parent (or the root node).
+            if let Some(parent) = link_ops.parent(tail) {
+                link_ops.set_right(parent, link_ops.left(tail));
+            } else {
+                self.tree.root = link_ops.left(tail);
+                if link_ops.left(tail).is_none() {
+                    self.tail = None;
+                }
+            }
+            if let Some(left) = link_ops.left(tail) {
+                link_ops.set_parent(left, link_ops.parent(tail));
+                self.tail = Some(last_child(link_ops, left));
+            } else {
+                self.tail = link_ops.parent(tail);
+            }
+            link_ops.release_link(tail);
+            Some(
+                self.tree
+                    .adapter
+                    .pointer_ops()
+                    .from_raw(self.tree.adapter.get_value(tail)),
+            )
+        }
+    }
+}
+
+// =============================================================================
+// Tests
+// =============================================================================
+
+#[cfg(test)]
+mod tests {
+    use super::{Entry, KeyAdapter, Link, PointerOps, RBTree};
+    use crate::Bound::*;
+    use rand::prelude::*;
+    use rand_xorshift::XorShiftRng;
+    use std::fmt;
+    use std::rc::Rc;
+    use std::vec::Vec;
+    use std::{format, vec};
+
+    #[derive(Clone)]
+    struct Obj {
+        link: Link,
+        value: i32,
+    }
+    impl fmt::Debug for Obj {
+        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+            write!(f, "{}", self.value)
+        }
+    }
+    intrusive_adapter!(ObjAdapter = Rc<Obj>: Obj { link: Link });
+    impl<'a> KeyAdapter<'a> for ObjAdapter {
+        type Key = i32;
+        fn get_key(&self, value: &'a <Self::PointerOps as PointerOps>::Value) -> i32 {
+            value.value
+        }
+    }
+    fn make_obj(value: i32) -> Rc<Obj> {
+        Rc::new(Obj {
+            link: Link::new(),
+            value,
+        })
+    }
+
+    #[test]
+    fn test_link() {
+        let a = make_obj(1);
+        assert!(!a.link.is_linked());
+        assert_eq!(format!("{:?}", a.link), "unlinked");
+
+        let mut b = RBTree::<ObjAdapter>::default();
+        assert!(b.is_empty());
+
+        assert_eq!(b.insert(a.clone()).get().unwrap().value, 1);
+        assert!(!b.is_empty());
+        assert!(a.link.is_linked());
+        assert_eq!(format!("{:?}", a.link), "linked");
+
+        let c = a.as_ref().clone();
+        assert!(!c.link.is_linked());
+
+        unsafe {
+            assert_eq!(b.cursor_from_ptr(a.as_ref()).get().unwrap().value, 1);
+            assert_eq!(b.cursor_mut_from_ptr(a.as_ref()).get().unwrap().value, 1);
+        }
+
+        assert_eq!(
+            b.front_mut().remove().unwrap().as_ref() as *const _,
+            a.as_ref() as *const _
+        );
+        assert!(b.is_empty());
+        assert!(!a.link.is_linked());
+    }
+
+    #[test]
+    fn test_cursor() {
+        let a = make_obj(1);
+        let b = make_obj(2);
+        let c = make_obj(3);
+        let mut t = RBTree::new(ObjAdapter::new());
+        let mut cur = t.cursor_mut();
+        assert!(cur.is_null());
+        assert!(cur.get().is_none());
+        assert!(cur.remove().is_none());
+
+        cur.insert_before(a.clone());
+        cur.insert_before(c.clone());
+        cur.move_prev();
+        cur.insert(b.clone());
+        assert!(cur.peek_next().is_null());
+        cur.move_next();
+        assert!(cur.is_null());
+
+        cur.move_next();
+        assert!(cur.peek_prev().is_null());
+        assert!(!cur.is_null());
+        assert_eq!(cur.get().unwrap() as *const _, a.as_ref() as *const _);
+
+        {
+            let mut cur2 = cur.as_cursor();
+            assert_eq!(cur2.get().unwrap() as *const _, a.as_ref() as *const _);
+            assert_eq!(cur2.peek_next().get().unwrap().value, 2);
+            cur2.move_next();
+            assert_eq!(cur2.get().unwrap().value, 2);
+            cur2.move_next();
+            assert_eq!(cur2.peek_prev().get().unwrap().value, 2);
+            assert_eq!(cur2.get().unwrap() as *const _, c.as_ref() as *const _);
+            cur2.move_prev();
+            assert_eq!(cur2.get().unwrap() as *const _, b.as_ref() as *const _);
+            cur2.move_next();
+            assert_eq!(cur2.get().unwrap() as *const _, c.as_ref() as *const _);
+            cur2.move_next();
+            assert!(cur2.is_null());
+            assert!(cur2.clone().get().is_none());
+        }
+        assert_eq!(cur.get().unwrap() as *const _, a.as_ref() as *const _);
+
+        let a2 = make_obj(1);
+        let b2 = make_obj(2);
+        let c2 = make_obj(3);
+        assert_eq!(
+            cur.replace_with(a2.clone()).unwrap().as_ref() as *const _,
+            a.as_ref() as *const _
+        );
+        assert!(!a.link.is_linked());
+        cur.move_next();
+        assert_eq!(
+            cur.replace_with(b2.clone()).unwrap().as_ref() as *const _,
+            b.as_ref() as *const _
+        );
+        assert!(!b.link.is_linked());
+        cur.move_next();
+        assert_eq!(
+            cur.replace_with(c2.clone()).unwrap().as_ref() as *const _,
+            c.as_ref() as *const _
+        );
+        assert!(!c.link.is_linked());
+        cur.move_next();
+        assert_eq!(
+            cur.replace_with(c.clone()).unwrap_err().as_ref() as *const _,
+            c.as_ref() as *const _
+        );
+    }
+
+    #[cfg(not(miri))]
+    #[test]
+    fn test_insert_remove() {
+        let v = (0..100).map(make_obj).collect::<Vec<_>>();
+        assert!(v.iter().all(|x| !x.link.is_linked()));
+        let mut t = RBTree::new(ObjAdapter::new());
+        assert!(t.is_empty());
+        let mut rng = XorShiftRng::seed_from_u64(0);
+
+        {
+            let mut expected = Vec::new();
+            for x in v.iter() {
+                t.insert(x.clone());
+                expected.push(x.value);
+                assert_eq!(t.iter().map(|x| x.value).collect::<Vec<_>>(), expected);
+            }
+
+            while let Some(x) = t.front_mut().remove() {
+                assert_eq!(x.value, expected.remove(0));
+                assert_eq!(t.iter().map(|x| x.value).collect::<Vec<_>>(), expected);
+            }
+            assert!(expected.is_empty());
+            assert!(t.is_empty());
+        }
+
+        {
+            let mut expected = Vec::new();
+            for x in v.iter().rev() {
+                t.insert(x.clone());
+                expected.insert(0, x.value);
+                assert_eq!(t.iter().map(|x| x.value).collect::<Vec<_>>(), expected);
+            }
+
+            while let Some(x) = t.back_mut().remove() {
+                assert_eq!(x.value, expected.pop().unwrap());
+                assert_eq!(t.iter().map(|x| x.value).collect::<Vec<_>>(), expected);
+            }
+            assert!(expected.is_empty());
+            assert!(t.is_empty());
+        }
+
+        {
+            let mut indices = (0..v.len()).collect::<Vec<_>>();
+            indices.shuffle(&mut rng);
+            let mut expected = Vec::new();
+            for i in indices {
+                t.insert(v[i].clone());
+                expected.push(v[i].value);
+                expected[..].sort();
+                assert_eq!(t.iter().map(|x| x.value).collect::<Vec<_>>(), expected);
+            }
+
+            while !expected.is_empty() {
+                {
+                    let index = rng.gen_range(0, expected.len());
+                    let mut c = t.cursor_mut();
+                    for _ in 0..(index + 1) {
+                        c.move_next();
+                    }
+                    assert_eq!(c.remove().unwrap().value, expected.remove(index));
+                }
+                assert_eq!(t.iter().map(|x| x.value).collect::<Vec<_>>(), expected);
+            }
+            assert!(t.is_empty());
+        }
+
+        {
+            let mut indices = (0..v.len()).collect::<Vec<_>>();
+            indices.shuffle(&mut rng);
+            let mut expected = Vec::new();
+            for i in indices {
+                {
+                    let mut c = t.front_mut();
+                    loop {
+                        if let Some(x) = c.get() {
+                            if x.value > v[i].value {
+                                break;
+                            }
+                        } else {
+                            break;
+                        }
+                        c.move_next();
+                    }
+                    c.insert_before(v[i].clone());
+                }
+                expected.push(v[i].value);
+                expected[..].sort();
+                assert_eq!(t.iter().map(|x| x.value).collect::<Vec<_>>(), expected);
+            }
+
+            t.clear();
+            assert!(t.is_empty());
+        }
+
+        {
+            let mut indices = (0..v.len()).collect::<Vec<_>>();
+            indices.shuffle(&mut rng);
+            let mut expected = Vec::new();
+            for i in indices {
+                {
+                    let mut c = t.back_mut();
+                    loop {
+                        if let Some(x) = c.get() {
+                            if x.value < v[i].value {
+                                break;
+                            }
+                        } else {
+                            break;
+                        }
+                        c.move_prev();
+                    }
+                    c.insert_after(v[i].clone());
+                }
+                expected.push(v[i].value);
+                expected[..].sort();
+                assert_eq!(t.iter().map(|x| x.value).collect::<Vec<_>>(), expected);
+            }
+        }
+    }
+
+    #[cfg(not(miri))]
+    #[test]
+    fn test_iter() {
+        let v = (0..10).map(|x| make_obj(x * 10)).collect::<Vec<_>>();
+        let mut t = RBTree::new(ObjAdapter::new());
+        for x in v.iter() {
+            t.insert(x.clone());
+        }
+
+        assert_eq!(
+            format!("{:?}", t),
+            "{0, 10, 20, 30, 40, 50, 60, 70, 80, 90}"
+        );
+
+        assert_eq!(
+            t.iter().clone().map(|x| x.value).collect::<Vec<_>>(),
+            vec![0, 10, 20, 30, 40, 50, 60, 70, 80, 90]
+        );
+        assert_eq!(
+            (&t).into_iter().rev().map(|x| x.value).collect::<Vec<_>>(),
+            vec![90, 80, 70, 60, 50, 40, 30, 20, 10, 0]
+        );
+        assert_eq!(
+            t.range(Unbounded, Unbounded)
+                .map(|x| x.value)
+                .collect::<Vec<_>>(),
+            vec![0, 10, 20, 30, 40, 50, 60, 70, 80, 90]
+        );
+
+        assert_eq!(
+            t.range(Included(&0), Unbounded)
+                .map(|x| x.value)
+                .collect::<Vec<_>>(),
+            vec![0, 10, 20, 30, 40, 50, 60, 70, 80, 90]
+        );
+        assert_eq!(
+            t.range(Excluded(&0), Unbounded)
+                .map(|x| x.value)
+                .collect::<Vec<_>>(),
+            vec![10, 20, 30, 40, 50, 60, 70, 80, 90]
+        );
+        assert_eq!(
+            t.range(Included(&25), Unbounded)
+                .map(|x| x.value)
+                .collect::<Vec<_>>(),
+            vec![30, 40, 50, 60, 70, 80, 90]
+        );
+        assert_eq!(
+            t.range(Excluded(&25), Unbounded)
+                .map(|x| x.value)
+                .collect::<Vec<_>>(),
+            vec![30, 40, 50, 60, 70, 80, 90]
+        );
+        assert_eq!(
+            t.range(Included(&70), Unbounded)
+                .map(|x| x.value)
+                .collect::<Vec<_>>(),
+            vec![70, 80, 90]
+        );
+        assert_eq!(
+            t.range(Excluded(&70), Unbounded)
+                .map(|x| x.value)
+                .collect::<Vec<_>>(),
+            vec![80, 90]
+        );
+        assert_eq!(
+            t.range(Included(&100), Unbounded)
+                .map(|x| x.value)
+                .collect::<Vec<_>>(),
+            vec![]
+        );
+        assert_eq!(
+            t.range(Excluded(&100), Unbounded)
+                .map(|x| x.value)
+                .collect::<Vec<_>>(),
+            vec![]
+        );
+
+        assert_eq!(
+            t.range(Unbounded, Included(&90))
+                .map(|x| x.value)
+                .collect::<Vec<_>>(),
+            vec![0, 10, 20, 30, 40, 50, 60, 70, 80, 90]
+        );
+        assert_eq!(
+            t.range(Unbounded, Excluded(&90))
+                .map(|x| x.value)
+                .collect::<Vec<_>>(),
+            vec![0, 10, 20, 30, 40, 50, 60, 70, 80]
+        );
+        assert_eq!(
+            t.range(Unbounded, Included(&25))
+                .map(|x| x.value)
+                .collect::<Vec<_>>(),
+            vec![0, 10, 20]
+        );
+        assert_eq!(
+            t.range(Unbounded, Excluded(&25))
+                .map(|x| x.value)
+                .collect::<Vec<_>>(),
+            vec![0, 10, 20]
+        );
+        assert_eq!(
+            t.range(Unbounded, Included(&70))
+                .map(|x| x.value)
+                .collect::<Vec<_>>(),
+            vec![0, 10, 20, 30, 40, 50, 60, 70]
+        );
+        assert_eq!(
+            t.range(Unbounded, Excluded(&70))
+                .map(|x| x.value)
+                .collect::<Vec<_>>(),
+            vec![0, 10, 20, 30, 40, 50, 60]
+        );
+        assert_eq!(
+            t.range(Unbounded, Included(&-1))
+                .map(|x| x.value)
+                .collect::<Vec<_>>(),
+            vec![]
+        );
+        assert_eq!(
+            t.range(Unbounded, Excluded(&-1))
+                .map(|x| x.value)
+                .collect::<Vec<_>>(),
+            vec![]
+        );
+
+        assert_eq!(
+            t.range(Included(&25), Included(&80))
+                .map(|x| x.value)
+                .collect::<Vec<_>>(),
+            vec![30, 40, 50, 60, 70, 80]
+        );
+        assert_eq!(
+            t.range(Included(&25), Excluded(&80))
+                .map(|x| x.value)
+                .collect::<Vec<_>>(),
+            vec![30, 40, 50, 60, 70]
+        );
+        assert_eq!(
+            t.range(Excluded(&25), Included(&80))
+                .map(|x| x.value)
+                .collect::<Vec<_>>(),
+            vec![30, 40, 50, 60, 70, 80]
+        );
+        assert_eq!(
+            t.range(Excluded(&25), Excluded(&80))
+                .map(|x| x.value)
+                .collect::<Vec<_>>(),
+            vec![30, 40, 50, 60, 70]
+        );
+
+        assert_eq!(
+            t.range(Included(&25), Included(&25))
+                .map(|x| x.value)
+                .collect::<Vec<_>>(),
+            vec![]
+        );
+        assert_eq!(
+            t.range(Included(&25), Excluded(&25))
+                .map(|x| x.value)
+                .collect::<Vec<_>>(),
+            vec![]
+        );
+        assert_eq!(
+            t.range(Excluded(&25), Included(&25))
+                .map(|x| x.value)
+                .collect::<Vec<_>>(),
+            vec![]
+        );
+        assert_eq!(
+            t.range(Excluded(&25), Excluded(&25))
+                .map(|x| x.value)
+                .collect::<Vec<_>>(),
+            vec![]
+        );
+
+        assert_eq!(
+            t.range(Included(&50), Included(&50))
+                .map(|x| x.value)
+                .collect::<Vec<_>>(),
+            vec![50]
+        );
+        assert_eq!(
+            t.range(Included(&50), Excluded(&50))
+                .map(|x| x.value)
+                .collect::<Vec<_>>(),
+            vec![]
+        );
+        assert_eq!(
+            t.range(Excluded(&50), Included(&50))
+                .map(|x| x.value)
+                .collect::<Vec<_>>(),
+            vec![]
+        );
+        assert_eq!(
+            t.range(Excluded(&50), Excluded(&50))
+                .map(|x| x.value)
+                .collect::<Vec<_>>(),
+            vec![]
+        );
+
+        assert_eq!(
+            t.range(Included(&100), Included(&-2))
+                .map(|x| x.value)
+                .collect::<Vec<_>>(),
+            vec![]
+        );
+        assert_eq!(
+            t.range(Included(&100), Excluded(&-2))
+                .map(|x| x.value)
+                .collect::<Vec<_>>(),
+            vec![]
+        );
+        assert_eq!(
+            t.range(Excluded(&100), Included(&-2))
+                .map(|x| x.value)
+                .collect::<Vec<_>>(),
+            vec![]
+        );
+        assert_eq!(
+            t.range(Excluded(&100), Excluded(&-2))
+                .map(|x| x.value)
+                .collect::<Vec<_>>(),
+            vec![]
+        );
+
+        let mut v2 = Vec::new();
+        for x in t.take() {
+            v2.push(x.value);
+        }
+        assert_eq!(v2, vec![0, 10, 20, 30, 40, 50, 60, 70, 80, 90]);
+        assert!(t.is_empty());
+        for _ in t.take() {
+            unreachable!();
+        }
+
+        for x in v.iter() {
+            t.insert(x.clone());
+        }
+        v2.clear();
+        for x in t.into_iter().rev() {
+            v2.push(x.value);
+        }
+        assert_eq!(v2, vec![90, 80, 70, 60, 50, 40, 30, 20, 10, 0]);
+    }
+
+    #[test]
+    fn test_find() {
+        let v = (0..10).map(|x| make_obj(x * 10)).collect::<Vec<_>>();
+        let mut t = RBTree::new(ObjAdapter::new());
+        for x in v.iter() {
+            t.insert(x.clone());
+        }
+
+        for i in -9..100 {
+            fn mod10(x: i32) -> i32 {
+                if x < 0 {
+                    10 + x % 10
+                } else {
+                    x % 10
+                }
+            }
+            {
+                let c = t.find(&i);
+                assert_eq!(
+                    c.get().map(|x| x.value),
+                    if i % 10 == 0 { Some(i) } else { None }
+                );
+            }
+            {
+                let c = t.find_mut(&i);
+                assert_eq!(
+                    c.get().map(|x| x.value),
+                    if i % 10 == 0 { Some(i) } else { None }
+                );
+            }
+            {
+                let c = t.upper_bound(Unbounded);
+                assert_eq!(c.get().map(|x| x.value), Some(90));
+            }
+            {
+                let c = t.upper_bound_mut(Unbounded);
+                assert_eq!(c.get().map(|x| x.value), Some(90));
+            }
+            {
+                let c = t.upper_bound(Included(&i));
+                assert_eq!(
+                    c.get().map(|x| x.value),
+                    if i >= 0 { Some(i - mod10(i)) } else { None }
+                );
+            }
+            {
+                let c = t.upper_bound_mut(Included(&i));
+                assert_eq!(
+                    c.get().map(|x| x.value),
+                    if i >= 0 { Some(i - mod10(i)) } else { None }
+                );
+            }
+            {
+                let c = t.upper_bound(Excluded(&i));
+                assert_eq!(
+                    c.get().map(|x| x.value),
+                    if i > 0 {
+                        Some(i - 1 - mod10(i - 1))
+                    } else {
+                        None
+                    }
+                );
+            }
+            {
+                let c = t.upper_bound_mut(Excluded(&i));
+                assert_eq!(
+                    c.get().map(|x| x.value),
+                    if i > 0 {
+                        Some(i - 1 - mod10(i - 1))
+                    } else {
+                        None
+                    }
+                );
+            }
+            {
+                let c = t.lower_bound(Unbounded);
+                assert_eq!(c.get().map(|x| x.value), Some(0));
+            }
+            {
+                let c = t.lower_bound_mut(Unbounded);
+                assert_eq!(c.get().map(|x| x.value), Some(0));
+            }
+            {
+                let c = t.lower_bound(Included(&i));
+                assert_eq!(
+                    c.get().map(|x| x.value),
+                    if i <= 90 {
+                        Some((i + 9) - mod10(i + 9))
+                    } else {
+                        None
+                    }
+                );
+            }
+            {
+                let c = t.lower_bound_mut(Included(&i));
+                assert_eq!(
+                    c.get().map(|x| x.value),
+                    if i <= 90 {
+                        Some((i + 9) - mod10(i + 9))
+                    } else {
+                        None
+                    }
+                );
+            }
+            {
+                let c = t.lower_bound(Excluded(&i));
+                assert_eq!(
+                    c.get().map(|x| x.value),
+                    if i < 90 {
+                        Some((i + 10) - mod10(i + 10))
+                    } else {
+                        None
+                    }
+                );
+            }
+            {
+                let c = t.lower_bound_mut(Excluded(&i));
+                assert_eq!(
+                    c.get().map(|x| x.value),
+                    if i < 90 {
+                        Some((i + 10) - mod10(i + 10))
+                    } else {
+                        None
+                    }
+                );
+            }
+        }
+    }
+
+    #[test]
+    fn test_fast_clear() {
+        let mut t = RBTree::new(ObjAdapter::new());
+        let a = make_obj(1);
+        let b = make_obj(2);
+        let c = make_obj(3);
+        t.insert(a.clone());
+        t.insert(b.clone());
+        t.insert(c.clone());
+
+        t.fast_clear();
+        assert!(t.is_empty());
+        assert!(a.link.is_linked());
+        assert!(b.link.is_linked());
+        assert!(c.link.is_linked());
+        unsafe {
+            a.link.force_unlink();
+            b.link.force_unlink();
+            c.link.force_unlink();
+        }
+        assert!(t.is_empty());
+        assert!(!a.link.is_linked());
+        assert!(!b.link.is_linked());
+        assert!(!c.link.is_linked());
+    }
+
+    #[test]
+    fn test_entry() {
+        let mut t = RBTree::new(ObjAdapter::new());
+        let a = make_obj(1);
+        let b = make_obj(2);
+        let c = make_obj(3);
+        let d = make_obj(4);
+        let e = make_obj(5);
+        let f = make_obj(6);
+        t.entry(&3).or_insert(c.clone());
+        t.entry(&2).or_insert(b.clone());
+        t.entry(&1).or_insert(a.clone());
+
+        match t.entry(&2) {
+            Entry::Vacant(_) => unreachable!(),
+            Entry::Occupied(c) => assert_eq!(c.get().unwrap().value, 2),
+        }
+        assert_eq!(t.entry(&2).or_insert(b.clone()).get().unwrap().value, 2);
+        assert_eq!(
+            t.entry(&2)
+                .or_insert_with(|| b.clone())
+                .get()
+                .unwrap()
+                .value,
+            2
+        );
+
+        match t.entry(&5) {
+            Entry::Vacant(c) => assert_eq!(c.insert(e.clone()).get().unwrap().value, 5),
+            Entry::Occupied(_) => unreachable!(),
+        }
+        assert!(e.link.is_linked());
+        assert_eq!(t.entry(&4).or_insert(d.clone()).get().unwrap().value, 4);
+        assert!(d.link.is_linked());
+        assert_eq!(
+            t.entry(&6)
+                .or_insert_with(|| f.clone())
+                .get()
+                .unwrap()
+                .value,
+            6
+        );
+        assert!(f.link.is_linked());
+    }
+
+    #[test]
+    fn test_non_static() {
+        #[derive(Clone)]
+        struct Obj<'a, T> {
+            link: Link,
+            value: &'a T,
+        }
+        intrusive_adapter!(ObjAdapter<'a, T> = &'a Obj<'a, T>: Obj<'a, T> {link: Link} where T: 'a);
+        impl<'a, 'b, T: 'a + 'b> KeyAdapter<'a> for ObjAdapter<'b, T> {
+            type Key = &'a T;
+            fn get_key(&self, value: &'a Obj<'b, T>) -> &'a T {
+                value.value
+            }
+        }
+
+        let v = 5;
+        let a = Obj {
+            link: Link::default(),
+            value: &v,
+        };
+        let b = a.clone();
+        let mut l = RBTree::new(ObjAdapter::new());
+        l.insert(&a);
+        l.insert(&b);
+        assert_eq!(*l.front().get().unwrap().value, 5);
+        assert_eq!(*l.back().get().unwrap().value, 5);
+    }
+
+    macro_rules! test_clone_pointer {
+        ($ptr: ident, $ptr_import: path) => {
+            use $ptr_import;
+
+            #[derive(Clone)]
+            struct Obj {
+                link: Link,
+                value: usize,
+            }
+            intrusive_adapter!(ObjAdapter = $ptr<Obj>: Obj { link: Link });
+            impl<'a> KeyAdapter<'a> for ObjAdapter {
+                type Key = usize;
+                fn get_key(&self, value: &'a Obj) -> usize {
+                    value.value
+                }
+            }
+
+            let a = $ptr::new(Obj {
+                link: Link::new(),
+                value: 5,
+            });
+            let mut l = RBTree::new(ObjAdapter::new());
+            l.insert(a.clone());
+            assert_eq!(2, $ptr::strong_count(&a));
+
+            let pointer = l.front().clone_pointer().unwrap();
+            assert_eq!(pointer.value, 5);
+            assert_eq!(3, $ptr::strong_count(&a));
+
+            l.front_mut().remove();
+            assert!(l.front().clone_pointer().is_none());
+        };
+    }
+
+    #[test]
+    fn test_clone_pointer_rc() {
+        test_clone_pointer!(Rc, std::rc::Rc);
+    }
+
+    #[test]
+    fn test_clone_pointer_arc() {
+        test_clone_pointer!(Arc, std::sync::Arc);
+    }
+}
diff --git a/src/singly_linked_list.rs b/src/singly_linked_list.rs
new file mode 100644
index 0000000..29feeab
--- /dev/null
+++ b/src/singly_linked_list.rs
@@ -0,0 +1,1359 @@
+// Copyright 2016 Amanieu d'Antras
+// Copyright 2020 Amari Robinson
+//
+// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
+// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
+// http://opensource.org/licenses/MIT>, at your option. This file may not be
+// copied, modified, or distributed except according to those terms.
+
+//! Intrusive singly-linked list.
+
+use core::cell::Cell;
+use core::fmt;
+use core::ptr::NonNull;
+
+use crate::link_ops::{self, DefaultLinkOps};
+use crate::pointer_ops::PointerOps;
+use crate::xor_linked_list::XorLinkedListOps;
+use crate::Adapter;
+
+// =============================================================================
+// SinglyLinkedListOps
+// =============================================================================
+
+/// Link operations for `SinglyLinkedList`.
+pub unsafe trait SinglyLinkedListOps: link_ops::LinkOps {
+    /// Returns the "next" link pointer of `ptr`.
+    ///
+    /// # Safety
+    /// An implementation of `next` must not panic.
+    unsafe fn next(&self, ptr: Self::LinkPtr) -> Option<Self::LinkPtr>;
+
+    /// Sets the "next" link pointer of `ptr`.
+    ///
+    /// # Safety
+    /// An implementation of `set_next` must not panic.
+    unsafe fn set_next(&mut self, ptr: Self::LinkPtr, next: Option<Self::LinkPtr>);
+}
+
+// =============================================================================
+// Link
+// =============================================================================
+
+/// Intrusive link that allows an object to be inserted into a
+/// `SinglyLinkedList`.
+#[repr(align(2))]
+pub struct Link {
+    next: Cell<Option<NonNull<Link>>>,
+}
+
+// Use a special value to indicate an unlinked node
+const UNLINKED_MARKER: Option<NonNull<Link>> =
+    unsafe { Some(NonNull::new_unchecked(1 as *mut Link)) };
+
+impl Link {
+    /// Creates a new `Link`.
+    #[inline]
+    pub const fn new() -> Link {
+        Link {
+            next: Cell::new(UNLINKED_MARKER),
+        }
+    }
+
+    /// Checks whether the `Link` is linked into a `SinglyLinkedList`.
+    #[inline]
+    pub fn is_linked(&self) -> bool {
+        self.next.get() != UNLINKED_MARKER
+    }
+
+    /// Forcibly unlinks an object from a `SinglyLinkedList`.
+    ///
+    /// # Safety
+    ///
+    /// It is undefined behavior to call this function while still linked into a
+    /// `SinglyLinkedList`. The only situation where this function is useful is
+    /// after calling `fast_clear` on a `SinglyLinkedList`, since this clears
+    /// the collection without marking the nodes as unlinked.
+    #[inline]
+    pub unsafe fn force_unlink(&self) {
+        self.next.set(UNLINKED_MARKER);
+    }
+}
+
+impl DefaultLinkOps for Link {
+    type Ops = LinkOps;
+
+    const NEW: Self::Ops = LinkOps;
+}
+
+// An object containing a link can be sent to another thread if it is unlinked.
+unsafe impl Send for Link {}
+
+// Provide an implementation of Clone which simply initializes the new link as
+// unlinked. This allows structs containing a link to derive Clone.
+impl Clone for Link {
+    #[inline]
+    fn clone(&self) -> Link {
+        Link::new()
+    }
+}
+
+// Same as above
+impl Default for Link {
+    #[inline]
+    fn default() -> Link {
+        Link::new()
+    }
+}
+
+// Provide an implementation of Debug so that structs containing a link can
+// still derive Debug.
+impl fmt::Debug for Link {
+    #[inline]
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        // There isn't anything sensible to print here except whether the link
+        // is currently in a list.
+        if self.is_linked() {
+            write!(f, "linked")
+        } else {
+            write!(f, "unlinked")
+        }
+    }
+}
+
+// =============================================================================
+// LinkOps
+// =============================================================================
+
+/// Default `LinkOps` implementation for `SinglyLinkedList`.
+#[derive(Clone, Copy, Default)]
+pub struct LinkOps;
+
+unsafe impl link_ops::LinkOps for LinkOps {
+    type LinkPtr = NonNull<Link>;
+
+    #[inline]
+    unsafe fn acquire_link(&mut self, ptr: Self::LinkPtr) -> bool {
+        if ptr.as_ref().is_linked() {
+            false
+        } else {
+            ptr.as_ref().next.set(None);
+            true
+        }
+    }
+
+    #[inline]
+    unsafe fn release_link(&mut self, ptr: Self::LinkPtr) {
+        ptr.as_ref().next.set(UNLINKED_MARKER);
+    }
+}
+
+unsafe impl SinglyLinkedListOps for LinkOps {
+    #[inline]
+    unsafe fn next(&self, ptr: Self::LinkPtr) -> Option<Self::LinkPtr> {
+        ptr.as_ref().next.get()
+    }
+
+    #[inline]
+    unsafe fn set_next(&mut self, ptr: Self::LinkPtr, next: Option<Self::LinkPtr>) {
+        ptr.as_ref().next.set(next);
+    }
+}
+
+unsafe impl XorLinkedListOps for LinkOps {
+    #[inline]
+    unsafe fn next(
+        &self,
+        ptr: Self::LinkPtr,
+        prev: Option<Self::LinkPtr>,
+    ) -> Option<Self::LinkPtr> {
+        let packed = ptr
+            .as_ref()
+            .next
+            .get()
+            .map(|x| x.as_ptr() as usize)
+            .unwrap_or(0);
+        let raw = packed ^ prev.map(|x| x.as_ptr() as usize).unwrap_or(0);
+
+        NonNull::new(raw as *mut _)
+    }
+
+    #[inline]
+    unsafe fn prev(
+        &self,
+        ptr: Self::LinkPtr,
+        next: Option<Self::LinkPtr>,
+    ) -> Option<Self::LinkPtr> {
+        let packed = ptr
+            .as_ref()
+            .next
+            .get()
+            .map(|x| x.as_ptr() as usize)
+            .unwrap_or(0);
+        let raw = packed ^ next.map(|x| x.as_ptr() as usize).unwrap_or(0);
+        NonNull::new(raw as *mut _)
+    }
+
+    #[inline]
+    unsafe fn set(
+        &mut self,
+        ptr: Self::LinkPtr,
+        prev: Option<Self::LinkPtr>,
+        next: Option<Self::LinkPtr>,
+    ) {
+        let new_packed = prev.map(|x| x.as_ptr() as usize).unwrap_or(0)
+            ^ next.map(|x| x.as_ptr() as usize).unwrap_or(0);
+
+        let new_next = NonNull::new(new_packed as *mut _);
+        ptr.as_ref().next.set(new_next);
+    }
+
+    #[inline]
+    unsafe fn replace_next_or_prev(
+        &mut self,
+        ptr: Self::LinkPtr,
+        old: Option<Self::LinkPtr>,
+        new: Option<Self::LinkPtr>,
+    ) {
+        let packed = ptr
+            .as_ref()
+            .next
+            .get()
+            .map(|x| x.as_ptr() as usize)
+            .unwrap_or(0);
+        let new_packed = packed
+            ^ old.map(|x| x.as_ptr() as usize).unwrap_or(0)
+            ^ new.map(|x| x.as_ptr() as usize).unwrap_or(0);
+
+        let new_next = NonNull::new(new_packed as *mut _);
+        ptr.as_ref().next.set(new_next);
+    }
+}
+
+#[inline]
+unsafe fn link_between<T: SinglyLinkedListOps>(
+    link_ops: &mut T,
+    ptr: T::LinkPtr,
+    prev: Option<T::LinkPtr>,
+    next: Option<T::LinkPtr>,
+) {
+    if let Some(prev) = prev {
+        link_ops.set_next(prev, Some(ptr));
+    }
+    link_ops.set_next(ptr, next);
+}
+
+#[inline]
+unsafe fn link_after<T: SinglyLinkedListOps>(link_ops: &mut T, ptr: T::LinkPtr, prev: T::LinkPtr) {
+    link_between(link_ops, ptr, Some(prev), link_ops.next(prev));
+}
+
+#[inline]
+unsafe fn replace_with<T: SinglyLinkedListOps>(
+    link_ops: &mut T,
+    ptr: T::LinkPtr,
+    prev: Option<T::LinkPtr>,
+    new: T::LinkPtr,
+) {
+    if let Some(prev) = prev {
+        link_ops.set_next(prev, Some(new));
+    }
+    link_ops.set_next(new, link_ops.next(ptr));
+    link_ops.release_link(ptr);
+}
+
+#[inline]
+unsafe fn remove<T: SinglyLinkedListOps>(
+    link_ops: &mut T,
+    ptr: T::LinkPtr,
+    prev: Option<T::LinkPtr>,
+) {
+    if let Some(prev) = prev {
+        link_ops.set_next(prev, link_ops.next(ptr));
+    }
+    link_ops.release_link(ptr);
+}
+
+#[inline]
+unsafe fn splice<T: SinglyLinkedListOps>(
+    link_ops: &mut T,
+    start: T::LinkPtr,
+    end: T::LinkPtr,
+    prev: Option<T::LinkPtr>,
+    next: Option<T::LinkPtr>,
+) {
+    link_ops.set_next(end, next);
+    if let Some(prev) = prev {
+        link_ops.set_next(prev, Some(start));
+    }
+}
+
+// =============================================================================
+// Cursor, CursorMut
+// =============================================================================
+
+/// A cursor which provides read-only access to a `SinglyLinkedList`.
+pub struct Cursor<'a, A: Adapter>
+where
+    A::LinkOps: SinglyLinkedListOps,
+{
+    current: Option<<A::LinkOps as link_ops::LinkOps>::LinkPtr>,
+    list: &'a SinglyLinkedList<A>,
+}
+
+impl<'a, A: Adapter> Clone for Cursor<'a, A>
+where
+    A::LinkOps: SinglyLinkedListOps,
+{
+    #[inline]
+    fn clone(&self) -> Cursor<'a, A> {
+        Cursor {
+            current: self.current,
+            list: self.list,
+        }
+    }
+}
+
+impl<'a, A: Adapter> Cursor<'a, A>
+where
+    A::LinkOps: SinglyLinkedListOps,
+{
+    /// Checks if the cursor is currently pointing to the null object.
+    #[inline]
+    pub fn is_null(&self) -> bool {
+        self.current.is_none()
+    }
+
+    /// Returns a reference to the object that the cursor is currently
+    /// pointing to.
+    ///
+    /// This returns `None` if the cursor is currently pointing to the null
+    /// object.
+    #[inline]
+    pub fn get(&self) -> Option<&'a <A::PointerOps as PointerOps>::Value> {
+        Some(unsafe { &*self.list.adapter.get_value(self.current?) })
+    }
+
+    /// Clones and returns the pointer that points to the element that the
+    /// cursor is referencing.
+    ///
+    /// This returns `None` if the cursor is currently pointing to the null
+    /// object.
+    #[inline]
+    pub fn clone_pointer(&self) -> Option<<A::PointerOps as PointerOps>::Pointer>
+    where
+        <A::PointerOps as PointerOps>::Pointer: Clone,
+    {
+        let raw_pointer = self.get()? as *const <A::PointerOps as PointerOps>::Value;
+        Some(unsafe {
+            crate::pointer_ops::clone_pointer_from_raw(self.list.adapter.pointer_ops(), raw_pointer)
+        })
+    }
+
+    /// Moves the cursor to the next element of the `SinglyLinkedList`.
+    ///
+    /// If the cursor is pointer to the null object then this will move it to
+    /// the first element of the `SinglyLinkedList`. If it is pointing to the
+    /// last element of the `SinglyLinkedList` then this will move it to the
+    /// null object.
+    #[inline]
+    pub fn move_next(&mut self) {
+        if let Some(current) = self.current {
+            self.current = unsafe { self.list.adapter.link_ops().next(current) };
+        } else {
+            self.current = self.list.head;
+        }
+    }
+
+    /// Returns a cursor pointing to the next element of the `SinglyLinkedList`.
+    ///
+    /// If the cursor is pointer to the null object then this will return the
+    /// first element of the `SinglyLinkedList`. If it is pointing to the last
+    /// element of the `SinglyLinkedList` then this will return a null cursor.
+    #[inline]
+    pub fn peek_next(&self) -> Cursor<'_, A> {
+        let mut next = self.clone();
+        next.move_next();
+        next
+    }
+}
+
+/// A cursor which provides mutable access to a `SinglyLinkedList`.
+pub struct CursorMut<'a, A: Adapter>
+where
+    A::LinkOps: SinglyLinkedListOps,
+{
+    current: Option<<A::LinkOps as link_ops::LinkOps>::LinkPtr>,
+    list: &'a mut SinglyLinkedList<A>,
+}
+
+impl<'a, A: Adapter> CursorMut<'a, A>
+where
+    A::LinkOps: SinglyLinkedListOps,
+{
+    /// Checks if the cursor is currently pointing to the null object.
+    #[inline]
+    pub fn is_null(&self) -> bool {
+        self.current.is_none()
+    }
+
+    /// Returns a reference to the object that the cursor is currently
+    /// pointing to.
+    ///
+    /// This returns None if the cursor is currently pointing to the null
+    /// object.
+    #[inline]
+    pub fn get(&self) -> Option<&<A::PointerOps as PointerOps>::Value> {
+        Some(unsafe { &*self.list.adapter.get_value(self.current?) })
+    }
+
+    /// Returns a read-only cursor pointing to the current element.
+    ///
+    /// The lifetime of the returned `Cursor` is bound to that of the
+    /// `CursorMut`, which means it cannot outlive the `CursorMut` and that the
+    /// `CursorMut` is frozen for the lifetime of the `Cursor`.
+    #[inline]
+    pub fn as_cursor(&self) -> Cursor<'_, A> {
+        Cursor {
+            current: self.current,
+            list: self.list,
+        }
+    }
+
+    /// Moves the cursor to the next element of the `SinglyLinkedList`.
+    ///
+    /// If the cursor is pointer to the null object then this will move it to
+    /// the first element of the `SinglyLinkedList`. If it is pointing to the
+    /// last element of the `SinglyLinkedList` then this will move it to the
+    /// null object.
+    #[inline]
+    pub fn move_next(&mut self) {
+        if let Some(current) = self.current {
+            self.current = unsafe { self.list.adapter.link_ops().next(current) };
+        } else {
+            self.current = self.list.head;
+        }
+    }
+
+    /// Returns a cursor pointing to the next element of the `SinglyLinkedList`.
+    ///
+    /// If the cursor is pointer to the null object then this will return the
+    /// first element of the `SinglyLinkedList`. If it is pointing to the last
+    /// element of the `SinglyLinkedList` then this will return a null cursor.
+    #[inline]
+    pub fn peek_next(&self) -> Cursor<'_, A> {
+        let mut next = self.as_cursor();
+        next.move_next();
+        next
+    }
+
+    /// Removes the next element from the `SinglyLinkedList`.
+    ///
+    /// A pointer to the element that was removed is returned, and the cursor is
+    /// not moved.
+    ///
+    /// If the cursor is currently pointing to the last element of the
+    /// `SinglyLinkedList` then no element is removed and `None` is returned.
+    #[inline]
+    pub fn remove_next(&mut self) -> Option<<A::PointerOps as PointerOps>::Pointer> {
+        unsafe {
+            let next = if let Some(current) = self.current {
+                self.list.adapter.link_ops().next(current)
+            } else {
+                self.list.head
+            }?;
+
+            if self.is_null() {
+                self.list.head = self.list.adapter.link_ops().next(next);
+            }
+            remove(self.list.adapter.link_ops_mut(), next, self.current);
+
+            Some(
+                self.list
+                    .adapter
+                    .pointer_ops()
+                    .from_raw(self.list.adapter.get_value(next)),
+            )
+        }
+    }
+
+    /// Removes the next element from the `SinglyLinkedList` and inserts
+    /// another object in its place.
+    ///
+    /// A pointer to the element that was removed is returned, and the cursor is
+    /// not moved.
+    ///
+    /// If the cursor is currently pointing to the last element of the
+    /// `SinglyLinkedList` then no element is added or removed and an error is
+    /// returned containing the given `val` parameter.
+    ///
+    /// # Panics
+    ///
+    /// Panics if the new element is already linked to a different intrusive
+    /// collection.
+    #[inline]
+    pub fn replace_next_with(
+        &mut self,
+        val: <A::PointerOps as PointerOps>::Pointer,
+    ) -> Result<<A::PointerOps as PointerOps>::Pointer, <A::PointerOps as PointerOps>::Pointer>
+    {
+        unsafe {
+            let next = if let Some(current) = self.current {
+                self.list.adapter.link_ops().next(current)
+            } else {
+                self.list.head
+            };
+            match next {
+                Some(next) => {
+                    let new = self.list.node_from_value(val);
+                    if self.is_null() {
+                        self.list.head = Some(new);
+                    }
+                    replace_with(self.list.adapter.link_ops_mut(), next, self.current, new);
+                    Ok(self
+                        .list
+                        .adapter
+                        .pointer_ops()
+                        .from_raw(self.list.adapter.get_value(next)))
+                }
+                None => Err(val),
+            }
+        }
+    }
+
+    /// Inserts a new element into the `SinglyLinkedList` after the current one.
+    ///
+    /// If the cursor is pointing at the null object then the new element is
+    /// inserted at the front of the `SinglyLinkedList`.
+    ///
+    /// # Panics
+    ///
+    /// Panics if the new element is already linked to a different intrusive
+    /// collection.
+    #[inline]
+    pub fn insert_after(&mut self, val: <A::PointerOps as PointerOps>::Pointer) {
+        unsafe {
+            let new = self.list.node_from_value(val);
+            if let Some(current) = self.current {
+                link_after(self.list.adapter.link_ops_mut(), new, current);
+            } else {
+                link_between(self.list.adapter.link_ops_mut(), new, None, self.list.head);
+                self.list.head = Some(new);
+            }
+        }
+    }
+
+    /// Inserts the elements from the given `SinglyLinkedList` after the current
+    /// one.
+    ///
+    /// If the cursor is pointing at the null object then the new elements are
+    /// inserted at the start of the `SinglyLinkedList`.
+    ///
+    /// Note that if the cursor is not pointing to the last element of the
+    /// `SinglyLinkedList` then the given list must be scanned to find its last
+    /// element. This has linear time complexity.
+    #[inline]
+    pub fn splice_after(&mut self, mut list: SinglyLinkedList<A>) {
+        if let Some(head) = list.head {
+            unsafe {
+                let next = if let Some(current) = self.current {
+                    self.list.adapter.link_ops().next(current)
+                } else {
+                    self.list.head
+                };
+                if let Some(next) = next {
+                    let mut tail = head;
+                    while let Some(x) = self.list.adapter.link_ops().next(tail) {
+                        tail = x;
+                    }
+                    splice(
+                        self.list.adapter.link_ops_mut(),
+                        head,
+                        tail,
+                        self.current,
+                        Some(next),
+                    );
+                    if self.is_null() {
+                        self.list.head = list.head;
+                    }
+                } else {
+                    if let Some(current) = self.current {
+                        self.list
+                            .adapter
+                            .link_ops_mut()
+                            .set_next(current, list.head);
+                    } else {
+                        self.list.head = list.head;
+                    }
+                }
+                list.head = None;
+            }
+        }
+    }
+
+    /// Splits the list into two after the current element. This will return a
+    /// new list consisting of everything after the cursor, with the original
+    /// list retaining everything before.
+    ///
+    /// If the cursor is pointing at the null object then the entire contents
+    /// of the `SinglyLinkedList` are moved.
+    #[inline]
+    pub fn split_after(&mut self) -> SinglyLinkedList<A>
+    where
+        A: Clone,
+    {
+        if let Some(current) = self.current {
+            unsafe {
+                let list = SinglyLinkedList {
+                    head: self.list.adapter.link_ops().next(current),
+                    adapter: self.list.adapter.clone(),
+                };
+                self.list.adapter.link_ops_mut().set_next(current, None);
+                list
+            }
+        } else {
+            let list = SinglyLinkedList {
+                head: self.list.head,
+                adapter: self.list.adapter.clone(),
+            };
+            self.list.head = None;
+            list
+        }
+    }
+}
+
+// =============================================================================
+// SinglyLinkedList
+// =============================================================================
+
+/// An intrusive singly-linked list.
+///
+/// When this collection is dropped, all elements linked into it will be
+/// converted back to owned pointers and dropped.
+pub struct SinglyLinkedList<A: Adapter>
+where
+    A::LinkOps: SinglyLinkedListOps,
+{
+    head: Option<<A::LinkOps as link_ops::LinkOps>::LinkPtr>,
+    adapter: A,
+}
+
+impl<A: Adapter> SinglyLinkedList<A>
+where
+    A::LinkOps: SinglyLinkedListOps,
+{
+    #[inline]
+    fn node_from_value(
+        &mut self,
+        val: <A::PointerOps as PointerOps>::Pointer,
+    ) -> <A::LinkOps as link_ops::LinkOps>::LinkPtr {
+        use link_ops::LinkOps;
+
+        unsafe {
+            let raw = self.adapter.pointer_ops().into_raw(val);
+            let link = self.adapter.get_link(raw);
+
+            if !self.adapter.link_ops_mut().acquire_link(link) {
+                // convert the node back into a pointer
+                self.adapter.pointer_ops().from_raw(raw);
+
+                panic!("attempted to insert an object that is already linked");
+            }
+
+            link
+        }
+    }
+
+    /// Creates an empty `SinglyLinkedList`.
+    #[cfg(not(feature = "nightly"))]
+    #[inline]
+    pub fn new(adapter: A) -> SinglyLinkedList<A> {
+        SinglyLinkedList {
+            head: None,
+            adapter,
+        }
+    }
+
+    /// Creates an empty `SinglyLinkedList`.
+    #[cfg(feature = "nightly")]
+    #[inline]
+    pub const fn new(adapter: A) -> SinglyLinkedList<A> {
+        SinglyLinkedList {
+            head: None,
+            adapter,
+        }
+    }
+
+    /// Returns `true` if the `SinglyLinkedList` is empty.
+    #[inline]
+    pub fn is_empty(&self) -> bool {
+        self.head.is_none()
+    }
+
+    /// Returns a null `Cursor` for this list.
+    #[inline]
+    pub fn cursor(&self) -> Cursor<'_, A> {
+        Cursor {
+            current: None,
+            list: self,
+        }
+    }
+
+    /// Returns a null `CursorMut` for this list.
+    #[inline]
+    pub fn cursor_mut(&mut self) -> CursorMut<'_, A> {
+        CursorMut {
+            current: None,
+            list: self,
+        }
+    }
+
+    /// Creates a `Cursor` from a pointer to an element.
+    ///
+    /// # Safety
+    ///
+    /// `ptr` must be a pointer to an object that is part of this list.
+    #[inline]
+    pub unsafe fn cursor_from_ptr(
+        &self,
+        ptr: *const <A::PointerOps as PointerOps>::Value,
+    ) -> Cursor<'_, A> {
+        Cursor {
+            current: Some(self.adapter.get_link(ptr)),
+            list: self,
+        }
+    }
+
+    /// Creates a `CursorMut` from a pointer to an element.
+    ///
+    /// # Safety
+    ///
+    /// `ptr` must be a pointer to an object that is part of this list.
+    #[inline]
+    pub unsafe fn cursor_mut_from_ptr(
+        &mut self,
+        ptr: *const <A::PointerOps as PointerOps>::Value,
+    ) -> CursorMut<'_, A> {
+        CursorMut {
+            current: Some(self.adapter.get_link(ptr)),
+            list: self,
+        }
+    }
+
+    /// Returns a `Cursor` pointing to the first element of the list. If the
+    /// list is empty then a null cursor is returned.
+    #[inline]
+    pub fn front(&self) -> Cursor<'_, A> {
+        let mut cursor = self.cursor();
+        cursor.move_next();
+        cursor
+    }
+
+    /// Returns a `CursorMut` pointing to the first element of the list. If the
+    /// the list is empty then a null cursor is returned.
+    #[inline]
+    pub fn front_mut(&mut self) -> CursorMut<'_, A> {
+        let mut cursor = self.cursor_mut();
+        cursor.move_next();
+        cursor
+    }
+
+    /// Gets an iterator over the objects in the `SinglyLinkedList`.
+    #[inline]
+    pub fn iter(&self) -> Iter<'_, A> {
+        Iter {
+            current: self.head,
+            list: self,
+        }
+    }
+
+    /// Removes all elements from the `SinglyLinkedList`.
+    ///
+    /// This will unlink all object currently in the list, which requires
+    /// iterating through all elements in the `SinglyLinkedList`. Each element is
+    /// converted back to an owned pointer and then dropped.
+    #[inline]
+    pub fn clear(&mut self) {
+        use link_ops::LinkOps;
+
+        let mut current = self.head;
+        self.head = None;
+        while let Some(x) = current {
+            unsafe {
+                let next = self.adapter.link_ops().next(x);
+                self.adapter.link_ops_mut().release_link(x);
+                self.adapter
+                    .pointer_ops()
+                    .from_raw(self.adapter.get_value(x));
+                current = next;
+            }
+        }
+    }
+
+    /// Empties the `SinglyLinkedList` without unlinking or freeing objects in it.
+    ///
+    /// Since this does not unlink any objects, any attempts to link these
+    /// objects into another `SinglyLinkedList` will fail but will not cause any
+    /// memory unsafety. To unlink those objects manually, you must call the
+    /// `force_unlink` function on them.
+    #[inline]
+    pub fn fast_clear(&mut self) {
+        self.head = None;
+    }
+
+    /// Takes all the elements out of the `SinglyLinkedList`, leaving it empty.
+    /// The taken elements are returned as a new `SinglyLinkedList`.
+    #[inline]
+    pub fn take(&mut self) -> SinglyLinkedList<A>
+    where
+        A: Clone,
+    {
+        let list = SinglyLinkedList {
+            head: self.head,
+            adapter: self.adapter.clone(),
+        };
+        self.head = None;
+        list
+    }
+
+    /// Inserts a new element at the start of the `SinglyLinkedList`.
+    #[inline]
+    pub fn push_front(&mut self, val: <A::PointerOps as PointerOps>::Pointer) {
+        self.cursor_mut().insert_after(val);
+    }
+
+    /// Removes the first element of the `SinglyLinkedList`.
+    ///
+    /// This returns `None` if the `SinglyLinkedList` is empty.
+    #[inline]
+    pub fn pop_front(&mut self) -> Option<<A::PointerOps as PointerOps>::Pointer> {
+        self.cursor_mut().remove_next()
+    }
+}
+
+// Allow read-only access to values from multiple threads
+unsafe impl<A: Adapter + Sync> Sync for SinglyLinkedList<A>
+where
+    <A::PointerOps as PointerOps>::Value: Sync,
+    A::LinkOps: SinglyLinkedListOps,
+{
+}
+
+// Allow sending to another thread if the ownership (represented by the <A::PointerOps as PointerOps>::Pointer owned
+// pointer type) can be transferred to another thread.
+unsafe impl<A: Adapter + Send> Send for SinglyLinkedList<A>
+where
+    <A::PointerOps as PointerOps>::Pointer: Send,
+    A::LinkOps: SinglyLinkedListOps,
+{
+}
+
+// Drop all owned pointers if the collection is dropped
+impl<A: Adapter> Drop for SinglyLinkedList<A>
+where
+    A::LinkOps: SinglyLinkedListOps,
+{
+    #[inline]
+    fn drop(&mut self) {
+        self.clear();
+    }
+}
+
+impl<A: Adapter> IntoIterator for SinglyLinkedList<A>
+where
+    A::LinkOps: SinglyLinkedListOps,
+{
+    type Item = <A::PointerOps as PointerOps>::Pointer;
+    type IntoIter = IntoIter<A>;
+
+    #[inline]
+    fn into_iter(self) -> IntoIter<A> {
+        IntoIter { list: self }
+    }
+}
+
+impl<'a, A: Adapter + 'a> IntoIterator for &'a SinglyLinkedList<A>
+where
+    A::LinkOps: SinglyLinkedListOps,
+{
+    type Item = &'a <A::PointerOps as PointerOps>::Value;
+    type IntoIter = Iter<'a, A>;
+
+    #[inline]
+    fn into_iter(self) -> Iter<'a, A> {
+        self.iter()
+    }
+}
+
+impl<A: Adapter + Default> Default for SinglyLinkedList<A>
+where
+    A::LinkOps: SinglyLinkedListOps,
+{
+    fn default() -> SinglyLinkedList<A> {
+        SinglyLinkedList::new(A::default())
+    }
+}
+
+impl<A: Adapter> fmt::Debug for SinglyLinkedList<A>
+where
+    A::LinkOps: SinglyLinkedListOps,
+    <A::PointerOps as PointerOps>::Value: fmt::Debug,
+{
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_list().entries(self.iter()).finish()
+    }
+}
+
+// =============================================================================
+// Iter
+// =============================================================================
+
+/// An iterator over references to the items of a `SinglyLinkedList`.
+pub struct Iter<'a, A: Adapter>
+where
+    A::LinkOps: SinglyLinkedListOps,
+{
+    current: Option<<A::LinkOps as link_ops::LinkOps>::LinkPtr>,
+    list: &'a SinglyLinkedList<A>,
+}
+impl<'a, A: Adapter + 'a> Iterator for Iter<'a, A>
+where
+    A::LinkOps: SinglyLinkedListOps,
+{
+    type Item = &'a <A::PointerOps as PointerOps>::Value;
+
+    #[inline]
+    fn next(&mut self) -> Option<&'a <A::PointerOps as PointerOps>::Value> {
+        let current = self.current?;
+
+        self.current = unsafe { self.list.adapter.link_ops().next(current) };
+        Some(unsafe { &*self.list.adapter.get_value(current) })
+    }
+}
+impl<'a, A: Adapter + 'a> Clone for Iter<'a, A>
+where
+    A::LinkOps: SinglyLinkedListOps,
+{
+    #[inline]
+    fn clone(&self) -> Iter<'a, A> {
+        Iter {
+            current: self.current,
+            list: self.list,
+        }
+    }
+}
+
+// =============================================================================
+// IntoIter
+// =============================================================================
+
+/// An iterator which consumes a `SinglyLinkedList`.
+pub struct IntoIter<A: Adapter>
+where
+    A::LinkOps: SinglyLinkedListOps,
+{
+    list: SinglyLinkedList<A>,
+}
+impl<A: Adapter> Iterator for IntoIter<A>
+where
+    A::LinkOps: SinglyLinkedListOps,
+{
+    type Item = <A::PointerOps as PointerOps>::Pointer;
+
+    #[inline]
+    fn next(&mut self) -> Option<<A::PointerOps as PointerOps>::Pointer> {
+        self.list.pop_front()
+    }
+}
+
+// =============================================================================
+// Tests
+// =============================================================================
+
+#[cfg(test)]
+mod tests {
+    use super::{Link, SinglyLinkedList};
+    use std::fmt;
+    use std::format;
+    use std::rc::Rc;
+    use std::vec::Vec;
+
+    struct Obj {
+        link1: Link,
+        link2: Link,
+        value: u32,
+    }
+    impl fmt::Debug for Obj {
+        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+            write!(f, "{}", self.value)
+        }
+    }
+    intrusive_adapter!(ObjAdapter1 = Rc<Obj>: Obj { link1: Link });
+    intrusive_adapter!(ObjAdapter2 = Rc<Obj>: Obj { link2: Link });
+    fn make_obj(value: u32) -> Rc<Obj> {
+        Rc::new(Obj {
+            link1: Link::new(),
+            link2: Link::default(),
+            value,
+        })
+    }
+
+    #[test]
+    fn test_link() {
+        let a = make_obj(1);
+        assert!(!a.link1.is_linked());
+        assert!(!a.link2.is_linked());
+
+        let mut b = SinglyLinkedList::<ObjAdapter1>::default();
+        assert!(b.is_empty());
+
+        b.push_front(a.clone());
+        assert!(!b.is_empty());
+        assert!(a.link1.is_linked());
+        assert!(!a.link2.is_linked());
+        assert_eq!(format!("{:?}", a.link1), "linked");
+        assert_eq!(format!("{:?}", a.link2), "unlinked");
+
+        assert_eq!(
+            b.pop_front().unwrap().as_ref() as *const _,
+            a.as_ref() as *const _
+        );
+        assert!(b.is_empty());
+        assert!(!a.link1.is_linked());
+        assert!(!a.link2.is_linked());
+    }
+
+    #[test]
+    fn test_cursor() {
+        let a = make_obj(1);
+        let b = make_obj(2);
+        let c = make_obj(3);
+
+        let mut l = SinglyLinkedList::new(ObjAdapter1::new());
+        let mut cur = l.cursor_mut();
+        assert!(cur.is_null());
+        assert!(cur.get().is_none());
+        assert!(cur.remove_next().is_none());
+        assert_eq!(
+            cur.replace_next_with(a.clone()).unwrap_err().as_ref() as *const _,
+            a.as_ref() as *const _
+        );
+
+        cur.insert_after(c.clone());
+        cur.insert_after(a.clone());
+        cur.move_next();
+        cur.insert_after(b.clone());
+        cur.move_next();
+        cur.move_next();
+        assert!(cur.peek_next().is_null());
+        cur.move_next();
+        assert!(cur.is_null());
+
+        cur.move_next();
+        assert!(!cur.is_null());
+        assert_eq!(cur.get().unwrap() as *const _, a.as_ref() as *const _);
+
+        {
+            let mut cur2 = cur.as_cursor();
+            assert_eq!(cur2.get().unwrap() as *const _, a.as_ref() as *const _);
+            assert_eq!(cur2.peek_next().get().unwrap().value, 2);
+            cur2.move_next();
+            assert_eq!(cur2.get().unwrap().value, 2);
+            cur2.move_next();
+            assert_eq!(cur2.get().unwrap() as *const _, c.as_ref() as *const _);
+            cur2.move_next();
+            assert!(cur2.is_null());
+            assert!(cur2.clone().get().is_none());
+        }
+        assert_eq!(cur.get().unwrap() as *const _, a.as_ref() as *const _);
+
+        assert_eq!(
+            cur.remove_next().unwrap().as_ref() as *const _,
+            b.as_ref() as *const _
+        );
+        assert_eq!(cur.get().unwrap() as *const _, a.as_ref() as *const _);
+        cur.insert_after(b.clone());
+        assert_eq!(cur.get().unwrap() as *const _, a.as_ref() as *const _);
+        cur.move_next();
+        assert_eq!(cur.get().unwrap() as *const _, b.as_ref() as *const _);
+        assert_eq!(
+            cur.remove_next().unwrap().as_ref() as *const _,
+            c.as_ref() as *const _
+        );
+        assert!(!c.link1.is_linked());
+        assert!(a.link1.is_linked());
+        assert_eq!(cur.get().unwrap() as *const _, b.as_ref() as *const _);
+        cur.move_next();
+        assert!(cur.is_null());
+        assert_eq!(
+            cur.replace_next_with(c.clone()).unwrap().as_ref() as *const _,
+            a.as_ref() as *const _
+        );
+        assert!(!a.link1.is_linked());
+        assert!(c.link1.is_linked());
+        assert!(cur.is_null());
+        cur.move_next();
+        assert_eq!(cur.get().unwrap() as *const _, c.as_ref() as *const _);
+        assert_eq!(
+            cur.replace_next_with(a.clone()).unwrap().as_ref() as *const _,
+            b.as_ref() as *const _
+        );
+        assert!(a.link1.is_linked());
+        assert!(!b.link1.is_linked());
+        assert!(c.link1.is_linked());
+        assert_eq!(cur.get().unwrap() as *const _, c.as_ref() as *const _);
+    }
+
+    #[test]
+    fn test_split_splice() {
+        let mut l1 = SinglyLinkedList::new(ObjAdapter1::new());
+        let mut l2 = SinglyLinkedList::new(ObjAdapter1::new());
+        let mut l3 = SinglyLinkedList::new(ObjAdapter1::new());
+
+        let a = make_obj(1);
+        let b = make_obj(2);
+        let c = make_obj(3);
+        let d = make_obj(4);
+        l1.cursor_mut().insert_after(d.clone());
+        l1.cursor_mut().insert_after(c.clone());
+        l1.cursor_mut().insert_after(b.clone());
+        l1.cursor_mut().insert_after(a.clone());
+        assert_eq!(l1.iter().map(|x| x.value).collect::<Vec<_>>(), [1, 2, 3, 4]);
+        assert_eq!(l2.iter().map(|x| x.value).collect::<Vec<_>>(), []);
+        assert_eq!(l3.iter().map(|x| x.value).collect::<Vec<_>>(), []);
+        {
+            let mut cur = l1.front_mut();
+            cur.move_next();
+            l2 = cur.split_after();
+        }
+        assert_eq!(l1.iter().map(|x| x.value).collect::<Vec<_>>(), [1, 2]);
+        assert_eq!(l2.iter().map(|x| x.value).collect::<Vec<_>>(), [3, 4]);
+        assert_eq!(l3.iter().map(|x| x.value).collect::<Vec<_>>(), []);
+        {
+            let mut cur = l2.front_mut();
+            l3 = cur.split_after();
+        }
+        assert_eq!(l1.iter().map(|x| x.value).collect::<Vec<_>>(), [1, 2]);
+        assert_eq!(l2.iter().map(|x| x.value).collect::<Vec<_>>(), [3]);
+        assert_eq!(l3.iter().map(|x| x.value).collect::<Vec<_>>(), [4]);
+        {
+            let mut cur = l1.front_mut();
+            cur.splice_after(l2.take());
+        }
+        assert_eq!(l1.iter().map(|x| x.value).collect::<Vec<_>>(), [1, 3, 2]);
+        assert_eq!(l2.iter().map(|x| x.value).collect::<Vec<_>>(), []);
+        assert_eq!(l3.iter().map(|x| x.value).collect::<Vec<_>>(), [4]);
+        {
+            let mut cur = l1.cursor_mut();
+            cur.splice_after(l3.take());
+        }
+        assert_eq!(l1.iter().map(|x| x.value).collect::<Vec<_>>(), [4, 1, 3, 2]);
+        assert_eq!(l2.iter().map(|x| x.value).collect::<Vec<_>>(), []);
+        assert_eq!(l3.iter().map(|x| x.value).collect::<Vec<_>>(), []);
+        {
+            let mut cur = l1.cursor_mut();
+            l2 = cur.split_after();
+        }
+        assert_eq!(l1.iter().map(|x| x.value).collect::<Vec<_>>(), []);
+        assert_eq!(l2.iter().map(|x| x.value).collect::<Vec<_>>(), [4, 1, 3, 2]);
+        assert_eq!(l3.iter().map(|x| x.value).collect::<Vec<_>>(), []);
+        {
+            let mut cur = l2.front_mut();
+            cur.move_next();
+            l3 = cur.split_after();
+        }
+        assert_eq!(l1.iter().map(|x| x.value).collect::<Vec<_>>(), []);
+        assert_eq!(l2.iter().map(|x| x.value).collect::<Vec<_>>(), [4, 1]);
+        assert_eq!(l3.iter().map(|x| x.value).collect::<Vec<_>>(), [3, 2]);
+        {
+            let mut cur = l2.front_mut();
+            cur.splice_after(l3.take());
+        }
+        assert_eq!(l1.iter().map(|x| x.value).collect::<Vec<_>>(), []);
+        assert_eq!(l2.iter().map(|x| x.value).collect::<Vec<_>>(), [4, 3, 2, 1]);
+        assert_eq!(l3.iter().map(|x| x.value).collect::<Vec<_>>(), []);
+        {
+            let mut cur = l3.cursor_mut();
+            cur.splice_after(l2.take());
+        }
+        assert_eq!(l1.iter().map(|x| x.value).collect::<Vec<_>>(), []);
+        assert_eq!(l2.iter().map(|x| x.value).collect::<Vec<_>>(), []);
+        assert_eq!(l3.iter().map(|x| x.value).collect::<Vec<_>>(), [4, 3, 2, 1]);
+        {
+            let mut cur = l3.front_mut();
+            cur.move_next();
+            l2 = cur.split_after();
+        }
+        assert_eq!(l1.iter().map(|x| x.value).collect::<Vec<_>>(), []);
+        assert_eq!(l2.iter().map(|x| x.value).collect::<Vec<_>>(), [2, 1]);
+        assert_eq!(l3.iter().map(|x| x.value).collect::<Vec<_>>(), [4, 3]);
+        {
+            let mut cur = l2.front_mut();
+            cur.move_next();
+            cur.splice_after(l3.take());
+        }
+        assert_eq!(l1.iter().map(|x| x.value).collect::<Vec<_>>(), []);
+        assert_eq!(l2.iter().map(|x| x.value).collect::<Vec<_>>(), [2, 1, 4, 3]);
+        assert_eq!(l3.iter().map(|x| x.value).collect::<Vec<_>>(), []);
+    }
+
+    #[test]
+    fn test_iter() {
+        let mut l = SinglyLinkedList::new(ObjAdapter1::new());
+        let a = make_obj(1);
+        let b = make_obj(2);
+        let c = make_obj(3);
+        let d = make_obj(4);
+        l.cursor_mut().insert_after(d.clone());
+        l.cursor_mut().insert_after(c.clone());
+        l.cursor_mut().insert_after(b.clone());
+        l.cursor_mut().insert_after(a.clone());
+
+        assert_eq!(l.front().get().unwrap().value, 1);
+        unsafe {
+            assert_eq!(l.cursor_from_ptr(b.as_ref()).get().unwrap().value, 2);
+            assert_eq!(l.cursor_mut_from_ptr(c.as_ref()).get().unwrap().value, 3);
+        }
+
+        let mut v = Vec::new();
+        for x in &l {
+            v.push(x.value);
+        }
+        assert_eq!(v, [1, 2, 3, 4]);
+        assert_eq!(
+            l.iter().clone().map(|x| x.value).collect::<Vec<_>>(),
+            [1, 2, 3, 4]
+        );
+        assert_eq!(l.iter().map(|x| x.value).collect::<Vec<_>>(), [1, 2, 3, 4]);
+
+        assert_eq!(format!("{:?}", l), "[1, 2, 3, 4]");
+
+        let mut v = Vec::new();
+        for x in l.take() {
+            v.push(x.value);
+        }
+        assert_eq!(v, [1, 2, 3, 4]);
+        assert!(l.is_empty());
+        assert!(!a.link1.is_linked());
+        assert!(!b.link1.is_linked());
+        assert!(!c.link1.is_linked());
+        assert!(!d.link1.is_linked());
+
+        l.cursor_mut().insert_after(d.clone());
+        l.cursor_mut().insert_after(c.clone());
+        l.cursor_mut().insert_after(b.clone());
+        l.cursor_mut().insert_after(a.clone());
+        l.clear();
+        assert!(l.is_empty());
+        assert!(!a.link1.is_linked());
+        assert!(!b.link1.is_linked());
+        assert!(!c.link1.is_linked());
+        assert!(!d.link1.is_linked());
+    }
+
+    #[test]
+    fn test_multi_list() {
+        let mut l1 = SinglyLinkedList::new(ObjAdapter1::new());
+        let mut l2 = SinglyLinkedList::new(ObjAdapter2::new());
+        let a = make_obj(1);
+        let b = make_obj(2);
+        let c = make_obj(3);
+        let d = make_obj(4);
+        l1.cursor_mut().insert_after(d.clone());
+        l1.cursor_mut().insert_after(c.clone());
+        l1.cursor_mut().insert_after(b.clone());
+        l1.cursor_mut().insert_after(a.clone());
+        l2.cursor_mut().insert_after(a.clone());
+        l2.cursor_mut().insert_after(b.clone());
+        l2.cursor_mut().insert_after(c.clone());
+        l2.cursor_mut().insert_after(d.clone());
+        assert_eq!(l1.iter().map(|x| x.value).collect::<Vec<_>>(), [1, 2, 3, 4]);
+        assert_eq!(l2.iter().map(|x| x.value).collect::<Vec<_>>(), [4, 3, 2, 1]);
+    }
+
+    #[test]
+    fn test_fast_clear() {
+        let mut l = SinglyLinkedList::new(ObjAdapter1::new());
+        let a = make_obj(1);
+        let b = make_obj(2);
+        let c = make_obj(3);
+        l.cursor_mut().insert_after(a.clone());
+        l.cursor_mut().insert_after(b.clone());
+        l.cursor_mut().insert_after(c.clone());
+
+        l.fast_clear();
+        assert!(l.is_empty());
+        assert!(a.link1.is_linked());
+        assert!(b.link1.is_linked());
+        assert!(c.link1.is_linked());
+        unsafe {
+            a.link1.force_unlink();
+            b.link1.force_unlink();
+            c.link1.force_unlink();
+        }
+        assert!(l.is_empty());
+        assert!(!a.link1.is_linked());
+        assert!(!b.link1.is_linked());
+        assert!(!c.link1.is_linked());
+    }
+
+    #[test]
+    fn test_non_static() {
+        #[derive(Clone)]
+        struct Obj<'a, T> {
+            link: Link,
+            value: &'a T,
+        }
+        intrusive_adapter!(ObjAdapter<'a, T> = &'a Obj<'a, T>: Obj<'a, T> {link: Link} where T: 'a);
+
+        let v = 5;
+        let a = Obj {
+            link: Link::new(),
+            value: &v,
+        };
+        let b = a.clone();
+        let mut l = SinglyLinkedList::new(ObjAdapter::new());
+        l.cursor_mut().insert_after(&a);
+        l.cursor_mut().insert_after(&b);
+        assert_eq!(*l.front().get().unwrap().value, 5);
+        assert_eq!(*l.front().get().unwrap().value, 5);
+    }
+
+    macro_rules! test_clone_pointer {
+        ($ptr: ident, $ptr_import: path) => {
+            use $ptr_import;
+
+            #[derive(Clone)]
+            struct Obj {
+                link: Link,
+                value: usize,
+            }
+            intrusive_adapter!(ObjAdapter = $ptr<Obj>: Obj { link: Link });
+
+            let a = $ptr::new(Obj {
+                link: Link::new(),
+                value: 5,
+            });
+            let mut l = SinglyLinkedList::new(ObjAdapter::new());
+            l.cursor_mut().insert_after(a.clone());
+            assert_eq!(2, $ptr::strong_count(&a));
+
+            let pointer = l.front().clone_pointer().unwrap();
+            assert_eq!(pointer.value, 5);
+            assert_eq!(3, $ptr::strong_count(&a));
+
+            l.clear();
+            assert!(l.front().clone_pointer().is_none());
+        };
+    }
+
+    #[test]
+    fn test_clone_pointer_rc() {
+        test_clone_pointer!(Rc, std::rc::Rc);
+    }
+
+    #[test]
+    fn test_clone_pointer_arc() {
+        test_clone_pointer!(Arc, std::sync::Arc);
+    }
+}
diff --git a/src/unchecked_option.rs b/src/unchecked_option.rs
new file mode 100644
index 0000000..3b3de7f
--- /dev/null
+++ b/src/unchecked_option.rs
@@ -0,0 +1,35 @@
+// Copyright 2020 Amari Robinson
+//
+// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
+// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
+// http://opensource.org/licenses/MIT>, at your option. This file may not be
+// copied, modified, or distributed except according to those terms.
+
+use core::hint;
+
+/// An extension trait on `Option`.
+pub trait UncheckedOptionExt<T> {
+    /// Returns the contained value.
+    ///
+    /// # Safety
+    ///
+    /// It is up to the caller to guarantee that the `Option<T>` is `Some(v)`.
+    /// Calling this when it is `None` causes undefined behavior.
+    unsafe fn unwrap_unchecked(self) -> T;
+}
+
+impl<T> UncheckedOptionExt<T> for Option<T> {
+    #[inline]
+    unsafe fn unwrap_unchecked(self) -> T {
+        match self {
+            Some(x) => x,
+            None => {
+                if cfg!(debug_assertions) {
+                    unreachable!()
+                } else {
+                    hint::unreachable_unchecked()
+                }
+            }
+        }
+    }
+}
diff --git a/src/unsafe_ref.rs b/src/unsafe_ref.rs
new file mode 100644
index 0000000..fec8b94
--- /dev/null
+++ b/src/unsafe_ref.rs
@@ -0,0 +1,109 @@
+// Copyright 2016 Amanieu d'Antras
+//
+// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
+// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
+// http://opensource.org/licenses/MIT>, at your option. This file may not be
+// copied, modified, or distributed except according to those terms.
+
+#[cfg(feature = "alloc")]
+use crate::alloc::boxed::Box;
+use core::borrow::Borrow;
+use core::fmt;
+use core::ops::Deref;
+use core::ptr::NonNull;
+
+/// Unchecked shared pointer
+///
+/// This type acts like a `Rc` or `Arc` except that no reference count is
+/// maintained. Instead, the user is responsible for freeing the managed object
+/// once it is no longer in use.
+///
+/// You must guarantee that an object managed by an `UnsafeRef` is not
+/// moved, dropped or accessed through a mutable reference as long as at least
+/// one `UnsafeRef` is pointing to it.
+pub struct UnsafeRef<T: ?Sized> {
+    ptr: NonNull<T>,
+}
+
+impl<T: ?Sized> UnsafeRef<T> {
+    /// Creates an `UnsafeRef` from a raw pointer
+    ///
+    /// # Safety
+    ///
+    /// You must ensure that the `UnsafeRef` guarantees are upheld.
+    #[inline]
+    pub unsafe fn from_raw(val: *const T) -> UnsafeRef<T> {
+        UnsafeRef {
+            ptr: NonNull::new_unchecked(val as *mut _),
+        }
+    }
+
+    /// Converts an `UnsafeRef` into a raw pointer
+    #[inline]
+    pub fn into_raw(ptr: Self) -> *mut T {
+        ptr.ptr.as_ptr()
+    }
+}
+
+#[cfg(feature = "alloc")]
+impl<T: ?Sized> UnsafeRef<T> {
+    /// Creates an `UnsafeRef` from a `Box`
+    #[inline]
+    pub fn from_box(val: Box<T>) -> UnsafeRef<T> {
+        unsafe { UnsafeRef::from_raw(Box::into_raw(val)) }
+    }
+
+    /// Converts an `UnsafeRef` into a `Box`
+    ///
+    /// # Safety
+    ///
+    /// You must ensure that this is the only `UnsafeRef` managing this
+    /// object and that it is not currently a member of any intrusive
+    /// collections. This operation is only valid if the `UnsafeRef` was
+    /// created using `UnsafeRef::from_box`.
+    #[inline]
+    pub unsafe fn into_box(ptr: Self) -> Box<T> {
+        Box::from_raw(UnsafeRef::into_raw(ptr))
+    }
+}
+
+impl<T: ?Sized> Clone for UnsafeRef<T> {
+    #[inline]
+    fn clone(&self) -> UnsafeRef<T> {
+        UnsafeRef { ptr: self.ptr }
+    }
+}
+
+impl<T: ?Sized> Deref for UnsafeRef<T> {
+    type Target = T;
+
+    #[inline]
+    fn deref(&self) -> &T {
+        self.as_ref()
+    }
+}
+
+impl<T: ?Sized> AsRef<T> for UnsafeRef<T> {
+    #[inline]
+    fn as_ref(&self) -> &T {
+        unsafe { self.ptr.as_ref() }
+    }
+}
+
+impl<T: ?Sized> Borrow<T> for UnsafeRef<T> {
+    #[inline]
+    fn borrow(&self) -> &T {
+        self.as_ref()
+    }
+}
+
+impl<T: fmt::Debug + ?Sized> fmt::Debug for UnsafeRef<T> {
+    #[inline]
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        fmt::Debug::fmt(self.as_ref(), f)
+    }
+}
+
+unsafe impl<T: ?Sized + Send> Send for UnsafeRef<T> {}
+
+unsafe impl<T: ?Sized + Sync> Sync for UnsafeRef<T> {}
diff --git a/src/xor_linked_list.rs b/src/xor_linked_list.rs
new file mode 100644
index 0000000..e0e4f95
--- /dev/null
+++ b/src/xor_linked_list.rs
@@ -0,0 +1,1912 @@
+// Copyright 2016 Amanieu d'Antras
+// Copyright 2020 Amari Robinson
+//
+// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
+// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
+// http://opensource.org/licenses/MIT>, at your option. This file may not be
+// copied, modified, or distributed except according to those terms.
+
+//! Intrusive xor doubly-linked list which uses less memory than a regular doubly linked list.
+//!
+//! In exchange for less memory use, it is impossible to create a cursor from a pointer to
+//! an element.
+
+use core::cell::Cell;
+use core::fmt;
+use core::ptr::NonNull;
+
+use crate::link_ops::{self, DefaultLinkOps};
+use crate::pointer_ops::PointerOps;
+use crate::singly_linked_list::SinglyLinkedListOps;
+use crate::unchecked_option::UncheckedOptionExt;
+use crate::Adapter;
+
+// =============================================================================
+// XorLinkedListOps
+// =============================================================================
+
+/// Link operations for `XorLinkedList`.
+pub unsafe trait XorLinkedListOps: link_ops::LinkOps {
+    /// Returns the "next" link pointer of `ptr`.
+    ///
+    /// # Safety
+    /// `prev` must have been previously passed to the [`set`] method, or
+    /// `prev` must be equal to the `new` argument previously passed to [`replace_next_or_prev`].
+    ///
+    /// An implementation of `next` must not panic.
+    ///
+    /// [`replace_next_or_prev`]: #tymethod.replace_next_or_prev
+    /// [`set`]: #tymethod.set
+    unsafe fn next(&self, ptr: Self::LinkPtr, prev: Option<Self::LinkPtr>)
+        -> Option<Self::LinkPtr>;
+
+    /// Returns the "prev" link pointer of `ptr`.
+    ///
+    /// # Safety
+    /// `next` must have been previously passed to the [`set`] method, or
+    /// `next` must be equal to the `new` argument previously passed to [`replace_next_or_prev`].
+    ///
+    /// An implementation of `prev` must not panic.
+    ///
+    /// [`replace_next_or_prev`]: #tymethod.replace_next_or_prev
+    /// [`set`]: #tymethod.set
+    unsafe fn prev(&self, ptr: Self::LinkPtr, next: Option<Self::LinkPtr>)
+        -> Option<Self::LinkPtr>;
+
+    /// Assigns the "prev" and "next" link pointers of `ptr`.
+    ///
+    /// # Safety
+    /// An implementation of `set` must not panic.
+    unsafe fn set(
+        &mut self,
+        ptr: Self::LinkPtr,
+        prev: Option<Self::LinkPtr>,
+        next: Option<Self::LinkPtr>,
+    );
+
+    /// Replaces the "next" or "prev" link pointer of `ptr`.
+    ///
+    /// # Safety
+    /// `old` must be equal to either the `next` or `prev` argument previously passed to the [`set`] method, or
+    /// `old` must be equal to the `new` argument previously passed to `replace_next_or_prev`.
+    ///
+    /// An implementation of `replace_next_or_prev` must not panic.
+    ///
+    /// [`set`]: #tymethod.set
+    unsafe fn replace_next_or_prev(
+        &mut self,
+        ptr: Self::LinkPtr,
+        old: Option<Self::LinkPtr>,
+        new: Option<Self::LinkPtr>,
+    );
+}
+
+// =============================================================================
+// Link
+// =============================================================================
+
+/// Intrusive link that allows an object to be inserted into a
+/// `XorLinkedList`.
+#[repr(align(2))]
+pub struct Link {
+    packed: Cell<usize>,
+}
+
+// Use a special value to indicate an unlinked node
+const UNLINKED_MARKER: usize = 1_usize;
+
+impl Link {
+    /// Creates a new `Link`.
+    #[inline]
+    pub const fn new() -> Link {
+        Link {
+            packed: Cell::new(UNLINKED_MARKER),
+        }
+    }
+
+    /// Checks whether the `Link` is linked into a `XorLinkedList`.
+    #[inline]
+    pub fn is_linked(&self) -> bool {
+        self.packed.get() != UNLINKED_MARKER
+    }
+
+    /// Forcibly unlinks an object from a `XorLinkedList`.
+    ///
+    /// # Safety
+    ///
+    /// It is undefined behavior to call this function while still linked into a
+    /// `XorLinkedList`. The only situation where this function is useful is
+    /// after calling `fast_clear` on a `XorLinkedList`, since this clears
+    /// the collection without marking the nodes as unlinked.
+    #[inline]
+    pub unsafe fn force_unlink(&self) {
+        self.packed.set(UNLINKED_MARKER);
+    }
+}
+
+impl DefaultLinkOps for Link {
+    type Ops = LinkOps;
+
+    const NEW: Self::Ops = LinkOps;
+}
+
+// An object containing a link can be sent to another thread if it is unlinked.
+unsafe impl Send for Link {}
+
+// Provide an implementation of Clone which simply initializes the new link as
+// unlinked. This allows structs containing a link to derive Clone.
+impl Clone for Link {
+    #[inline]
+    fn clone(&self) -> Link {
+        Link::new()
+    }
+}
+
+// Same as above
+impl Default for Link {
+    #[inline]
+    fn default() -> Link {
+        Link::new()
+    }
+}
+
+// Provide an implementation of Debug so that structs containing a link can
+// still derive Debug.
+impl fmt::Debug for Link {
+    #[inline]
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        // There isn't anything sensible to print here except whether the link
+        // is currently in a list.
+        if self.is_linked() {
+            write!(f, "linked")
+        } else {
+            write!(f, "unlinked")
+        }
+    }
+}
+
+// =============================================================================
+// LinkOps
+// =============================================================================
+
+/// Default `LinkOps` implementation for `XorLinkedList`.
+#[derive(Clone, Copy, Default)]
+pub struct LinkOps;
+
+unsafe impl link_ops::LinkOps for LinkOps {
+    type LinkPtr = NonNull<Link>;
+
+    #[inline]
+    unsafe fn acquire_link(&mut self, ptr: Self::LinkPtr) -> bool {
+        if ptr.as_ref().is_linked() {
+            false
+        } else {
+            ptr.as_ref().packed.set(0);
+            true
+        }
+    }
+
+    #[inline]
+    unsafe fn release_link(&mut self, ptr: Self::LinkPtr) {
+        ptr.as_ref().packed.set(UNLINKED_MARKER);
+    }
+}
+
+unsafe impl XorLinkedListOps for LinkOps {
+    #[inline]
+    unsafe fn next(
+        &self,
+        ptr: Self::LinkPtr,
+        prev: Option<Self::LinkPtr>,
+    ) -> Option<Self::LinkPtr> {
+        let raw = ptr.as_ref().packed.get() ^ prev.map(|x| x.as_ptr() as usize).unwrap_or(0);
+        NonNull::new(raw as *mut _)
+    }
+
+    #[inline]
+    unsafe fn prev(
+        &self,
+        ptr: Self::LinkPtr,
+        next: Option<Self::LinkPtr>,
+    ) -> Option<Self::LinkPtr> {
+        let raw = ptr.as_ref().packed.get() ^ next.map(|x| x.as_ptr() as usize).unwrap_or(0);
+        NonNull::new(raw as *mut _)
+    }
+
+    #[inline]
+    unsafe fn set(
+        &mut self,
+        ptr: Self::LinkPtr,
+        prev: Option<Self::LinkPtr>,
+        next: Option<Self::LinkPtr>,
+    ) {
+        let new_packed = prev.map(|x| x.as_ptr() as usize).unwrap_or(0)
+            ^ next.map(|x| x.as_ptr() as usize).unwrap_or(0);
+        ptr.as_ref().packed.set(new_packed);
+    }
+
+    #[inline]
+    unsafe fn replace_next_or_prev(
+        &mut self,
+        ptr: Self::LinkPtr,
+        old: Option<Self::LinkPtr>,
+        new: Option<Self::LinkPtr>,
+    ) {
+        let new_packed = ptr.as_ref().packed.get()
+            ^ old.map(|x| x.as_ptr() as usize).unwrap_or(0)
+            ^ new.map(|x| x.as_ptr() as usize).unwrap_or(0);
+
+        ptr.as_ref().packed.set(new_packed);
+    }
+}
+
+unsafe impl SinglyLinkedListOps for LinkOps {
+    #[inline]
+    unsafe fn next(&self, ptr: Self::LinkPtr) -> Option<Self::LinkPtr> {
+        let raw = ptr.as_ref().packed.get();
+        NonNull::new(raw as *mut _)
+    }
+
+    #[inline]
+    unsafe fn set_next(&mut self, ptr: Self::LinkPtr, next: Option<Self::LinkPtr>) {
+        ptr.as_ref()
+            .packed
+            .set(next.map(|x| x.as_ptr() as usize).unwrap_or(0));
+    }
+}
+
+#[inline]
+unsafe fn link_between<T: XorLinkedListOps>(
+    link_ops: &mut T,
+    ptr: T::LinkPtr,
+    prev: Option<T::LinkPtr>,
+    next: Option<T::LinkPtr>,
+) {
+    if let Some(prev) = prev {
+        let prev_of_prev = link_ops.prev(prev, next);
+        link_ops.set(prev, prev_of_prev, Some(ptr));
+    }
+    if let Some(next) = next {
+        let next_of_next = link_ops.next(next, prev);
+        link_ops.set(next, Some(ptr), next_of_next);
+    }
+    link_ops.set(ptr, prev, next);
+}
+
+// =============================================================================
+// Cursor, CursorMut
+// =============================================================================
+
+/// A cursor which provides read-only access to a `XorLinkedList`.
+pub struct Cursor<'a, A: Adapter>
+where
+    A::LinkOps: XorLinkedListOps,
+{
+    current: Option<<A::LinkOps as link_ops::LinkOps>::LinkPtr>,
+    prev: Option<<A::LinkOps as link_ops::LinkOps>::LinkPtr>,
+    next: Option<<A::LinkOps as link_ops::LinkOps>::LinkPtr>,
+    list: &'a XorLinkedList<A>,
+}
+
+impl<'a, A: Adapter> Clone for Cursor<'a, A>
+where
+    A::LinkOps: XorLinkedListOps,
+{
+    #[inline]
+    fn clone(&self) -> Cursor<'a, A> {
+        Cursor {
+            current: self.current,
+            prev: self.prev,
+            next: self.next,
+            list: self.list,
+        }
+    }
+}
+
+impl<'a, A: Adapter> Cursor<'a, A>
+where
+    A::LinkOps: XorLinkedListOps,
+{
+    /// Checks if the cursor is currently pointing to the null object.
+    #[inline]
+    pub fn is_null(&self) -> bool {
+        self.current.is_none()
+    }
+
+    /// Returns a reference to the object that the cursor is currently
+    /// pointing to.
+    ///
+    /// This returns `None` if the cursor is currently pointing to the null
+    /// object.
+    #[inline]
+    pub fn get(&self) -> Option<&'a <A::PointerOps as PointerOps>::Value> {
+        Some(unsafe { &*self.list.adapter.get_value(self.current?) })
+    }
+
+    /// Clones and returns the pointer that points to the element that the
+    /// cursor is referencing.
+    ///
+    /// This returns `None` if the cursor is currently pointing to the null
+    /// object.
+    #[inline]
+    pub fn clone_pointer(&self) -> Option<<A::PointerOps as PointerOps>::Pointer>
+    where
+        <A::PointerOps as PointerOps>::Pointer: Clone,
+    {
+        let raw_pointer = self.get()? as *const <A::PointerOps as PointerOps>::Value;
+        Some(unsafe {
+            crate::pointer_ops::clone_pointer_from_raw(self.list.adapter.pointer_ops(), raw_pointer)
+        })
+    }
+
+    /// Moves the cursor to the next element of the `XorLinkedList`.
+    ///
+    /// If the cursor is pointer to the null object then this will move it to
+    /// the first element of the `XorLinkedList`. If it is pointing to the
+    /// last element of the `XorLinkedList` then this will move it to the
+    /// null object.
+    #[inline]
+    pub fn move_next(&mut self) {
+        let prev = self.current;
+        self.current = self.next;
+        unsafe {
+            if let Some(current) = self.current {
+                self.prev = prev;
+                self.next = self.list.adapter.link_ops().next(current, prev);
+            } else {
+                self.prev = self.list.tail;
+                self.next = self.list.head;
+            }
+        }
+    }
+
+    /// Moves the cursor to the previous element of the `XorLinkedList`.
+    ///
+    /// If the cursor is pointer to the null object then this will move it to
+    /// the last element of the `XorLinkedList`. If it is pointing to the first
+    /// element of the `XorLinkedList` then this will move it to the null object.
+    #[inline]
+    pub fn move_prev(&mut self) {
+        let next = self.current;
+        self.current = self.prev;
+        unsafe {
+            if let Some(current) = self.current {
+                self.prev = self.list.adapter.link_ops().prev(current, next);
+                self.next = next;
+            } else {
+                self.prev = self.list.tail;
+                self.next = self.list.head;
+            }
+        }
+    }
+
+    /// Returns a cursor pointing to the next element of the `XorLinkedList`.
+    ///
+    /// If the cursor is pointer to the null object then this will return the
+    /// first element of the `XorLinkedList`. If it is pointing to the last
+    /// element of the `XorLinkedList` then this will return a null cursor.
+    #[inline]
+    pub fn peek_next(&self) -> Cursor<'_, A> {
+        let mut next = self.clone();
+        next.move_next();
+        next
+    }
+
+    /// Returns a cursor pointing to the previous element of the `XorLinkedList`.
+    ///
+    /// If the cursor is pointer to the null object then this will return the
+    /// last element of the `XorLinkedList`. If it is pointing to the first
+    /// element of the `XorLinkedList` then this will return a null cursor.
+    #[inline]
+    pub fn peek_prev(&self) -> Cursor<'_, A> {
+        let mut prev = self.clone();
+        prev.move_prev();
+        prev
+    }
+}
+
+/// A cursor which provides mutable access to a `XorLinkedList`.
+pub struct CursorMut<'a, A: Adapter>
+where
+    A::LinkOps: XorLinkedListOps,
+{
+    current: Option<<A::LinkOps as link_ops::LinkOps>::LinkPtr>,
+    prev: Option<<A::LinkOps as link_ops::LinkOps>::LinkPtr>,
+    next: Option<<A::LinkOps as link_ops::LinkOps>::LinkPtr>,
+    list: &'a mut XorLinkedList<A>,
+}
+
+impl<'a, A: Adapter> CursorMut<'a, A>
+where
+    A::LinkOps: XorLinkedListOps,
+{
+    /// Checks if the cursor is currently pointing to the null object.
+    #[inline]
+    pub fn is_null(&self) -> bool {
+        self.current.is_none()
+    }
+
+    /// Returns a reference to the object that the cursor is currently
+    /// pointing to.
+    ///
+    /// This returns None if the cursor is currently pointing to the null
+    /// object.
+    #[inline]
+    pub fn get(&self) -> Option<&<A::PointerOps as PointerOps>::Value> {
+        Some(unsafe { &*self.list.adapter.get_value(self.current?) })
+    }
+
+    /// Returns a read-only cursor pointing to the current element.
+    ///
+    /// The lifetime of the returned `Cursor` is bound to that of the
+    /// `CursorMut`, which means it cannot outlive the `CursorMut` and that the
+    /// `CursorMut` is frozen for the lifetime of the `Cursor`.
+    #[inline]
+    pub fn as_cursor(&self) -> Cursor<'_, A> {
+        Cursor {
+            current: self.current,
+            prev: self.prev,
+            next: self.next,
+            list: self.list,
+        }
+    }
+
+    /// Moves the cursor to the next element of the `XorLinkedList`.
+    ///
+    /// If the cursor is pointer to the null object then this will move it to
+    /// the first element of the `XorLinkedList`. If it is pointing to the
+    /// last element of the `XorLinkedList` then this will move it to the
+    /// null object.
+    #[inline]
+    pub fn move_next(&mut self) {
+        let prev = self.current;
+        self.current = self.next;
+        unsafe {
+            if let Some(current) = self.current {
+                self.prev = prev;
+                self.next = self.list.adapter.link_ops().next(current, prev);
+            } else {
+                self.prev = self.list.tail;
+                self.next = self.list.head;
+            }
+        }
+    }
+
+    /// Moves the cursor to the previous element of the `XorLinkedList`.
+    ///
+    /// If the cursor is pointer to the null object then this will move it to
+    /// the last element of the `XorLinkedList`. If it is pointing to the first
+    /// element of the `XorLinkedList` then this will move it to the null object.
+    #[inline]
+    pub fn move_prev(&mut self) {
+        let next = self.current;
+        self.current = self.prev;
+        unsafe {
+            if let Some(current) = self.current {
+                self.prev = self.list.adapter.link_ops().prev(current, next);
+                self.next = next;
+            } else {
+                self.prev = self.list.tail;
+                self.next = self.list.head;
+            }
+        }
+    }
+
+    /// Returns a cursor pointing to the next element of the `XorLinkedList`.
+    ///
+    /// If the cursor is pointer to the null object then this will return the
+    /// first element of the `XorLinkedList`. If it is pointing to the last
+    /// element of the `XorLinkedList` then this will return a null cursor.
+    #[inline]
+    pub fn peek_next(&self) -> Cursor<'_, A> {
+        let mut next = self.as_cursor();
+        next.move_next();
+        next
+    }
+
+    /// Returns a cursor pointing to the previous element of the `XorLinkedList`.
+    ///
+    /// If the cursor is pointer to the null object then this will return the
+    /// last element of the `XorLinkedList`. If it is pointing to the first
+    /// element of the `XorLinkedList` then this will return a null cursor.
+    #[inline]
+    pub fn peek_prev(&self) -> Cursor<'_, A> {
+        let mut prev = self.as_cursor();
+        prev.move_prev();
+        prev
+    }
+
+    /// Removes the current element from the `XorLinkedList`.
+    ///
+    /// A pointer to the element that was removed is returned, and the cursor is
+    /// moved to point to the next element in the `XorLinkedList`.
+    ///
+    /// If the cursor is currently pointing to the null object then no element
+    /// is removed and `None` is returned.
+    #[inline]
+    pub fn remove(&mut self) -> Option<<A::PointerOps as PointerOps>::Pointer> {
+        use link_ops::LinkOps;
+
+        unsafe {
+            let current = self.current?;
+            let result = current;
+
+            self.list.adapter.link_ops_mut().release_link(current);
+            if let Some(prev) = self.prev {
+                self.list.adapter.link_ops_mut().replace_next_or_prev(
+                    prev,
+                    Some(current),
+                    self.next,
+                );
+            }
+            if let Some(next) = self.next {
+                self.list.adapter.link_ops_mut().replace_next_or_prev(
+                    next,
+                    Some(current),
+                    self.prev,
+                );
+            }
+            if self.list.head == Some(current) {
+                self.list.head = self.next;
+            }
+            if self.list.tail == Some(current) {
+                self.list.tail = self.prev;
+            }
+            self.current = self.next;
+            if let Some(current) = self.current {
+                self.next = self.list.adapter.link_ops().next(current, self.prev);
+            } else {
+                self.prev = self.list.tail;
+                self.next = self.list.head;
+            }
+
+            Some(
+                self.list
+                    .adapter
+                    .pointer_ops()
+                    .from_raw(self.list.adapter.get_value(result)),
+            )
+        }
+    }
+
+    /// Removes the current element from the `XorLinkedList` and inserts another
+    /// object in its place.
+    ///
+    /// A pointer to the element that was removed is returned, and the cursor is
+    /// modified to point to the newly added element.
+    ///
+    /// If the cursor is currently pointing to the null object then an error is
+    /// returned containing the given `val` parameter.
+    ///
+    /// # Panics
+    ///
+    /// Panics if the new element is already linked to a different intrusive
+    /// collection.
+    #[inline]
+    pub fn replace_with(
+        &mut self,
+        val: <A::PointerOps as PointerOps>::Pointer,
+    ) -> Result<<A::PointerOps as PointerOps>::Pointer, <A::PointerOps as PointerOps>::Pointer>
+    {
+        use link_ops::LinkOps;
+
+        unsafe {
+            if let Some(current) = self.current {
+                let new = self.list.node_from_value(val);
+                let result = current;
+
+                if self.list.head == Some(current) {
+                    self.list.head = Some(new);
+                }
+                if self.list.tail == Some(current) {
+                    self.list.tail = Some(new);
+                }
+
+                if let Some(prev) = self.prev {
+                    self.list.adapter.link_ops_mut().replace_next_or_prev(
+                        prev,
+                        Some(current),
+                        Some(new),
+                    );
+                }
+                if let Some(next) = self.next {
+                    self.list.adapter.link_ops_mut().replace_next_or_prev(
+                        next,
+                        Some(current),
+                        Some(new),
+                    );
+                }
+
+                self.list
+                    .adapter
+                    .link_ops_mut()
+                    .set(new, self.prev, self.next);
+                self.list.adapter.link_ops_mut().release_link(result);
+                self.current = Some(new);
+
+                Ok(self
+                    .list
+                    .adapter
+                    .pointer_ops()
+                    .from_raw(self.list.adapter.get_value(result)))
+            } else {
+                Err(val)
+            }
+        }
+    }
+
+    /// Inserts a new element into the `XorLinkedList` after the current one.
+    ///
+    /// If the cursor is pointing at the null object then the new element is
+    /// inserted at the front of the `XorLinkedList`.
+    ///
+    /// # Panics
+    ///
+    /// Panics if the new element is already linked to a different intrusive
+    /// collection.
+    #[inline]
+    pub fn insert_after(&mut self, val: <A::PointerOps as PointerOps>::Pointer) {
+        unsafe {
+            let new = self.list.node_from_value(val);
+            if let Some(current) = self.current {
+                link_between(
+                    self.list.adapter.link_ops_mut(),
+                    new,
+                    Some(current),
+                    self.next,
+                );
+                if self.next.is_none() {
+                    // Current pointer was tail
+                    self.list.tail = Some(new);
+                }
+                self.next = Some(new);
+            } else {
+                link_between(self.list.adapter.link_ops_mut(), new, None, self.list.head);
+                self.list.head = Some(new);
+                if self.list.tail.is_none() {
+                    self.list.tail = Some(new);
+                }
+                self.prev = self.list.tail;
+                self.next = self.list.head;
+            }
+        }
+    }
+
+    /// Inserts a new element into the `XorLinkedList` before the current one.
+    ///
+    /// If the cursor is pointing at the null object then the new element is
+    /// inserted at the end of the `XorLinkedList`.
+    ///
+    /// # Panics
+    ///
+    /// Panics if the new element is already linked to a different intrusive
+    /// collection.
+    #[inline]
+    pub fn insert_before(&mut self, val: <A::PointerOps as PointerOps>::Pointer) {
+        unsafe {
+            let new = self.list.node_from_value(val);
+            if let Some(current) = self.current {
+                link_between(
+                    self.list.adapter.link_ops_mut(),
+                    new,
+                    self.prev,
+                    Some(current),
+                );
+                if self.prev.is_none() {
+                    // Current pointer was tail
+                    self.list.head = Some(new);
+                }
+                self.prev = Some(new);
+            } else {
+                link_between(self.list.adapter.link_ops_mut(), new, self.list.tail, None);
+                self.list.tail = Some(new);
+                if self.list.head.is_none() {
+                    self.list.head = Some(new);
+                }
+                self.prev = self.list.tail;
+                self.next = self.list.head;
+            }
+        }
+    }
+
+    /// Inserts the elements from the given `XorLinkedList` after the current one.
+    ///
+    /// If the cursor is pointing at the null object then the new elements are
+    /// inserted at the start of the `XorLinkedList`.
+    #[inline]
+    pub fn splice_after(&mut self, mut list: XorLinkedList<A>) {
+        if !list.is_empty() {
+            unsafe {
+                let head = list.head.unwrap_unchecked();
+                let tail = list.tail.unwrap_unchecked();
+
+                let link_ops = self.list.adapter.link_ops_mut();
+
+                if let Some(current) = self.current {
+                    if let Some(next) = self.next {
+                        link_ops.replace_next_or_prev(next, Some(current), Some(tail));
+                        link_ops.replace_next_or_prev(tail, None, Some(next));
+                    }
+                    link_ops.replace_next_or_prev(head, None, Some(current));
+                    self.next = list.head;
+                    link_ops.set(current, self.prev, self.next);
+                } else {
+                    if let Some(x) = self.list.head {
+                        link_ops.replace_next_or_prev(tail, None, Some(x));
+                        link_ops.replace_next_or_prev(x, None, Some(tail));
+                    }
+                    self.list.head = list.head;
+                    self.next = list.head;
+                }
+                if self.list.tail == self.current {
+                    self.list.tail = list.tail;
+                }
+                list.head = None;
+                list.tail = None;
+            }
+        }
+    }
+
+    /// Moves all element from the given `XorLinkedList` before the current one.
+    ///
+    /// If the cursor is pointing at the null object then the new elements are
+    /// inserted at the end of the `XorLinkedList`.
+    #[inline]
+    pub fn splice_before(&mut self, mut list: XorLinkedList<A>) {
+        if !list.is_empty() {
+            unsafe {
+                let head = list.head.unwrap_unchecked();
+                let tail = list.tail.unwrap_unchecked();
+
+                let link_ops = self.list.adapter.link_ops_mut();
+
+                if let Some(current) = self.current {
+                    if let Some(prev) = self.prev {
+                        link_ops.replace_next_or_prev(prev, Some(current), Some(head));
+                        link_ops.replace_next_or_prev(head, None, Some(prev));
+                    }
+                    link_ops.replace_next_or_prev(tail, None, Some(current));
+                    self.prev = list.tail;
+                    link_ops.set(current, self.prev, self.next);
+                } else {
+                    if let Some(x) = self.list.tail {
+                        link_ops.replace_next_or_prev(head, None, Some(x));
+                        link_ops.replace_next_or_prev(x, None, Some(head));
+                    }
+                    self.list.head = list.head;
+                    self.next = list.head;
+                }
+                if self.list.tail == self.current {
+                    self.list.tail = list.tail;
+                }
+                list.head = None;
+                list.tail = None;
+            }
+        }
+    }
+
+    /// Splits the list into two after the current element. This will return a
+    /// new list consisting of everything after the cursor, with the original
+    /// list retaining everything before.
+    ///
+    /// If the cursor is pointing at the null object then the entire contents
+    /// of the `XorLinkedList` are moved.
+    #[inline]
+    pub fn split_after(&mut self) -> XorLinkedList<A>
+    where
+        A: Clone,
+    {
+        if let Some(current) = self.current {
+            unsafe {
+                let mut list = XorLinkedList {
+                    head: self.next,
+                    tail: self.list.tail,
+                    adapter: self.list.adapter.clone(),
+                };
+                if let Some(head) = list.head {
+                    self.list.adapter.link_ops_mut().replace_next_or_prev(
+                        head,
+                        Some(current),
+                        None,
+                    );
+                    self.next = None;
+                } else {
+                    list.tail = None;
+                }
+                self.list
+                    .adapter
+                    .link_ops_mut()
+                    .set(current, self.prev, None);
+                self.list.tail = self.current;
+                list
+            }
+        } else {
+            let list = XorLinkedList {
+                head: self.list.head,
+                tail: self.list.tail,
+                adapter: self.list.adapter.clone(),
+            };
+            self.list.head = None;
+            self.list.tail = None;
+            list
+        }
+    }
+
+    /// Splits the list into two before the current element. This will return a
+    /// new list consisting of everything before the cursor, with the original
+    /// list retaining everything after.
+    ///
+    /// If the cursor is pointing at the null object then the entire contents
+    /// of the `XorLinkedList` are moved.
+    #[inline]
+    pub fn split_before(&mut self) -> XorLinkedList<A>
+    where
+        A: Clone,
+    {
+        if let Some(current) = self.current {
+            unsafe {
+                let mut list = XorLinkedList {
+                    head: self.list.head,
+                    tail: self.prev,
+                    adapter: self.list.adapter.clone(),
+                };
+                if let Some(tail) = list.tail {
+                    self.list.adapter.link_ops_mut().replace_next_or_prev(
+                        tail,
+                        Some(current),
+                        None,
+                    );
+                    self.prev = None;
+                } else {
+                    list.head = None;
+                }
+                self.list
+                    .adapter
+                    .link_ops_mut()
+                    .set(current, None, self.next);
+                self.list.head = self.current;
+                list
+            }
+        } else {
+            let list = XorLinkedList {
+                head: self.list.head,
+                tail: self.list.tail,
+                adapter: self.list.adapter.clone(),
+            };
+            self.list.head = None;
+            self.list.tail = None;
+            list
+        }
+    }
+}
+
+// =============================================================================
+// XorLinkedList
+// =============================================================================
+
+/// Intrusive xor doubly-linked list which uses less memory than a regular doubly linked list
+///
+/// In exchange for less memory use, it is impossible to create a cursor from a pointer to
+/// an element.
+///
+/// When this collection is dropped, all elements linked into it will be
+/// converted back to owned pointers and dropped.
+pub struct XorLinkedList<A: Adapter>
+where
+    A::LinkOps: XorLinkedListOps,
+{
+    head: Option<<A::LinkOps as link_ops::LinkOps>::LinkPtr>,
+    tail: Option<<A::LinkOps as link_ops::LinkOps>::LinkPtr>,
+    adapter: A,
+}
+
+impl<A: Adapter> XorLinkedList<A>
+where
+    A::LinkOps: XorLinkedListOps,
+{
+    #[inline]
+    fn node_from_value(
+        &mut self,
+        val: <A::PointerOps as PointerOps>::Pointer,
+    ) -> <A::LinkOps as link_ops::LinkOps>::LinkPtr {
+        use link_ops::LinkOps;
+
+        unsafe {
+            let raw = self.adapter.pointer_ops().into_raw(val);
+            let link = self.adapter.get_link(raw);
+
+            if !self.adapter.link_ops_mut().acquire_link(link) {
+                // convert the node back into a pointer
+                self.adapter.pointer_ops().from_raw(raw);
+
+                panic!("attempted to insert an object that is already linked");
+            }
+
+            link
+        }
+    }
+
+    /// Creates an empty `XorLinkedList`.
+    #[cfg(not(feature = "nightly"))]
+    #[inline]
+    pub fn new(adapter: A) -> XorLinkedList<A> {
+        XorLinkedList {
+            head: None,
+            tail: None,
+            adapter,
+        }
+    }
+
+    /// Creates an empty `XorLinkedList`.
+    #[cfg(feature = "nightly")]
+    #[inline]
+    pub const fn new(adapter: A) -> XorLinkedList<A> {
+        XorLinkedList {
+            head: None,
+            tail: None,
+            adapter,
+        }
+    }
+
+    /// Returns `true` if the `XorLinkedList` is empty.
+    #[inline]
+    pub fn is_empty(&self) -> bool {
+        self.head.is_none()
+    }
+
+    /// Returns a null `Cursor` for this list.
+    #[inline]
+    pub fn cursor(&self) -> Cursor<'_, A> {
+        Cursor {
+            current: None,
+            prev: self.tail,
+            next: self.head,
+            list: self,
+        }
+    }
+
+    /// Returns a null `CursorMut` for this list.
+    #[inline]
+    pub fn cursor_mut(&mut self) -> CursorMut<'_, A> {
+        CursorMut {
+            current: None,
+            prev: self.tail,
+            next: self.head,
+            list: self,
+        }
+    }
+
+    /// Creates a `Cursor` from a pointer to an element and a pointer to the previous element.
+    ///
+    /// # Safety
+    ///
+    /// `ptr` must be a pointer to an object that is part of this list.
+    /// `prev` must be a pointer to an object that is the previous object in this list (null for the head)
+    #[inline]
+    pub unsafe fn cursor_from_ptr_and_prev(
+        &self,
+        ptr: *const <A::PointerOps as PointerOps>::Value,
+        prev: *const <A::PointerOps as PointerOps>::Value,
+    ) -> Cursor<'_, A> {
+        let current = self.adapter.get_link(ptr);
+        let prev = if !prev.is_null() {
+            Some(self.adapter.get_link(prev))
+        } else {
+            None
+        };
+        let next = self.adapter.link_ops().next(current, prev);
+
+        Cursor {
+            current: Some(current),
+            prev,
+            next,
+            list: self,
+        }
+    }
+
+    /// Creates a `CursorMut` from a pointer to an element and a pointer to the previous element.
+    ///
+    /// # Safety
+    ///
+    /// `ptr` must be a pointer to an object that is part of this list.
+    /// `prev` must be a pointer to an object that is the previous object in this list (null for the head)
+    #[inline]
+    pub unsafe fn cursor_mut_from_ptr_and_prev(
+        &mut self,
+        ptr: *const <A::PointerOps as PointerOps>::Value,
+        prev: *const <A::PointerOps as PointerOps>::Value,
+    ) -> CursorMut<'_, A> {
+        let current = self.adapter.get_link(ptr);
+        let prev = if !prev.is_null() {
+            Some(self.adapter.get_link(prev))
+        } else {
+            None
+        };
+        let next = self.adapter.link_ops().next(current, prev);
+
+        CursorMut {
+            current: Some(current),
+            prev,
+            next,
+            list: self,
+        }
+    }
+
+    /// Creates a `Cursor` from a pointer to an element and a pointer to the next element.
+    ///
+    /// # Safety
+    ///
+    /// `ptr` must be a pointer to an object that is part of this list.
+    /// `next` must be a pointer to an object that is the next object in this list (null for the tail)
+    #[inline]
+    pub unsafe fn cursor_from_ptr_and_next(
+        &self,
+        ptr: *const <A::PointerOps as PointerOps>::Value,
+        next: *const <A::PointerOps as PointerOps>::Value,
+    ) -> Cursor<'_, A> {
+        let current = self.adapter.get_link(ptr);
+        let next = if !next.is_null() {
+            Some(self.adapter.get_link(next))
+        } else {
+            None
+        };
+        let prev = self.adapter.link_ops().prev(current, next);
+
+        Cursor {
+            current: Some(current),
+            prev,
+            next,
+            list: self,
+        }
+    }
+
+    /// Creates a `CursorMut` from a pointer to an element and a pointer to the next element.
+    ///
+    /// # Safety
+    ///
+    /// `ptr` must be a pointer to an object that is part of this list.
+    /// `next` must be a pointer to an object that is the next object in this list (null for the tail)
+    #[inline]
+    pub unsafe fn cursor_mut_from_ptr_and_next(
+        &mut self,
+        ptr: *const <A::PointerOps as PointerOps>::Value,
+        next: *const <A::PointerOps as PointerOps>::Value,
+    ) -> CursorMut<'_, A> {
+        let current = self.adapter.get_link(ptr);
+        let next = if !next.is_null() {
+            Some(self.adapter.get_link(next))
+        } else {
+            None
+        };
+        let prev = self.adapter.link_ops().prev(current, next);
+
+        CursorMut {
+            current: Some(current),
+            prev,
+            next,
+            list: self,
+        }
+    }
+
+    /// Returns a `Cursor` pointing to the first element of the list. If the
+    /// list is empty then a null cursor is returned.
+    #[inline]
+    pub fn front(&self) -> Cursor<'_, A> {
+        let mut cursor = self.cursor();
+        cursor.move_next();
+        cursor
+    }
+
+    /// Returns a `CursorMut` pointing to the first element of the list. If the
+    /// the list is empty then a null cursor is returned.
+    #[inline]
+    pub fn front_mut(&mut self) -> CursorMut<'_, A> {
+        let mut cursor = self.cursor_mut();
+        cursor.move_next();
+        cursor
+    }
+
+    /// Returns a `Cursor` pointing to the last element of the list. If the list
+    /// is empty then a null cursor is returned.
+    #[inline]
+    pub fn back(&self) -> Cursor<'_, A> {
+        let mut cursor = self.cursor();
+        cursor.move_prev();
+        cursor
+    }
+
+    /// Returns a `CursorMut` pointing to the last element of the list. If the
+    /// list is empty then a null cursor is returned.
+    #[inline]
+    pub fn back_mut(&mut self) -> CursorMut<'_, A> {
+        let mut cursor = self.cursor_mut();
+        cursor.move_prev();
+        cursor
+    }
+
+    /// Gets an iterator over the objects in the `XorLinkedList`.
+    #[inline]
+    pub fn iter(&self) -> Iter<'_, A> {
+        Iter {
+            prev_head: None,
+            head: self.head,
+            tail: self.tail,
+            next_tail: None,
+            list: self,
+        }
+    }
+
+    /// Removes all elements from the `XorLinkedList`.
+    ///
+    /// This will unlink all object currently in the list, which requires
+    /// iterating through all elements in the `XorLinkedList`. Each element is
+    /// converted back to an owned pointer and then dropped.
+    #[inline]
+    pub fn clear(&mut self) {
+        use link_ops::LinkOps;
+
+        let mut current = self.head;
+        let mut prev = None;
+        self.head = None;
+        self.tail = None;
+        while let Some(x) = current {
+            unsafe {
+                let next = self.adapter.link_ops().next(x, prev);
+                self.adapter.link_ops_mut().release_link(x);
+                self.adapter
+                    .pointer_ops()
+                    .from_raw(self.adapter.get_value(x));
+                prev = current;
+                current = next;
+            }
+        }
+    }
+
+    /// Empties the `XorLinkedList` without unlinking or freeing objects in it.
+    ///
+    /// Since this does not unlink any objects, any attempts to link these
+    /// objects into another `XorLinkedList` will fail but will not cause any
+    /// memory unsafety. To unlink those objects manually, you must call the
+    /// `force_unlink` function on them.
+    #[inline]
+    pub fn fast_clear(&mut self) {
+        self.head = None;
+        self.tail = None;
+    }
+
+    /// Takes all the elements out of the `XorLinkedList`, leaving it empty.
+    /// The taken elements are returned as a new `XorLinkedList`.
+    #[inline]
+    pub fn take(&mut self) -> XorLinkedList<A>
+    where
+        A: Clone,
+    {
+        let list = XorLinkedList {
+            head: self.head,
+            tail: self.tail,
+            adapter: self.adapter.clone(),
+        };
+        self.head = None;
+        self.tail = None;
+        list
+    }
+
+    /// Inserts a new element at the start of the `XorLinkedList`.
+    #[inline]
+    pub fn push_front(&mut self, val: <A::PointerOps as PointerOps>::Pointer) {
+        self.cursor_mut().insert_after(val);
+    }
+
+    /// Inserts a new element at the end of the `XorLinkedList`.
+    #[inline]
+    pub fn push_back(&mut self, val: <A::PointerOps as PointerOps>::Pointer) {
+        self.cursor_mut().insert_before(val);
+    }
+
+    /// Removes the first element of the `XorLinkedList`.
+    ///
+    /// This returns `None` if the `XorLinkedList` is empty.
+    #[inline]
+    pub fn pop_front(&mut self) -> Option<<A::PointerOps as PointerOps>::Pointer> {
+        self.front_mut().remove()
+    }
+
+    /// Removes the last element of the `XorLinkedList`.
+    ///
+    /// This returns `None` if the `XorLinkedList` is empty.
+    #[inline]
+    pub fn pop_back(&mut self) -> Option<<A::PointerOps as PointerOps>::Pointer> {
+        self.back_mut().remove()
+    }
+}
+
+// Allow read-only access to values from multiple threads
+unsafe impl<A: Adapter + Sync> Sync for XorLinkedList<A>
+where
+    <A::PointerOps as PointerOps>::Value: Sync,
+    A::LinkOps: XorLinkedListOps,
+{
+}
+
+// Allow sending to another thread if the ownership (represented by the <A::PointerOps as PointerOps>::Pointer owned
+// pointer type) can be transferred to another thread.
+unsafe impl<A: Adapter + Send> Send for XorLinkedList<A>
+where
+    <A::PointerOps as PointerOps>::Pointer: Send,
+    A::LinkOps: XorLinkedListOps,
+{
+}
+
+// Drop all owned pointers if the collection is dropped
+impl<A: Adapter> Drop for XorLinkedList<A>
+where
+    A::LinkOps: XorLinkedListOps,
+{
+    #[inline]
+    fn drop(&mut self) {
+        self.clear();
+    }
+}
+
+impl<A: Adapter> IntoIterator for XorLinkedList<A>
+where
+    A::LinkOps: XorLinkedListOps,
+{
+    type Item = <A::PointerOps as PointerOps>::Pointer;
+    type IntoIter = IntoIter<A>;
+
+    #[inline]
+    fn into_iter(self) -> IntoIter<A> {
+        IntoIter { list: self }
+    }
+}
+
+impl<'a, A: Adapter + 'a> IntoIterator for &'a XorLinkedList<A>
+where
+    A::LinkOps: XorLinkedListOps,
+{
+    type Item = &'a <A::PointerOps as PointerOps>::Value;
+    type IntoIter = Iter<'a, A>;
+
+    #[inline]
+    fn into_iter(self) -> Iter<'a, A> {
+        self.iter()
+    }
+}
+
+impl<A: Adapter + Default> Default for XorLinkedList<A>
+where
+    A::LinkOps: XorLinkedListOps,
+{
+    fn default() -> XorLinkedList<A> {
+        XorLinkedList::new(A::default())
+    }
+}
+
+impl<A: Adapter> fmt::Debug for XorLinkedList<A>
+where
+    A::LinkOps: XorLinkedListOps,
+    <A::PointerOps as PointerOps>::Value: fmt::Debug,
+{
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_list().entries(self.iter()).finish()
+    }
+}
+
+// =============================================================================
+// Iter
+// =============================================================================
+
+/// An iterator over references to the items of a `XorLinkedList`.
+pub struct Iter<'a, A: Adapter>
+where
+    A::LinkOps: XorLinkedListOps,
+{
+    prev_head: Option<<A::LinkOps as link_ops::LinkOps>::LinkPtr>,
+    head: Option<<A::LinkOps as link_ops::LinkOps>::LinkPtr>,
+    tail: Option<<A::LinkOps as link_ops::LinkOps>::LinkPtr>,
+    next_tail: Option<<A::LinkOps as link_ops::LinkOps>::LinkPtr>,
+    list: &'a XorLinkedList<A>,
+}
+impl<'a, A: Adapter + 'a> Iterator for Iter<'a, A>
+where
+    A::LinkOps: XorLinkedListOps,
+{
+    type Item = &'a <A::PointerOps as PointerOps>::Value;
+
+    #[inline]
+    fn next(&mut self) -> Option<&'a <A::PointerOps as PointerOps>::Value> {
+        let head = self.head?;
+
+        if Some(head) == self.tail {
+            self.prev_head = None;
+            self.head = None;
+            self.next_tail = None;
+            self.tail = None;
+        } else {
+            let next = unsafe { self.list.adapter.link_ops().next(head, self.prev_head) };
+            self.prev_head = self.head;
+            self.head = next;
+        }
+        Some(unsafe { &*self.list.adapter.get_value(head) })
+    }
+}
+impl<'a, A: Adapter + 'a> DoubleEndedIterator for Iter<'a, A>
+where
+    A::LinkOps: XorLinkedListOps,
+{
+    #[inline]
+    fn next_back(&mut self) -> Option<&'a <A::PointerOps as PointerOps>::Value> {
+        let tail = self.tail?;
+
+        if Some(tail) == self.head {
+            self.prev_head = None;
+            self.head = None;
+            self.next_tail = None;
+            self.tail = None;
+        } else {
+            let new_tail = unsafe { self.list.adapter.link_ops().prev(tail, self.next_tail) };
+            self.next_tail = self.tail;
+            self.tail = new_tail;
+        }
+        Some(unsafe { &*self.list.adapter.get_value(tail) })
+    }
+}
+impl<'a, A: Adapter + 'a> Clone for Iter<'a, A>
+where
+    A::LinkOps: XorLinkedListOps,
+{
+    #[inline]
+    fn clone(&self) -> Iter<'a, A> {
+        Iter {
+            prev_head: self.prev_head,
+            head: self.head,
+            tail: self.tail,
+            next_tail: self.next_tail,
+            list: self.list,
+        }
+    }
+}
+
+// =============================================================================
+// IntoIter
+// =============================================================================
+
+/// An iterator which consumes a `XorLinkedList`.
+pub struct IntoIter<A: Adapter>
+where
+    A::LinkOps: XorLinkedListOps,
+{
+    list: XorLinkedList<A>,
+}
+impl<A: Adapter> Iterator for IntoIter<A>
+where
+    A::LinkOps: XorLinkedListOps,
+{
+    type Item = <A::PointerOps as PointerOps>::Pointer;
+
+    #[inline]
+    fn next(&mut self) -> Option<<A::PointerOps as PointerOps>::Pointer> {
+        self.list.pop_front()
+    }
+}
+impl<A: Adapter> DoubleEndedIterator for IntoIter<A>
+where
+    A::LinkOps: XorLinkedListOps,
+{
+    #[inline]
+    fn next_back(&mut self) -> Option<<A::PointerOps as PointerOps>::Pointer> {
+        self.list.pop_back()
+    }
+}
+
+// =============================================================================
+// Tests
+// =============================================================================
+
+#[cfg(test)]
+mod tests {
+    use super::{Link, XorLinkedList};
+    use core::cell::Cell;
+    use core::ptr;
+    use std::boxed::Box;
+    use std::fmt;
+    use std::format;
+    use std::rc::Rc;
+    use std::vec::Vec;
+
+    struct Obj {
+        link1: Link,
+        link2: Link,
+        value: u32,
+    }
+    impl fmt::Debug for Obj {
+        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+            write!(f, "{}", self.value)
+        }
+    }
+    intrusive_adapter!(ObjAdapter1 = Rc<Obj>: Obj { link1: Link });
+    intrusive_adapter!(ObjAdapter2 = Rc<Obj>: Obj { link2: Link });
+
+    fn make_obj(value: u32) -> Rc<Obj> {
+        Rc::new(Obj {
+            link1: Link::new(),
+            link2: Link::default(),
+            value,
+        })
+    }
+
+    #[test]
+    fn test_link() {
+        let a = make_obj(1);
+        assert!(!a.link1.is_linked());
+        assert!(!a.link2.is_linked());
+
+        let mut b = XorLinkedList::<ObjAdapter1>::default();
+        assert!(b.is_empty());
+
+        b.cursor_mut().insert_after(a.clone());
+        assert!(!b.is_empty());
+        assert!(a.link1.is_linked());
+        assert!(!a.link2.is_linked());
+        assert_eq!(format!("{:?}", a.link1), "linked");
+        assert_eq!(format!("{:?}", a.link2), "unlinked");
+
+        assert_eq!(
+            b.front_mut().remove().unwrap().as_ref() as *const _,
+            a.as_ref() as *const _
+        );
+        assert!(b.is_empty());
+        assert!(!a.link1.is_linked());
+        assert!(!a.link2.is_linked());
+    }
+
+    #[test]
+    fn test_cursor() {
+        let a = make_obj(1);
+        let b = make_obj(2);
+        let c = make_obj(3);
+
+        let mut l = XorLinkedList::new(ObjAdapter1::new());
+        let mut cur = l.cursor_mut();
+        assert!(cur.is_null());
+        assert!(cur.get().is_none());
+        assert!(cur.remove().is_none());
+        assert_eq!(
+            cur.replace_with(a.clone()).unwrap_err().as_ref() as *const _,
+            a.as_ref() as *const _
+        );
+
+        cur.insert_before(a.clone());
+        cur.insert_before(c.clone());
+        cur.move_prev();
+        cur.insert_before(b.clone());
+        assert!(cur.peek_next().is_null());
+        cur.move_next();
+        assert!(cur.is_null());
+
+        cur.move_next();
+        assert!(cur.peek_prev().is_null());
+        assert!(!cur.is_null());
+        assert_eq!(cur.get().unwrap() as *const _, a.as_ref() as *const _);
+
+        {
+            let mut cur2 = cur.as_cursor();
+            assert_eq!(cur2.get().unwrap() as *const _, a.as_ref() as *const _);
+            assert_eq!(cur2.peek_next().get().unwrap().value, 2);
+            cur2.move_next();
+            assert_eq!(cur2.get().unwrap().value, 2);
+            cur2.move_next();
+            assert_eq!(cur2.peek_prev().get().unwrap().value, 2);
+            assert_eq!(cur2.get().unwrap() as *const _, c.as_ref() as *const _);
+            cur2.move_prev();
+            assert_eq!(cur2.get().unwrap() as *const _, b.as_ref() as *const _);
+            cur2.move_next();
+            assert_eq!(cur2.get().unwrap() as *const _, c.as_ref() as *const _);
+            cur2.move_next();
+            assert!(cur2.is_null());
+            assert!(cur2.clone().get().is_none());
+        }
+        assert_eq!(cur.get().unwrap() as *const _, a.as_ref() as *const _);
+
+        cur.move_next();
+        assert_eq!(
+            cur.remove().unwrap().as_ref() as *const _,
+            b.as_ref() as *const _
+        );
+        assert_eq!(cur.get().unwrap() as *const _, c.as_ref() as *const _);
+        cur.insert_after(b.clone());
+        assert_eq!(cur.get().unwrap() as *const _, c.as_ref() as *const _);
+        cur.move_prev();
+        assert_eq!(cur.get().unwrap() as *const _, a.as_ref() as *const _);
+        assert_eq!(
+            cur.remove().unwrap().as_ref() as *const _,
+            a.as_ref() as *const _
+        );
+        assert!(!a.link1.is_linked());
+        assert!(c.link1.is_linked());
+        assert_eq!(cur.get().unwrap() as *const _, c.as_ref() as *const _);
+        assert_eq!(
+            cur.replace_with(a.clone()).unwrap().as_ref() as *const _,
+            c.as_ref() as *const _
+        );
+        assert!(a.link1.is_linked());
+        assert!(!c.link1.is_linked());
+        assert_eq!(cur.get().unwrap() as *const _, a.as_ref() as *const _);
+        cur.move_next();
+        assert_eq!(
+            cur.replace_with(c.clone()).unwrap().as_ref() as *const _,
+            b.as_ref() as *const _
+        );
+        assert!(a.link1.is_linked());
+        assert!(!b.link1.is_linked());
+        assert!(c.link1.is_linked());
+        assert_eq!(cur.get().unwrap() as *const _, c.as_ref() as *const _);
+    }
+
+    #[test]
+    fn test_push_pop() {
+        let a = make_obj(1);
+        let b = make_obj(2);
+        let c = make_obj(3);
+
+        let mut l = XorLinkedList::new(ObjAdapter1::new());
+        l.push_front(a);
+        assert_eq!(l.iter().map(|x| x.value).collect::<Vec<_>>(), [1]);
+        l.push_front(b);
+        assert_eq!(l.iter().map(|x| x.value).collect::<Vec<_>>(), [2, 1]);
+        l.push_back(c);
+        assert_eq!(l.iter().map(|x| x.value).collect::<Vec<_>>(), [2, 1, 3]);
+        assert_eq!(l.pop_front().unwrap().value, 2);
+        assert_eq!(l.iter().map(|x| x.value).collect::<Vec<_>>(), [1, 3]);
+        assert_eq!(l.pop_back().unwrap().value, 3);
+        assert_eq!(l.iter().map(|x| x.value).collect::<Vec<_>>(), [1]);
+        assert_eq!(l.pop_front().unwrap().value, 1);
+        assert_eq!(l.iter().map(|x| x.value).collect::<Vec<_>>(), []);
+        assert!(l.pop_front().is_none());
+        assert_eq!(l.iter().map(|x| x.value).collect::<Vec<_>>(), []);
+        assert!(l.pop_back().is_none());
+        assert_eq!(l.iter().map(|x| x.value).collect::<Vec<_>>(), []);
+    }
+
+    #[test]
+    fn test_split_splice() {
+        let mut l1 = XorLinkedList::new(ObjAdapter1::new());
+        let mut l2 = XorLinkedList::new(ObjAdapter1::new());
+        let mut l3 = XorLinkedList::new(ObjAdapter1::new());
+
+        let a = make_obj(1);
+        let b = make_obj(2);
+        let c = make_obj(3);
+        let d = make_obj(4);
+        l1.cursor_mut().insert_before(a);
+        l1.cursor_mut().insert_before(b);
+        l1.cursor_mut().insert_before(c);
+        l1.cursor_mut().insert_before(d);
+        assert_eq!(l1.iter().map(|x| x.value).collect::<Vec<_>>(), [1, 2, 3, 4]);
+        assert_eq!(l2.iter().map(|x| x.value).collect::<Vec<_>>(), []);
+        assert_eq!(l3.iter().map(|x| x.value).collect::<Vec<_>>(), []);
+        {
+            let mut cur = l1.front_mut();
+            cur.move_next();
+            l2 = cur.split_after();
+        }
+        assert_eq!(l1.iter().map(|x| x.value).collect::<Vec<_>>(), [1, 2]);
+        assert_eq!(l2.iter().map(|x| x.value).collect::<Vec<_>>(), [3, 4]);
+        assert_eq!(l3.iter().map(|x| x.value).collect::<Vec<_>>(), []);
+        {
+            let mut cur = l2.back_mut();
+            l3 = cur.split_before();
+        }
+        assert_eq!(l1.iter().map(|x| x.value).collect::<Vec<_>>(), [1, 2]);
+        assert_eq!(l2.iter().map(|x| x.value).collect::<Vec<_>>(), [4]);
+        assert_eq!(l3.iter().map(|x| x.value).collect::<Vec<_>>(), [3]);
+        {
+            let mut cur = l1.front_mut();
+            cur.splice_after(l2.take());
+        }
+        assert_eq!(l1.iter().map(|x| x.value).collect::<Vec<_>>(), [1, 4, 2]);
+        assert_eq!(l2.iter().map(|x| x.value).collect::<Vec<_>>(), []);
+        assert_eq!(l3.iter().map(|x| x.value).collect::<Vec<_>>(), [3]);
+        {
+            let mut cur = l1.front_mut();
+            cur.move_next();
+            cur.splice_before(l3.take());
+        }
+        assert_eq!(l1.iter().map(|x| x.value).collect::<Vec<_>>(), [1, 3, 4, 2]);
+        assert_eq!(l2.iter().map(|x| x.value).collect::<Vec<_>>(), []);
+        assert_eq!(l3.iter().map(|x| x.value).collect::<Vec<_>>(), []);
+        {
+            let mut cur = l2.cursor_mut();
+            cur.splice_after(l1.take());
+        }
+        assert_eq!(l1.iter().map(|x| x.value).collect::<Vec<_>>(), []);
+        assert_eq!(l2.iter().map(|x| x.value).collect::<Vec<_>>(), [1, 3, 4, 2]);
+        assert_eq!(l3.iter().map(|x| x.value).collect::<Vec<_>>(), []);
+        {
+            let mut cur = l1.cursor_mut();
+            cur.splice_before(l2.take());
+        }
+        assert_eq!(l1.iter().map(|x| x.value).collect::<Vec<_>>(), [1, 3, 4, 2]);
+        assert_eq!(l2.iter().map(|x| x.value).collect::<Vec<_>>(), []);
+        assert_eq!(l3.iter().map(|x| x.value).collect::<Vec<_>>(), []);
+        {
+            let mut cur = l1.cursor_mut();
+            l2 = cur.split_after();
+        }
+        assert_eq!(l1.iter().map(|x| x.value).collect::<Vec<_>>(), []);
+        assert_eq!(l2.iter().map(|x| x.value).collect::<Vec<_>>(), [1, 3, 4, 2]);
+        assert_eq!(l3.iter().map(|x| x.value).collect::<Vec<_>>(), []);
+        {
+            let mut cur = l2.cursor_mut();
+            l1 = cur.split_before();
+        }
+        assert_eq!(l1.iter().map(|x| x.value).collect::<Vec<_>>(), [1, 3, 4, 2]);
+        assert_eq!(l2.iter().map(|x| x.value).collect::<Vec<_>>(), []);
+        assert_eq!(l3.iter().map(|x| x.value).collect::<Vec<_>>(), []);
+        {
+            let mut cur = l1.front_mut();
+            l2 = cur.split_before();
+        }
+        assert_eq!(l1.iter().map(|x| x.value).collect::<Vec<_>>(), [1, 3, 4, 2]);
+        assert_eq!(l2.iter().map(|x| x.value).collect::<Vec<_>>(), []);
+        assert_eq!(l3.iter().map(|x| x.value).collect::<Vec<_>>(), []);
+        {
+            let mut cur = l1.back_mut();
+            l2 = cur.split_after();
+        }
+        assert_eq!(l1.iter().map(|x| x.value).collect::<Vec<_>>(), [1, 3, 4, 2]);
+        assert_eq!(l2.iter().map(|x| x.value).collect::<Vec<_>>(), []);
+        assert_eq!(l3.iter().map(|x| x.value).collect::<Vec<_>>(), []);
+    }
+
+    #[test]
+    fn test_iter() {
+        let mut l = XorLinkedList::new(ObjAdapter1::new());
+        let a = make_obj(1);
+        let b = make_obj(2);
+        let c = make_obj(3);
+        let d = make_obj(4);
+        l.cursor_mut().insert_before(a.clone());
+        l.cursor_mut().insert_before(b.clone());
+        l.cursor_mut().insert_before(c.clone());
+        l.cursor_mut().insert_before(d.clone());
+
+        assert_eq!(l.front().get().unwrap().value, 1);
+        assert_eq!(l.back().get().unwrap().value, 4);
+        unsafe {
+            let mut cursor = l.cursor_from_ptr_and_prev(b.as_ref(), a.as_ref());
+            assert_eq!(cursor.get().unwrap().value, 2);
+            cursor.move_next();
+            assert_eq!(cursor.get().unwrap().value, 3);
+
+            assert_eq!(
+                l.cursor_mut_from_ptr_and_next(c.as_ref(), d.as_ref())
+                    .get()
+                    .unwrap()
+                    .value,
+                3
+            );
+
+            assert_eq!(
+                l.cursor_mut_from_ptr_and_prev(a.as_ref(), ptr::null())
+                    .get()
+                    .unwrap()
+                    .value,
+                1
+            );
+            assert_eq!(
+                l.cursor_mut_from_ptr_and_next(d.as_ref(), ptr::null())
+                    .get()
+                    .unwrap()
+                    .value,
+                4
+            );
+
+            let mut cursor = l.cursor_from_ptr_and_next(d.as_ref(), ptr::null());
+            assert_eq!(cursor.get().unwrap().value, 4);
+            cursor.move_prev();
+            assert_eq!(cursor.get().unwrap().value, 3);
+            cursor.move_next();
+            assert_eq!(cursor.get().unwrap().value, 4);
+            cursor.move_next();
+            assert!(cursor.is_null());
+        }
+
+        let mut v = Vec::new();
+        for x in &l {
+            v.push(x.value);
+        }
+        assert_eq!(v, [1, 2, 3, 4]);
+        assert_eq!(
+            l.iter().clone().map(|x| x.value).collect::<Vec<_>>(),
+            [1, 2, 3, 4]
+        );
+        assert_eq!(
+            l.iter().rev().map(|x| x.value).collect::<Vec<_>>(),
+            [4, 3, 2, 1]
+        );
+        assert_eq!(l.iter().map(|x| x.value).collect::<Vec<_>>(), [1, 2, 3, 4]);
+
+        assert_eq!(format!("{:?}", l), "[1, 2, 3, 4]");
+
+        let mut v = Vec::new();
+        for x in l.take() {
+            v.push(x.value);
+        }
+        assert_eq!(v, [1, 2, 3, 4]);
+        assert!(l.is_empty());
+        assert!(!a.link1.is_linked());
+        assert!(!b.link1.is_linked());
+        assert!(!c.link1.is_linked());
+        assert!(!d.link1.is_linked());
+
+        l.cursor_mut().insert_before(a.clone());
+        l.cursor_mut().insert_before(b.clone());
+        l.cursor_mut().insert_before(c.clone());
+        l.cursor_mut().insert_before(d.clone());
+        l.clear();
+        assert!(l.is_empty());
+        assert!(!a.link1.is_linked());
+        assert!(!b.link1.is_linked());
+        assert!(!c.link1.is_linked());
+        assert!(!d.link1.is_linked());
+
+        v.clear();
+        l.cursor_mut().insert_before(a.clone());
+        l.cursor_mut().insert_before(b.clone());
+        l.cursor_mut().insert_before(c.clone());
+        l.cursor_mut().insert_before(d.clone());
+        for x in l.into_iter().rev() {
+            v.push(x.value);
+        }
+        assert_eq!(v, [4, 3, 2, 1]);
+        assert!(!a.link1.is_linked());
+        assert!(!b.link1.is_linked());
+        assert!(!c.link1.is_linked());
+        assert!(!d.link1.is_linked());
+    }
+
+    #[test]
+    fn test_multi_list() {
+        let mut l1 = XorLinkedList::new(ObjAdapter1::new());
+        let mut l2 = XorLinkedList::new(ObjAdapter2::new());
+        let a = make_obj(1);
+        let b = make_obj(2);
+        let c = make_obj(3);
+        let d = make_obj(4);
+        l1.cursor_mut().insert_before(a.clone());
+        l1.cursor_mut().insert_before(b.clone());
+        l1.cursor_mut().insert_before(c.clone());
+        l1.cursor_mut().insert_before(d.clone());
+        l2.cursor_mut().insert_after(a.clone());
+        l2.cursor_mut().insert_after(b.clone());
+        l2.cursor_mut().insert_after(c.clone());
+        l2.cursor_mut().insert_after(d.clone());
+        assert_eq!(l1.iter().map(|x| x.value).collect::<Vec<_>>(), [1, 2, 3, 4]);
+        assert_eq!(l2.iter().map(|x| x.value).collect::<Vec<_>>(), [4, 3, 2, 1]);
+    }
+
+    #[test]
+    fn test_force_unlink() {
+        let mut l = XorLinkedList::new(ObjAdapter1::new());
+        let a = make_obj(1);
+        let b = make_obj(2);
+        let c = make_obj(3);
+        l.cursor_mut().insert_before(a.clone());
+        l.cursor_mut().insert_before(b.clone());
+        l.cursor_mut().insert_before(c.clone());
+
+        l.fast_clear();
+        assert!(l.is_empty());
+        assert!(a.link1.is_linked());
+        assert!(b.link1.is_linked());
+        assert!(c.link1.is_linked());
+        unsafe {
+            a.link1.force_unlink();
+            b.link1.force_unlink();
+            c.link1.force_unlink();
+        }
+        assert!(l.is_empty());
+        assert!(!a.link1.is_linked());
+        assert!(!b.link1.is_linked());
+        assert!(!c.link1.is_linked());
+    }
+
+    #[test]
+    fn test_non_static() {
+        #[derive(Clone)]
+        struct Obj<'a, T> {
+            link: Link,
+            value: &'a T,
+        }
+        intrusive_adapter!(ObjAdapter<'a, T> = &'a Obj<'a, T>: Obj<'a, T> {link: Link} where T: 'a);
+
+        let v = 5;
+        let a = Obj {
+            link: Link::new(),
+            value: &v,
+        };
+        let b = a.clone();
+        let mut l = XorLinkedList::new(ObjAdapter::new());
+        l.cursor_mut().insert_before(&a);
+        l.cursor_mut().insert_before(&b);
+        assert_eq!(*l.front().get().unwrap().value, 5);
+        assert_eq!(*l.back().get().unwrap().value, 5);
+    }
+
+    #[test]
+    fn test_drop() {
+        #[derive(Clone)]
+        struct Obj<'a> {
+            link: Link,
+            value: &'a Cell<u32>,
+        }
+        impl<'a> Drop for Obj<'a> {
+            fn drop(&mut self) {
+                let val = self.value.get();
+                self.value.set(val + 1);
+            }
+        }
+        intrusive_adapter!(ObjAdapter<'a> = Box<Obj<'a>>: Obj<'a> {link: Link});
+
+        let v = Cell::new(0);
+        let obj = Obj {
+            link: Link::new(),
+            value: &v,
+        };
+        let mut l = XorLinkedList::new(ObjAdapter::new());
+        l.cursor_mut().insert_before(Box::new(obj.clone()));
+        l.cursor_mut().insert_before(Box::new(obj.clone()));
+        assert_eq!(l.front().get().unwrap().value.get(), 0);
+        assert_eq!(l.back().get().unwrap().value.get(), 0);
+        assert_eq!(v.get(), 0);
+
+        l.pop_front();
+        assert_eq!(v.get(), 1);
+
+        l.front_mut().insert_after(Box::new(obj.clone()));
+        assert_eq!(v.get(), 1);
+
+        drop(l);
+        assert_eq!(v.get(), 3);
+    }
+
+    macro_rules! test_clone_pointer {
+        ($ptr: ident, $ptr_import: path) => {
+            use $ptr_import;
+
+            #[derive(Clone)]
+            struct Obj {
+                link: Link,
+                value: usize,
+            }
+            intrusive_adapter!(ObjAdapter = $ptr<Obj>: Obj { link: Link });
+
+            let a = $ptr::new(Obj {
+                link: Link::new(),
+                value: 5,
+            });
+            let mut l = XorLinkedList::new(ObjAdapter::new());
+            l.cursor_mut().insert_before(a.clone());
+            assert_eq!(2, $ptr::strong_count(&a));
+
+            let pointer = l.front().clone_pointer().unwrap();
+            assert_eq!(pointer.value, 5);
+            assert_eq!(3, $ptr::strong_count(&a));
+
+            l.front_mut().remove();
+            assert!(l.front().clone_pointer().is_none());
+        };
+    }
+
+    #[test]
+    fn test_clone_pointer_rc() {
+        test_clone_pointer!(Rc, std::rc::Rc);
+    }
+
+    #[test]
+    fn test_clone_pointer_arc() {
+        test_clone_pointer!(Arc, std::sync::Arc);
+    }
+}