kcode-k1-rust-code-document 0.1.1

Represent and chunk one authored K1 Rust code document
Documentation
use kcode_k1_rust_code_document::RustCodeDocument;
use kcode_k1_rust_package::{AuthorityId, LibraryFamily, LibraryId, SourceFile, SourcePackage};
use kcode_k1_transaction_id::TxId;
use semver::Version;
use std::ops::Range;

fn identity() -> LibraryId {
    let authority = AuthorityId::new(TxId::from_bytes([7; 12]));
    let family = LibraryFamily::new(authority, "demo").unwrap();
    LibraryId::new(family, Version::new(0, 1, 0)).unwrap()
}

fn default_manifest() -> String {
    RustCodeDocument::approved_default(identity())
        .unwrap()
        .manifest()
        .to_owned()
}

fn document_with_code(code: &str) -> RustCodeDocument {
    RustCodeDocument::new(
        identity(),
        "# Consumer contract\n",
        default_manifest(),
        code,
    )
    .unwrap()
}

fn ranges(code: &str) -> Vec<Range<usize>> {
    document_with_code(code).code_chunk_ranges()
}

fn whole(end: usize) -> Vec<Range<usize>> {
    std::iter::once(0..end).collect()
}

fn reconstruct(code: &str, ranges: &[Range<usize>]) -> String {
    ranges.iter().map(|range| &code[range.clone()]).collect()
}

#[test]
fn approved_default_is_minimal_exact_and_round_trips() {
    let document = RustCodeDocument::approved_default(identity()).unwrap();
    let expected_manifest = concat!(
        "[package]\n",
        "name = \"k1-070707070707070707070707-demo\"\n",
        "version = \"0.1.0\"\n",
        "edition = \"2024\"\n",
        "rust-version = \"1.97\"\n",
        "license = \"MIT\"\n"
    );
    assert_eq!(
        document.documentation(),
        "# Consumer contract\n\n`run` performs no operation.\n"
    );
    assert_eq!(document.manifest(), expected_manifest);
    assert_eq!(document.code(), "pub fn run() {}\n");
    assert_eq!(document.identity(), &identity());
    let package = document.clone().into_source_package();
    let paths: Vec<&str> = package.files().iter().map(|file| file.path()).collect();
    assert_eq!(paths, ["Cargo.toml", "Documentation.md", "src/lib.rs"]);
    let recovered = RustCodeDocument::from_source_package(package.clone()).unwrap();
    assert_eq!(recovered.into_source_package(), package);
}

#[test]
fn ordinary_cargo_manifest_and_binary_target_are_accepted() {
    let manifest = concat!(
        "[package]\n",
        "name = \"k1-070707070707070707070707-demo\"\n",
        "version = \"0.1.0\"\n",
        "edition = \"2024\"\n",
        "autolib = false\n",
        "authors = [\"Example\"]\n",
        "description = \"ordinary metadata\"\n\n",
        "[[bin]]\n",
        "name = \"demo-tool\"\n",
        "path = \"src/lib.rs\"\n\n",
        "[features]\n",
        "default = []\n\n",
        "[profile.release]\n",
        "lto = true\n"
    );
    let code = "fn main() { unsafe { core::ptr::read_volatile(&0); } }\n";
    let document = RustCodeDocument::new(identity(), "docs", manifest, code).unwrap();
    assert_eq!(document.manifest(), manifest);
    assert_eq!(document.code(), code);
}

#[test]
fn shape_utf8_and_identity_are_enforced_without_extra_manifest_policy() {
    let base = RustCodeDocument::approved_default(identity())
        .unwrap()
        .into_source_package();
    let mut extra = base.files().to_vec();
    extra.push(SourceFile::new("README.md", b"extra".to_vec()));
    let extra = SourcePackage::new(identity(), extra).unwrap();
    assert!(RustCodeDocument::from_source_package(extra).is_err());

    let missing: Vec<SourceFile> = base
        .files()
        .iter()
        .filter(|file| file.path() != "src/lib.rs")
        .cloned()
        .collect();
    let missing = SourcePackage::new(identity(), missing).unwrap();
    assert!(RustCodeDocument::from_source_package(missing).is_err());

    let mut non_utf: Vec<SourceFile> = base
        .files()
        .iter()
        .filter(|file| file.path() != "src/lib.rs")
        .cloned()
        .collect();
    non_utf.push(SourceFile::new("src/lib.rs", vec![0xff]));
    let non_utf = SourcePackage::new(identity(), non_utf).unwrap();
    assert!(RustCodeDocument::from_source_package(non_utf).is_err());

    let changed_name = default_manifest().replace(
        "k1-070707070707070707070707-demo",
        "k1-070707070707070707070707-other",
    );
    assert!(RustCodeDocument::new(identity(), "docs", changed_name, "code").is_err());
    let changed_version = default_manifest().replace("0.1.0", "0.1.1");
    assert!(RustCodeDocument::new(identity(), "docs", changed_version, "code").is_err());
    assert!(RustCodeDocument::new(identity(), "docs", "not toml", "code").is_err());
}

#[test]
fn dependency_forms_remain_supported() {
    let additions = concat!(
        "\n[dependencies]\n",
        "serde = \"1\"\n",
        "peer = { package = \"k1-090909090909090909090909-peer\", version = \"0.3\", registry = \"k1\" }\n"
    );
    let manifest = format!("{}{additions}", default_manifest());
    let document =
        RustCodeDocument::new(identity(), "docs", manifest.clone(), "pub fn run() {}\n").unwrap();
    assert_eq!(document.manifest(), manifest);
    assert_eq!(
        document.clone().into_source_package().dependencies().len(),
        1
    );
    assert_eq!(
        RustCodeDocument::from_source_package(document.into_source_package())
            .unwrap()
            .manifest(),
        manifest
    );
}

#[test]
fn every_content_preserves_line_endings_bom_and_final_newline() {
    let documentation = "\u{feff}# Contract\r\n\r\nExact";
    let manifest = default_manifest().replace('\n', "\r\n");
    let code = "\u{feff}pub fn run() {\r\n}";
    let document =
        RustCodeDocument::new(identity(), documentation, manifest.clone(), code).unwrap();
    assert_eq!(document.documentation(), documentation);
    assert_eq!(document.manifest(), manifest);
    assert_eq!(document.code(), code);
    assert_eq!(reconstruct(code, &document.code_chunk_ranges()), code);
    let default = RustCodeDocument::approved_default(identity()).unwrap();
    assert!(default.documentation().ends_with('\n'));
    assert!(default.manifest().ends_with('\n'));
    assert!(default.code().ends_with('\n'));
}

#[test]
fn top_level_items_split_on_unicode_scalar_floor() {
    let first = format!("const FIRST: &str = r#\"{}\"#;", "é".repeat(810));
    let second = format!("const SECOND: &str = r#\"{}\"#;", "界".repeat(810));
    let code = format!("{first}\n{second}\n");
    let chunks = ranges(&code);
    assert_eq!(chunks.len(), 2);
    assert_eq!(chunks[0], 0..first.len());
    assert_eq!(reconstruct(&code, &chunks), code);
    assert!(
        chunks
            .iter()
            .all(|range| code[range.clone()].chars().count() >= 800)
    );
}

#[test]
fn direct_impl_and_trait_members_are_safe_points() {
    let text = "x".repeat(810);
    let code = format!(
        "struct Unit;\nimpl Unit {{\nfn one() -> &'static str {{ r#\"{text}\"# }}\nfn two() -> &'static str {{ r#\"{text}\"# }}\n}}\ntrait Work {{\nfn three() -> &'static str {{ r#\"{text}\"# }}\nfn four() -> &'static str {{ r#\"{text}\"# }}\n}}\n"
    );
    let chunks = ranges(&code);
    assert_eq!(chunks.len(), 4);
    assert_eq!(reconstruct(&code, &chunks), code);
    assert!(
        chunks
            .iter()
            .all(|range| code[range.clone()].chars().count() >= 800)
    );
}

#[test]
fn attributes_raw_strings_macros_comments_and_nesting_stay_indivisible() {
    let first = [
        "#[allow(dead_code)]\nfn complex() {\nlet raw = r###\"",
        &"}\"#/*".repeat(180),
        "\"###;\nmacro_rules! local { () => {{ raw.len() }}; }\nlet _ = local!();\n/* kept */\n}",
    ]
    .concat();
    let second = format!(
        "#[allow(dead_code)]\nfn second() {{ let _ = r#\"{}\"#; }}",
        "z".repeat(900)
    );
    let code = format!("{first} // trailing\r\n{second}");
    let chunks = ranges(&code);
    assert_eq!(chunks.len(), 2);
    assert_eq!(chunks[0], 0..first.len());
    assert_eq!(reconstruct(&code, &chunks), code);
}

#[test]
fn malformed_small_huge_and_short_tail_use_whole_file_fallbacks() {
    assert_eq!(ranges(""), whole(0));
    let small = "pub fn run() {}\n";
    assert_eq!(ranges(small), whole(small.len()));
    let malformed = format!("fn broken({}", "x".repeat(2000));
    assert_eq!(ranges(&malformed), whole(malformed.len()));
    let huge = format!("const ONLY: &str = r#\"{}\"#;", "q".repeat(5000));
    assert_eq!(ranges(&huge), whole(huge.len()));
    let first = format!("const FIRST: &str = r#\"{}\"#;", "a".repeat(900));
    let short_tail = format!("{first}\nconst T: u8 = 1;");
    assert_eq!(ranges(&short_tail), whole(short_tail.len()));
}