]> git.proxmox.com Git - rustc.git/blob - vendor/gix-config/src/file/access/comfort.rs
New upstream version 1.70.0+dfsg2
[rustc.git] / vendor / gix-config / src / file / access / comfort.rs
1 use std::{borrow::Cow, convert::TryFrom};
2
3 use bstr::BStr;
4
5 use crate::{file::MetadataFilter, value, File};
6
7 /// Comfortable API for accessing values
8 impl<'event> File<'event> {
9 /// Like [`value()`][File::value()], but returning `None` if the string wasn't found.
10 ///
11 /// As strings perform no conversions, this will never fail.
12 pub fn string(
13 &self,
14 section_name: impl AsRef<str>,
15 subsection_name: Option<&BStr>,
16 key: impl AsRef<str>,
17 ) -> Option<Cow<'_, BStr>> {
18 self.string_filter(section_name, subsection_name, key, &mut |_| true)
19 }
20
21 /// Like [`string()`][File::string()], but suitable for statically known `key`s like `remote.origin.url`.
22 pub fn string_by_key<'a>(&self, key: impl Into<&'a BStr>) -> Option<Cow<'_, BStr>> {
23 self.string_filter_by_key(key, &mut |_| true)
24 }
25
26 /// Like [`string()`][File::string()], but the section containing the returned value must pass `filter` as well.
27 pub fn string_filter(
28 &self,
29 section_name: impl AsRef<str>,
30 subsection_name: Option<&BStr>,
31 key: impl AsRef<str>,
32 filter: &mut MetadataFilter,
33 ) -> Option<Cow<'_, BStr>> {
34 self.raw_value_filter(section_name, subsection_name, key, filter).ok()
35 }
36
37 /// Like [`string_filter()`][File::string_filter()], but suitable for statically known `key`s like `remote.origin.url`.
38 pub fn string_filter_by_key<'a>(
39 &self,
40 key: impl Into<&'a BStr>,
41 filter: &mut MetadataFilter,
42 ) -> Option<Cow<'_, BStr>> {
43 let key = crate::parse::key(key)?;
44 self.raw_value_filter(key.section_name, key.subsection_name, key.value_name, filter)
45 .ok()
46 }
47
48 /// Like [`value()`][File::value()], but returning `None` if the path wasn't found.
49 ///
50 /// Note that this path is not vetted and should only point to resources which can't be used
51 /// to pose a security risk. Prefer using [`path_filter()`][File::path_filter()] instead.
52 ///
53 /// As paths perform no conversions, this will never fail.
54 pub fn path(
55 &self,
56 section_name: impl AsRef<str>,
57 subsection_name: Option<&BStr>,
58 key: impl AsRef<str>,
59 ) -> Option<crate::Path<'_>> {
60 self.path_filter(section_name, subsection_name, key, &mut |_| true)
61 }
62
63 /// Like [`path()`][File::path()], but suitable for statically known `key`s like `remote.origin.url`.
64 pub fn path_by_key<'a>(&self, key: impl Into<&'a BStr>) -> Option<crate::Path<'_>> {
65 self.path_filter_by_key(key, &mut |_| true)
66 }
67
68 /// Like [`path()`][File::path()], but the section containing the returned value must pass `filter` as well.
69 ///
70 /// This should be the preferred way of accessing paths as those from untrusted
71 /// locations can be
72 ///
73 /// As paths perform no conversions, this will never fail.
74 pub fn path_filter(
75 &self,
76 section_name: impl AsRef<str>,
77 subsection_name: Option<&BStr>,
78 key: impl AsRef<str>,
79 filter: &mut MetadataFilter,
80 ) -> Option<crate::Path<'_>> {
81 self.raw_value_filter(section_name, subsection_name, key, filter)
82 .ok()
83 .map(crate::Path::from)
84 }
85
86 /// Like [`path_filter()`][File::path_filter()], but suitable for statically known `key`s like `remote.origin.url`.
87 pub fn path_filter_by_key<'a>(
88 &self,
89 key: impl Into<&'a BStr>,
90 filter: &mut MetadataFilter,
91 ) -> Option<crate::Path<'_>> {
92 let key = crate::parse::key(key)?;
93 self.path_filter(key.section_name, key.subsection_name, key.value_name, filter)
94 }
95
96 /// Like [`value()`][File::value()], but returning `None` if the boolean value wasn't found.
97 pub fn boolean(
98 &self,
99 section_name: impl AsRef<str>,
100 subsection_name: Option<&BStr>,
101 key: impl AsRef<str>,
102 ) -> Option<Result<bool, value::Error>> {
103 self.boolean_filter(section_name, subsection_name, key, &mut |_| true)
104 }
105
106 /// Like [`boolean()`][File::boolean()], but suitable for statically known `key`s like `remote.origin.url`.
107 pub fn boolean_by_key<'a>(&self, key: impl Into<&'a BStr>) -> Option<Result<bool, value::Error>> {
108 self.boolean_filter_by_key(key, &mut |_| true)
109 }
110
111 /// Like [`boolean()`][File::boolean()], but the section containing the returned value must pass `filter` as well.
112 pub fn boolean_filter(
113 &self,
114 section_name: impl AsRef<str>,
115 subsection_name: Option<&BStr>,
116 key: impl AsRef<str>,
117 filter: &mut MetadataFilter,
118 ) -> Option<Result<bool, value::Error>> {
119 let section_name = section_name.as_ref();
120 let section_ids = self
121 .section_ids_by_name_and_subname(section_name, subsection_name)
122 .ok()?;
123 let key = key.as_ref();
124 for section_id in section_ids.rev() {
125 let section = self.sections.get(&section_id).expect("known section id");
126 if !filter(section.meta()) {
127 continue;
128 }
129 match section.value_implicit(key) {
130 Some(Some(v)) => return Some(crate::Boolean::try_from(v).map(|b| b.into())),
131 Some(None) => return Some(Ok(true)),
132 None => continue,
133 }
134 }
135 None
136 }
137
138 /// Like [`boolean_filter()`][File::boolean_filter()], but suitable for statically known `key`s like `remote.origin.url`.
139 pub fn boolean_filter_by_key<'a>(
140 &self,
141 key: impl Into<&'a BStr>,
142 filter: &mut MetadataFilter,
143 ) -> Option<Result<bool, value::Error>> {
144 let key = crate::parse::key(key)?;
145 self.boolean_filter(key.section_name, key.subsection_name, key.value_name, filter)
146 }
147
148 /// Like [`value()`][File::value()], but returning an `Option` if the integer wasn't found.
149 pub fn integer(
150 &self,
151 section_name: impl AsRef<str>,
152 subsection_name: Option<&BStr>,
153 key: impl AsRef<str>,
154 ) -> Option<Result<i64, value::Error>> {
155 self.integer_filter(section_name, subsection_name, key, &mut |_| true)
156 }
157
158 /// Like [`integer()`][File::integer()], but suitable for statically known `key`s like `remote.origin.url`.
159 pub fn integer_by_key<'a>(&self, key: impl Into<&'a BStr>) -> Option<Result<i64, value::Error>> {
160 self.integer_filter_by_key(key, &mut |_| true)
161 }
162
163 /// Like [`integer()`][File::integer()], but the section containing the returned value must pass `filter` as well.
164 pub fn integer_filter(
165 &self,
166 section_name: impl AsRef<str>,
167 subsection_name: Option<&BStr>,
168 key: impl AsRef<str>,
169 filter: &mut MetadataFilter,
170 ) -> Option<Result<i64, value::Error>> {
171 let int = self.raw_value_filter(section_name, subsection_name, key, filter).ok()?;
172 Some(crate::Integer::try_from(int.as_ref()).and_then(|b| {
173 b.to_decimal()
174 .ok_or_else(|| value::Error::new("Integer overflow", int.into_owned()))
175 }))
176 }
177
178 /// Like [`integer_filter()`][File::integer_filter()], but suitable for statically known `key`s like `remote.origin.url`.
179 pub fn integer_filter_by_key<'a>(
180 &self,
181 key: impl Into<&'a BStr>,
182 filter: &mut MetadataFilter,
183 ) -> Option<Result<i64, value::Error>> {
184 let key = crate::parse::key(key)?;
185 self.integer_filter(key.section_name, key.subsection_name, key.value_name, filter)
186 }
187
188 /// Similar to [`values(…)`][File::values()] but returning strings if at least one of them was found.
189 pub fn strings(
190 &self,
191 section_name: impl AsRef<str>,
192 subsection_name: Option<&BStr>,
193 key: impl AsRef<str>,
194 ) -> Option<Vec<Cow<'_, BStr>>> {
195 self.raw_values(section_name, subsection_name, key).ok()
196 }
197
198 /// Like [`strings()`][File::strings()], but suitable for statically known `key`s like `remote.origin.url`.
199 pub fn strings_by_key<'a>(&self, key: impl Into<&'a BStr>) -> Option<Vec<Cow<'_, BStr>>> {
200 let key = crate::parse::key(key)?;
201 self.strings(key.section_name, key.subsection_name, key.value_name)
202 }
203
204 /// Similar to [`strings(…)`][File::strings()], but all values are in sections that passed `filter`.
205 pub fn strings_filter(
206 &self,
207 section_name: impl AsRef<str>,
208 subsection_name: Option<&BStr>,
209 key: impl AsRef<str>,
210 filter: &mut MetadataFilter,
211 ) -> Option<Vec<Cow<'_, BStr>>> {
212 self.raw_values_filter(section_name, subsection_name, key, filter).ok()
213 }
214
215 /// Like [`strings_filter()`][File::strings_filter()], but suitable for statically known `key`s like `remote.origin.url`.
216 pub fn strings_filter_by_key<'a>(
217 &self,
218 key: impl Into<&'a BStr>,
219 filter: &mut MetadataFilter,
220 ) -> Option<Vec<Cow<'_, BStr>>> {
221 let key = crate::parse::key(key)?;
222 self.strings_filter(key.section_name, key.subsection_name, key.value_name, filter)
223 }
224
225 /// Similar to [`values(…)`][File::values()] but returning integers if at least one of them was found
226 /// and if none of them overflows.
227 pub fn integers(
228 &self,
229 section_name: impl AsRef<str>,
230 subsection_name: Option<&BStr>,
231 key: impl AsRef<str>,
232 ) -> Option<Result<Vec<i64>, value::Error>> {
233 self.integers_filter(section_name, subsection_name, key, &mut |_| true)
234 }
235
236 /// Like [`integers()`][File::integers()], but suitable for statically known `key`s like `remote.origin.url`.
237 pub fn integers_by_key<'a>(&self, key: impl Into<&'a BStr>) -> Option<Result<Vec<i64>, value::Error>> {
238 self.integers_filter_by_key(key, &mut |_| true)
239 }
240
241 /// Similar to [`integers(…)`][File::integers()] but all integers are in sections that passed `filter`
242 /// and that are not overflowing.
243 pub fn integers_filter(
244 &self,
245 section_name: impl AsRef<str>,
246 subsection_name: Option<&BStr>,
247 key: impl AsRef<str>,
248 filter: &mut MetadataFilter,
249 ) -> Option<Result<Vec<i64>, value::Error>> {
250 self.raw_values_filter(section_name, subsection_name, key, filter)
251 .ok()
252 .map(|values| {
253 values
254 .into_iter()
255 .map(|v| {
256 crate::Integer::try_from(v.as_ref()).and_then(|int| {
257 int.to_decimal()
258 .ok_or_else(|| value::Error::new("Integer overflow", v.into_owned()))
259 })
260 })
261 .collect()
262 })
263 }
264
265 /// Like [`integers_filter()`][File::integers_filter()], but suitable for statically known `key`s like `remote.origin.url`.
266 pub fn integers_filter_by_key<'a>(
267 &self,
268 key: impl Into<&'a BStr>,
269 filter: &mut MetadataFilter,
270 ) -> Option<Result<Vec<i64>, value::Error>> {
271 let key = crate::parse::key(key)?;
272 self.integers_filter(key.section_name, key.subsection_name, key.value_name, filter)
273 }
274 }