From a9e01cd17313ff13225a421aee2d4a7a74b41268 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Sun, 22 Aug 2021 16:08:33 +0800 Subject: [PATCH] Add support for returning displaced entries for re-use. --- Cargo.toml | 4 ++++ README.md | 5 +++++ src/lib.rs | 29 ++++++++++++++++++++++++++++- 3 files changed, 37 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index c86366f..9c8d88d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,5 +11,9 @@ categories = ["data-structures", "no-std"] readme = "README.md" include = ["src/**/*", "LICENSE", "README.md"] +[features] +default = [] +std = [] + [dependencies] arrayvec = { version = "0.7", default-features = false } diff --git a/README.md b/README.md index 8224478..60846f3 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,11 @@ Servo's style system. insertion, and `O(n)` lookup. It does not require an allocator and can be used in `no_std` crates. It is implemented in 100% safe Rust. +## Cargo Features + +By default, this crate won't need the standard library. However, if the `std` cargo feature is enabled, `insert()` will +return a replaced value which allows to reuse memory it may have contained. + * [Documentation](https://docs.rs/uluru) * [crates.io](https://crates.io/crates/uluru) * [Release notes](https://github.com/servo/uluru/releases) diff --git a/src/lib.rs b/src/lib.rs index de50011..206d251 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,7 +2,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#![no_std] +#![cfg_attr(not(feature = "std"), no_std)] #![deny(unsafe_code)] //! A simple, fast, least-recently-used (LRU) cache. @@ -96,6 +96,33 @@ impl LRUCache { /// /// This item becomes the front (most-recently-used) item in the cache. If the cache is full, /// the back (least-recently-used) item will be removed. + #[cfg(feature = "std")] + pub fn insert(&mut self, val: T) -> Option { + let entry = Entry { + val, + prev: 0, + next: 0, + }; + + // If the cache is full, replace the oldest entry. Otherwise, add an entry. + let (new_head, previous_entry) = if self.entries.len() == self.entries.capacity() { + let i = self.pop_back(); + let previous_entry = std::mem::replace(&mut self.entries[i as usize], entry); + (i, Some(previous_entry.val)) + } else { + self.entries.push(entry); + (self.entries.len() as u16 - 1, None) + }; + + self.push_front(new_head); + previous_entry + } + + /// Insert a given key in the cache. + /// + /// This item becomes the front (most-recently-used) item in the cache. If the cache is full, + /// the back (least-recently-used) item will be removed. + #[cfg(not(feature = "std"))] pub fn insert(&mut self, val: T) { let entry = Entry { val,