acadrust 0.3.3

A pure Rust library for reading and writing CAD files in DXF format (ASCII and Binary) and DWG format (Binary).
Documentation
//! DWG App Info section writer
//!
//! Writes the AppInfo section for DWG R2004+ files. This section
//! contains application metadata (product name, build version, etc.).
//!
//! ## Format
//!
//! ```text
//! [class_version: 4 bytes (UInt32)]
//! [App info name: TU (Unicode string)]
//! [num strings: 4 bytes (UInt32)]
//! [Version checksum: 16 zero bytes]
//! [Version: TU]
//! [Comment checksum: 16 zero bytes]
//! [Comment: TU]
//! [Product checksum: 16 zero bytes]
//! [Product: TU (XML)]
//! ```
//!
//! Based on ACadSharp's `DwgAppInfoWriter`.

use crate::io::dwg::dwg_stream_writers::DwgBitWriter;
use crate::io::dwg::dwg_version::DwgVersion;
use crate::types::DxfVersion;

/// The library name embedded in AppInfo.
const APP_NAME: &str = "AppInfoDataList";

/// The library version string.
const LIB_VERSION: &str = "0.1.0";

/// Write the App Info section.
///
/// This section is only meaningful for R2004+ files but will produce
/// valid (if ignored) output for earlier versions.
///
/// # Returns
/// Raw section bytes ready for `add_section("AcDb:AppInfo", ...)`.
pub fn write_app_info(version: DxfVersion) -> Vec<u8> {
    let dwg_version = DwgVersion::from_dxf_version(version)
        .unwrap_or(DwgVersion::AC18);
    let mut writer = DwgBitWriter::new(dwg_version, version);

    let empty_checksum = [0u8; 16];

    // UInt32: class_version (2 for R2007/R2004, 3 for R2013+)
    let class_version = if version >= DxfVersion::AC1027 { 3 } else { 2 };
    writer.write_int(class_version);

    // String (TU): App info name
    writer.write_text_unicode(APP_NAME);

    // UInt32: num strings (default: 3)
    writer.write_int(3);

    // Version data checksum (16 zero bytes) + Version string
    writer.write_bytes(&empty_checksum);
    writer.write_text_unicode(LIB_VERSION);

    // Comment data checksum (16 zero bytes) + Comment string
    writer.write_bytes(&empty_checksum);
    writer.write_text_unicode("Generated by acadrust");

    // Product data checksum (16 zero bytes) + Product XML string
    writer.write_bytes(&empty_checksum);
    let product_xml = format!(
        "<ProductInformation name=\"acadrust\" build_version=\"{}\" \
         registry_version=\"{}\" install_id_string=\"acadrust\" \
         registry_localeID=\"1033\"/>",
        LIB_VERSION, LIB_VERSION
    );
    writer.write_text_unicode(&product_xml);

    writer.into_bytes()
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_write_app_info_not_empty() {
        let data = write_app_info(DxfVersion::AC1018);
        // Should produce non-trivial output
        assert!(data.len() > 80, "App info should be at least 80 bytes, got {}", data.len());
    }

    #[test]
    fn test_write_app_info_starts_with_version_2() {
        let data = write_app_info(DxfVersion::AC1018);
        // First 4 bytes = class_version = 2 for R2004/R2007 (LE)
        assert_eq!(&data[0..4], &[2, 0, 0, 0]);
    }
}