#![doc = include_str!(concat!(env!("OUT_DIR"), "/generated.md"))]
#![no_std]
include!(concat!(env!("OUT_DIR"), "/generated.rs"));
pub mod docs {
include!(concat!(env!("OUT_DIR"), "/docs.rs"));
}
mod simd;
pub use simd::*;
const fn str_eq(a: &str, b: &str) -> bool {
let a = a.as_bytes();
let b = b.as_bytes();
if a.len() != b.len() {
return false;
}
let mut i = 0;
while i < a.len() {
if a[i] != b[i] {
return false;
}
i += 1;
}
true
}
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum Architecture {
Arm,
AArch64,
Bpf,
Hexagon,
Mips,
PowerPC,
RiscV,
Wasm,
X86,
Unsupported,
}
impl Architecture {
pub const fn from_str(architecture: &str) -> Self {
if str_eq(architecture, "arm") {
Self::Arm
} else if str_eq(architecture, "aarch64") {
Self::AArch64
} else if str_eq(architecture, "bpf") {
Self::Bpf
} else if str_eq(architecture, "hexagon") {
Self::Hexagon
} else if str_eq(architecture, "mips") || str_eq(architecture, "mips64") {
Self::Mips
} else if str_eq(architecture, "powerpc") || str_eq(architecture, "powerpc64") {
Self::PowerPC
} else if str_eq(architecture, "riscv32") || str_eq(architecture, "riscv64") {
Self::RiscV
} else if str_eq(architecture, "wasm32") || str_eq(architecture, "wasm64") {
Self::Wasm
} else if str_eq(architecture, "x86") || str_eq(architecture, "x86_64") {
Self::X86
} else {
Self::Unsupported
}
}
}
#[derive(Copy, Clone, Debug)]
pub struct UnknownFeature;
impl core::fmt::Display for UnknownFeature {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
write!(f, "unknown target feature")
}
}
#[derive(Copy, Clone, Debug)]
pub struct UnknownCpu;
impl core::fmt::Display for UnknownCpu {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
write!(f, "unknown target CPU")
}
}
#[derive(Copy, Clone, PartialEq, Eq)]
pub struct Feature(usize);
impl core::fmt::Debug for Feature {
fn fmt(&self, f: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error> {
f.debug_struct("Feature")
.field("architecture", &self.architecture())
.field("name", &self.name())
.finish()
}
}
impl Feature {
pub const fn new(architecture: Architecture, feature: &str) -> Result<Self, UnknownFeature> {
let mut i = 0;
while i < FEATURES.len() {
if (architecture as u8) == (FEATURES[i].0 as u8) && str_eq(feature, FEATURES[i].1) {
return Ok(Self(i));
}
i += 1;
}
Err(UnknownFeature)
}
pub const fn name(&self) -> &'static str {
FEATURES[self.0].1
}
pub const fn architecture(&self) -> Architecture {
FEATURES[self.0].0
}
pub const fn description(&self) -> &'static str {
FEATURES[self.0].2
}
pub const fn implies(&self) -> &'static [Feature] {
FEATURES[self.0].3
}
}
pub struct FeaturesIter {
target: Target,
index: usize,
}
impl Iterator for FeaturesIter {
type Item = Feature;
fn next(&mut self) -> Option<Self::Item> {
while self.index < self.target.features.len() {
let feature = if self.target.features[self.index] {
Some(Feature(self.index))
} else {
None
};
self.index += 1;
if feature.is_some() {
return feature;
}
}
None
}
}
impl core::fmt::Debug for Target {
fn fmt(&self, f: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error> {
struct FeaturesHelper(Target);
impl core::fmt::Debug for FeaturesHelper {
fn fmt(&self, f: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error> {
f.debug_list().entries(self.0.features()).finish()
}
}
f.debug_struct("Target")
.field("architecture", &self.architecture())
.field("features", &FeaturesHelper(*self))
.finish()
}
}
#[derive(Copy, Clone, PartialEq, Eq)]
pub struct Target {
architecture: Architecture,
features: [bool; FEATURES.len()],
}
impl Target {
pub const fn new(architecture: Architecture) -> Self {
Self {
architecture,
features: [false; FEATURES.len()],
}
}
pub const fn from_cpu(architecture: Architecture, cpu: &str) -> Result<Self, UnknownCpu> {
let mut target = Self::new(architecture);
let mut i = 0;
while i < CPUS.len() {
if architecture as u8 == CPUS[i].0 as u8 && str_eq(cpu, CPUS[i].1) {
let mut j = 0;
while j < CPUS[i].2.len() {
target = target.with_feature(CPUS[i].2[j]);
j += 1;
}
return Ok(target);
}
i += 1;
}
Err(UnknownCpu)
}
pub const fn architecture(&self) -> Architecture {
self.architecture
}
pub const fn features(&self) -> FeaturesIter {
FeaturesIter {
target: *self,
index: 0,
}
}
pub const fn supports_feature(&self, feature: Feature) -> bool {
self.features[feature.0]
}
pub const fn supports_feature_str(&self, feature: &str) -> bool {
if let Ok(feature) = Feature::new(self.architecture, feature) {
self.supports_feature(feature)
} else {
panic!("unknown feature");
}
}
pub const fn with_feature(mut self, feature: Feature) -> Self {
assert!(feature.architecture() as u8 == self.architecture as u8);
self.features[feature.0] = true;
let mut i = 0;
let implies = feature.implies();
while i < implies.len() {
self.features[implies[i].0] = true;
i += 1;
}
self
}
pub const fn with_feature_str(self, feature: &str) -> Self {
if let Ok(feature) = Feature::new(self.architecture, feature) {
self.with_feature(feature)
} else {
panic!("unknown feature");
}
}
}