go_tool_dist_list/
lib.rs

1use std::{ops::Deref, process::Command};
2
3pub struct Targets(Vec<u8>);
4
5impl Targets {
6    pub fn iter(&self) -> Result<TargetsIter, std::str::Utf8Error> {
7        std::str::from_utf8(&self.0)
8            .map(str::lines)
9            .map(TargetsIter)
10    }
11
12    pub fn collect_strs(&self) -> Result<CollectedTargetsStrs, std::str::Utf8Error> {
13        std::str::from_utf8(&self.0)
14            .map(str::lines)
15            .map(|targets| targets.collect())
16            .map(CollectedTargetsStrs::from_vec)
17    }
18}
19
20pub struct TargetsIter<'a>(std::str::Lines<'a>);
21
22impl<'a> Iterator for TargetsIter<'a> {
23    type Item = &'a str;
24
25    fn next(&mut self) -> Option<Self::Item> {
26        self.0.next()
27    }
28}
29
30pub struct CollectedTargetsStrs<'a>(Vec<&'a str>);
31
32impl<'a> CollectedTargetsStrs<'a> {
33    fn from_vec(vec: Vec<&'a str>) -> Self {
34        #[cfg(debug_assertions)]
35        for window in vec.windows(2) {
36            assert!(
37                window[0] < window[1],
38                "The targets from `go tool dist list` were expected to be sorted lexicographically."
39            );
40        }
41        Self(vec)
42    }
43}
44
45impl<'a> CollectedTargetsStrs<'a> {
46    pub fn contains(&self, target: &str) -> bool {
47        self.0.binary_search(&target).is_ok()
48    }
49}
50
51impl<'a> Deref for CollectedTargetsStrs<'a> {
52    type Target = [&'a str];
53
54    fn deref(&self) -> &Self::Target {
55        self.0.as_slice()
56    }
57}
58
59/// Returns the list of targets supported by the current go compiler using CLI.
60///
61/// The list of targets can be iterated over using the `iter` method:
62///
63/// # Example
64///
65/// ```rust
66#[doc = include_str!("../examples/targets.rs")]
67/// ```
68pub fn from_cli() -> Result<Targets, std::io::Error> {
69    let output = Command::new("go")
70        .arg("tool")
71        .arg("dist")
72        .arg("list")
73        .output()?;
74
75    Ok(Targets(output.stdout))
76}