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