config_disassembler/xml_cmd.rs
1//! `xml` subcommand: thin wrapper around the in-tree XML disassembler CLI.
2//!
3//! All arguments after `config-disassembler xml` are forwarded directly to
4//! [`crate::xml::cli::run`], so every option from the original
5//! `xml-disassembler` crate works unchanged here. This subcommand
6//! intentionally does not duplicate any of the XML logic — it simply
7//! delegates to the in-tree port.
8
9use crate::error::{Error, Result};
10
11/// Run the in-tree XML disassembler CLI with the provided arguments.
12///
13/// `args` should be the trailing arguments after `config-disassembler xml`,
14/// e.g. `["disassemble", "path/to/file.xml", "--format", "json"]`.
15pub async fn run(args: Vec<String>) -> Result<()> {
16 let mut forwarded = Vec::with_capacity(args.len() + 1);
17 forwarded.push("xml-disassembler".to_string());
18 forwarded.extend(args);
19
20 crate::xml::cli::run(forwarded)
21 .await
22 .map_err(|e| Error::Xml(e.to_string()))
23}
24
25#[cfg(test)]
26mod tests {
27 use super::*;
28
29 #[tokio::test]
30 async fn run_forwards_args_and_succeeds_for_valid_disassemble() {
31 // Round-trip through the public entry point so a regression that
32 // short-circuits this function to `Ok(())` without actually invoking
33 // the in-tree XML CLI would be caught: the assertion below depends on
34 // files written by the underlying disassembler.
35 let tmp = tempfile::tempdir().unwrap();
36 let xml_path = tmp.path().join("sample.xml");
37 std::fs::write(
38 &xml_path,
39 r#"<?xml version="1.0" encoding="UTF-8"?>
40<Root xmlns="http://example.com">
41 <child><name>one</name></child>
42 <child><name>two</name></child>
43</Root>"#,
44 )
45 .unwrap();
46 run(vec![
47 "disassemble".to_string(),
48 xml_path.to_string_lossy().to_string(),
49 ])
50 .await
51 .unwrap();
52 assert!(tmp.path().join("sample").exists());
53 }
54
55 #[tokio::test]
56 async fn run_propagates_unknown_subcommand_as_ok() {
57 // The underlying CLI treats unknown subcommands as a non-error
58 // (prints a message and returns Ok). Asserting it explicitly here
59 // pins down the no-op shim behavior.
60 run(vec!["definitely-not-a-real-subcommand".to_string()])
61 .await
62 .unwrap();
63 }
64}