Skip to main content

wpl/eval/builtins/
hex.rs

1use bytes::Bytes;
2use orion_error::compat_traits::ErrorOweBase;
3use orion_error::{ErrorWith, UvsFrom};
4use std::sync::Arc;
5
6use wp_model_core::raw::RawData;
7use wp_parse_api::{PipeProcessor, WparseReason, WparseResult};
8
9#[derive(Debug)]
10pub struct HexProc;
11
12impl PipeProcessor for HexProc {
13    /// Decodes hex-encoded data while preserving the input container type.
14    /// For string inputs, attempts UTF-8 conversion but falls back to bytes on invalid UTF-8.
15    fn process(&self, data: RawData) -> WparseResult<RawData> {
16        match data {
17            RawData::String(s) => {
18                let decoded = hex::decode(s.as_bytes())
19                    .owe(WparseReason::from_data())
20                    .doing("hex decode")?;
21                let vstring = String::from_utf8(decoded)
22                    .owe(WparseReason::from_data())
23                    .doing("to-json")?;
24                Ok(RawData::from_string(vstring))
25            }
26            RawData::Bytes(b) => {
27                let decoded = hex::decode(b.as_ref())
28                    .owe(WparseReason::from_data())
29                    .doing("hex decode")?;
30                Ok(RawData::Bytes(Bytes::from(decoded)))
31            }
32            RawData::ArcBytes(b) => {
33                let decoded = hex::decode(b.as_ref())
34                    .owe(WparseReason::from_data())
35                    .doing("hex decode")?;
36                // 注意:RawData::ArcBytes 现在使用 Arc<Vec<u8>>
37                Ok(RawData::ArcBytes(Arc::new(decoded)))
38            }
39        }
40    }
41
42    fn name(&self) -> &'static str {
43        "decode/hex"
44    }
45}
46
47#[cfg(test)]
48mod tests {
49    use crate::parser::error::IntoWplCodeError;
50    use crate::parser::error::WplCodeResult;
51    use bytes::Bytes;
52    use std::sync::Arc;
53
54    use super::*;
55
56    #[test]
57    fn test_hex() -> WplCodeResult<()> {
58        let data = RawData::from_string("48656c6c6f20776f726c6421".to_string());
59        let y = HexProc.process(data).map_err(|e| e.into_wpl_err())?;
60        assert_eq!(
61            crate::eval::builtins::raw_to_utf8_string(&y),
62            "Hello world!"
63        );
64
65        // Test with a longer complex hex string
66        let data = RawData::from_string("5468697320697320612074657374206f6620612068657820656e636f64656420737472696e672120405f5f252026262a2b2b".to_string());
67        let what = HexProc.process(data).map_err(|e| e.into_wpl_err())?;
68        let decoded = crate::eval::builtins::raw_to_utf8_string(&what);
69        assert!(decoded.starts_with("This is a test of a hex encoded string! @__% &&*++"));
70
71        let bytes_data = RawData::Bytes(Bytes::from_static(b"48656c6c6f"));
72        let result = HexProc.process(bytes_data).map_err(|e| e.into_wpl_err())?;
73        assert!(matches!(result, RawData::Bytes(_)));
74        assert_eq!(crate::eval::builtins::raw_to_utf8_string(&result), "Hello");
75
76        let arc_data = RawData::ArcBytes(Arc::new(b"48656c6c6f20776f726c64".to_vec()));
77        let result = HexProc.process(arc_data).map_err(|e| e.into_wpl_err())?;
78        assert!(matches!(result, RawData::ArcBytes(_)));
79        assert_eq!(
80            crate::eval::builtins::raw_to_utf8_string(&result),
81            "Hello world"
82        );
83        Ok(())
84    }
85}