1 use libc_rust_gen::free; 2 use mesa_rust_gen::*; 3 4 use std::ffi::{c_void, CString}; 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: &str, func_ptrs: &[*mut c_void], flags: u64) -> Option<Self>78 pub fn new(name: &str, func_ptrs: &[*mut c_void], flags: u64) -> Option<Self> { 79 let c_name = CString::new(name).unwrap(); 80 let mut sha_ctx = SHA1_CTX::default(); 81 let mut sha = [0; SHA1_DIGEST_LENGTH as usize]; 82 let mut cache_id = [0; SHA1_DIGEST_STRING_LENGTH as usize]; 83 84 let cache = unsafe { 85 SHA1Init(&mut sha_ctx); 86 87 for &func_ptr in func_ptrs { 88 if !disk_cache_get_function_identifier(func_ptr, &mut sha_ctx) { 89 return None; 90 } 91 } 92 SHA1Final(&mut sha, &mut sha_ctx); 93 mesa_bytes_to_hex(cache_id.as_mut_ptr(), sha.as_ptr(), sha.len() as u32); 94 disk_cache_create(c_name.as_ptr(), cache_id.as_ptr(), flags) 95 }; 96 97 DiskCacheBorrowed::from_ptr(cache).map(|c| Self { inner: c }) 98 } 99 } 100 101 impl Deref for DiskCache { 102 type Target = DiskCacheBorrowed; 103 deref(&self) -> &Self::Target104 fn deref(&self) -> &Self::Target { 105 &self.inner 106 } 107 } 108 109 impl Drop for DiskCache { drop(&mut self)110 fn drop(&mut self) { 111 unsafe { 112 disk_cache_destroy(self.cache.as_ptr()); 113 } 114 } 115 } 116 117 pub struct DiskCacheEntry<'a> { 118 data: &'a mut [u8], 119 } 120 121 impl<'a> Deref for DiskCacheEntry<'a> { 122 type Target = [u8]; 123 deref(&self) -> &Self::Target124 fn deref(&self) -> &Self::Target { 125 self.data 126 } 127 } 128 129 impl<'a> Drop for DiskCacheEntry<'a> { drop(&mut self)130 fn drop(&mut self) { 131 unsafe { 132 free(self.data.as_mut_ptr().cast()); 133 } 134 } 135 } 136