lib

Core libraries for Radroots
git clone https://radroots.dev/git/lib.git
Log | Files | Refs | README

package_boundary.rs (4081B)


      1 use std::collections::BTreeSet;
      2 
      3 const MANIFEST: &str = include_str!("../Cargo.toml");
      4 const ROOT: &str = include_str!("../src/lib.rs");
      5 const CAPABILITY: &str = include_str!("../src/capability.rs");
      6 const ERROR: &str = include_str!("../src/error.rs");
      7 const EVENT: &str = include_str!("../src/event.rs");
      8 const RADROOTSD: &str = include_str!("../src/radrootsd.rs");
      9 const RUNTIME: &str = include_str!("../src/runtime.rs");
     10 const VERSIONED_SOURCES: &[&str] = &[
     11     include_str!("../src/capability/v1.rs"),
     12     include_str!("../src/error/v1.rs"),
     13     include_str!("../src/event/v1.rs"),
     14     include_str!("../src/radrootsd/transport_publish/v5.rs"),
     15     include_str!("../src/runtime/v1.rs"),
     16     include_str!("../src/schema.rs"),
     17 ];
     18 
     19 #[test]
     20 fn manifest_has_final_identity_features_and_no_radroots_dependencies() {
     21     assert!(MANIFEST.contains("name = \"radroots_protocol\""));
     22     assert!(MANIFEST.contains("version = \"0.1.0-alpha\""));
     23     assert!(MANIFEST.contains("publish = [\"crates-io\"]"));
     24     assert!(MANIFEST.contains("[lib]\nname = \"radroots_protocol\""));
     25     assert!(MANIFEST.contains("default = [\"std\", \"serde\"]"));
     26     assert_eq!(
     27         table_keys(MANIFEST, "[features]"),
     28         BTreeSet::from(["default", "serde", "std"])
     29     );
     30     assert_eq!(
     31         table_keys(MANIFEST, "[dependencies]"),
     32         BTreeSet::from(["serde"])
     33     );
     34     assert_eq!(
     35         table_keys(MANIFEST, "[dev-dependencies]"),
     36         BTreeSet::from(["serde_json"])
     37     );
     38 }
     39 
     40 #[test]
     41 fn crate_root_exposes_only_the_approved_versioned_skeleton() {
     42     assert!(ROOT.contains("#![cfg_attr(not(feature = \"std\"), no_std)]"));
     43     assert_eq!(
     44         root_declarations("pub mod "),
     45         BTreeSet::from([
     46             "capability",
     47             "error",
     48             "event",
     49             "radrootsd",
     50             "runtime",
     51             "schema"
     52         ])
     53     );
     54     for source in [CAPABILITY, EVENT] {
     55         assert!(source.lines().any(|line| line.trim() == "pub mod v1;"));
     56     }
     57     assert!(ERROR.lines().any(|line| line.trim() == "pub mod v1;"));
     58     assert!(RUNTIME.lines().any(|line| line.trim() == "pub mod v1;"));
     59     assert!(RADROOTSD.contains("pub mod transport_publish {"));
     60     assert!(RADROOTSD.lines().any(|line| line.trim() == "pub mod v5;"));
     61     assert!(
     62         !ROOT
     63             .lines()
     64             .map(str::trim)
     65             .any(|line| line.starts_with("pub use "))
     66     );
     67 }
     68 
     69 #[test]
     70 fn public_contract_sources_exclude_runtime_dependencies_and_wrapper_traits() {
     71     assert!(ROOT.contains("#![forbid(unsafe_code)]"));
     72     for source in VERSIONED_SOURCES {
     73         for forbidden in [
     74             "dto_bindgen",
     75             "wasm_bindgen",
     76             "uniffi",
     77             "tokio::",
     78             "sqlx::",
     79             "reqwest::",
     80             "nostr::",
     81             "std::fs",
     82             "std::net",
     83             "std::process",
     84             "impl core::ops::Deref",
     85             "impl std::ops::Deref",
     86             "unsafe fn",
     87             "unsafe impl",
     88             "unsafe {",
     89         ] {
     90             assert!(
     91                 !source.contains(forbidden),
     92                 "protocol contract source contains forbidden surface `{forbidden}`"
     93             );
     94         }
     95     }
     96 }
     97 
     98 fn table_keys<'a>(manifest: &'a str, heading: &str) -> BTreeSet<&'a str> {
     99     let Some((_, table)) = manifest.split_once(heading) else {
    100         return BTreeSet::new();
    101     };
    102     table
    103         .lines()
    104         .skip(1)
    105         .take_while(|line| !line.trim_start().starts_with('['))
    106         .filter_map(|line| {
    107             let line = line.trim();
    108             (line
    109                 .bytes()
    110                 .next()
    111                 .is_some_and(|byte| byte.is_ascii_lowercase() || byte == b'_')
    112                 && !line.starts_with('#'))
    113             .then(|| line.split_once('=').map(|(key, _)| key.trim()))
    114             .flatten()
    115         })
    116         .collect()
    117 }
    118 
    119 fn root_declarations(prefix: &str) -> BTreeSet<&str> {
    120     ROOT.lines()
    121         .map(str::trim)
    122         .filter_map(|line| line.strip_prefix(prefix))
    123         .filter_map(|name| name.strip_suffix(';'))
    124         .collect()
    125 }