1 //! A wrapper around LLVM's archive (.a) code 2 3 use rustc_fs_util::path_to_c_string; 4 use std::path::Path; 5 use std::slice; 6 use std::str; 7 8 pub struct ArchiveRO { 9 pub raw: &'static mut super::Archive, 10 } 11 12 unsafe impl Send for ArchiveRO {} 13 14 pub struct Iter<'a> { 15 raw: &'a mut super::ArchiveIterator<'a>, 16 } 17 18 pub struct Child<'a> { 19 pub raw: &'a mut super::ArchiveChild<'a>, 20 } 21 22 impl ArchiveRO { 23 /// Opens a static archive for read-only purposes. This is more optimized 24 /// than the `open` method because it uses LLVM's internal `Archive` class 25 /// rather than shelling out to `ar` for everything. 26 /// 27 /// If this archive is used with a mutable method, then an error will be 28 /// raised. open(dst: &Path) -> Result<ArchiveRO, String>29 pub fn open(dst: &Path) -> Result<ArchiveRO, String> { 30 unsafe { 31 let s = path_to_c_string(dst); 32 let ar = super::LLVMRustOpenArchive(s.as_ptr()).ok_or_else(|| { 33 super::last_error().unwrap_or_else(|| "failed to open archive".to_owned()) 34 })?; 35 Ok(ArchiveRO { raw: ar }) 36 } 37 } 38 iter(&self) -> Iter<'_>39 pub fn iter(&self) -> Iter<'_> { 40 unsafe { Iter { raw: super::LLVMRustArchiveIteratorNew(self.raw) } } 41 } 42 } 43 44 impl Drop for ArchiveRO { drop(&mut self)45 fn drop(&mut self) { 46 unsafe { 47 super::LLVMRustDestroyArchive(&mut *(self.raw as *mut _)); 48 } 49 } 50 } 51 52 impl<'a> Iterator for Iter<'a> { 53 type Item = Result<Child<'a>, String>; 54 next(&mut self) -> Option<Result<Child<'a>, String>>55 fn next(&mut self) -> Option<Result<Child<'a>, String>> { 56 unsafe { 57 match super::LLVMRustArchiveIteratorNext(self.raw) { 58 Some(raw) => Some(Ok(Child { raw })), 59 None => super::last_error().map(Err), 60 } 61 } 62 } 63 } 64 65 impl<'a> Drop for Iter<'a> { drop(&mut self)66 fn drop(&mut self) { 67 unsafe { 68 super::LLVMRustArchiveIteratorFree(&mut *(self.raw as *mut _)); 69 } 70 } 71 } 72 73 impl<'a> Child<'a> { name(&self) -> Option<&'a str>74 pub fn name(&self) -> Option<&'a str> { 75 unsafe { 76 let mut name_len = 0; 77 let name_ptr = super::LLVMRustArchiveChildName(self.raw, &mut name_len); 78 if name_ptr.is_null() { 79 None 80 } else { 81 let name = slice::from_raw_parts(name_ptr as *const u8, name_len as usize); 82 str::from_utf8(name).ok().map(|s| s.trim()) 83 } 84 } 85 } 86 data(&self) -> &'a [u8]87 pub fn data(&self) -> &'a [u8] { 88 unsafe { 89 let mut data_len = 0; 90 let data_ptr = super::LLVMRustArchiveChildData(self.raw, &mut data_len); 91 if data_ptr.is_null() { 92 panic!("failed to read data from archive child"); 93 } 94 slice::from_raw_parts(data_ptr as *const u8, data_len as usize) 95 } 96 } 97 } 98 99 impl<'a> Drop for Child<'a> { drop(&mut self)100 fn drop(&mut self) { 101 unsafe { 102 super::LLVMRustArchiveChildFree(&mut *(self.raw as *mut _)); 103 } 104 } 105 } 106