bc_envelope_pattern/pattern/
dcbor_integration.rs

1//! # DCBor Pattern Integration
2//!
3//! This module provides integration between dcbor-pattern and
4//! bc-envelope-pattern, allowing dcbor patterns to be used as envelope patterns
5//! through conversion.
6
7use crate::{
8    DCBORPattern, Pattern, Result,
9    pattern::{
10        leaf::{
11            ArrayPattern, BoolPattern, ByteStringPattern, CBORPattern,
12            DatePattern, KnownValuePattern, LeafPattern, MapPattern,
13            NullPattern, NumberPattern, TaggedPattern, TextPattern,
14        },
15        meta::{AnyPattern, MetaPattern},
16    },
17};
18
19/// Convert a dcbor-pattern Pattern to a bc-envelope-pattern Pattern.
20///
21/// This function serves as the bridge between the two pattern systems,
22/// allowing dcbor-pattern expressions to be used in envelope pattern contexts.
23///
24/// # Arguments
25///
26/// * `dcbor_pattern` - The dcbor-pattern Pattern to convert
27///
28/// # Returns
29///
30/// * `Result<Pattern>` - The converted envelope pattern, or an error if
31///   conversion fails
32///
33/// # Examples
34///
35/// ```rust
36/// use dcbor_pattern as dp;
37/// use bc_envelope_pattern::dcbor_integration::convert_dcbor_pattern_to_envelope_pattern;
38///
39/// // Convert a simple boolean pattern
40/// let dcbor_bool = dp::Pattern::bool(true);
41/// let envelope_pattern = convert_dcbor_pattern_to_envelope_pattern(dcbor_bool).unwrap();
42/// ```
43pub fn convert_dcbor_pattern_to_envelope_pattern(
44    dcbor_pattern: DCBORPattern,
45) -> Result<Pattern> {
46    match dcbor_pattern {
47        DCBORPattern::Value(value_pattern) => {
48            convert_value_pattern_to_envelope_pattern(value_pattern)
49        }
50        DCBORPattern::Structure(structure_pattern) => {
51            convert_structure_pattern_to_envelope_pattern(structure_pattern)
52        }
53        DCBORPattern::Meta(meta_pattern) => {
54            convert_meta_pattern_to_envelope_pattern(meta_pattern)
55        }
56    }
57}
58
59/// Convert a dcbor-pattern ValuePattern to an envelope leaf pattern.
60fn convert_value_pattern_to_envelope_pattern(
61    value_pattern: dcbor_pattern::ValuePattern,
62) -> Result<Pattern> {
63    let leaf_pattern = match value_pattern {
64        dcbor_pattern::ValuePattern::Bool(bool_pattern) => {
65            LeafPattern::Bool(BoolPattern::from_dcbor_pattern(bool_pattern))
66        }
67        dcbor_pattern::ValuePattern::Number(number_pattern) => {
68            LeafPattern::Number(NumberPattern::from_dcbor_pattern(
69                number_pattern,
70            ))
71        }
72        dcbor_pattern::ValuePattern::Text(text_pattern) => {
73            LeafPattern::Text(TextPattern::from_dcbor_pattern(text_pattern))
74        }
75        dcbor_pattern::ValuePattern::ByteString(bytestring_pattern) => {
76            LeafPattern::ByteString(ByteStringPattern::from_dcbor_pattern(
77                bytestring_pattern,
78            ))
79        }
80        dcbor_pattern::ValuePattern::Date(date_pattern) => {
81            LeafPattern::Date(DatePattern::from_dcbor_pattern(date_pattern))
82        }
83        dcbor_pattern::ValuePattern::KnownValue(known_value_pattern) => {
84            LeafPattern::KnownValue(KnownValuePattern::from_dcbor_pattern(
85                known_value_pattern,
86            ))
87        }
88        dcbor_pattern::ValuePattern::Null(_) => LeafPattern::Null(NullPattern),
89        dcbor_pattern::ValuePattern::Digest(digest_pattern) => {
90            // Digest patterns don't have a direct envelope equivalent yet
91            // For now, wrap as a generic CBOR pattern
92            return Ok(Pattern::Leaf(LeafPattern::Cbor(
93                CBORPattern::from_dcbor_pattern(DCBORPattern::Value(
94                    dcbor_pattern::ValuePattern::Digest(digest_pattern),
95                )),
96            )));
97        }
98    };
99
100    Ok(Pattern::Leaf(leaf_pattern))
101}
102
103/// Convert a dcbor-pattern StructurePattern to an envelope pattern.
104fn convert_structure_pattern_to_envelope_pattern(
105    structure_pattern: dcbor_pattern::StructurePattern,
106) -> Result<Pattern> {
107    let leaf_pattern = match structure_pattern {
108        dcbor_pattern::StructurePattern::Array(array_pattern) => {
109            LeafPattern::Array(ArrayPattern::from_dcbor_array_pattern(
110                array_pattern,
111            ))
112        }
113        dcbor_pattern::StructurePattern::Map(map_pattern) => {
114            LeafPattern::Map(MapPattern::from_dcbor_pattern(map_pattern))
115        }
116        dcbor_pattern::StructurePattern::Tagged(tagged_pattern) => {
117            LeafPattern::Tag(TaggedPattern::from_dcbor_pattern(tagged_pattern))
118        }
119    };
120
121    Ok(Pattern::Leaf(leaf_pattern))
122}
123
124/// Convert a dcbor-pattern MetaPattern to an envelope meta pattern.
125fn convert_meta_pattern_to_envelope_pattern(
126    meta_pattern: dcbor_pattern::MetaPattern,
127) -> Result<Pattern> {
128    let meta_pattern_clone = meta_pattern.clone();
129    match meta_pattern {
130        dcbor_pattern::MetaPattern::Any(_) => {
131            // The dcbor "any" pattern corresponds to our "any" meta pattern
132            Ok(Pattern::Meta(MetaPattern::Any(AnyPattern::new())))
133        }
134        dcbor_pattern::MetaPattern::And(and_pattern) => {
135            // Convert AND pattern by recursively converting each sub-pattern
136            let mut converted_patterns = Vec::new();
137            for pattern in and_pattern.patterns() {
138                converted_patterns.push(
139                    convert_dcbor_pattern_to_envelope_pattern(pattern.clone())?,
140                );
141            }
142            Ok(Pattern::and(converted_patterns))
143        }
144        dcbor_pattern::MetaPattern::Or(or_pattern) => {
145            // Convert OR pattern by recursively converting each sub-pattern
146            let mut converted_patterns = Vec::new();
147            for pattern in or_pattern.patterns() {
148                converted_patterns.push(
149                    convert_dcbor_pattern_to_envelope_pattern(pattern.clone())?,
150                );
151            }
152            Ok(Pattern::or(converted_patterns))
153        }
154        dcbor_pattern::MetaPattern::Not(not_pattern) => {
155            // Convert NOT pattern by recursively converting the inner pattern
156            let inner_pattern = convert_dcbor_pattern_to_envelope_pattern(
157                not_pattern.pattern().clone(),
158            )?;
159            Ok(Pattern::not_matching(inner_pattern))
160        }
161        dcbor_pattern::MetaPattern::Capture(_capture_pattern) => {
162            // Capture patterns don't have a direct envelope equivalent yet
163            // For now, wrap as a generic CBOR pattern
164            Ok(Pattern::Leaf(LeafPattern::Cbor(
165                CBORPattern::from_dcbor_pattern(DCBORPattern::Meta(
166                    meta_pattern_clone,
167                )),
168            )))
169        }
170        dcbor_pattern::MetaPattern::Repeat(_repeat_pattern) => {
171            // Repeat patterns don't have a direct envelope equivalent
172            // For now, wrap as a generic CBOR pattern
173            Ok(Pattern::Leaf(LeafPattern::Cbor(
174                CBORPattern::from_dcbor_pattern(DCBORPattern::Meta(
175                    meta_pattern_clone,
176                )),
177            )))
178        }
179        dcbor_pattern::MetaPattern::Search(_search_pattern) => {
180            // Search patterns don't have a direct envelope equivalent
181            // For now, wrap as a generic CBOR pattern
182            Ok(Pattern::Leaf(LeafPattern::Cbor(
183                CBORPattern::from_dcbor_pattern(DCBORPattern::Meta(
184                    meta_pattern_clone,
185                )),
186            )))
187        }
188        dcbor_pattern::MetaPattern::Sequence(_sequence_pattern) => {
189            // Sequence patterns don't have a direct envelope equivalent
190            // For now, wrap as a generic CBOR pattern
191            Ok(Pattern::Leaf(LeafPattern::Cbor(
192                CBORPattern::from_dcbor_pattern(DCBORPattern::Meta(
193                    meta_pattern_clone,
194                )),
195            )))
196        }
197    }
198}
199
200#[cfg(test)]
201mod tests {
202    use dcbor_pattern as dp;
203
204    use super::*;
205
206    #[test]
207    fn test_convert_bool_pattern() {
208        let dcbor_bool = dp::Pattern::bool(true);
209        let envelope_pattern =
210            convert_dcbor_pattern_to_envelope_pattern(dcbor_bool).unwrap();
211
212        match envelope_pattern {
213            Pattern::Leaf(LeafPattern::Bool(_)) => {
214                // Success - converted to boolean pattern
215            }
216            _ => panic!("Expected boolean leaf pattern"),
217        }
218    }
219
220    #[test]
221    fn test_convert_number_pattern() {
222        let dcbor_number = dp::Pattern::number(42);
223        let envelope_pattern =
224            convert_dcbor_pattern_to_envelope_pattern(dcbor_number).unwrap();
225
226        match envelope_pattern {
227            Pattern::Leaf(LeafPattern::Number(_)) => {
228                // Success - converted to number pattern
229            }
230            _ => panic!("Expected number leaf pattern"),
231        }
232    }
233
234    #[test]
235    fn test_convert_text_pattern() {
236        let dcbor_text = dp::Pattern::text("hello");
237        let envelope_pattern =
238            convert_dcbor_pattern_to_envelope_pattern(dcbor_text).unwrap();
239
240        match envelope_pattern {
241            Pattern::Leaf(LeafPattern::Text(_)) => {
242                // Success - converted to text pattern
243            }
244            _ => panic!("Expected text leaf pattern"),
245        }
246    }
247
248    #[test]
249    fn test_convert_any_pattern() {
250        let dcbor_any = dp::Pattern::any();
251        let envelope_pattern =
252            convert_dcbor_pattern_to_envelope_pattern(dcbor_any).unwrap();
253
254        match envelope_pattern {
255            Pattern::Meta(MetaPattern::Any(_)) => {
256                // Success - converted to any meta pattern
257            }
258            _ => panic!("Expected any meta pattern"),
259        }
260    }
261
262    #[test]
263    fn test_convert_or_pattern() {
264        let dcbor_or = dp::Pattern::or(vec![
265            dp::Pattern::bool(true),
266            dp::Pattern::number(42),
267        ]);
268        let envelope_pattern =
269            convert_dcbor_pattern_to_envelope_pattern(dcbor_or).unwrap();
270
271        match envelope_pattern {
272            Pattern::Meta(MetaPattern::Or(_)) => {
273                // Success - converted to or meta pattern
274            }
275            _ => panic!("Expected or meta pattern"),
276        }
277    }
278
279    #[test]
280    fn test_convert_and_pattern() {
281        let dcbor_and = dp::Pattern::and(vec![
282            dp::Pattern::any_bool(),
283            dp::Pattern::any_number(),
284        ]);
285        let envelope_pattern =
286            convert_dcbor_pattern_to_envelope_pattern(dcbor_and).unwrap();
287
288        match envelope_pattern {
289            Pattern::Meta(MetaPattern::And(_)) => {
290                // Success - converted to and meta pattern
291            }
292            _ => panic!("Expected and meta pattern"),
293        }
294    }
295
296    #[test]
297    fn test_convert_not_pattern() {
298        let dcbor_not = dp::Pattern::not_matching(dp::Pattern::bool(false));
299        let envelope_pattern =
300            convert_dcbor_pattern_to_envelope_pattern(dcbor_not).unwrap();
301
302        match envelope_pattern {
303            Pattern::Meta(MetaPattern::Not(_)) => {
304                // Success - converted to not meta pattern
305            }
306            _ => panic!("Expected not meta pattern"),
307        }
308    }
309
310    #[test]
311    fn test_convert_capture_pattern() {
312        // Since capture patterns don't have direct envelope equivalents,
313        // they should be wrapped as CBOR patterns
314        let dcbor_capture =
315            dp::Pattern::capture("test", dp::Pattern::bool(true));
316        let envelope_pattern =
317            convert_dcbor_pattern_to_envelope_pattern(dcbor_capture).unwrap();
318
319        match envelope_pattern {
320            Pattern::Leaf(LeafPattern::Cbor(_)) => {
321                // Success - converted to CBOR pattern (fallback)
322            }
323            _ => panic!("Expected CBOR leaf pattern as fallback"),
324        }
325    }
326}