• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use libc_rust_gen::free;
2 use mesa_rust_gen::*;
3 
4 use std::ffi::{c_void, CStr};
5 use std::ops::Deref;
6 use std::ptr;
7 use std::ptr::NonNull;
8 use std::slice;
9 
10 pub struct DiskCacheBorrowed {
11     cache: NonNull<disk_cache>,
12 }
13 
14 pub struct DiskCache {
15     inner: DiskCacheBorrowed,
16 }
17 
18 // disk_cache is thread safe
19 unsafe impl Sync for DiskCacheBorrowed {}
20 
21 impl DiskCacheBorrowed {
from_ptr(cache: *mut disk_cache) -> Option<Self>22     pub fn from_ptr(cache: *mut disk_cache) -> Option<Self> {
23         NonNull::new(cache).map(|c| Self { cache: c })
24     }
25 
put(&self, data: &[u8], key: &mut cache_key)26     pub fn put(&self, data: &[u8], key: &mut cache_key) {
27         unsafe {
28             disk_cache_put(
29                 self.cache.as_ptr(),
30                 key,
31                 data.as_ptr().cast(),
32                 data.len(),
33                 ptr::null_mut(),
34             );
35         }
36     }
37 
get(&self, key: &mut cache_key) -> Option<DiskCacheEntry>38     pub fn get(&self, key: &mut cache_key) -> Option<DiskCacheEntry> {
39         let mut size = 0;
40 
41         unsafe {
42             let data = disk_cache_get(self.cache.as_ptr(), key, &mut size);
43             if data.is_null() {
44                 None
45             } else {
46                 Some(DiskCacheEntry {
47                     data: slice::from_raw_parts_mut(data.cast(), size),
48                 })
49             }
50         }
51     }
52 
gen_key(&self, data: &[u8]) -> cache_key53     pub fn gen_key(&self, data: &[u8]) -> cache_key {
54         let mut key = cache_key::default();
55 
56         unsafe {
57             disk_cache_compute_key(
58                 self.cache.as_ptr(),
59                 data.as_ptr().cast(),
60                 data.len(),
61                 &mut key,
62             );
63         }
64 
65         key
66     }
67 
as_ptr(s: &Option<Self>) -> *mut disk_cache68     pub fn as_ptr(s: &Option<Self>) -> *mut disk_cache {
69         if let Some(s) = s {
70             s.cache.as_ptr()
71         } else {
72             ptr::null_mut()
73         }
74     }
75 }
76 
77 impl DiskCache {
new(name: &CStr, func_ptrs: &[*mut c_void], flags: u64) -> Option<Self>78     pub fn new(name: &CStr, func_ptrs: &[*mut c_void], flags: u64) -> Option<Self> {
79         let mut sha_ctx = SHA1_CTX::default();
80         let mut sha = [0; SHA1_DIGEST_LENGTH as usize];
81         let mut cache_id = [0; SHA1_DIGEST_STRING_LENGTH as usize];
82 
83         let cache = unsafe {
84             SHA1Init(&mut sha_ctx);
85 
86             for &func_ptr in func_ptrs {
87                 if !disk_cache_get_function_identifier(func_ptr, &mut sha_ctx) {
88                     return None;
89                 }
90             }
91             SHA1Final(&mut sha, &mut sha_ctx);
92             mesa_bytes_to_hex(cache_id.as_mut_ptr(), sha.as_ptr(), sha.len() as u32);
93             disk_cache_create(name.as_ptr(), cache_id.as_ptr(), flags)
94         };
95 
96         DiskCacheBorrowed::from_ptr(cache).map(|c| Self { inner: c })
97     }
98 }
99 
100 impl Deref for DiskCache {
101     type Target = DiskCacheBorrowed;
102 
deref(&self) -> &Self::Target103     fn deref(&self) -> &Self::Target {
104         &self.inner
105     }
106 }
107 
108 impl Drop for DiskCache {
drop(&mut self)109     fn drop(&mut self) {
110         unsafe {
111             disk_cache_destroy(self.cache.as_ptr());
112         }
113     }
114 }
115 
116 pub struct DiskCacheEntry<'a> {
117     data: &'a mut [u8],
118 }
119 
120 impl Deref for DiskCacheEntry<'_> {
121     type Target = [u8];
122 
deref(&self) -> &Self::Target123     fn deref(&self) -> &Self::Target {
124         self.data
125     }
126 }
127 
128 impl Drop for DiskCacheEntry<'_> {
drop(&mut self)129     fn drop(&mut self) {
130         unsafe {
131             free(self.data.as_mut_ptr().cast());
132         }
133     }
134 }
135