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