]> git.proxmox.com Git - rustc.git/blobdiff - src/librustc_llvm/archive_ro.rs
Imported Upstream version 1.1.0+dfsg1
[rustc.git] / src / librustc_llvm / archive_ro.rs
index 647f4bc6a40fdbe7118dd31349b6de4657af6bae..b591e37f893e254d919441924b5176aefd6f935e 100644 (file)
 
 //! A wrapper around LLVM's archive (.a) code
 
-use libc;
 use ArchiveRef;
 
 use std::ffi::CString;
-use std::slice;
 use std::path::Path;
+use std::slice;
+use std::str;
 
-pub struct ArchiveRO {
-    ptr: ArchiveRef,
+pub struct ArchiveRO { ptr: ArchiveRef }
+
+pub struct Iter<'a> {
+    archive: &'a ArchiveRO,
+    ptr: ::ArchiveIteratorRef,
+}
+
+pub struct Child<'a> {
+    name: Option<&'a str>,
+    data: &'a [u8],
 }
 
 impl ArchiveRO {
@@ -52,18 +60,9 @@ impl ArchiveRO {
         }
     }
 
-    /// Reads a file in the archive
-    pub fn read<'a>(&'a self, file: &str) -> Option<&'a [u8]> {
+    pub fn iter(&self) -> Iter {
         unsafe {
-            let mut size = 0 as libc::size_t;
-            let file = CString::new(file).unwrap();
-            let ptr = ::LLVMRustArchiveReadSection(self.ptr, file.as_ptr(),
-                                                   &mut size);
-            if ptr.is_null() {
-                None
-            } else {
-                Some(slice::from_raw_parts(ptr as *const u8, size as usize))
-            }
+            Iter { ptr: ::LLVMRustArchiveIteratorNew(self.ptr), archive: self }
         }
     }
 }
@@ -75,3 +74,46 @@ impl Drop for ArchiveRO {
         }
     }
 }
+
+impl<'a> Iterator for Iter<'a> {
+    type Item = Child<'a>;
+
+    fn next(&mut self) -> Option<Child<'a>> {
+        unsafe {
+            let ptr = ::LLVMRustArchiveIteratorCurrent(self.ptr);
+            if ptr.is_null() {
+                return None
+            }
+            let mut name_len = 0;
+            let name_ptr = ::LLVMRustArchiveChildName(ptr, &mut name_len);
+            let mut data_len = 0;
+            let data_ptr = ::LLVMRustArchiveChildData(ptr, &mut data_len);
+            let child = Child {
+                name: if name_ptr.is_null() {
+                    None
+                } else {
+                    let name = slice::from_raw_parts(name_ptr as *const u8,
+                                                     name_len as usize);
+                    str::from_utf8(name).ok().map(|s| s.trim())
+                },
+                data: slice::from_raw_parts(data_ptr as *const u8,
+                                            data_len as usize),
+            };
+            ::LLVMRustArchiveIteratorNext(self.ptr);
+            Some(child)
+        }
+    }
+}
+
+impl<'a> Drop for Iter<'a> {
+    fn drop(&mut self) {
+        unsafe {
+            ::LLVMRustArchiveIteratorFree(self.ptr);
+        }
+    }
+}
+
+impl<'a> Child<'a> {
+    pub fn name(&self) -> Option<&'a str> { self.name }
+    pub fn data(&self) -> &'a [u8] { self.data }
+}