1use std::iter::FusedIterator;
4use std::ops::Range;
5use std::str;
6
7use crate::raw;
8use crate::util::Binding;
9use crate::Error;
10
11pub struct StringArray {
17 raw: raw::git_strarray,
18}
19
20pub struct Iter<'a> {
22 range: Range<usize>,
23 arr: &'a StringArray,
24}
25
26pub struct IterBytes<'a> {
28 range: Range<usize>,
29 arr: &'a StringArray,
30}
31
32impl StringArray {
33 pub fn get(&self, i: usize) -> Result<Option<&str>, Error> {
35 match self.get_bytes(i) {
36 Some(gb) => str::from_utf8(gb).map(|s| Some(s)).map_err(|e| e.into()),
37 None => Ok(None),
38 }
39 }
40
41 pub fn get_bytes(&self, i: usize) -> Option<&[u8]> {
43 if i < self.raw.count as usize {
44 unsafe {
45 let ptr = *self.raw.strings.add(i) as *const _;
46 Some(crate::opt_bytes(self, ptr).unwrap())
47 }
48 } else {
49 None
50 }
51 }
52
53 pub fn iter(&self) -> Iter<'_> {
58 Iter {
59 range: 0..self.len(),
60 arr: self,
61 }
62 }
63
64 pub fn iter_bytes(&self) -> IterBytes<'_> {
67 IterBytes {
68 range: 0..self.len(),
69 arr: self,
70 }
71 }
72
73 pub fn len(&self) -> usize {
75 self.raw.count as usize
76 }
77
78 pub fn is_empty(&self) -> bool {
80 self.len() == 0
81 }
82}
83
84impl Binding for StringArray {
85 type Raw = raw::git_strarray;
86 unsafe fn from_raw(raw: raw::git_strarray) -> StringArray {
87 StringArray { raw }
88 }
89 fn raw(&self) -> raw::git_strarray {
90 self.raw
91 }
92}
93
94impl<'a> IntoIterator for &'a StringArray {
95 type Item = Result<Option<&'a str>, Error>;
96 type IntoIter = Iter<'a>;
97 fn into_iter(self) -> Self::IntoIter {
98 self.iter()
99 }
100}
101
102impl<'a> Iterator for Iter<'a> {
103 type Item = Result<Option<&'a str>, Error>;
104 fn next(&mut self) -> Option<Result<Option<&'a str>, Error>> {
105 self.range.next().map(|i| self.arr.get(i))
106 }
107 fn size_hint(&self) -> (usize, Option<usize>) {
108 self.range.size_hint()
109 }
110}
111impl<'a> DoubleEndedIterator for Iter<'a> {
112 fn next_back(&mut self) -> Option<Result<Option<&'a str>, Error>> {
113 self.range.next_back().map(|i| self.arr.get(i))
114 }
115}
116impl<'a> FusedIterator for Iter<'a> {}
117impl<'a> ExactSizeIterator for Iter<'a> {}
118
119impl<'a> Iterator for IterBytes<'a> {
120 type Item = &'a [u8];
121 fn next(&mut self) -> Option<&'a [u8]> {
122 self.range.next().and_then(|i| self.arr.get_bytes(i))
123 }
124 fn size_hint(&self) -> (usize, Option<usize>) {
125 self.range.size_hint()
126 }
127}
128impl<'a> DoubleEndedIterator for IterBytes<'a> {
129 fn next_back(&mut self) -> Option<&'a [u8]> {
130 self.range.next_back().and_then(|i| self.arr.get_bytes(i))
131 }
132}
133impl<'a> FusedIterator for IterBytes<'a> {}
134impl<'a> ExactSizeIterator for IterBytes<'a> {}
135
136impl Drop for StringArray {
137 fn drop(&mut self) {
138 unsafe { raw::git_strarray_free(&mut self.raw) }
139 }
140}