Add opaque newtype Targets over ArrayVec<Box<str>, 2>

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>
This commit is contained in:
Jiahao XU 2022-06-07 11:45:53 +10:00
parent 11fe943a11
commit efc8119c45
No known key found for this signature in database
GPG key ID: 591C0B03040416D6

View file

@ -1,11 +1,49 @@
use arrayvec::ArrayVec; use arrayvec::ArrayVec;
use std::io::{BufRead, Cursor}; use std::io::{BufRead, Cursor};
use std::iter::IntoIterator;
use std::ops::Deref;
use std::process::Output; use std::process::Output;
use tokio::process::Command; use tokio::process::Command;
/// Compiled target triple, used as default for binary fetching /// Compiled target triple, used as default for binary fetching
pub const TARGET: &str = env!("TARGET"); pub const TARGET: &str = env!("TARGET");
#[derive(Debug, Clone)]
pub struct Targets(ArrayVec<Box<str>, 2>);
impl Targets {
fn from_array<const LEN: usize>(arr: [Box<str>; LEN]) -> Self {
let mut v = ArrayVec::new();
for elem in arr {
v.push(elem);
}
Self(v)
}
fn push(&mut self, s: Box<str>) {
self.0.push(s)
}
}
impl Deref for Targets {
type Target = [Box<str>];
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl IntoIterator for Targets {
type Item = Box<str>;
type IntoIter = arrayvec::IntoIter<Box<str>, 2>;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}
/// Detect the targets supported at runtime, /// Detect the targets supported at runtime,
/// which might be different from `TARGET` which is detected /// which might be different from `TARGET` which is detected
/// at compile-time. /// at compile-time.
@ -19,9 +57,9 @@ pub const TARGET: &str = env!("TARGET");
/// ///
/// Check [this issue](https://github.com/ryankurte/cargo-binstall/issues/155) /// Check [this issue](https://github.com/ryankurte/cargo-binstall/issues/155)
/// for more information. /// for more information.
pub async fn detect_targets() -> ArrayVec<Box<str>, 2> { pub async fn detect_targets() -> Targets {
if let Some(target) = get_targets_from_rustc().await { if let Some(target) = get_targets_from_rustc().await {
let mut v = from_array([target]); let mut v = Targets::from_array([target]);
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
if v[0].contains("gnu") { if v[0].contains("gnu") {
@ -45,7 +83,7 @@ pub async fn detect_targets() -> ArrayVec<Box<str>, 2> {
} }
#[cfg(not(any(target_os = "linux", target_os = "macos")))] #[cfg(not(any(target_os = "linux", target_os = "macos")))]
{ {
from_array([TARGET.into()]) Targets::from_array([TARGET.into()])
} }
} }
} }
@ -64,21 +102,11 @@ async fn get_targets_from_rustc() -> Option<Box<str>> {
} }
} }
fn from_array<T, const LEN: usize, const CAP: usize>(arr: [T; LEN]) -> ArrayVec<T, CAP> {
let mut v = ArrayVec::new();
for elem in arr {
v.push(elem);
}
v
}
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
mod linux { mod linux {
use super::{from_array, ArrayVec, Command, Output, TARGET}; use super::{Command, Output, Targets, TARGET};
pub(super) async fn detect_targets_linux() -> ArrayVec<Box<str>, 2> { pub(super) async fn detect_targets_linux() -> Targets {
let abi = parse_abi(); let abi = parse_abi();
if let Ok(Output { if let Ok(Output {
@ -93,11 +121,11 @@ mod linux {
} else if let Some(libc_version) = parse_libc_version_from_ldd_output(&stderr) { } else if let Some(libc_version) = parse_libc_version_from_ldd_output(&stderr) {
libc_version libc_version
} else { } else {
return from_array([create_target_str("musl", abi)]); return Targets::from_array([create_target_str("musl", abi)]);
}; };
if libc_version == "gnu" { if libc_version == "gnu" {
return from_array([ return Targets::from_array([
create_target_str("gnu", abi), create_target_str("gnu", abi),
create_target_str("musl", abi), create_target_str("musl", abi),
]); ]);
@ -105,7 +133,7 @@ mod linux {
} }
// Fallback to using musl // Fallback to using musl
from_array([create_target_str("musl", abi)]) Targets::from_array([create_target_str("musl", abi)])
} }
fn parse_libc_version_from_ldd_output(output: &[u8]) -> Option<&'static str> { fn parse_libc_version_from_ldd_output(output: &[u8]) -> Option<&'static str> {
@ -146,17 +174,17 @@ mod linux {
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
mod macos { mod macos {
use super::{from_array, ArrayVec}; use super::Targets;
use guess_host_triple::guess_host_triple; use guess_host_triple::guess_host_triple;
pub(super) const AARCH64: &str = "aarch64-apple-darwin"; pub(super) const AARCH64: &str = "aarch64-apple-darwin";
pub(super) const X86: &str = "x86_64-apple-darwin"; pub(super) const X86: &str = "x86_64-apple-darwin";
pub(super) fn detect_targets_macos() -> ArrayVec<Box<str>, 2> { pub(super) fn detect_targets_macos() -> Targets {
if guess_host_triple() == Some(AARCH64) { if guess_host_triple() == Some(AARCH64) {
from_array([AARCH64.into(), X86.into()]) Targets::from_array([AARCH64.into(), X86.into()])
} else { } else {
from_array([X86.into()]) Targets::from_array([X86.into()])
} }
} }
} }