mqtt-typed-client 0.1.0

Type-safe async MQTT client with automatic topic routing
Documentation
use std::env;
use std::fs;
use std::path::Path;

use regex::Regex;

const INPUT_PATH: &str = "examples/README.md";
const OUTPUT_FILENAME: &str = "examples.README.doc.md";

// README.md processing constants
const README_INPUT_PATH: &str = "README.md";
const README_OUTPUT_FILENAME: &str = "README.doc.md";

fn main() {
	println!("cargo:rerun-if-changed={INPUT_PATH}");
	println!("cargo:rerun-if-changed={README_INPUT_PATH}");

	generate_doc_readme();
	generate_readme_doc();
}

fn generate_doc_readme() {
	let out_dir = env::var("OUT_DIR").unwrap();
	let output_dir = Path::new(&out_dir).join("generated");
	let output_path = output_dir.join(OUTPUT_FILENAME);

	// Create output directory if it doesn't exist
	if let Err(e) = fs::create_dir_all(&output_dir) {
		eprintln!("Warning: Failed to create {} directory: {e}", output_dir.display());
		return;
	}

	// Read the original README
	let content = match fs::read_to_string(INPUT_PATH) {
		| Ok(content) => content,
		| Err(e) => {
			eprintln!("Warning: Failed to read {INPUT_PATH}: {e}");
			return;
		}
	};

	// Transform GitHub links to rust doc links
	let transformed_content = transform_example_links(&content);

	// Write the transformed content
	if let Err(e) = fs::write(&output_path, transformed_content) {
		eprintln!("Warning: Failed to write {}: {}", output_path.display(), e);
	} else {
		println!("Generated {}", output_path.display());
	}
}

fn transform_example_links(content: &str) -> String {
	// Add auto-generation warning at the top
	let header = format!(
		"<!-- \nTHIS FILE IS AUTO-GENERATED BY build.rs\n\nDO NOT EDIT THIS \
		 FILE DIRECTLY!\nInstead, edit {INPUT_PATH} and run `cargo build` to \
		 regenerate.\n-->\n\n"
	);

	// Regex to match links with #example marker
	// Pattern: [filename.rs](path#example) -> [filename.rs](example_modulename/index.html)
	let re = Regex::new(r"\[([^]]+\.rs)\]\([^)]*#example\)").unwrap();

	let transformed_content = re
		.replace_all(content, |caps: &regex::Captures| {
			let filename = &caps[1];

			// Extract module name from filename (remove .rs extension)
			let module_name = filename.replace(".rs", "");

			// Generate rust doc link
			format!("[{filename}](example_{module_name}/index.html)")
		})
		.to_string();

	format!("{header}{transformed_content}")
}

fn generate_readme_doc() {
	let out_dir = env::var("OUT_DIR").unwrap();
	let output_dir = Path::new(&out_dir).join("generated");
	let output_path = output_dir.join(README_OUTPUT_FILENAME);

	// Create output directory if it doesn't exist
	if let Err(e) = fs::create_dir_all(&output_dir) {
		eprintln!("Warning: Failed to create {} directory: {e}", output_dir.display());
		return;
	}

	// Read the original README
	let content = match fs::read_to_string(README_INPUT_PATH) {
		| Ok(content) => content,
		| Err(e) => {
			eprintln!("Warning: Failed to read {README_INPUT_PATH}: {e}");
			return;
		}
	};

	// Transform GitHub links to rust doc links
	let transformed_content = transform_readme_links(&content);

	// Write the transformed content
	if let Err(e) = fs::write(&output_path, transformed_content) {
		eprintln!("Warning: Failed to write {}: {}", output_path.display(), e);
	} else {
		println!("Generated {}", output_path.display());
	}
}

fn transform_readme_links(content: &str) -> String {
	// Add auto-generation warning at the top
	let header = format!(
		"<!-- \nTHIS FILE IS AUTO-GENERATED BY build.rs\n\nDO NOT EDIT THIS \
		 FILE DIRECTLY!\nInstead, edit {README_INPUT_PATH} and run `cargo \
		 build` to regenerate.\n-->\n\n"
	);

	// Transform GitHub examples link back to crate link for docs.rs
	// [examples/](examples/) -> [crate::examples]
	let examples_re = Regex::new(r"\[examples/\]\(examples/\)").unwrap();
	let transformed_content = examples_re
		.replace_all(content, "[`crate::examples`]")
		.to_string();

	format!("{header}{transformed_content}")
}