1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
use std::str;
use raw;
/// A string array structure used by libgit2
///
/// Some apis return arrays of strings which originate from libgit2. This
/// wrapper type behaves a little like `Vec<&str>` but does so without copying
/// the underlying strings until necessary.
pub struct StringArray {
raw: raw::git_strarray,
}
/// A forward iterator over the strings of an array, casted to `&str`.
pub struct StringArrayItems<'a> {
cur: uint,
arr: &'a StringArray,
}
/// A forward iterator over the strings of an array, casted to `&[u8]`.
pub struct StringArrayBytes<'a> {
cur: uint,
arr: &'a StringArray,
}
impl StringArray {
/// Creates a new string array from the raw representation.
///
/// This is unsafe because it consumes ownership of the array and there is
/// no guarantee that the array itself is valid or that no one else is using
/// it.
pub unsafe fn from_raw(raw: raw::git_strarray) -> StringArray {
StringArray { raw: raw }
}
/// Returns None if the i'th string is not utf8 or if i is out of bounds.
pub fn get(&self, i: uint) -> Option<&str> {
self.get_bytes(i).and_then(|s| str::from_utf8(s).ok())
}
/// Returns None if `i` is out of bounds.
pub fn get_bytes(&self, i: uint) -> Option<&[u8]> {
if i < self.raw.count as uint {
unsafe {
let ptr = *self.raw.strings.offset(i as int) as *const _;
Some(::opt_bytes(self, ptr).unwrap())
}
} else {
None
}
}
/// Returns an iterator over the strings contained within this array.
///
/// The iterator yields `Option<&str>` as it is unknown whether the contents
/// are utf-8 or not.
pub fn iter(&self) -> StringArrayItems {
StringArrayItems { cur: 0, arr: self }
}
/// Returns an iterator over the strings contained within this array,
/// yielding byte slices.
pub fn iter_bytes(&self) -> StringArrayBytes {
StringArrayBytes { cur: 0, arr: self }
}
/// Returns the number of strings in this array.
pub fn len(&self) -> uint { self.raw.count as uint }
}
impl<'a> Iterator for StringArrayItems<'a> {
type Item = Option<&'a str>;
fn next(&mut self) -> Option<Option<&'a str>> {
if self.cur < self.arr.len() {
self.cur += 1;
Some(self.arr.get(self.cur - 1))
} else {
None
}
}
}
impl<'a> Iterator for StringArrayBytes<'a> {
type Item = &'a [u8];
fn next(&mut self) -> Option<&'a [u8]> {
if self.cur < self.arr.len() {
self.cur += 1;
self.arr.get_bytes(self.cur - 1)
} else {
None
}
}
}
impl Drop for StringArray {
fn drop(&mut self) {
unsafe { raw::git_strarray_free(&mut self.raw) }
}
}