]>
git.proxmox.com Git - rustc.git/blob - vendor/gix-pack/src/cache/object.rs
1 //! This module is a bit 'misplaced' if spelled out like '`gix_pack::cache::object::`*' but is best placed here for code re-use and
2 //! general usefulness.
5 #[cfg(feature = "object-cache-dynamic")]
7 use std
::num
::NonZeroUsize
;
15 kind
: gix_object
::Kind
,
18 type Key
= gix_hash
::ObjectId
;
22 impl WeightScale
<Key
, Entry
> for CustomScale
{
23 fn weight(&self, key
: &Key
, value
: &Entry
) -> usize {
24 value
.data
.len() + std
::mem
::size_of
::<Entry
>() + key
.as_bytes().len()
28 /// An LRU cache with hash map backing and an eviction rule based on the memory usage for object data in bytes.
29 pub struct MemoryCappedHashmap
{
30 inner
: clru
::CLruCache
<Key
, Entry
, gix_hashtable
::hash
::Builder
, CustomScale
>,
31 free_list
: Vec
<Vec
<u8>>,
32 debug
: gix_features
::cache
::Debug
,
35 impl MemoryCappedHashmap
{
36 /// The amount of bytes we can hold in total, or the value we saw in `new(…)`.
37 pub fn capacity(&self) -> usize {
40 /// Return a new instance which evicts least recently used items if it uses more than `memory_cap_in_bytes`
42 pub fn new(memory_cap_in_bytes
: usize) -> MemoryCappedHashmap
{
44 inner
: clru
::CLruCache
::with_config(
45 clru
::CLruCacheConfig
::new(NonZeroUsize
::new(memory_cap_in_bytes
).expect("non zero"))
46 .with_hasher(gix_hashtable
::hash
::Builder
)
47 .with_scale(CustomScale
),
49 free_list
: Vec
::new(),
50 debug
: gix_features
::cache
::Debug
::new(format
!("MemoryCappedObjectHashmap({memory_cap_in_bytes}B)")),
55 impl cache
::Object
for MemoryCappedHashmap
{
56 /// Put the object going by `id` of `kind` with `data` into the cache.
57 fn put(&mut self, id
: gix_hash
::ObjectId
, kind
: gix_object
::Kind
, data
: &[u8]) {
59 let res
= self.inner
.put_with_weight(
62 data
: self.free_list
.pop().map_or_else(
66 v
.resize(data
.len(), 0);
67 v
.copy_from_slice(data
);
75 Ok(Some(previous_entry
)) => self.free_list
.push(previous_entry
.data
),
77 Err((_key
, value
)) => self.free_list
.push(value
.data
),
81 /// Try to retrieve the object named `id` and place its data into `out` if available and return `Some(kind)` if found.
82 fn get(&mut self, id
: &gix_hash
::ObjectId
, out
: &mut Vec
<u8>) -> Option
<gix_object
::Kind
> {
83 let res
= self.inner
.get(id
).map(|e
| {
84 out
.resize(e
.data
.len(), 0);
85 out
.copy_from_slice(&e
.data
);
97 #[cfg(feature = "object-cache-dynamic")]
98 pub use memory
::MemoryCappedHashmap
;
100 /// A cache implementation that doesn't do any caching.
103 impl cache
::Object
for Never
{
105 fn put(&mut self, _id
: gix_hash
::ObjectId
, _kind
: gix_object
::Kind
, _data
: &[u8]) {}
108 fn get(&mut self, _id
: &gix_hash
::ObjectId
, _out
: &mut Vec
<u8>) -> Option
<gix_object
::Kind
> {
113 impl<T
: cache
::Object
+ ?Sized
> cache
::Object
for Box
<T
> {
114 fn put(&mut self, id
: gix_hash
::ObjectId
, kind
: gix_object
::Kind
, data
: &[u8]) {
115 use std
::ops
::DerefMut
;
116 self.deref_mut().put(id
, kind
, data
)
119 fn get(&mut self, id
: &gix_hash
::ObjectId
, out
: &mut Vec
<u8>) -> Option
<gix_object
::Kind
> {
120 use std
::ops
::DerefMut
;
121 self.deref_mut().get(id
, out
)