use std::collections::{BTreeMap, HashMap};
use std::fmt;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum ContractKind {
Precondition,
Postcondition,
Assert,
PreconditionAudit,
PostconditionAudit,
AssertAudit,
}
impl ContractKind {
pub fn is_audit(&self) -> bool {
matches!(
self,
Self::PreconditionAudit | Self::PostconditionAudit | Self::AssertAudit
)
}
pub fn is_precondition(&self) -> bool {
matches!(self, Self::Precondition | Self::PreconditionAudit)
}
pub fn is_postcondition(&self) -> bool {
matches!(self, Self::Postcondition | Self::PostconditionAudit)
}
pub fn is_assert(&self) -> bool {
matches!(self, Self::Assert | Self::AssertAudit)
}
pub fn default_semantic(&self) -> ContractSemantic {
match self {
Self::Precondition | Self::Postcondition | Self::Assert => ContractSemantic::Default,
Self::PreconditionAudit | Self::PostconditionAudit | Self::AssertAudit => {
ContractSemantic::Audit
}
}
}
}
impl fmt::Display for ContractKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Precondition => write!(f, "pre"),
Self::Postcondition => write!(f, "post"),
Self::Assert => write!(f, "assert"),
Self::PreconditionAudit => write!(f, "pre audit"),
Self::PostconditionAudit => write!(f, "post audit"),
Self::AssertAudit => write!(f, "assert audit"),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ContractSemantic {
Default,
Audit,
Axiom,
}
impl ContractSemantic {
pub fn from_str(s: &str) -> Option<Self> {
match s {
"default" => Some(Self::Default),
"audit" => Some(Self::Audit),
"axiom" => Some(Self::Axiom),
_ => None,
}
}
pub fn is_checked_at_runtime(&self, build_level: ContractBuildLevel) -> bool {
match self {
Self::Default => build_level != ContractBuildLevel::Off,
Self::Audit => build_level == ContractBuildLevel::Audit,
Self::Axiom => false,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ContractBuildLevel {
Off,
Default,
Audit,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ContractContinuationMode {
NeverContinue,
MaybeContinue,
AlwaysContinue,
}
impl fmt::Display for ContractContinuationMode {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::NeverContinue => write!(f, "never_continue"),
Self::MaybeContinue => write!(f, "maybe_continue"),
Self::AlwaysContinue => write!(f, "always_continue"),
}
}
}
#[derive(Debug, Clone)]
pub struct ContractAnnotation {
pub kind: ContractKind,
pub semantic: ContractSemantic,
pub predicate: String,
pub result_identifier: Option<String>,
pub location: ContractSourceLocation,
pub custom_handler: Option<String>,
pub continuation: ContractContinuationMode,
}
#[derive(Debug, Clone)]
pub struct ContractSourceLocation {
pub file: String,
pub line: u32,
pub column: u32,
pub function_name: String,
}
impl Default for ContractSourceLocation {
fn default() -> Self {
Self {
file: String::new(),
line: 0,
column: 0,
function_name: String::new(),
}
}
}
#[derive(Debug, Clone)]
pub struct ContractViolationHandler {
pub name: String,
pub terminates: bool,
pub logs: bool,
pub custom_code: Option<String>,
}
impl ContractViolationHandler {
pub fn default_handler() -> Self {
Self {
name: "default".to_string(),
terminates: true,
logs: false,
custom_code: None,
}
}
pub fn log_handler() -> Self {
Self {
name: "log".to_string(),
terminates: false,
logs: true,
custom_code: None,
}
}
pub fn custom(name: &str, code: &str, terminates: bool) -> Self {
Self {
name: name.to_string(),
terminates,
logs: true,
custom_code: Some(code.to_string()),
}
}
pub fn handler_signature(&self) -> String {
format!(
"void handle_contract_violation_{}(const std::contract_violation& violation)",
self.name
)
}
pub fn call_site(&self, annotation: &ContractAnnotation) -> String {
format!(
"if (!({condition})) {{ handle_contract_violation_{handler}(std::contract_violation{{\"{kind}\", \"{func}\", \"{file}\", {line}}}); }}",
condition = annotation.predicate,
handler = self.name,
kind = annotation.kind,
func = annotation.location.function_name,
file = annotation.location.file,
line = annotation.location.line
)
}
}
#[derive(Debug, Clone)]
pub struct FunctionContracts {
pub function_name: String,
pub preconditions: Vec<ContractAnnotation>,
pub postconditions: Vec<ContractAnnotation>,
pub assertions: Vec<ContractAnnotation>,
pub handler: ContractViolationHandler,
}
impl FunctionContracts {
pub fn new(function_name: &str) -> Self {
Self {
function_name: function_name.to_string(),
preconditions: Vec::new(),
postconditions: Vec::new(),
assertions: Vec::new(),
handler: ContractViolationHandler::default_handler(),
}
}
pub fn add_precondition(&mut self, predicate: &str, semantic: ContractSemantic) {
self.preconditions.push(ContractAnnotation {
kind: if semantic == ContractSemantic::Audit {
ContractKind::PreconditionAudit
} else {
ContractKind::Precondition
},
semantic,
predicate: predicate.to_string(),
result_identifier: None,
location: ContractSourceLocation::default(),
custom_handler: None,
continuation: ContractContinuationMode::NeverContinue,
});
}
pub fn add_postcondition(
&mut self,
result_id: &str,
predicate: &str,
semantic: ContractSemantic,
) {
self.postconditions.push(ContractAnnotation {
kind: if semantic == ContractSemantic::Audit {
ContractKind::PostconditionAudit
} else {
ContractKind::Postcondition
},
semantic,
predicate: predicate.to_string(),
result_identifier: Some(result_id.to_string()),
location: ContractSourceLocation::default(),
custom_handler: None,
continuation: ContractContinuationMode::NeverContinue,
});
}
pub fn add_assertion(&mut self, predicate: &str, semantic: ContractSemantic) {
self.assertions.push(ContractAnnotation {
kind: if semantic == ContractSemantic::Audit {
ContractKind::AssertAudit
} else {
ContractKind::Assert
},
semantic,
predicate: predicate.to_string(),
result_identifier: None,
location: ContractSourceLocation::default(),
custom_handler: None,
continuation: ContractContinuationMode::NeverContinue,
});
}
pub fn total_count(&self) -> usize {
self.preconditions.len() + self.postconditions.len() + self.assertions.len()
}
pub fn all_audit(&self) -> bool {
self.preconditions.iter().all(|c| c.is_audit())
&& self.postconditions.iter().all(|c| c.is_audit())
&& self.assertions.iter().all(|c| c.is_audit())
}
}
#[derive(Debug, Clone)]
pub struct ContractBuildConfig {
pub level: ContractBuildLevel,
pub handler: ContractViolationHandler,
pub default_continuation: ContractContinuationMode,
pub enable_assertions: bool,
}
impl Default for ContractBuildConfig {
fn default() -> Self {
Self {
level: ContractBuildLevel::Default,
handler: ContractViolationHandler::default_handler(),
default_continuation: ContractContinuationMode::NeverContinue,
enable_assertions: true,
}
}
}
impl ContractBuildConfig {
pub fn with_audit() -> Self {
Self {
level: ContractBuildLevel::Audit,
..Default::default()
}
}
pub fn off() -> Self {
Self {
level: ContractBuildLevel::Off,
..Default::default()
}
}
pub fn should_evaluate(&self, annotation: &ContractAnnotation) -> bool {
if !self.enable_assertions && annotation.kind.is_assert() {
return false;
}
annotation.semantic.is_checked_at_runtime(self.level)
}
}
#[derive(Debug, Clone)]
pub struct MetaInfo {
pub handle: u64,
pub entity_kind: MetaEntityKind,
pub source_location: Option<String>,
pub display_name: String,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MetaEntityKind {
Type,
Variable,
Function,
MemberFunction,
Namespace,
Template,
Concept,
Expression,
Statement,
Enum,
EnumValue,
Class,
Struct,
Union,
BaseClass,
DataMember,
Parameter,
Lambda,
Alias,
}
impl fmt::Display for MetaEntityKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Type => write!(f, "type"),
Self::Variable => write!(f, "variable"),
Self::Function => write!(f, "function"),
Self::MemberFunction => write!(f, "member_function"),
Self::Namespace => write!(f, "namespace"),
Self::Template => write!(f, "template"),
Self::Concept => write!(f, "concept"),
Self::Expression => write!(f, "expression"),
Self::Statement => write!(f, "statement"),
Self::Enum => write!(f, "enum"),
Self::EnumValue => write!(f, "enumerator"),
Self::Class => write!(f, "class"),
Self::Struct => write!(f, "struct"),
Self::Union => write!(f, "union"),
Self::BaseClass => write!(f, "base_class"),
Self::DataMember => write!(f, "data_member"),
Self::Parameter => write!(f, "parameter"),
Self::Lambda => write!(f, "lambda"),
Self::Alias => write!(f, "alias"),
}
}
}
#[derive(Debug, Clone)]
pub struct ReflectionOperator {
pub entity: String,
pub info: MetaInfo,
}
impl ReflectionOperator {
pub fn reflect(entity: &str, kind: MetaEntityKind) -> Self {
Self {
entity: entity.to_string(),
info: MetaInfo {
handle: 0,
entity_kind: kind,
source_location: None,
display_name: entity.to_string(),
},
}
}
pub fn reflect_type(type_name: &str) -> Self {
Self::reflect(type_name, MetaEntityKind::Type)
}
pub fn reflect_class(class_name: &str) -> Self {
Self::reflect(class_name, MetaEntityKind::Class)
}
pub fn reflect_function(fn_name: &str) -> Self {
Self::reflect(fn_name, MetaEntityKind::Function)
}
pub fn reflect_data_member(member_name: &str) -> Self {
Self::reflect(member_name, MetaEntityKind::DataMember)
}
pub fn generate_expression(&self) -> String {
format!("^{}^{}", "", self.entity)
}
}
#[derive(Debug, Clone)]
pub struct Splicer {
pub expression: String,
pub reflected_info: Option<MetaInfo>,
pub result_type: Option<String>,
}
impl Splicer {
pub fn new(expression: &str) -> Self {
Self {
expression: expression.to_string(),
reflected_info: None,
result_type: None,
}
}
pub fn type_splicer(type_expr: &str) -> Self {
Self {
expression: type_expr.to_string(),
reflected_info: None,
result_type: Some("typename".to_string()),
}
}
pub fn value_splicer(value_expr: &str) -> Self {
Self {
expression: value_expr.to_string(),
reflected_info: None,
result_type: Some("auto".to_string()),
}
}
pub fn generate(&self) -> String {
format!("[:{}:]", self.expression)
}
pub fn produces_type(&self) -> bool {
self.result_type.as_deref() == Some("typename")
}
pub fn produces_value(&self) -> bool {
self.result_type.as_deref() == Some("auto")
}
}
#[derive(Debug, Clone)]
pub enum MetaQuery {
NameOf(String),
TypeOf(String),
MembersOf(String),
BasesOf(String),
ParametersOf(String),
AccessCheck(String, MetaAccess),
IsVirtual(String),
IsConstexpr(String),
IsNoexcept(String),
SizeOfReflected(String),
AlignOfReflected(String),
Custom(String, String),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MetaAccess {
Public,
Protected,
Private,
}
impl fmt::Display for MetaAccess {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Public => write!(f, "public"),
Self::Protected => write!(f, "protected"),
Self::Private => write!(f, "private"),
}
}
}
impl MetaQuery {
pub fn generate(&self) -> String {
match self {
Self::NameOf(entity) => format!("name_of(^{}^{})", "", entity),
Self::TypeOf(entity) => format!("type_of(^{}^{})", "", entity),
Self::MembersOf(entity) => format!("members_of(^{}^{})", "", entity),
Self::BasesOf(entity) => format!("bases_of(^{}^{})", "", entity),
Self::ParametersOf(entity) => format!("parameters_of(^{}^{})", "", entity),
Self::AccessCheck(entity, access) => {
format!("has_{}_access(^{}^{})", access, "", entity)
}
Self::IsVirtual(entity) => format!("is_virtual(^{}^{})", "", entity),
Self::IsConstexpr(entity) => format!("is_constexpr(^{}^{})", "", entity),
Self::IsNoexcept(entity) => format!("is_noexcept(^{}^{})", "", entity),
Self::SizeOfReflected(entity) => format!("size_of(^{}^{})", "", entity),
Self::AlignOfReflected(entity) => format!("align_of(^{}^{})", "", entity),
Self::Custom(name, entity) => format!("{}(^{}^{})", name, "", entity),
}
}
pub fn target_entity(&self) -> &str {
match self {
Self::NameOf(e)
| Self::TypeOf(e)
| Self::MembersOf(e)
| Self::BasesOf(e)
| Self::ParametersOf(e)
| Self::AccessCheck(e, _)
| Self::IsVirtual(e)
| Self::IsConstexpr(e)
| Self::IsNoexcept(e)
| Self::SizeOfReflected(e)
| Self::AlignOfReflected(e)
| Self::Custom(_, e) => e,
}
}
}
#[derive(Debug, Clone)]
pub struct ReflectionContext {
pub operations: Vec<MetaQuery>,
pub splicers: Vec<Splicer>,
pub generated_code: Vec<String>,
pub nesting_depth: usize,
}
impl ReflectionContext {
pub fn new() -> Self {
Self {
operations: Vec::new(),
splicers: Vec::new(),
generated_code: Vec::new(),
nesting_depth: 0,
}
}
pub fn add_query(&mut self, query: MetaQuery) {
self.operations.push(query);
}
pub fn add_splicer(&mut self, splicer: Splicer) {
self.splicers.push(splicer);
}
pub fn generate_enum_to_string(enum_name: &str) -> String {
let mut code = String::new();
code.push_str(&format!(
"constexpr std::string_view to_string({} value) {{\n",
enum_name
));
code.push_str(" switch (value) {\n");
code.push_str(&format!(
" template for (constexpr auto e : members_of(^{}^{})) {{\n",
"", enum_name
));
code.push_str(" case [:e:]: return name_of(e);\n");
code.push_str(" }\n");
code.push_str(" }\n");
code.push_str(" return \"unknown\";\n");
code.push_str("}\n");
code
}
pub fn generate_struct_to_tuple(struct_name: &str) -> String {
let mut code = String::new();
code.push_str(&format!(
"auto to_tuple(const {}& s) {{\n",
struct_name
));
code.push_str(&format!(
" return std::make_tuple([:members_of(^{}^{}):]...);\n",
"", struct_name
));
code.push_str("}\n");
code
}
}
impl Default for ReflectionContext {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone)]
pub enum MatchPattern {
Wildcard,
Binding(String),
Literal(MatchLiteral),
Destructure(Vec<MatchPattern>),
Alternative(Vec<MatchPattern>),
Guard {
pattern: Box<MatchPattern>,
condition: String,
},
TypePattern {
type_name: String,
binding: Option<String>,
},
StructuredBinding(Vec<String>),
Variant(String, Box<MatchPattern>),
Optional {
some_binding: Option<String>,
none: bool,
},
}
#[derive(Debug, Clone)]
pub enum MatchLiteral {
Integer(i64),
Float(f64),
Boolean(bool),
String(String),
Char(char),
Nullptr,
}
impl fmt::Display for MatchLiteral {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Integer(v) => write!(f, "{}", v),
Self::Float(v) => write!(f, "{}", v),
Self::Boolean(v) => write!(f, "{}", v),
Self::String(v) => write!(f, "\"{}\"", v),
Self::Char(v) => write!(f, "'{}'", v),
Self::Nullptr => write!(f, "nullptr"),
}
}
}
#[derive(Debug, Clone)]
pub struct InspectCase {
pub pattern: MatchPattern,
pub action: String,
pub is_terminating: bool,
}
#[derive(Debug, Clone)]
pub struct InspectExpression {
pub scrutinee: String,
pub scrutinee_type: String,
pub cases: Vec<InspectCase>,
pub result_type: Option<String>,
pub exhaustive: bool,
}
impl InspectExpression {
pub fn new(scrutinee: &str, scrutinee_type: &str) -> Self {
Self {
scrutinee: scrutinee.to_string(),
scrutinee_type: scrutinee_type.to_string(),
cases: Vec::new(),
result_type: None,
exhaustive: true,
}
}
pub fn add_case(&mut self, pattern: MatchPattern, action: &str) {
self.cases.push(InspectCase {
pattern,
action: action.to_string(),
is_terminating: false,
});
}
pub fn generate(&self) -> String {
let mut code = format!("inspect ({}) {{\n", self.scrutinee);
for case in &self.cases {
let pattern_str = pattern_to_string(&case.pattern);
code.push_str(&format!(" {} => {{\n", pattern_str));
code.push_str(&format!(" {}\n", case.action));
code.push_str(" }\n");
}
if self.exhaustive {
code.push_str(" _ => { std::unreachable(); }\n");
}
code.push_str("}");
code
}
pub fn check_exhaustiveness(&self) -> ExhaustivenessResult {
if self.exhaustive && !self.has_wildcard() {
ExhaustivenessResult::NonExhaustive {
missing: vec!["_ wildcard".to_string()],
}
} else {
ExhaustivenessResult::Exhaustive
}
}
fn has_wildcard(&self) -> bool {
self.cases
.iter()
.any(|c| matches!(c.pattern, MatchPattern::Wildcard))
}
}
#[derive(Debug, Clone)]
pub enum ExhaustivenessResult {
Exhaustive,
NonExhaustive { missing: Vec<String> },
}
fn pattern_to_string(pattern: &MatchPattern) -> String {
match pattern {
MatchPattern::Wildcard => "_".to_string(),
MatchPattern::Binding(name) => format!("let {}", name),
MatchPattern::Literal(lit) => lit.to_string(),
MatchPattern::Destructure(parts) => {
let parts: Vec<String> = parts.iter().map(pattern_to_string).collect();
format!("[{}]", parts.join(", "))
}
MatchPattern::Alternative(alts) => {
let alts: Vec<String> = alts.iter().map(pattern_to_string).collect();
alts.join(" | ")
}
MatchPattern::Guard { pattern, condition } => {
format!("{} if {}", pattern_to_string(pattern), condition)
}
MatchPattern::TypePattern {
type_name,
binding,
} => {
if let Some(b) = binding {
format!("{} {}", type_name, b)
} else {
type_name.clone()
}
}
MatchPattern::StructuredBinding(bindings) => {
format!("[{}]", bindings.join(", "))
}
MatchPattern::Variant(type_name, inner) => {
format!("{} -> {}", type_name, pattern_to_string(inner))
}
MatchPattern::Optional {
some_binding,
none,
} => {
if *none {
"none".to_string()
} else if let Some(b) = some_binding {
format!("some({})", b)
} else {
"some(_)".to_string()
}
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum CompletionSignal {
SetValue,
SetError,
SetStopped,
}
impl fmt::Display for CompletionSignal {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::SetValue => write!(f, "set_value"),
Self::SetError => write!(f, "set_error"),
Self::SetStopped => write!(f, "set_stopped"),
}
}
}
#[derive(Debug, Clone)]
pub struct SenderDescriptor {
pub sender_type: String,
pub value_types: Vec<String>,
pub error_type: Option<String>,
pub always_completes: bool,
pub is_just: bool,
pub is_schedule: bool,
}
impl SenderDescriptor {
pub fn just(values: &[&str]) -> Self {
Self {
sender_type: "std::execution::just_t<...>".to_string(),
value_types: values.iter().map(|s| s.to_string()).collect(),
error_type: None,
always_completes: true,
is_just: true,
is_schedule: false,
}
}
pub fn schedule(scheduler_type: &str) -> Self {
Self {
sender_type: format!("schedule_result_t<{}>", scheduler_type),
value_types: vec![],
error_type: None,
always_completes: true,
is_just: false,
is_schedule: true,
}
}
pub fn from_stop_source() -> Self {
Self {
sender_type: "get_stop_token_sender".to_string(),
value_types: vec!["std::stop_token".to_string()],
error_type: None,
always_completes: true,
is_just: false,
is_schedule: false,
}
}
}
#[derive(Debug, Clone)]
pub enum SenderAdaptor {
Then {
function: String,
input_type: String,
output_type: String,
},
UponError {
function: String,
error_type: String,
},
UponStopped { function: String },
LetValue {
function: String,
input_type: String,
},
LetError {
function: String,
error_type: String,
},
LetStopped { function: String },
Bulk {
count: usize,
function: String,
},
Split,
WhenAll { sender_count: usize },
Transfer { scheduler: String },
TransferJust {
scheduler: String,
values: Vec<String>,
},
StartOn { scheduler: String },
On {
scheduler: String,
function: String,
},
IntoVariant,
EnsureStarted,
}
impl SenderAdaptor {
pub fn type_name(&self) -> String {
match self {
Self::Then { .. } => "then_t".to_string(),
Self::UponError { .. } => "upon_error_t".to_string(),
Self::UponStopped { .. } => "upon_stopped_t".to_string(),
Self::LetValue { .. } => "let_value_t".to_string(),
Self::LetError { .. } => "let_error_t".to_string(),
Self::LetStopped { .. } => "let_stopped_t".to_string(),
Self::Bulk { .. } => "bulk_t".to_string(),
Self::Split => "split_t".to_string(),
Self::WhenAll { .. } => "when_all_t".to_string(),
Self::Transfer { .. } => "transfer_t".to_string(),
Self::TransferJust { .. } => "transfer_just_t".to_string(),
Self::StartOn { .. } => "start_on_t".to_string(),
Self::On { .. } => "on_t".to_string(),
Self::IntoVariant => "into_variant_t".to_string(),
Self::EnsureStarted => "ensure_started_t".to_string(),
}
}
pub fn input_arity(&self) -> usize {
match self {
Self::WhenAll { sender_count } => *sender_count,
Self::Split => 1,
_ => 1,
}
}
}
#[derive(Debug, Clone)]
pub struct ReceiverDescriptor {
pub name: String,
pub value_handler: Option<String>,
pub error_handler: Option<String>,
pub stopped_handler: Option<String>,
}
impl ReceiverDescriptor {
pub fn with_value_handler(name: &str, handler: &str) -> Self {
Self {
name: name.to_string(),
value_handler: Some(handler.to_string()),
error_handler: None,
stopped_handler: None,
}
}
pub fn full(
name: &str,
value_handler: &str,
error_handler: &str,
stopped_handler: &str,
) -> Self {
Self {
name: name.to_string(),
value_handler: Some(value_handler.to_string()),
error_handler: Some(error_handler.to_string()),
stopped_handler: Some(stopped_handler.to_string()),
}
}
}
#[derive(Debug, Clone)]
pub struct SyncWait {
pub sender_type: String,
pub result_type: String,
pub timeout_ms: Option<u64>,
}
impl SyncWait {
pub fn new(sender_type: &str, result_type: &str) -> Self {
Self {
sender_type: sender_type.to_string(),
result_type: result_type.to_string(),
timeout_ms: None,
}
}
pub fn generate(&self) -> String {
format!(
"auto result = std::this_thread::sync_wait({});",
self.sender_type
)
}
}
#[derive(Debug, Clone)]
pub struct SchedulerDescriptor {
pub name: String,
pub scheduler_type: SchedulerType,
pub concurrency: usize,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SchedulerType {
Inline,
ThreadPool,
SingleThread,
System,
}
impl SchedulerType {
pub fn from_str(s: &str) -> Option<Self> {
match s {
"inline" => Some(Self::Inline),
"thread_pool" => Some(Self::ThreadPool),
"single" => Some(Self::SingleThread),
"system" => Some(Self::System),
_ => None,
}
}
}
impl SchedulerDescriptor {
pub fn inline_scheduler() -> Self {
Self {
name: "inline_scheduler".to_string(),
scheduler_type: SchedulerType::Inline,
concurrency: 1,
}
}
pub fn thread_pool(concurrency: usize) -> Self {
Self {
name: "thread_pool".to_string(),
scheduler_type: SchedulerType::ThreadPool,
concurrency,
}
}
}
#[derive(Debug, Clone)]
pub struct ExecutionContext {
pub scheduler: SchedulerDescriptor,
pub active_senders: Vec<SenderDescriptor>,
pub adaptors: Vec<SenderAdaptor>,
}
impl ExecutionContext {
pub fn new(scheduler: SchedulerDescriptor) -> Self {
Self {
scheduler,
active_senders: Vec::new(),
adaptors: Vec::new(),
}
}
pub fn then(&mut self, function: &str, input_type: &str, output_type: &str) {
self.adaptors.push(SenderAdaptor::Then {
function: function.to_string(),
input_type: input_type.to_string(),
output_type: output_type.to_string(),
});
}
pub fn upon_error(&mut self, function: &str, error_type: &str) {
self.adaptors.push(SenderAdaptor::UponError {
function: function.to_string(),
error_type: error_type.to_string(),
});
}
pub fn generate_chain(&self) -> String {
let mut chain = "just(42)".to_string();
for adaptor in &self.adaptors {
match adaptor {
SenderAdaptor::Then { function, .. } => {
chain = format!("{} | then({})", chain, function);
}
SenderAdaptor::UponError { function, .. } => {
chain = format!("{} | upon_error({})", chain, function);
}
SenderAdaptor::UponStopped { function } => {
chain = format!("{} | upon_stopped({})", chain, function);
}
_ => {
chain = format!("{} | {}", chain, adaptor.type_name());
}
}
}
chain
}
}
#[derive(Debug, Clone)]
pub struct HazardPointer {
pub index: usize,
pub protected_address: Option<u64>,
pub is_active: bool,
}
impl HazardPointer {
pub fn new(index: usize) -> Self {
Self {
index,
protected_address: None,
is_active: false,
}
}
pub fn protect(&mut self, address: u64) {
self.protected_address = Some(address);
self.is_active = true;
}
pub fn reset(&mut self) {
self.protected_address = None;
self.is_active = false;
}
pub fn is_protecting(&self) -> bool {
self.is_active && self.protected_address.is_some()
}
pub fn address(&self) -> Option<u64> {
self.protected_address
}
}
#[derive(Debug, Clone)]
pub struct HazardPointerDomain {
pub pointers: Vec<HazardPointer>,
pub max_pointers: usize,
pub retired_list: Vec<RetiredObject>,
}
#[derive(Debug, Clone)]
pub struct RetiredObject {
pub address: u64,
pub retire_time: u64,
pub reclaim_fn: String,
}
impl HazardPointerDomain {
pub fn new(max_pointers: usize) -> Self {
let pointers: Vec<HazardPointer> = (0..max_pointers).map(HazardPointer::new).collect();
Self {
pointers,
max_pointers,
retired_list: Vec::new(),
}
}
pub fn acquire(&mut self) -> Option<usize> {
for (i, hp) in self.pointers.iter_mut().enumerate() {
if !hp.is_active {
hp.is_active = true;
return Some(i);
}
}
None
}
pub fn release(&mut self, index: usize) {
if index < self.pointers.len() {
self.pointers[index].reset();
}
}
pub fn retire(&mut self, address: u64, reclaim_fn: &str) {
self.retired_list.push(RetiredObject {
address,
retire_time: 0,
reclaim_fn: reclaim_fn.to_string(),
});
}
pub fn reclaim(&mut self) -> usize {
let protected_addrs: Vec<u64> = self
.pointers
.iter()
.filter_map(|hp| hp.protected_address)
.collect();
let mut keep = Vec::new();
let mut reclaimed = 0;
for obj in &self.retired_list {
if protected_addrs.contains(&obj.address) {
keep.push(obj.clone());
} else {
reclaimed += 1;
}
}
self.retired_list = keep;
reclaimed
}
pub fn active_count(&self) -> usize {
self.pointers.iter().filter(|hp| hp.is_active).count()
}
pub fn retired_count(&self) -> usize {
self.retired_list.len()
}
}
#[derive(Debug, Clone)]
pub struct HazardPointerRegistry {
pub domains: HashMap<String, HazardPointerDomain>,
pub max_per_domain: usize,
}
impl HazardPointerRegistry {
pub fn new(max_per_domain: usize) -> Self {
Self {
domains: HashMap::new(),
max_per_domain,
}
}
pub fn domain_for(&mut self, thread_id: &str) -> &mut HazardPointerDomain {
self.domains
.entry(thread_id.to_string())
.or_insert_with(|| HazardPointerDomain::new(self.max_per_domain))
}
pub fn total_active(&self) -> usize {
self.domains.values().map(|d| d.active_count()).sum()
}
}
#[derive(Debug, Clone)]
pub struct RcuDomain {
pub id: u64,
pub generation: u64,
pub callbacks: Vec<RcuCallback>,
pub grace_period_active: bool,
}
#[derive(Debug, Clone)]
pub struct RcuCallback {
pub id: u64,
pub data_address: u64,
pub callback_fn: String,
pub registered_generation: u64,
}
impl RcuDomain {
pub fn new(id: u64) -> Self {
Self {
id,
generation: 0,
callbacks: Vec::new(),
grace_period_active: false,
}
}
pub fn rcu_read_lock(&self) -> RcuReadGuard {
RcuReadGuard {
domain_id: self.id,
generation: self.generation,
}
}
pub fn synchronize_rcu(&mut self) {
self.generation = self.generation.wrapping_add(1);
}
pub fn call_rcu(&mut self, data_address: u64, callback_fn: &str) {
self.callbacks.push(RcuCallback {
id: self.callbacks.len() as u64,
data_address,
callback_fn: callback_fn.to_string(),
registered_generation: self.generation,
});
}
pub fn process_callbacks(&mut self, current_generation: u64) -> Vec<RcuCallback> {
let (ready, pending): (Vec<_>, Vec<_>) = self
.callbacks
.drain(..)
.partition(|cb| cb.registered_generation < current_generation);
self.callbacks = pending;
ready
}
pub fn is_reader_active(&self) -> bool {
self.grace_period_active
}
}
#[derive(Debug, Clone)]
pub struct RcuReadGuard {
pub domain_id: u64,
pub generation: u64,
}
impl RcuReadGuard {
pub fn generation(&self) -> u64 {
self.generation
}
}
#[derive(Debug, Clone)]
pub struct RcuProtected<T: Clone> {
pub data: T,
pub domain: RcuDomain,
pub update_pending: bool,
}
impl<T: Clone> RcuProtected<T> {
pub fn new(data: T, domain_id: u64) -> Self {
Self {
data,
domain: RcuDomain::new(domain_id),
update_pending: false,
}
}
pub fn read(&self) -> &T {
&self.data
}
pub fn update(&mut self, new_data: T) {
let old_data = std::mem::replace(&mut self.data, new_data);
let _ = old_data;
self.domain.synchronize_rcu();
self.update_pending = false;
}
}
#[derive(Debug, Clone)]
pub enum SubmdspanSlice {
Index(usize),
FullExtent,
Range(usize, usize),
StridedSlice { offset: usize, extent: usize, stride: usize },
AllBut(usize),
}
impl SubmdspanSlice {
pub fn from_str(s: &str) -> Option<Self> {
if s == "_" || s == "full_extent" {
Some(Self::FullExtent)
} else if let Ok(idx) = s.parse::<usize>() {
Some(Self::Index(idx))
} else if s.starts_with("range(") {
let inner = s.trim_start_matches("range(").trim_end_matches(')');
let parts: Vec<&str> = inner.split(',').collect();
if parts.len() == 2 {
let start = parts[0].trim().parse().ok()?;
let end = parts[1].trim().parse().ok()?;
Some(Self::Range(start, end))
} else {
None
}
} else {
None
}
}
pub fn to_cpp(&self) -> String {
match self {
Self::Index(i) => i.to_string(),
Self::FullExtent => "std::full_extent".to_string(),
Self::Range(start, end) => format!("std::pair{{{}, {}}}", start, end),
Self::StridedSlice {
offset,
extent,
stride,
} => format!(
"std::strided_slice{{{}, {}, {}}}",
offset, extent, stride
),
Self::AllBut(n) => format!("std::all_but<{}>()", n),
}
}
}
#[derive(Debug, Clone)]
pub struct SubmdspanOp {
pub source: String,
pub element_type: String,
pub slices: Vec<SubmdspanSlice>,
pub source_rank: usize,
pub result_rank: usize,
}
impl SubmdspanOp {
pub fn new(source: &str, element_type: &str, source_rank: usize) -> Self {
Self {
source: source.to_string(),
element_type: element_type.to_string(),
slices: Vec::new(),
source_rank,
result_rank: source_rank,
}
}
pub fn add_slice(&mut self, slice: SubmdspanSlice) {
match &slice {
SubmdspanSlice::Index(_) => self.result_rank -= 1,
_ => {}
}
self.slices.push(slice);
}
pub fn generate(&self) -> String {
let slices_str: Vec<String> = self.slices.iter().map(|s| s.to_cpp()).collect();
format!(
"auto sub = std::submdspan({}, {});",
self.source,
slices_str.join(", ")
)
}
pub fn result_extents(&self, source_extents: &[usize]) -> Vec<usize> {
let mut result = Vec::new();
for (i, (extent, slice)) in source_extents
.iter()
.zip(self.slices.iter().chain(std::iter::repeat(&SubmdspanSlice::FullExtent)))
.enumerate()
{
match slice {
SubmdspanSlice::Index(_) => {
}
SubmdspanSlice::FullExtent => {
result.push(*extent);
}
SubmdspanSlice::Range(start, end) => {
result.push(end - start);
}
SubmdspanSlice::StridedSlice {
extent: slice_extent, ..
} => {
result.push(*slice_extent);
}
SubmdspanSlice::AllBut(n) => {
if i != *n {
result.push(*extent);
}
}
}
}
result
}
}
#[derive(Debug, Clone)]
pub enum MdspanLayout {
LayoutRight,
LayoutLeft,
LayoutStride,
}
impl MdspanLayout {
pub fn to_cpp(&self) -> String {
match self {
Self::LayoutRight => "std::layout_right".to_string(),
Self::LayoutLeft => "std::layout_left".to_string(),
Self::LayoutStride => "std::layout_stride".to_string(),
}
}
pub fn is_strided(&self) -> bool {
matches!(self, Self::LayoutStride)
}
}
#[derive(Debug, Clone)]
pub struct SimdType {
pub scalar_type: String,
pub size: usize,
pub abi_tag: String,
}
impl SimdType {
pub fn new(scalar_type: &str, size: usize) -> Self {
Self {
scalar_type: scalar_type.to_string(),
size,
abi_tag: "std::simd_abi::native".to_string(),
}
}
pub fn type_name(&self) -> String {
format!("std::simd<{}, {}>", self.scalar_type, self.size)
}
pub fn mask_type(&self) -> String {
format!("std::simd_mask<{}, {}>", self.scalar_type, self.size)
}
}
#[derive(Debug, Clone)]
pub enum SimdMathOp {
Frexp,
Ldexp,
Logb,
Modf,
Remquo,
Nextafter,
Copysign,
Fdim,
Fma,
Hypot,
Sin,
Cos,
Tan,
Asin,
Acos,
Atan,
Atan2,
Sinh,
Cosh,
Tanh,
Exp,
Exp2,
Expm1,
Log,
Log2,
Log10,
Log1p,
Pow,
Sqrt,
Cbrt,
Erf,
Erfc,
Tgamma,
Lgamma,
Ceil,
Floor,
Trunc,
Round,
Abs,
}
impl SimdMathOp {
pub fn function_name(&self) -> &'static str {
match self {
Self::Frexp => "frexp",
Self::Ldexp => "ldexp",
Self::Logb => "logb",
Self::Modf => "modf",
Self::Remquo => "remquo",
Self::Nextafter => "nextafter",
Self::Copysign => "copysign",
Self::Fdim => "fdim",
Self::Fma => "fma",
Self::Hypot => "hypot",
Self::Sin => "sin",
Self::Cos => "cos",
Self::Tan => "tan",
Self::Asin => "asin",
Self::Acos => "acos",
Self::Atan => "atan",
Self::Atan2 => "atan2",
Self::Sinh => "sinh",
Self::Cosh => "cosh",
Self::Tanh => "tanh",
Self::Exp => "exp",
Self::Exp2 => "exp2",
Self::Expm1 => "expm1",
Self::Log => "log",
Self::Log2 => "log2",
Self::Log10 => "log10",
Self::Log1p => "log1p",
Self::Pow => "pow",
Self::Sqrt => "sqrt",
Self::Cbrt => "cbrt",
Self::Erf => "erf",
Self::Erfc => "erfc",
Self::Tgamma => "tgamma",
Self::Lgamma => "lgamma",
Self::Ceil => "ceil",
Self::Floor => "floor",
Self::Trunc => "trunc",
Self::Round => "round",
Self::Abs => "abs",
}
}
pub fn arity(&self) -> usize {
match self {
Self::Fma | Self::Atan2 | Self::Remquo => 3,
Self::Frexp | Self::Ldexp | Self::Modf | Self::Hypot
| Self::Pow | Self::Nextafter | Self::Copysign | Self::Fdim => 2,
_ => 1,
}
}
pub fn available_for_integer(&self) -> bool {
matches!(self, Self::Abs | Self::Copysign)
}
pub fn generate_call(&self, simd_type: &SimdType) -> String {
match self.arity() {
1 => format!(
"std::simd_{}({} a)",
self.function_name(),
simd_type.type_name()
),
2 => format!(
"std::simd_{}({} a, {} b)",
self.function_name(),
simd_type.type_name(),
simd_type.type_name()
),
3 => format!(
"std::simd_{}({} a, {} b, {} c)",
self.function_name(),
simd_type.type_name(),
simd_type.type_name(),
simd_type.type_name()
),
_ => String::new(),
}
}
}
#[derive(Debug, Clone)]
pub struct SimdMathRegistry {
pub supported_ops: Vec<SimdMathOp>,
pub simd_type: SimdType,
pub has_float_support: bool,
pub has_integer_support: bool,
}
impl SimdMathRegistry {
pub fn new(simd_type: SimdType) -> Self {
let scalar_is_float = matches!(
simd_type.scalar_type.as_str(),
"float" | "double" | "long double"
);
let mut ops = vec![
SimdMathOp::Abs,
SimdMathOp::Fma,
SimdMathOp::Sqrt,
SimdMathOp::Ceil,
SimdMathOp::Floor,
SimdMathOp::Trunc,
SimdMathOp::Round,
SimdMathOp::Copysign,
SimdMathOp::Fdim,
SimdMathOp::Hypot,
SimdMathOp::Pow,
];
if scalar_is_float {
ops.extend_from_slice(&[
SimdMathOp::Frexp,
SimdMathOp::Ldexp,
SimdMathOp::Logb,
SimdMathOp::Modf,
SimdMathOp::Remquo,
SimdMathOp::Nextafter,
SimdMathOp::Sin,
SimdMathOp::Cos,
SimdMathOp::Tan,
SimdMathOp::Asin,
SimdMathOp::Acos,
SimdMathOp::Atan,
SimdMathOp::Atan2,
SimdMathOp::Sinh,
SimdMathOp::Cosh,
SimdMathOp::Tanh,
SimdMathOp::Exp,
SimdMathOp::Exp2,
SimdMathOp::Expm1,
SimdMathOp::Log,
SimdMathOp::Log2,
SimdMathOp::Log10,
SimdMathOp::Log1p,
SimdMathOp::Erf,
SimdMathOp::Erfc,
SimdMathOp::Tgamma,
SimdMathOp::Lgamma,
]);
}
Self {
supported_ops: ops,
simd_type,
has_float_support: scalar_is_float,
has_integer_support: !scalar_is_float,
}
}
pub fn available_ops(&self) -> Vec<&SimdMathOp> {
self.supported_ops.iter().collect()
}
pub fn supports(&self, op: SimdMathOp) -> bool {
self.supported_ops.contains(&op)
}
pub fn op_count(&self) -> usize {
self.supported_ops.len()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum LinalgOp {
MatrixProduct,
MatrixVectorProduct,
SymmetricMatrixProduct,
HermitianMatrixProduct,
TriangularMatrixProduct,
TriangularMatrixSolve,
Rank1Update,
RankKUpdate,
Rank2KUpdate,
Dot,
Norm2,
Norm1,
NormInf,
MatrixNorm1,
MatrixNormInf,
MatrixNormFrobenius,
Asum,
Scal,
Copy,
Swap,
Axpy,
Rotg,
Rot,
Rotm,
}
impl LinalgOp {
pub fn name(&self) -> &'static str {
match self {
Self::MatrixProduct => "matrix_product",
Self::MatrixVectorProduct => "matrix_vector_product",
Self::SymmetricMatrixProduct => "symmetric_matrix_product",
Self::HermitianMatrixProduct => "hermitian_matrix_product",
Self::TriangularMatrixProduct => "triangular_matrix_product",
Self::TriangularMatrixSolve => "triangular_matrix_solve",
Self::Rank1Update => "rank1_update",
Self::RankKUpdate => "rank_k_update",
Self::Rank2KUpdate => "rank2k_update",
Self::Dot => "dot",
Self::Norm2 => "vector_norm2",
Self::Norm1 => "vector_norm1",
Self::NormInf => "vector_norm_inf",
Self::MatrixNorm1 => "matrix_norm1",
Self::MatrixNormInf => "matrix_norm_inf",
Self::MatrixNormFrobenius => "matrix_norm_frobenius",
Self::Asum => "vector_sum_of_abs",
Self::Scal => "scal",
Self::Copy => "copy",
Self::Swap => "swap_elements",
Self::Axpy => "add_scaled",
Self::Rotg => "rotg",
Self::Rot => "rot",
Self::Rotm => "rotm",
}
}
pub fn is_blas1(&self) -> bool {
matches!(
self,
Self::Dot
| Self::Norm2
| Self::Norm1
| Self::NormInf
| Self::Asum
| Self::Scal
| Self::Copy
| Self::Swap
| Self::Axpy
| Self::Rotg
| Self::Rot
| Self::Rotm
)
}
pub fn is_blas2(&self) -> bool {
matches!(
self,
Self::MatrixVectorProduct | Self::TriangularMatrixSolve | Self::Rank1Update
)
}
pub fn is_blas3(&self) -> bool {
matches!(
self,
Self::MatrixProduct
| Self::SymmetricMatrixProduct
| Self::HermitianMatrixProduct
| Self::TriangularMatrixProduct
| Self::RankKUpdate
| Self::Rank2KUpdate
)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MatrixLayout {
ColumnMajor,
RowMajor,
}
impl MatrixLayout {
pub fn transpose(&self) -> Self {
match self {
Self::ColumnMajor => Self::RowMajor,
Self::RowMajor => Self::ColumnMajor,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Triangle {
Upper,
Lower,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum DiagonalStorage {
Unit,
NonUnit,
ExplicitUnit,
}
#[derive(Debug, Clone)]
pub struct LinalgConfig {
pub op: LinalgOp,
pub element_type: String,
pub layout: MatrixLayout,
pub triangle: Option<Triangle>,
pub diag: Option<DiagonalStorage>,
pub alpha: Option<String>,
pub beta: Option<String>,
pub m: usize,
pub n: usize,
pub k: usize,
pub lda: usize,
pub ldb: usize,
pub ldc: usize,
}
impl LinalgConfig {
pub fn matrix_product(
element_type: &str,
layout: MatrixLayout,
m: usize,
n: usize,
k: usize,
) -> Self {
Self {
op: LinalgOp::MatrixProduct,
element_type: element_type.to_string(),
layout,
triangle: None,
diag: None,
alpha: None,
beta: None,
m,
n,
k,
lda: if layout == MatrixLayout::ColumnMajor { m } else { k },
ldb: if layout == MatrixLayout::ColumnMajor { k } else { n },
ldc: if layout == MatrixLayout::ColumnMajor { m } else { m },
}
}
pub fn with_scalars(mut self, alpha: &str, beta: &str) -> Self {
self.alpha = Some(alpha.to_string());
self.beta = Some(beta.to_string());
self
}
pub fn generate(&self) -> String {
let layout_str = match self.layout {
MatrixLayout::ColumnMajor => "std::linalg::column_major",
MatrixLayout::RowMajor => "std::linalg::row_major",
};
format!(
"std::linalg::{}({}, A, B, C)",
self.op.name(),
layout_str
)
}
}
#[derive(Debug, Clone)]
pub struct LinalgRegistry {
pub operations: Vec<LinalgConfig>,
pub supported_types: Vec<String>,
pub blas_level1_count: usize,
pub blas_level2_count: usize,
pub blas_level3_count: usize,
}
impl LinalgRegistry {
pub fn default_registry() -> Self {
let float_types = vec![
"float".to_string(),
"double".to_string(),
"std::complex<float>".to_string(),
"std::complex<double>".to_string(),
];
let mut ops = Vec::new();
for t in &float_types {
ops.push(LinalgConfig::matrix_product(t, MatrixLayout::ColumnMajor, 16, 16, 16));
ops.push(LinalgConfig {
op: LinalgOp::Dot,
element_type: t.clone(),
layout: MatrixLayout::ColumnMajor,
triangle: None,
diag: None,
alpha: None,
beta: None,
m: 16,
n: 1,
k: 0,
lda: 16,
ldb: 0,
ldc: 0,
});
}
Self {
operations: ops,
supported_types: float_types,
blas_level1_count: 12,
blas_level2_count: 3,
blas_level3_count: 6,
}
}
pub fn total_ops(&self) -> usize {
self.operations.len()
}
}
#[derive(Debug, Clone)]
pub struct InplaceVector<T: Clone> {
pub capacity: usize,
pub size: usize,
pub elements: Vec<Option<T>>,
}
impl<T: Clone> InplaceVector<T> {
pub fn new(capacity: usize) -> Self {
Self {
capacity,
size: 0,
elements: vec![None; capacity],
}
}
pub fn push_back(&mut self, value: T) -> bool {
if self.size >= self.capacity {
return false;
}
self.elements[self.size] = Some(value);
self.size += 1;
true
}
pub fn pop_back(&mut self) -> Option<T> {
if self.size == 0 {
return None;
}
self.size -= 1;
self.elements[self.size].take()
}
pub fn get(&self, index: usize) -> Option<&T> {
if index < self.size {
self.elements[index].as_ref()
} else {
None
}
}
pub fn get_mut(&mut self, index: usize) -> Option<&mut T> {
if index < self.size {
self.elements[index].as_mut()
} else {
None
}
}
pub fn clear(&mut self) {
for i in 0..self.size {
self.elements[i] = None;
}
self.size = 0;
}
pub fn is_empty(&self) -> bool {
self.size == 0
}
pub fn is_full(&self) -> bool {
self.size == self.capacity
}
pub fn insert(&mut self, index: usize, value: T) -> bool {
if self.size >= self.capacity || index > self.size {
return false;
}
for i in (index..self.size).rev() {
self.elements[i + 1] = self.elements[i].take();
}
self.elements[index] = Some(value);
self.size += 1;
true
}
pub fn erase(&mut self, index: usize) -> Option<T> {
if index >= self.size {
return None;
}
let erased = self.elements[index].take();
for i in index..self.size - 1 {
self.elements[i] = self.elements[i + 1].take();
}
self.elements[self.size - 1] = None;
self.size -= 1;
erased
}
pub fn try_emplace_back(&mut self, value: T) -> Result<(), &'static str> {
if self.push_back(value) {
Ok(())
} else {
Err("inplace_vector is full")
}
}
pub unsafe fn unchecked_push(&mut self, value: T) {
self.elements[self.size] = Some(value);
self.size += 1;
}
pub fn try_push_back(&mut self, value: T) -> Result<(), T> {
if self.size >= self.capacity {
return Err(value);
}
self.elements[self.size] = Some(value);
self.size += 1;
Ok(())
}
pub fn reserve(&mut self, _additional: usize) {
}
pub fn resize(&mut self, new_size: usize, value: T) -> bool {
if new_size > self.capacity {
return false;
}
while self.size < new_size {
self.elements[self.size] = Some(value.clone());
self.size += 1;
}
while self.size > new_size {
self.pop_back();
}
true
}
}
#[derive(Debug, Clone)]
pub struct InplaceVectorIter<'a, T: Clone> {
vec: &'a InplaceVector<T>,
position: usize,
}
impl<'a, T: Clone> InplaceVectorIter<'a, T> {
pub fn new(vec: &'a InplaceVector<T>) -> Self {
Self { vec, position: 0 }
}
pub fn next(&mut self) -> Option<&T> {
if self.position < self.vec.size {
let val = self.vec.elements[self.position].as_ref();
self.position += 1;
val
} else {
None
}
}
pub fn has_next(&self) -> bool {
self.position < self.vec.size
}
}
#[derive(Debug, Clone)]
pub struct HiveElement<T: Clone> {
pub value: T,
pub is_active: bool,
pub next_free: Option<usize>,
}
#[derive(Debug, Clone)]
pub struct HiveBucket<T: Clone> {
pub elements: Vec<HiveElement<T>>,
pub capacity: usize,
pub active_count: usize,
}
impl<T: Clone> HiveBucket<T> {
pub fn new(capacity: usize) -> Self {
Self {
elements: Vec::with_capacity(capacity),
capacity,
active_count: 0,
}
}
pub fn insert(&mut self, value: T) -> Option<usize> {
if self.active_count >= self.capacity {
return None;
}
self.elements.push(HiveElement {
value,
is_active: true,
next_free: None,
});
let idx = self.elements.len() - 1;
self.active_count += 1;
Some(idx)
}
pub fn erase(&mut self, index: usize) -> bool {
if index >= self.elements.len() || !self.elements[index].is_active {
return false;
}
self.elements[index].is_active = false;
self.active_count -= 1;
true
}
pub fn is_full(&self) -> bool {
self.active_count >= self.capacity
}
pub fn is_empty(&self) -> bool {
self.active_count == 0
}
}
#[derive(Debug, Clone)]
pub struct Hive<T: Clone> {
pub buckets: Vec<HiveBucket<T>>,
pub bucket_capacity: usize,
pub total_elements: usize,
}
impl<T: Clone> Hive<T> {
pub fn new(bucket_capacity: usize) -> Self {
Self {
buckets: vec![HiveBucket::new(bucket_capacity)],
bucket_capacity,
total_elements: 0,
}
}
pub fn insert(&mut self, value: T) -> HiveIterator {
for bucket in &mut self.buckets {
if !bucket.is_full() {
let idx = bucket.insert(value).unwrap();
self.total_elements += 1;
return HiveIterator {
bucket_index: 0,
element_index: idx,
};
}
}
let mut new_bucket = HiveBucket::new(self.bucket_capacity);
let idx = new_bucket.insert(value).unwrap();
self.buckets.push(new_bucket);
self.total_elements += 1;
HiveIterator {
bucket_index: self.buckets.len() - 1,
element_index: idx,
}
}
pub fn erase(&mut self, bucket_index: usize, element_index: usize) -> bool {
if bucket_index >= self.buckets.len() {
return false;
}
if self.buckets[bucket_index].erase(element_index) {
self.total_elements -= 1;
true
} else {
false
}
}
pub fn size(&self) -> usize {
self.total_elements
}
pub fn is_empty(&self) -> bool {
self.total_elements == 0
}
pub fn bucket_count(&self) -> usize {
self.buckets.len()
}
pub fn capacity(&self) -> usize {
self.buckets.len() * self.bucket_capacity
}
pub fn compact(&mut self) {
for bucket in &mut self.buckets {
bucket.elements.retain(|e| e.is_active);
}
self.buckets.retain(|b| !b.is_empty());
}
pub fn to_vec(&self) -> Vec<T> {
self.buckets
.iter()
.flat_map(|b| {
b.elements
.iter()
.filter(|e| e.is_active)
.map(|e| e.value.clone())
})
.collect()
}
}
#[derive(Debug, Clone)]
pub struct HiveIterator {
pub bucket_index: usize,
pub element_index: usize,
}
impl HiveIterator {
pub fn new() -> Self {
Self {
bucket_index: 0,
element_index: 0,
}
}
pub fn is_valid(&self, hive: &Hive<impl Clone>) -> bool {
if self.bucket_index >= hive.buckets.len() {
return false;
}
let bucket = &hive.buckets[self.bucket_index];
if self.element_index >= bucket.elements.len() {
return false;
}
bucket.elements[self.element_index].is_active
}
}
#[derive(Debug, Clone)]
pub struct DebuggingSupport {
pub debugger_present: bool,
pub breakpoint_count: u64,
pub breakpoints_enabled: bool,
pub platform_breakpoint: PlatformBreakpoint,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum PlatformBreakpoint {
X86Int3,
ArmBkpt,
Aarch64Brk,
RiscvEbreak,
Portable,
PpcTrap,
}
impl PlatformBreakpoint {
pub fn for_triple(triple: &str) -> Self {
if triple.contains("x86") || triple.contains("i386") || triple.contains("i686") {
Self::X86Int3
} else if triple.contains("arm") || triple.contains("thumb") {
Self::ArmBkpt
} else if triple.contains("aarch64") {
Self::Aarch64Brk
} else if triple.contains("riscv") {
Self::RiscvEbreak
} else if triple.contains("powerpc") || triple.contains("ppc") {
Self::PpcTrap
} else {
Self::Portable
}
}
pub fn asm_instruction(&self) -> String {
match self {
Self::X86Int3 => "int3".to_string(),
Self::ArmBkpt => "bkpt #0".to_string(),
Self::Aarch64Brk => "brk #0".to_string(),
Self::RiscvEbreak => "ebreak".to_string(),
Self::PpcTrap => "trap".to_string(),
Self::Portable => "__builtin_debugtrap()".to_string(),
}
}
}
impl DebuggingSupport {
pub fn new() -> Self {
Self {
debugger_present: false,
breakpoint_count: 0,
breakpoints_enabled: true,
platform_breakpoint: PlatformBreakpoint::Portable,
}
}
pub fn is_debugger_present(&self) -> bool {
self.debugger_present
}
pub fn set_debugger_present(&mut self, present: bool) {
self.debugger_present = present;
}
pub fn breakpoint_if_debugging(&mut self) -> bool {
if self.breakpoints_enabled && self.debugger_present {
self.breakpoint_count += 1;
true
} else {
false
}
}
pub fn disable_breakpoints(&mut self) {
self.breakpoints_enabled = false;
}
pub fn enable_breakpoints(&mut self) {
self.breakpoints_enabled = true;
}
pub fn generate_breakpoint(&self) -> String {
format!(
"if (std::is_debugger_present()) {{\n {}\n}}",
self.platform_breakpoint.asm_instruction()
)
}
pub fn generate_is_debugger_present_check(&self) -> String {
if cfg!(target_os = "windows") {
"IsDebuggerPresent() != 0".to_string()
} else if cfg!(target_os = "linux") || cfg!(target_os = "macos") {
"std::debugging::__is_debugger_present_impl()".to_string()
} else {
"false".to_string()
}
}
}
impl Default for DebuggingSupport {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum TextEncodingMib {
Ascii = 3,
Utf8 = 106,
Utf16Be = 1013,
Utf16Le = 1014,
Utf32Be = 1017,
Utf32Le = 1018,
Iso8859_1 = 4,
Iso8859_2 = 5,
ShiftJis = 17,
EucJp = 18,
Iso2022Jp = 39,
Gbk = 113,
Gb18030 = 114,
Big5 = 2026,
Windows1252 = 2252,
Koi8R = 2084,
Koi8U = 2088,
Macintosh = 2027,
Ibm850 = 2009,
Ibm866 = 2086,
Other = 29,
Unknown = 0,
}
impl TextEncodingMib {
pub fn from_u32(value: u32) -> Option<Self> {
match value {
3 => Some(Self::Ascii),
106 => Some(Self::Utf8),
1013 => Some(Self::Utf16Be),
1014 => Some(Self::Utf16Le),
1017 => Some(Self::Utf32Be),
1018 => Some(Self::Utf32Le),
4 => Some(Self::Iso8859_1),
5 => Some(Self::Iso8859_2),
17 => Some(Self::ShiftJis),
18 => Some(Self::EucJp),
39 => Some(Self::Iso2022Jp),
113 => Some(Self::Gbk),
114 => Some(Self::Gb18030),
2026 => Some(Self::Big5),
2252 => Some(Self::Windows1252),
2084 => Some(Self::Koi8R),
2088 => Some(Self::Koi8U),
2027 => Some(Self::Macintosh),
2009 => Some(Self::Ibm850),
2086 => Some(Self::Ibm866),
29 => Some(Self::Other),
0 => Some(Self::Unknown),
_ => None,
}
}
pub fn value(&self) -> u32 {
*self as u32
}
pub fn is_unicode(&self) -> bool {
matches!(
self,
Self::Utf8 | Self::Utf16Be | Self::Utf16Le | Self::Utf32Be | Self::Utf32Le
)
}
pub fn is_ascii_compatible(&self) -> bool {
!matches!(
self,
Self::Utf16Be | Self::Utf16Le | Self::Utf32Be | Self::Utf32Le
)
}
}
#[derive(Debug, Clone)]
pub struct TextEncoding {
pub name: String,
pub mib: TextEncodingMib,
pub aliases: Vec<String>,
}
impl TextEncoding {
pub fn from_mib(mib: TextEncodingMib) -> Self {
let (name, aliases) = match mib {
TextEncodingMib::Ascii => ("US-ASCII".to_string(), vec!["ASCII".to_string(), "ANSI_X3.4-1968".to_string(), "iso-ir-6".to_string()]),
TextEncodingMib::Utf8 => ("UTF-8".to_string(), vec!["utf8".to_string(), "unicode-1-1-utf-8".to_string()]),
TextEncodingMib::Utf16Be => ("UTF-16BE".to_string(), vec!["UTF-16".to_string()]),
TextEncodingMib::Utf16Le => ("UTF-16LE".to_string(), vec![]),
TextEncodingMib::Utf32Be => ("UTF-32BE".to_string(), vec!["UTF-32".to_string()]),
TextEncodingMib::Utf32Le => ("UTF-32LE".to_string(), vec![]),
TextEncodingMib::Iso8859_1 => ("ISO-8859-1".to_string(), vec!["Latin-1".to_string(), "latin1".to_string()]),
TextEncodingMib::Iso8859_2 => ("ISO-8859-2".to_string(), vec!["Latin-2".to_string(), "latin2".to_string()]),
TextEncodingMib::ShiftJis => ("Shift_JIS".to_string(), vec!["MS_Kanji".to_string(), "csShiftJIS".to_string()]),
TextEncodingMib::EucJp => ("EUC-JP".to_string(), vec!["Extended_UNIX_Code_Packed_Format_for_Japanese".to_string()]),
TextEncodingMib::Iso2022Jp => ("ISO-2022-JP".to_string(), vec!["csISO2022JP".to_string()]),
TextEncodingMib::Gbk => ("GBK".to_string(), vec!["CP936".to_string(), "MS936".to_string()]),
TextEncodingMib::Gb18030 => ("GB18030".to_string(), vec!["GB18030-2000".to_string()]),
TextEncodingMib::Big5 => ("Big5".to_string(), vec!["csBig5".to_string(), "Big-5".to_string()]),
TextEncodingMib::Windows1252 => ("windows-1252".to_string(), vec!["CP1252".to_string()]),
TextEncodingMib::Koi8R => ("KOI8-R".to_string(), vec!["csKOI8R".to_string()]),
TextEncodingMib::Koi8U => ("KOI8-U".to_string(), vec![]),
TextEncodingMib::Macintosh => ("macintosh".to_string(), vec!["MacRoman".to_string()]),
TextEncodingMib::Ibm850 => ("IBM850".to_string(), vec!["CP850".to_string(), "850".to_string()]),
TextEncodingMib::Ibm866 => ("IBM866".to_string(), vec!["CP866".to_string(), "866".to_string()]),
TextEncodingMib::Other => ("Other".to_string(), vec![]),
TextEncodingMib::Unknown => ("Unknown".to_string(), vec![]),
};
Self { name, mib, aliases }
}
pub fn lookup(name: &str) -> Option<Self> {
let lower = name.to_lowercase();
for mib_val in [3u32, 106, 1013, 1014, 1017, 1018, 4, 5, 17, 18, 39, 113, 114, 2026, 2252, 2084, 2088, 2027, 2009, 2086, 29, 0] {
if let Some(mib) = TextEncodingMib::from_u32(mib_val) {
let enc = Self::from_mib(mib);
if enc.name.to_lowercase() == lower {
return Some(enc);
}
for alias in &enc.aliases {
if alias.to_lowercase() == lower {
return Some(enc);
}
}
}
}
None
}
pub fn mib_value(&self) -> u32 {
self.mib.value()
}
pub fn is_known(&self) -> bool {
!matches!(self.mib, TextEncodingMib::Other | TextEncodingMib::Unknown)
}
pub fn alias_count(&self) -> usize {
self.aliases.len()
}
}
#[derive(Debug, Clone)]
pub struct TextEncodingRegistry {
pub encodings: Vec<TextEncoding>,
pub by_mib: BTreeMap<u32, usize>,
pub by_name: HashMap<String, usize>,
}
impl TextEncodingRegistry {
pub fn full() -> Self {
let mib_values: Vec<u32> = vec![
0, 3, 4, 5, 17, 18, 29, 39, 106, 113, 114, 1013, 1014, 1017, 1018, 2009, 2026, 2027,
2084, 2086, 2088, 2252,
];
let mut encodings = Vec::new();
let mut by_mib = BTreeMap::new();
let mut by_name = HashMap::new();
for (i, &mib_val) in mib_values.iter().enumerate() {
if let Some(mib) = TextEncodingMib::from_u32(mib_val) {
let enc = TextEncoding::from_mib(mib);
by_mib.insert(mib_val, i);
by_name.insert(enc.name.to_lowercase(), i);
for alias in &enc.aliases {
by_name.entry(alias.to_lowercase()).or_insert(i);
}
encodings.push(enc);
}
}
Self {
encodings,
by_mib,
by_name,
}
}
pub fn by_mib(&self, mib: u32) -> Option<&TextEncoding> {
self.by_mib.get(&mib).map(|&i| &self.encodings[i])
}
pub fn by_name(&self, name: &str) -> Option<&TextEncoding> {
self.by_name
.get(&name.to_lowercase())
.map(|&i| &self.encodings[i])
}
pub fn count(&self) -> usize {
self.encodings.len()
}
pub fn unicode_encodings(&self) -> Vec<&TextEncoding> {
self.encodings
.iter()
.filter(|e| e.mib.is_unicode())
.collect()
}
pub fn ascii_compatible_encodings(&self) -> Vec<&TextEncoding> {
self.encodings
.iter()
.filter(|e| e.mib.is_ascii_compatible())
.collect()
}
}
#[derive(Debug, Clone)]
pub struct NonTemplatePack {
pub name: String,
pub element_type: String,
pub size: usize,
}
impl NonTemplatePack {
pub fn new(name: &str, element_type: &str, size: usize) -> Self {
Self {
name: name.to_string(),
element_type: element_type.to_string(),
size,
}
}
pub fn generate_declaration(&self) -> String {
format!("auto {}... auto", self.name)
}
pub fn generate_function(callable: &str, pack_name: &str, body: &str) -> String {
format!(
"auto {}(auto... {}) {{\n {}\n}}",
callable, pack_name, body
)
}
pub fn expand_pack(pack_name: &str, expr: &str) -> String {
expr.replace("$p", &format!("{}...", pack_name))
}
}
#[derive(Debug, Clone)]
pub struct ConstexprAllocation {
pub address: u64,
pub size: usize,
pub alignment: usize,
pub deallocated: bool,
pub constructed_type: String,
}
impl ConstexprAllocation {
pub fn new(size: usize, alignment: usize, constructed_type: &str) -> Self {
Self {
address: 0,
size,
alignment,
deallocated: false,
constructed_type: constructed_type.to_string(),
}
}
pub fn is_aligned(&self) -> bool {
self.address % self.alignment as u64 == 0
}
pub fn deallocate(&mut self) {
self.deallocated = true;
}
pub fn generate_placement_new(&self, buffer_name: &str) -> String {
format!(
"new ({}) {}(/* args */)",
buffer_name, self.constructed_type
)
}
pub fn generate_delete(&self, ptr_name: &str) -> String {
format!("delete {};", ptr_name)
}
}
#[derive(Debug, Clone)]
pub struct ConstexprAllocator {
pub allocations: Vec<ConstexprAllocation>,
pub total_allocated: usize,
pub total_deallocated: usize,
pub leak_detected: bool,
}
impl ConstexprAllocator {
pub fn new() -> Self {
Self {
allocations: Vec::new(),
total_allocated: 0,
total_deallocated: 0,
leak_detected: false,
}
}
pub fn allocate(
&mut self,
size: usize,
alignment: usize,
constructed_type: &str,
) -> &ConstexprAllocation {
let alloc = ConstexprAllocation::new(size, alignment, constructed_type);
self.allocations.push(alloc);
self.total_allocated += size;
self.allocations.last().unwrap()
}
pub fn deallocate(&mut self, address: u64) -> bool {
if let Some(alloc) = self
.allocations
.iter_mut()
.find(|a| a.address == address && !a.deallocated)
{
alloc.deallocate();
self.total_deallocated += alloc.size;
true
} else {
false
}
}
pub fn check_leaks(&self) -> usize {
self.allocations.iter().filter(|a| !a.deallocated).count()
}
pub fn is_sound(&self) -> bool {
self.check_leaks() == 0
}
pub fn currently_allocated(&self) -> usize {
self.total_allocated - self.total_deallocated
}
}
impl Default for ConstexprAllocator {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum CXX26Feature {
Contracts,
Reflection,
PatternMatching,
SendersReceivers,
HazardPointers,
Rcu,
Submdspan,
SimdExtensions,
Linalg,
InplaceVector,
Hive,
Debugging,
TextEncoding,
PacksOutsideTemplates,
ConstexprPlacementNew,
StaticReflection,
MemberPackExpansion,
StructuredBindingPack,
ReduceFunctional,
ScanFunctional,
StencilFunctional,
MatrixFree,
SubmdspanLayoutStride,
}
impl CXX26Feature {
pub fn paper_number(&self) -> &'static str {
match self {
Self::Contracts => "P0542R5 / P2900R0",
Self::Reflection => "P2996R5",
Self::PatternMatching => "P1371R3",
Self::SendersReceivers => "P2300R10",
Self::HazardPointers => "P2530R3",
Self::Rcu => "P2545R4",
Self::Submdspan => "P2630R4",
Self::SimdExtensions => "P1928R9",
Self::Linalg => "P1673R13",
Self::InplaceVector => "P0843R8",
Self::Hive => "P0447R21",
Self::Debugging => "P2546R5",
Self::TextEncoding => "P1885R12",
Self::PacksOutsideTemplates => "P2877R2",
Self::ConstexprPlacementNew => "P2747R2",
Self::StaticReflection => "P2996R5",
Self::MemberPackExpansion => "P2280R4",
Self::StructuredBindingPack => "P1061R6",
Self::ReduceFunctional => "P2322R6",
Self::ScanFunctional => "P3179R1",
Self::StencilFunctional => "P3050R2",
Self::MatrixFree => "P2547R3",
Self::SubmdspanLayoutStride => "P2630R4",
}
}
pub fn feature_name(&self) -> &'static str {
match self {
Self::Contracts => "Contracts",
Self::Reflection => "Static Reflection",
Self::PatternMatching => "Pattern Matching",
Self::SendersReceivers => "Senders/Receivers",
Self::HazardPointers => "Hazard Pointers",
Self::Rcu => "RCU",
Self::Submdspan => "submdspan",
Self::SimdExtensions => "SIMD Math Extensions",
Self::Linalg => "Linear Algebra",
Self::InplaceVector => "inplace_vector",
Self::Hive => "hive Container",
Self::Debugging => "Debugging Support",
Self::TextEncoding => "Text Encoding",
Self::PacksOutsideTemplates => "Packs Outside Templates",
Self::ConstexprPlacementNew => "constexpr Placement New",
Self::StaticReflection => "Static Reflection (full)",
Self::MemberPackExpansion => "Member Pack Expansion",
Self::StructuredBindingPack => "Structured Binding Pack",
Self::ReduceFunctional => "reduce (functional)",
Self::ScanFunctional => "inclusive_scan (functional)",
Self::StencilFunctional => "stencil (functional)",
Self::MatrixFree => "Matrix-free Algorithms",
Self::SubmdspanLayoutStride => "submdspan with layout_stride",
}
}
}
#[derive(Debug, Clone)]
pub struct CXX26FeatureRegistry {
pub features: HashMap<CXX26Feature, bool>,
pub standard: CXXStandardVersion,
}
impl CXX26FeatureRegistry {
pub fn new(standard: CXXStandardVersion) -> Self {
let mut features = HashMap::new();
for feature in &CXX26Feature::ALL_FEATURES {
let enabled = match standard {
CXXStandardVersion::CXX26 => true,
CXXStandardVersion::CXX23 => {
matches!(
feature,
CXX26Feature::ConstexprPlacementNew
| CXX26Feature::InplaceVector
| CXX26Feature::Submdspan
| CXX26Feature::SimdExtensions
)
}
_ => false,
};
features.insert(*feature, enabled);
}
Self {
features,
standard,
}
}
pub fn is_enabled(&self, feature: CXX26Feature) -> bool {
self.features.get(&feature).copied().unwrap_or(false)
}
pub fn enable(&mut self, feature: CXX26Feature) {
self.features.insert(feature, true);
}
pub fn disable(&mut self, feature: CXX26Feature) {
self.features.insert(feature, false);
}
pub fn standard(&self) -> CXXStandardVersion {
self.standard
}
pub fn enabled_count(&self) -> usize {
self.features.values().filter(|&&v| v).count()
}
pub fn feature_count(&self) -> usize {
self.features.len()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum CXXStandardVersion {
CXX17,
CXX20,
CXX23,
CXX26,
}
impl CXXStandardVersion {
pub fn from_str(s: &str) -> Option<Self> {
match s {
"c++17" | "c++1z" | "gnu++17" => Some(Self::CXX17),
"c++20" | "c++2a" | "gnu++20" => Some(Self::CXX20),
"c++23" | "c++2b" | "gnu++23" => Some(Self::CXX23),
"c++26" | "c++2c" | "gnu++26" => Some(Self::CXX26),
_ => None,
}
}
pub fn as_str(&self) -> &'static str {
match self {
Self::CXX17 => "c++17",
Self::CXX20 => "c++20",
Self::CXX23 => "c++23",
Self::CXX26 => "c++26",
}
}
pub fn is_at_least(&self, other: Self) -> bool {
*self as u8 >= other as u8
}
}
impl CXX26Feature {
pub const ALL_FEATURES: &'static [CXX26Feature] = &[
CXX26Feature::Contracts,
CXX26Feature::Reflection,
CXX26Feature::PatternMatching,
CXX26Feature::SendersReceivers,
CXX26Feature::HazardPointers,
CXX26Feature::Rcu,
CXX26Feature::Submdspan,
CXX26Feature::SimdExtensions,
CXX26Feature::Linalg,
CXX26Feature::InplaceVector,
CXX26Feature::Hive,
CXX26Feature::Debugging,
CXX26Feature::TextEncoding,
CXX26Feature::PacksOutsideTemplates,
CXX26Feature::ConstexprPlacementNew,
CXX26Feature::StaticReflection,
CXX26Feature::MemberPackExpansion,
CXX26Feature::StructuredBindingPack,
CXX26Feature::ReduceFunctional,
CXX26Feature::ScanFunctional,
CXX26Feature::StencilFunctional,
CXX26Feature::MatrixFree,
CXX26Feature::SubmdspanLayoutStride,
];
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_contract_kind_is_audit() {
assert!(ContractKind::PreconditionAudit.is_audit());
assert!(ContractKind::PostconditionAudit.is_audit());
assert!(ContractKind::AssertAudit.is_audit());
assert!(!ContractKind::Precondition.is_audit());
assert!(!ContractKind::Postcondition.is_audit());
assert!(!ContractKind::Assert.is_audit());
}
#[test]
fn test_contract_kind_is_precondition() {
assert!(ContractKind::Precondition.is_precondition());
assert!(ContractKind::PreconditionAudit.is_precondition());
assert!(!ContractKind::Postcondition.is_precondition());
assert!(!ContractKind::Assert.is_precondition());
}
#[test]
fn test_contract_semantic_from_str() {
assert_eq!(
ContractSemantic::from_str("default"),
Some(ContractSemantic::Default)
);
assert_eq!(
ContractSemantic::from_str("audit"),
Some(ContractSemantic::Audit)
);
assert_eq!(
ContractSemantic::from_str("axiom"),
Some(ContractSemantic::Axiom)
);
assert_eq!(ContractSemantic::from_str("nonexistent"), None);
}
#[test]
fn test_contract_build_level_off() {
let level = ContractBuildLevel::Off;
assert!(!ContractSemantic::Default.is_checked_at_runtime(level));
assert!(!ContractSemantic::Audit.is_checked_at_runtime(level));
assert!(!ContractSemantic::Axiom.is_checked_at_runtime(level));
}
#[test]
fn test_contract_build_level_default() {
let level = ContractBuildLevel::Default;
assert!(ContractSemantic::Default.is_checked_at_runtime(level));
assert!(!ContractSemantic::Audit.is_checked_at_runtime(level));
assert!(!ContractSemantic::Axiom.is_checked_at_runtime(level));
}
#[test]
fn test_contract_build_level_audit() {
let level = ContractBuildLevel::Audit;
assert!(ContractSemantic::Default.is_checked_at_runtime(level));
assert!(ContractSemantic::Audit.is_checked_at_runtime(level));
assert!(!ContractSemantic::Axiom.is_checked_at_runtime(level));
}
#[test]
fn test_function_contracts_new() {
let fc = FunctionContracts::new("foo");
assert_eq!(fc.function_name, "foo");
assert_eq!(fc.total_count(), 0);
assert!(fc.all_audit());
}
#[test]
fn test_function_contracts_add_precondition() {
let mut fc = FunctionContracts::new("bar");
fc.add_precondition("x > 0", ContractSemantic::Default);
fc.add_precondition("x < 100", ContractSemantic::Audit);
assert_eq!(fc.preconditions.len(), 2);
assert_eq!(fc.total_count(), 2);
assert!(!fc.all_audit());
}
#[test]
fn test_function_contracts_add_postcondition() {
let mut fc = FunctionContracts::new("baz");
fc.add_postcondition("r", "r > 0", ContractSemantic::Default);
assert_eq!(fc.postconditions.len(), 1);
assert_eq!(fc.total_count(), 1);
assert_eq!(
fc.postconditions[0].result_identifier.as_deref(),
Some("r")
);
}
#[test]
fn test_contract_violation_handler_default() {
let handler = ContractViolationHandler::default_handler();
assert!(handler.terminates);
assert!(!handler.logs);
}
#[test]
fn test_contract_violation_handler_log() {
let handler = ContractViolationHandler::log_handler();
assert!(!handler.terminates);
assert!(handler.logs);
}
#[test]
fn test_contract_build_config_default() {
let config = ContractBuildConfig::default();
assert_eq!(config.level, ContractBuildLevel::Default);
assert!(config.enable_assertions);
}
#[test]
fn test_contract_build_config_off() {
let config = ContractBuildConfig::off();
assert_eq!(config.level, ContractBuildLevel::Off);
}
#[test]
fn test_contract_kind_display() {
assert_eq!(ContractKind::Precondition.to_string(), "pre");
assert_eq!(ContractKind::Postcondition.to_string(), "post");
assert_eq!(ContractKind::Assert.to_string(), "assert");
assert_eq!(ContractKind::PreconditionAudit.to_string(), "pre audit");
assert_eq!(ContractKind::PostconditionAudit.to_string(), "post audit");
assert_eq!(ContractKind::AssertAudit.to_string(), "assert audit");
}
#[test]
fn test_contract_continuation_mode_display() {
assert_eq!(
ContractContinuationMode::NeverContinue.to_string(),
"never_continue"
);
assert_eq!(
ContractContinuationMode::MaybeContinue.to_string(),
"maybe_continue"
);
assert_eq!(
ContractContinuationMode::AlwaysContinue.to_string(),
"always_continue"
);
}
#[test]
fn test_reflection_operator_reflect_type() {
let op = ReflectionOperator::reflect_type("int");
assert_eq!(op.entity, "int");
assert_eq!(op.info.entity_kind, MetaEntityKind::Type);
}
#[test]
fn test_reflection_operator_reflect_class() {
let op = ReflectionOperator::reflect_class("MyClass");
assert_eq!(op.entity, "MyClass");
assert_eq!(op.info.entity_kind, MetaEntityKind::Class);
}
#[test]
fn test_splicer_new() {
let splicer = Splicer::new("members_of(^^MyStruct)");
assert!(splicer.generate().starts_with("[:"));
assert!(splicer.generate().ends_with(":]"));
}
#[test]
fn test_splicer_type_splicer() {
let splicer = Splicer::type_splicer("type_of(^^T)");
assert!(splicer.produces_type());
assert!(!splicer.produces_value());
}
#[test]
fn test_splicer_value_splicer() {
let splicer = Splicer::value_splicer("name_of(^^e)");
assert!(!splicer.produces_type());
assert!(splicer.produces_value());
}
#[test]
fn test_meta_query_generate() {
let q = MetaQuery::NameOf("MyClass".to_string());
assert!(q.generate().contains("name_of"));
assert!(q.generate().contains("MyClass"));
}
#[test]
fn test_meta_query_access_check() {
let q = MetaQuery::AccessCheck("MyMember".to_string(), MetaAccess::Public);
assert!(q.generate().contains("public_access"));
}
#[test]
fn test_reflection_context_new() {
let ctx = ReflectionContext::new();
assert_eq!(ctx.operations.len(), 0);
assert_eq!(ctx.splicers.len(), 0);
assert_eq!(ctx.nesting_depth, 0);
}
#[test]
fn test_reflection_context_add_query() {
let mut ctx = ReflectionContext::new();
ctx.add_query(MetaQuery::NameOf("int".to_string()));
assert_eq!(ctx.operations.len(), 1);
}
#[test]
fn test_reflection_context_generate_enum_to_string() {
let code = ReflectionContext::generate_enum_to_string("Color");
assert!(code.contains("to_string"));
assert!(code.contains("members_of"));
assert!(code.contains("Color"));
}
#[test]
fn test_reflection_context_generate_struct_to_tuple() {
let code = ReflectionContext::generate_struct_to_tuple("Point");
assert!(code.contains("to_tuple"));
assert!(code.contains("members_of"));
assert!(code.contains("Point"));
}
#[test]
fn test_meta_entity_kind_display() {
assert_eq!(MetaEntityKind::Type.to_string(), "type");
assert_eq!(MetaEntityKind::Variable.to_string(), "variable");
assert_eq!(MetaEntityKind::Function.to_string(), "function");
assert_eq!(MetaEntityKind::Class.to_string(), "class");
assert_eq!(MetaEntityKind::Enum.to_string(), "enum");
}
#[test]
fn test_inspect_expression_new() {
let insp = InspectExpression::new("value", "int");
assert_eq!(insp.scrutinee, "value");
assert_eq!(insp.scrutinee_type, "int");
assert!(insp.exhaustive);
}
#[test]
fn test_inspect_expression_add_case() {
let mut insp = InspectExpression::new("x", "int");
insp.add_case(MatchPattern::Literal(MatchLiteral::Integer(0)), "return 1;");
insp.add_case(MatchPattern::Wildcard, "return 0;");
assert_eq!(insp.cases.len(), 2);
}
#[test]
fn test_inspect_expression_generate() {
let mut insp = InspectExpression::new("val", "int");
insp.add_case(MatchPattern::Literal(MatchLiteral::Integer(42)), "std::cout << \"ok\";");
let code = insp.generate();
assert!(code.contains("inspect"));
assert!(code.contains("val"));
assert!(code.contains("42"));
}
#[test]
fn test_exhaustiveness_check_exhaustive() {
let mut insp = InspectExpression::new("x", "bool");
insp.add_case(
MatchPattern::Literal(MatchLiteral::Boolean(true)),
"return 0;",
);
insp.add_case(
MatchPattern::Literal(MatchLiteral::Boolean(false)),
"return 0;",
);
insp.add_case(MatchPattern::Wildcard, "return 0;");
let result = insp.check_exhaustiveness();
assert!(matches!(result, ExhaustivenessResult::Exhaustive));
}
#[test]
fn test_pattern_wildcard_to_string() {
assert_eq!(pattern_to_string(&MatchPattern::Wildcard), "_");
}
#[test]
fn test_pattern_binding_to_string() {
assert_eq!(
pattern_to_string(&MatchPattern::Binding("x".to_string())),
"let x"
);
}
#[test]
fn test_sender_descriptor_just() {
let sender = SenderDescriptor::just(&["int", "double"]);
assert!(sender.is_just);
assert_eq!(sender.value_types.len(), 2);
assert!(sender.always_completes);
}
#[test]
fn test_sender_adaptor_then_type_name() {
let adaptor = SenderAdaptor::Then {
function: "[](int x){ return x*2; }".to_string(),
input_type: "int".to_string(),
output_type: "int".to_string(),
};
assert_eq!(adaptor.type_name(), "then_t");
assert_eq!(adaptor.input_arity(), 1);
}
#[test]
fn test_sender_adaptor_when_all_arity() {
let adaptor = SenderAdaptor::WhenAll { sender_count: 3 };
assert_eq!(adaptor.input_arity(), 3);
}
#[test]
fn test_sync_wait_new() {
let sw = SyncWait::new("my_sender", "int");
assert_eq!(sw.result_type, "int");
assert!(sw.generate().contains("sync_wait"));
}
#[test]
fn test_scheduler_descriptor_inline() {
let sched = SchedulerDescriptor::inline_scheduler();
assert_eq!(sched.scheduler_type, SchedulerType::Inline);
assert_eq!(sched.concurrency, 1);
}
#[test]
fn test_scheduler_descriptor_thread_pool() {
let sched = SchedulerDescriptor::thread_pool(4);
assert_eq!(sched.scheduler_type, SchedulerType::ThreadPool);
assert_eq!(sched.concurrency, 4);
}
#[test]
fn test_execution_context_then_chain() {
let mut ctx = ExecutionContext::new(SchedulerDescriptor::inline_scheduler());
ctx.then("[](int x){ return x*2; }", "int", "int");
let chain = ctx.generate_chain();
assert!(chain.contains("then"));
}
#[test]
fn test_receiver_descriptor_with_value_handler() {
let recv = ReceiverDescriptor::with_value_handler("my_recv", "std::cout << v;");
assert!(recv.value_handler.is_some());
assert!(recv.error_handler.is_none());
}
#[test]
fn test_hazard_pointer_new() {
let hp = HazardPointer::new(0);
assert_eq!(hp.index, 0);
assert!(!hp.is_active);
assert_eq!(hp.protected_address, None);
}
#[test]
fn test_hazard_pointer_protect() {
let mut hp = HazardPointer::new(0);
hp.protect(0xDEAD_BEEF);
assert!(hp.is_active);
assert!(hp.is_protecting());
assert_eq!(hp.address(), Some(0xDEAD_BEEF));
}
#[test]
fn test_hazard_pointer_reset() {
let mut hp = HazardPointer::new(0);
hp.protect(0x1000);
hp.reset();
assert!(!hp.is_active);
assert!(!hp.is_protecting());
}
#[test]
fn test_hazard_pointer_domain_new() {
let domain = HazardPointerDomain::new(4);
assert_eq!(domain.max_pointers, 4);
assert_eq!(domain.pointers.len(), 4);
assert_eq!(domain.active_count(), 0);
}
#[test]
fn test_hazard_pointer_domain_acquire_release() {
let mut domain = HazardPointerDomain::new(2);
let idx0 = domain.acquire().unwrap();
assert_eq!(domain.active_count(), 1);
domain.release(idx0);
assert_eq!(domain.active_count(), 0);
}
#[test]
fn test_hazard_pointer_domain_retire_reclaim() {
let mut domain = HazardPointerDomain::new(2);
domain.retire(0x1000, "default_delete");
assert_eq!(domain.retired_count(), 1);
let reclaimed = domain.reclaim();
assert_eq!(reclaimed, 1);
assert_eq!(domain.retired_count(), 0);
}
#[test]
fn test_hazard_pointer_registry_new() {
let reg = HazardPointerRegistry::new(8);
assert_eq!(reg.max_per_domain, 8);
assert_eq!(reg.total_active(), 0);
}
#[test]
fn test_hazard_pointer_registry_domain_for() {
let mut reg = HazardPointerRegistry::new(4);
let domain = reg.domain_for("thread1");
assert_eq!(domain.max_pointers, 4);
}
#[test]
fn test_rcu_domain_new() {
let domain = RcuDomain::new(1);
assert_eq!(domain.id, 1);
assert_eq!(domain.generation, 0);
assert!(!domain.grace_period_active);
}
#[test]
fn test_rcu_read_lock() {
let domain = RcuDomain::new(1);
let guard = domain.rcu_read_lock();
assert_eq!(guard.domain_id, 1);
assert_eq!(guard.generation(), 0);
}
#[test]
fn test_rcu_synchronize() {
let mut domain = RcuDomain::new(1);
domain.synchronize_rcu();
assert_eq!(domain.generation, 1);
}
#[test]
fn test_rcu_call_rcu_and_process() {
let mut domain = RcuDomain::new(1);
domain.call_rcu(0x2000, "my_callback");
assert_eq!(domain.callbacks.len(), 1);
let processed = domain.process_callbacks(1);
assert_eq!(processed.len(), 0);
domain.synchronize_rcu();
let processed = domain.process_callbacks(2);
assert_eq!(processed.len(), 1);
}
#[test]
fn test_rcu_protected_read_update() {
let mut protected: RcuProtected<i32> = RcuProtected::new(42, 1);
assert_eq!(*protected.read(), 42);
protected.update(100);
assert_eq!(*protected.read(), 100);
}
#[test]
fn test_submdspan_slice_from_str_index() {
assert!(matches!(
SubmdspanSlice::from_str("5"),
Some(SubmdspanSlice::Index(5))
));
}
#[test]
fn test_submdspan_slice_from_str_full_extent() {
assert!(matches!(
SubmdspanSlice::from_str("_"),
Some(SubmdspanSlice::FullExtent)
));
}
#[test]
fn test_submdspan_slice_to_cpp() {
assert_eq!(SubmdspanSlice::Index(0).to_cpp(), "0");
assert_eq!(SubmdspanSlice::FullExtent.to_cpp(), "std::full_extent");
assert_eq!(
SubmdspanSlice::Range(1, 10).to_cpp(),
"std::pair{1, 10}"
);
}
#[test]
fn test_submdspan_op_new() {
let op = SubmdspanOp::new("A", "double", 3);
assert_eq!(op.source_rank, 3);
assert_eq!(op.result_rank, 3);
}
#[test]
fn test_submdspan_op_add_slice_index() {
let mut op = SubmdspanOp::new("B", "float", 2);
op.add_slice(SubmdspanSlice::Index(0));
assert_eq!(op.slices.len(), 1);
assert_eq!(op.result_rank, 1);
}
#[test]
fn test_submdspan_result_extents() {
let mut op = SubmdspanOp::new("C", "int", 3);
op.add_slice(SubmdspanSlice::Index(0));
op.add_slice(SubmdspanSlice::Range(1, 5));
op.add_slice(SubmdspanSlice::FullExtent);
let extents = op.result_extents(&[10, 10, 10]);
assert_eq!(extents.len(), 2);
assert_eq!(extents[0], 4);
assert_eq!(extents[1], 10);
}
#[test]
fn test_simd_type_new() {
let t = SimdType::new("float", 8);
assert_eq!(t.scalar_type, "float");
assert_eq!(t.size, 8);
assert!(t.type_name().contains("simd"));
}
#[test]
fn test_simd_math_op_function_name() {
assert_eq!(SimdMathOp::Frexp.function_name(), "frexp");
assert_eq!(SimdMathOp::Sin.function_name(), "sin");
assert_eq!(SimdMathOp::Log.function_name(), "log");
}
#[test]
fn test_simd_math_op_arity() {
assert_eq!(SimdMathOp::Fma.arity(), 3);
assert_eq!(SimdMathOp::Atan2.arity(), 2);
assert_eq!(SimdMathOp::Sin.arity(), 1);
}
#[test]
fn test_simd_math_registry_new_float() {
let t = SimdType::new("float", 4);
let reg = SimdMathRegistry::new(t);
assert!(reg.has_float_support);
assert!(!reg.has_integer_support);
}
#[test]
fn test_simd_math_registry_new_int() {
let t = SimdType::new("int", 4);
let reg = SimdMathRegistry::new(t);
assert!(!reg.has_float_support);
assert!(reg.has_integer_support);
}
#[test]
fn test_simd_math_registry_supports() {
let t = SimdType::new("float", 4);
let reg = SimdMathRegistry::new(t);
assert!(reg.supports(SimdMathOp::Sin));
assert!(!reg.supports(SimdMathOp::Sin)); }
#[test]
fn test_linalg_op_name() {
assert_eq!(LinalgOp::MatrixProduct.name(), "matrix_product");
assert_eq!(LinalgOp::Dot.name(), "dot");
assert_eq!(LinalgOp::Axpy.name(), "add_scaled");
}
#[test]
fn test_linalg_op_is_blas1() {
assert!(LinalgOp::Dot.is_blas1());
assert!(LinalgOp::Axpy.is_blas1());
assert!(!LinalgOp::MatrixProduct.is_blas1());
}
#[test]
fn test_linalg_op_is_blas2() {
assert!(LinalgOp::MatrixVectorProduct.is_blas2());
assert!(LinalgOp::Rank1Update.is_blas2());
assert!(!LinalgOp::Dot.is_blas2());
}
#[test]
fn test_linalg_op_is_blas3() {
assert!(LinalgOp::MatrixProduct.is_blas3());
assert!(LinalgOp::SymmetricMatrixProduct.is_blas3());
assert!(!LinalgOp::Dot.is_blas3());
}
#[test]
fn test_linalg_config_matrix_product() {
let config =
LinalgConfig::matrix_product("double", MatrixLayout::ColumnMajor, 16, 16, 16);
assert_eq!(config.op, LinalgOp::MatrixProduct);
assert_eq!(config.m, 16);
assert!(config.generate().contains("matrix_product"));
}
#[test]
fn test_linalg_registry_default() {
let reg = LinalgRegistry::default_registry();
assert_eq!(reg.blas_level1_count, 12);
assert_eq!(reg.blas_level2_count, 3);
assert_eq!(reg.blas_level3_count, 6);
assert_eq!(reg.supported_types.len(), 4);
}
#[test]
fn test_matrix_layout_transpose() {
assert_eq!(MatrixLayout::ColumnMajor.transpose(), MatrixLayout::RowMajor);
assert_eq!(MatrixLayout::RowMajor.transpose(), MatrixLayout::ColumnMajor);
}
#[test]
fn test_inplace_vector_new() {
let v: InplaceVector<i32> = InplaceVector::new(10);
assert!(v.is_empty());
assert!(!v.is_full());
assert_eq!(v.capacity, 10);
}
#[test]
fn test_inplace_vector_push_pop() {
let mut v: InplaceVector<i32> = InplaceVector::new(3);
assert!(v.push_back(1));
assert!(v.push_back(2));
assert_eq!(v.size, 2);
assert_eq!(v.pop_back(), Some(2));
assert_eq!(v.pop_back(), Some(1));
assert_eq!(v.pop_back(), None);
}
#[test]
fn test_inplace_vector_push_until_full() {
let mut v: InplaceVector<i32> = InplaceVector::new(2);
assert!(v.push_back(10));
assert!(v.push_back(20));
assert!(!v.push_back(30));
assert!(v.is_full());
}
#[test]
fn test_inplace_vector_get() {
let mut v: InplaceVector<i32> = InplaceVector::new(5);
v.push_back(100);
v.push_back(200);
assert_eq!(v.get(0), Some(&100));
assert_eq!(v.get(1), Some(&200));
assert_eq!(v.get(2), None);
}
#[test]
fn test_inplace_vector_insert() {
let mut v: InplaceVector<i32> = InplaceVector::new(5);
v.push_back(1);
v.push_back(3);
assert!(v.insert(1, 2));
assert_eq!(v.get(0), Some(&1));
assert_eq!(v.get(1), Some(&2));
assert_eq!(v.get(2), Some(&3));
}
#[test]
fn test_inplace_vector_erase() {
let mut v: InplaceVector<i32> = InplaceVector::new(5);
v.push_back(1);
v.push_back(2);
v.push_back(3);
assert_eq!(v.erase(1), Some(2));
assert_eq!(v.size, 2);
assert_eq!(v.get(0), Some(&1));
assert_eq!(v.get(1), Some(&3));
}
#[test]
fn test_inplace_vector_resize() {
let mut v: InplaceVector<i32> = InplaceVector::new(5);
assert!(v.resize(3, 42));
assert_eq!(v.size, 3);
assert_eq!(v.get(0), Some(&42));
assert!(v.resize(1, 0));
assert_eq!(v.size, 1);
}
#[test]
fn test_inplace_vector_try_push_back() {
let mut v: InplaceVector<i32> = InplaceVector::new(1);
assert!(v.try_push_back(99).is_ok());
assert!(v.try_push_back(100).is_err());
}
#[test]
fn test_inplace_vector_clear() {
let mut v: InplaceVector<i32> = InplaceVector::new(5);
v.push_back(1);
v.push_back(2);
v.clear();
assert!(v.is_empty());
assert_eq!(v.size, 0);
}
#[test]
fn test_hive_new() {
let h: Hive<i32> = Hive::new(4);
assert!(h.is_empty());
assert_eq!(h.size(), 0);
assert_eq!(h.bucket_count(), 1);
}
#[test]
fn test_hive_insert() {
let mut h: Hive<i32> = Hive::new(2);
let iter1 = h.insert(10);
let iter2 = h.insert(20);
assert_eq!(h.size(), 2);
assert!(iter1.is_valid(&h));
assert!(iter2.is_valid(&h));
}
#[test]
fn test_hive_erase() {
let mut h: Hive<i32> = Hive::new(2);
h.insert(10);
let iter = h.insert(20);
assert!(h.erase(iter.bucket_index, iter.element_index));
assert_eq!(h.size(), 1);
}
#[test]
fn test_hive_compact() {
let mut h: Hive<i32> = Hive::new(2);
let iter = h.insert(10);
h.insert(20);
h.erase(iter.bucket_index, iter.element_index);
h.compact();
assert_eq!(h.size(), 1);
}
#[test]
fn test_hive_to_vec() {
let mut h: Hive<i32> = Hive::new(2);
h.insert(1);
h.insert(2);
h.insert(3);
let v = h.to_vec();
assert_eq!(v.len(), 3);
assert!(v.contains(&1));
assert!(v.contains(&2));
assert!(v.contains(&3));
}
#[test]
fn test_hive_capacity() {
let h: Hive<i32> = Hive::new(8);
assert_eq!(h.capacity(), 8);
}
#[test]
fn test_hive_bucket_insert_full() {
let mut b: HiveBucket<i32> = HiveBucket::new(2);
assert!(b.insert(1).is_some());
assert!(b.insert(2).is_some());
assert!(b.insert(3).is_none());
}
#[test]
fn test_hive_bucket_erase() {
let mut b: HiveBucket<i32> = HiveBucket::new(2);
b.insert(1);
assert!(b.erase(0));
assert!(!b.erase(0));
}
#[test]
fn test_debugging_support_new() {
let dbg = DebuggingSupport::new();
assert!(!dbg.is_debugger_present());
assert_eq!(dbg.breakpoint_count, 0);
assert!(dbg.breakpoints_enabled);
}
#[test]
fn test_debugging_support_set_debugger_present() {
let mut dbg = DebuggingSupport::new();
dbg.set_debugger_present(true);
assert!(dbg.is_debugger_present());
}
#[test]
fn test_debugging_support_breakpoint_if_debugging() {
let mut dbg = DebuggingSupport::new();
assert!(!dbg.breakpoint_if_debugging());
dbg.set_debugger_present(true);
assert!(dbg.breakpoint_if_debugging());
assert_eq!(dbg.breakpoint_count, 1);
}
#[test]
fn test_debugging_support_disable_breakpoints() {
let mut dbg = DebuggingSupport::new();
dbg.set_debugger_present(true);
dbg.disable_breakpoints();
assert!(!dbg.breakpoint_if_debugging());
}
#[test]
fn test_platform_breakpoint_for_triple() {
assert_eq!(
PlatformBreakpoint::for_triple("x86_64-unknown-linux-gnu"),
PlatformBreakpoint::X86Int3
);
assert_eq!(
PlatformBreakpoint::for_triple("aarch64-unknown-linux-gnu"),
PlatformBreakpoint::Aarch64Brk
);
assert_eq!(
PlatformBreakpoint::for_triple("riscv64-unknown-linux-gnu"),
PlatformBreakpoint::RiscvEbreak
);
}
#[test]
fn test_platform_breakpoint_asm_instruction() {
assert_eq!(PlatformBreakpoint::X86Int3.asm_instruction(), "int3");
assert_eq!(PlatformBreakpoint::Aarch64Brk.asm_instruction(), "brk #0");
}
#[test]
fn test_text_encoding_from_mib_utf8() {
let enc = TextEncoding::from_mib(TextEncodingMib::Utf8);
assert_eq!(enc.name, "UTF-8");
assert_eq!(enc.mib_value(), 106);
assert!(enc.is_known());
}
#[test]
fn test_text_encoding_from_mib_unknown() {
let enc = TextEncoding::from_mib(TextEncodingMib::Unknown);
assert!(!enc.is_known());
}
#[test]
fn test_text_encoding_lookup() {
let enc = TextEncoding::lookup("UTF-8");
assert!(enc.is_some());
assert_eq!(enc.unwrap().mib, TextEncodingMib::Utf8);
}
#[test]
fn test_text_encoding_lookup_alias() {
let enc = TextEncoding::lookup("Latin-1");
assert!(enc.is_some());
assert_eq!(enc.unwrap().mib, TextEncodingMib::Iso8859_1);
}
#[test]
fn test_text_encoding_mib_is_unicode() {
assert!(TextEncodingMib::Utf8.is_unicode());
assert!(TextEncodingMib::Utf16Be.is_unicode());
assert!(!TextEncodingMib::Ascii.is_unicode());
}
#[test]
fn test_text_encoding_mib_is_ascii_compatible() {
assert!(TextEncodingMib::Utf8.is_ascii_compatible());
assert!(TextEncodingMib::Ascii.is_ascii_compatible());
assert!(!TextEncodingMib::Utf16Be.is_ascii_compatible());
}
#[test]
fn test_text_encoding_registry_full() {
let reg = TextEncodingRegistry::full();
assert!(reg.count() > 10);
}
#[test]
fn test_text_encoding_registry_by_mib() {
let reg = TextEncodingRegistry::full();
assert!(reg.by_mib(106).is_some());
assert!(reg.by_mib(9999).is_none());
}
#[test]
fn test_text_encoding_registry_unicode_encodings() {
let reg = TextEncodingRegistry::full();
let unicode = reg.unicode_encodings();
assert!(unicode.iter().any(|e| e.name == "UTF-8"));
}
#[test]
fn test_non_template_pack_new() {
let pack = NonTemplatePack::new("args", "auto", 3);
assert_eq!(pack.name, "args");
assert_eq!(pack.element_type, "auto");
assert_eq!(pack.size, 3);
}
#[test]
fn test_non_template_pack_generate_declaration() {
let pack = NonTemplatePack::new("vals", "auto", 2);
assert_eq!(pack.generate_declaration(), "auto vals... auto");
}
#[test]
fn test_non_template_pack_generate_function() {
let code = NonTemplatePack::generate_function("print_all", "args", "std::cout << args;");
assert!(code.contains("auto print_all"));
assert!(code.contains("auto... args"));
}
#[test]
fn test_constexpr_allocation_new() {
let alloc = ConstexprAllocation::new(64, 8, "MyClass");
assert_eq!(alloc.size, 64);
assert_eq!(alloc.alignment, 8);
assert!(!alloc.deallocated);
}
#[test]
fn test_constexpr_allocation_deallocate() {
let mut alloc = ConstexprAllocation::new(32, 4, "int");
alloc.deallocate();
assert!(alloc.deallocated);
}
#[test]
fn test_constexpr_allocator_new() {
let allocator = ConstexprAllocator::new();
assert_eq!(allocator.total_allocated, 0);
assert!(allocator.is_sound());
}
#[test]
fn test_constexpr_allocator_allocate_deallocate() {
let mut allocator = ConstexprAllocator::new();
allocator.allocate(128, 16, "std::string");
assert_eq!(allocator.total_allocated, 128);
allocator.allocate(64, 8, "int[8]");
assert_eq!(allocator.total_allocated, 192);
assert_eq!(allocator.check_leaks(), 2);
}
#[test]
fn test_constexpr_allocator_check_leaks() {
let mut allocator = ConstexprAllocator::new();
allocator.allocate(10, 1, "char");
allocator.allocate(20, 1, "char");
assert_eq!(allocator.check_leaks(), 2);
}
#[test]
fn test_cxx26_feature_paper_numbers() {
assert_eq!(CXX26Feature::Contracts.paper_number(), "P0542R5 / P2900R0");
assert_eq!(
CXX26Feature::Reflection.paper_number(),
"P2996R5"
);
assert_eq!(
CXX26Feature::SendersReceivers.paper_number(),
"P2300R10"
);
}
#[test]
fn test_cxx26_feature_registry_new_cxx26() {
let reg = CXX26FeatureRegistry::new(CXXStandardVersion::CXX26);
assert!(reg.is_enabled(CXX26Feature::Contracts));
assert!(reg.is_enabled(CXX26Feature::Reflection));
assert!(reg.is_enabled(CXX26Feature::Hive));
assert_eq!(reg.enabled_count(), reg.feature_count());
}
#[test]
fn test_cxx26_feature_registry_new_cxx23() {
let reg = CXX26FeatureRegistry::new(CXXStandardVersion::CXX23);
assert!(!reg.is_enabled(CXX26Feature::Contracts));
assert!(reg.is_enabled(CXX26Feature::ConstexprPlacementNew));
assert!(reg.is_enabled(CXX26Feature::InplaceVector));
}
#[test]
fn test_cxx26_feature_registry_new_cxx20() {
let reg = CXX26FeatureRegistry::new(CXXStandardVersion::CXX20);
assert!(!reg.is_enabled(CXX26Feature::Contracts));
assert!(!reg.is_enabled(CXX26Feature::InplaceVector));
}
#[test]
fn test_cxx26_feature_registry_enable_disable() {
let mut reg = CXX26FeatureRegistry::new(CXXStandardVersion::CXX23);
assert!(!reg.is_enabled(CXX26Feature::Contracts));
reg.enable(CXX26Feature::Contracts);
assert!(reg.is_enabled(CXX26Feature::Contracts));
reg.disable(CXX26Feature::Contracts);
assert!(!reg.is_enabled(CXX26Feature::Contracts));
}
#[test]
fn test_cxx_standard_version_from_str() {
assert_eq!(
CXXStandardVersion::from_str("c++26"),
Some(CXXStandardVersion::CXX26)
);
assert_eq!(
CXXStandardVersion::from_str("c++2c"),
Some(CXXStandardVersion::CXX26)
);
assert_eq!(
CXXStandardVersion::from_str("gnu++26"),
Some(CXXStandardVersion::CXX26)
);
}
#[test]
fn test_cxx_standard_version_is_at_least() {
assert!(CXXStandardVersion::CXX26.is_at_least(CXXStandardVersion::CXX23));
assert!(CXXStandardVersion::CXX26.is_at_least(CXXStandardVersion::CXX26));
assert!(!CXXStandardVersion::CXX23.is_at_least(CXXStandardVersion::CXX26));
}
#[test]
fn test_cxx26_all_features_count() {
assert_eq!(CXX26Feature::ALL_FEATURES.len(), 23);
}
#[test]
fn test_inplace_vector_iter() {
let mut v: InplaceVector<i32> = InplaceVector::new(5);
v.push_back(1);
v.push_back(2);
v.push_back(3);
let mut iter = InplaceVectorIter::new(&v);
assert_eq!(iter.next(), Some(&1));
assert_eq!(iter.next(), Some(&2));
assert_eq!(iter.next(), Some(&3));
assert_eq!(iter.next(), None);
}
#[test]
fn test_linalg_config_with_scalars() {
let config =
LinalgConfig::matrix_product("float", MatrixLayout::RowMajor, 8, 8, 8)
.with_scalars("1.0f", "0.0f");
assert_eq!(config.alpha.as_deref(), Some("1.0f"));
assert_eq!(config.beta.as_deref(), Some("0.0f"));
}
#[test]
fn test_simd_mask_type() {
let t = SimdType::new("int", 8);
assert!(t.mask_type().contains("simd_mask"));
}
#[test]
fn test_sender_adaptor_upon_error() {
let adaptor = SenderAdaptor::UponError {
function: "[](auto e){ return std::cerr << e; }".to_string(),
error_type: "std::exception_ptr".to_string(),
};
assert_eq!(adaptor.type_name(), "upon_error_t");
}
#[test]
fn test_meta_query_size_of() {
let q = MetaQuery::SizeOfReflected("BigStruct".to_string());
assert!(q.generate().contains("size_of"));
assert!(q.generate().contains("BigStruct"));
}
#[test]
fn test_linalg_op_norm_names() {
assert_eq!(LinalgOp::Norm2.name(), "vector_norm2");
assert_eq!(LinalgOp::MatrixNormFrobenius.name(), "matrix_norm_frobenius");
}
#[test]
fn test_rcu_read_guard_generation() {
let guard = RcuReadGuard {
domain_id: 2,
generation: 5,
};
assert_eq!(guard.generation(), 5);
assert_eq!(guard.domain_id, 2);
}
}