Skip to main content

wp_parse_api/
lib.rs

1//! Minimal Plugin API for WPL parsers.
2//! This crate defines core types for plugin development while maintaining
3//! compatibility with the wp-lang ecosystem.
4
5use std::sync::Arc;
6
7use wp_model_core::model::DataRecord;
8
9mod error;
10pub use error::{WparseError, WparseReason, WparseResult};
11#[allow(deprecated)]
12pub use error::{WplParseError, WplParseReason, WplParseResult};
13use wp_model_core::raw::RawData;
14// Re-export necessary types from wp-lang that we still need
15
16/// Result type for plugin parsing operations.
17///
18/// On success, returns a tuple of `(DataRecord, remaining_raw)`.
19/// On failure, returns a WparseError (旧名称 `WplParseError` 仍可用,但已弃用)。
20pub type DataResult = Result<(DataRecord, RawData), WparseError>;
21
22/// Trait for pipeline data processing operations.
23///
24/// This trait defines the interface for components that process RawData
25/// within a data pipeline, transforming it from one format to another
26/// (e.g., base64 decoding, hex decoding, string unescaping, etc.).
27///
28/// Pipeline processors are executed in sequence as part of a data processing
29/// pipeline, with the output of one processor becoming the input of the next.
30pub trait PipeProcessor {
31    /// Process the input data and return the transformed result.
32    ///
33    /// # Arguments
34    /// * `data` - The input data to be processed
35    ///
36    /// # Returns
37    /// The processed data in the appropriate output format
38    fn process(&self, data: RawData) -> WparseResult<RawData>;
39
40    /// Get the name/identifier of this pipeline processor.
41    ///
42    /// # Returns
43    /// A string slice representing the processor name
44    fn name(&self) -> &'static str;
45}
46
47pub type PipeHold = Arc<dyn PipeProcessor + Send + Sync>;
48
49#[cfg(test)]
50mod tests {
51    use super::RawData;
52    use bytes::Bytes;
53    use std::sync::Arc;
54
55    #[test]
56    fn rawdata_as_bytes_and_len_cover_all_variants() {
57        let text = RawData::from_string("hello");
58        assert_eq!(text.as_bytes(), b"hello");
59        assert_eq!(text.len(), 5);
60        assert!(!text.is_zero_copy());
61
62        let bytes = RawData::Bytes(Bytes::from_static(b"bin"));
63        assert_eq!(bytes.as_bytes(), b"bin");
64        assert_eq!(bytes.len(), 3);
65        assert!(bytes.to_bytes().eq(&Bytes::from_static(b"bin")));
66        assert!(!bytes.is_zero_copy());
67
68        let arc = Arc::new(vec![1u8, 2, 3, 4]);
69        let arc_raw = RawData::from_arc_bytes(arc.clone());
70        assert_eq!(arc_raw.as_bytes(), arc.as_slice());
71        assert_eq!(arc_raw.len(), 4);
72        assert!(arc_raw.is_zero_copy());
73        let bytes_from_arc = arc_raw.to_bytes();
74        assert_eq!(bytes_from_arc.as_ref(), &[1, 2, 3, 4]);
75
76        let owned = RawData::from_arc_bytes(Arc::new(vec![5u8, 6, 7]));
77        let converted = owned.into_bytes();
78        assert_eq!(converted.as_ref(), &[5, 6, 7]);
79    }
80
81    #[test]
82    fn rawdata_is_empty_handles_all_variants() {
83        assert!(RawData::from_string("").is_empty());
84        assert!(RawData::Bytes(Bytes::new()).is_empty());
85        assert!(RawData::from_arc_bytes(Arc::new(vec![])).is_empty());
86        assert!(!RawData::from_string("x").is_empty());
87    }
88}