Skip to main content

wpl/eval/builtins/
hex.rs

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