]> git.lizzy.rs Git - rust.git/blob - src/librustc_llvm/archive_ro.rs
Rollup merge of #31152 - durka:ty-follow-bracket, r=pnkfelix
[rust.git] / src / librustc_llvm / archive_ro.rs
1 // Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 //! A wrapper around LLVM's archive (.a) code
12
13 use ArchiveRef;
14
15 use std::ffi::CString;
16 use std::marker;
17 use std::path::Path;
18 use std::slice;
19 use std::str;
20
21 pub struct ArchiveRO { ptr: ArchiveRef }
22
23 pub struct Iter<'a> {
24     archive: &'a ArchiveRO,
25     ptr: ::ArchiveIteratorRef,
26 }
27
28 pub struct Child<'a> {
29     ptr: ::ArchiveChildRef,
30     _data: marker::PhantomData<&'a ArchiveRO>,
31 }
32
33 impl ArchiveRO {
34     /// Opens a static archive for read-only purposes. This is more optimized
35     /// than the `open` method because it uses LLVM's internal `Archive` class
36     /// rather than shelling out to `ar` for everything.
37     ///
38     /// If this archive is used with a mutable method, then an error will be
39     /// raised.
40     pub fn open(dst: &Path) -> Option<ArchiveRO> {
41         return unsafe {
42             let s = path2cstr(dst);
43             let ar = ::LLVMRustOpenArchive(s.as_ptr());
44             if ar.is_null() {
45                 None
46             } else {
47                 Some(ArchiveRO { ptr: ar })
48             }
49         };
50
51         #[cfg(unix)]
52         fn path2cstr(p: &Path) -> CString {
53             use std::os::unix::prelude::*;
54             use std::ffi::OsStr;
55             let p: &OsStr = p.as_ref();
56             CString::new(p.as_bytes()).unwrap()
57         }
58         #[cfg(windows)]
59         fn path2cstr(p: &Path) -> CString {
60             CString::new(p.to_str().unwrap()).unwrap()
61         }
62     }
63
64     pub fn raw(&self) -> ArchiveRef { self.ptr }
65
66     pub fn iter(&self) -> Iter {
67         unsafe {
68             Iter { ptr: ::LLVMRustArchiveIteratorNew(self.ptr), archive: self }
69         }
70     }
71 }
72
73 impl Drop for ArchiveRO {
74     fn drop(&mut self) {
75         unsafe {
76             ::LLVMRustDestroyArchive(self.ptr);
77         }
78     }
79 }
80
81 impl<'a> Iterator for Iter<'a> {
82     type Item = Child<'a>;
83
84     fn next(&mut self) -> Option<Child<'a>> {
85         let ptr = unsafe { ::LLVMRustArchiveIteratorNext(self.ptr) };
86         if ptr.is_null() {
87             None
88         } else {
89             Some(Child { ptr: ptr, _data: marker::PhantomData })
90         }
91     }
92 }
93
94 impl<'a> Drop for Iter<'a> {
95     fn drop(&mut self) {
96         unsafe {
97             ::LLVMRustArchiveIteratorFree(self.ptr);
98         }
99     }
100 }
101
102 impl<'a> Child<'a> {
103     pub fn name(&self) -> Option<&'a str> {
104         unsafe {
105             let mut name_len = 0;
106             let name_ptr = ::LLVMRustArchiveChildName(self.ptr, &mut name_len);
107             if name_ptr.is_null() {
108                 None
109             } else {
110                 let name = slice::from_raw_parts(name_ptr as *const u8,
111                                                  name_len as usize);
112                 str::from_utf8(name).ok().map(|s| s.trim())
113             }
114         }
115     }
116
117     pub fn data(&self) -> &'a [u8] {
118         unsafe {
119             let mut data_len = 0;
120             let data_ptr = ::LLVMRustArchiveChildData(self.ptr, &mut data_len);
121             if data_ptr.is_null() {
122                 panic!("failed to read data from archive child");
123             }
124             slice::from_raw_parts(data_ptr as *const u8, data_len as usize)
125         }
126     }
127
128     pub fn raw(&self) -> ::ArchiveChildRef { self.ptr }
129 }
130
131 impl<'a> Drop for Child<'a> {
132     fn drop(&mut self) {
133         unsafe { ::LLVMRustArchiveChildFree(self.ptr); }
134     }
135 }