///|
pub(all) struct NativeStubFfiShimFact {
file : String
wrapper : String
extern_target : String
} derive(Eq, Debug)
///|
pub(all) struct NativeStubFfiShimPolicyReport {
expected_fact_count : Int
actual_fact_count : Int
native_fact_count : Int
fallback_fact_count : Int
missing_fact_count : Int
extra_fact_count : Int
duplicate_fact_count : Int
fallback_native_binding_violation_count : Int
replaces_file_reading : Bool
replaces_wrapper_extraction : Bool
replaces_extern_target_extraction : Bool
live_io_evidence : Bool
} derive(Eq, Debug)
///|
pub fn NativeStubFfiShimPolicyReport::passes(
self : NativeStubFfiShimPolicyReport,
) -> Bool {
self.expected_fact_count > 0 &&
self.actual_fact_count == self.expected_fact_count &&
self.native_fact_count > 0 &&
self.fallback_fact_count > 0 &&
self.missing_fact_count == 0 &&
self.extra_fact_count == 0 &&
self.duplicate_fact_count == 0 &&
self.fallback_native_binding_violation_count == 0 &&
!self.replaces_file_reading &&
!self.replaces_wrapper_extraction &&
!self.replaces_extern_target_extraction &&
!self.live_io_evidence
}
///|
pub fn native_stub_expected_ffi_shim_facts() -> Array[NativeStubFfiShimFact] {
let facts : Array[NativeStubFfiShimFact] = []
for entry in native_stub_capability_ledger() {
for i in 0.. NativeStubFfiShimPolicyReport {
native_stub_ffi_shim_policy_report_from_expected(
native_stub_expected_ffi_shim_facts(),
actual,
)
}
///|
pub fn native_stub_ffi_shim_policy_report_from_expected(
expected : Array[NativeStubFfiShimFact],
actual : Array[NativeStubFfiShimFact],
) -> NativeStubFfiShimPolicyReport {
{
expected_fact_count: expected.length(),
actual_fact_count: actual.length(),
native_fact_count: count_ffi_shim_native_facts(actual),
fallback_fact_count: count_ffi_shim_fallback_facts(actual),
missing_fact_count: count_missing_ffi_shim_facts(expected, actual),
extra_fact_count: count_missing_ffi_shim_facts(actual, expected),
duplicate_fact_count: count_duplicate_ffi_shim_facts(actual),
fallback_native_binding_violation_count: count_fallback_native_binding_violations(
actual,
),
replaces_file_reading: false,
replaces_wrapper_extraction: false,
replaces_extern_target_extraction: false,
live_io_evidence: false,
}
}
///|
fn count_ffi_shim_native_facts(facts : Array[NativeStubFfiShimFact]) -> Int {
let mut count = 0
for fact in facts {
if fact.file.contains("_native.mbt") {
count += 1
}
}
count
}
///|
fn count_ffi_shim_fallback_facts(facts : Array[NativeStubFfiShimFact]) -> Int {
let mut count = 0
for fact in facts {
if fact.file.contains("_fallback.mbt") {
count += 1
}
}
count
}
///|
fn count_missing_ffi_shim_facts(
expected : Array[NativeStubFfiShimFact],
actual : Array[NativeStubFfiShimFact],
) -> Int {
let mut count = 0
for fact in expected {
if !contains_ffi_shim_fact(actual, fact) {
count += 1
}
}
count
}
///|
fn count_duplicate_ffi_shim_facts(facts : Array[NativeStubFfiShimFact]) -> Int {
let unique : Array[NativeStubFfiShimFact] = []
let mut count = 0
for fact in facts {
if contains_ffi_shim_fact(unique, fact) {
count += 1
} else {
unique.push(fact)
}
}
count
}
///|
fn count_fallback_native_binding_violations(
facts : Array[NativeStubFfiShimFact],
) -> Int {
let mut count = 0
for fact in facts {
if fact.file.contains("_fallback.mbt") && fact.extern_target != "" {
count += 1
}
}
count
}
///|
fn push_unique_ffi_shim_fact(
facts : Array[NativeStubFfiShimFact],
fact : NativeStubFfiShimFact,
) -> Unit {
if !contains_ffi_shim_fact(facts, fact) {
facts.push(fact)
}
}
///|
fn contains_ffi_shim_fact(
facts : Array[NativeStubFfiShimFact],
fact : NativeStubFfiShimFact,
) -> Bool {
for got in facts {
if got == fact {
return true
}
}
false
}