diff --git a/crates/cli/Cargo.toml b/crates/cli/Cargo.toml index 7610004..4b5a0d9 100644 --- a/crates/cli/Cargo.toml +++ b/crates/cli/Cargo.toml @@ -17,7 +17,7 @@ default = ["packet_capture", "bson", "json", "xml", "browser"] packet_capture = ["gamedig/packet_capture"] # Output formats -bson = ["dep:serde", "dep:bson", "dep:hex", "gamedig/serde"] +bson = ["dep:serde", "dep:bson", "dep:hex", "dep:base64", "gamedig/serde"] json = ["dep:serde", "dep:serde_json", "gamedig/serde"] xml = ["dep:serde", "dep:serde-xml-rs", "gamedig/serde"] @@ -40,6 +40,7 @@ serde = { version = "1", optional = true, default-features = false } # BSON bson = { version = "2.8.1", optional = true, default-features = false } +base64 = { version = "0.21.7", optional = true, default-features = false, features = ["std"]} hex = { version = "0.4.3", optional = true, default-features = false } # JSON @@ -50,3 +51,4 @@ serde-xml-rs = { version = "0.6.0", optional = true, default-features = false } # Browser webbrowser = { version = "0.8.12", optional = true, default-features = false } + diff --git a/crates/cli/src/main.rs b/crates/cli/src/main.rs index 84a4b1f..b106813 100644 --- a/crates/cli/src/main.rs +++ b/crates/cli/src/main.rs @@ -96,15 +96,23 @@ enum OutputMode { #[derive(Clone, Debug, PartialEq, Eq, ValueEnum)] enum OutputFormat { + /// Human readable structured output Debug, + /// RFC 8259 #[cfg(feature = "json")] JsonPretty, + /// RFC 8259 #[cfg(feature = "json")] Json, + /// Parser tries to be mostly XML 1.1 (RFC 7303) compliant #[cfg(feature = "xml")] Xml, + /// RFC 4648 section 8 #[cfg(feature = "bson")] - Bson, + BsonHex, + /// RFC 4648 section 4 + #[cfg(feature = "bson")] + BsonBase64, } /// Attempt to find a game from the [library game definitions](GAMES) based on @@ -211,9 +219,14 @@ fn output_result(output_mode: OutputMode, format: Ou OutputMode::ProtocolSpecific => panic!("XML format is not supported for protocol specific output"), }, #[cfg(feature = "bson")] - OutputFormat::Bson => match output_mode { - OutputMode::Generic => output_result_bson(result.as_json()), - OutputMode::ProtocolSpecific => output_result_bson(result.as_original()), + OutputFormat::BsonHex => match output_mode { + OutputMode::Generic => output_result_bson_hex(result.as_json()), + OutputMode::ProtocolSpecific => output_result_bson_hex(result.as_original()), + }, + #[cfg(feature = "bson")] + OutputFormat::BsonBase64 => match output_mode { + OutputMode::Generic => output_result_bson_base64(result.as_json()), + OutputMode::ProtocolSpecific => output_result_bson_base64(result.as_original()), }, } } @@ -248,7 +261,7 @@ fn output_result_xml(result: T) { } #[cfg(feature = "bson")] -fn output_result_bson(result: T) { +fn output_result_bson_hex(result: T) { let bson = bson::to_bson(&result).unwrap(); if let bson::Bson::Document(document) = bson { @@ -256,7 +269,22 @@ fn output_result_bson(result: T) { println!("{}", hex::encode(bytes)); } else { - panic!("Failed to convert result to BSON"); + panic!("Failed to convert result to BSON Hex"); + } +} + +#[cfg(feature = "bson")] +fn output_result_bson_base64(result: T) { + use base64::Engine; + + let bson = bson::to_bson(&result).unwrap(); + + if let bson::Bson::Document(document) = bson { + let bytes = bson::to_vec(&document).unwrap(); + + println!("{}", base64::prelude::BASE64_STANDARD.encode(&bytes)); + } else { + panic!("Failed to convert result to BSON Base64"); } }