genomicframe_core/formats/bed/
expression.rs1use crate::error::{Error, Result};
2use crate::expression::{
3 extract_string, CompiledAndFilter, CompiledNotFilter, CompiledOrFilter, Expr,
4};
5use crate::expression::{extract_u64, ExprToFilter};
6use crate::filters::RecordFilter;
7use crate::formats::bed::filters::*;
8use crate::formats::bed::BedRecord;
9
10impl ExprToFilter<BedRecord> for Expr {
11 fn compile(&self) -> Result<Box<dyn RecordFilter<BedRecord>>> {
12 match self {
13 Expr::OnChromosome(chrom) => Ok(Box::new(ChromosomeFilter::new(chrom.clone()))),
15
16 Expr::Eq(left, right) if matches!(**left, Expr::Column(ref name) if name == "chrom") =>
18 {
19 let chrom = extract_string(right)?;
20 Ok(Box::new(ChromosomeFilter::new(chrom)))
21 }
22
23 Expr::Eq(left, right) if matches!(**left, Expr::Column(ref name) if name == "strand") =>
25 {
26 let strand_str = extract_string(right)?;
27 let strand = if strand_str == "+" {
28 crate::formats::bed::filters::Strand::Forward
29 } else if strand_str == "-" {
30 crate::formats::bed::filters::Strand::Reverse
31 } else {
32 return Err(Error::invalid_input("Strand must be '+' or '-'"));
33 };
34 Ok(Box::new(StrandFilter { strand }))
35 }
36
37 Expr::Gt(left, right) | Expr::Gte(left, right) if matches!(**left, Expr::Column(ref name) if name == "length") =>
39 {
40 let min_length = extract_u64(right)?;
41 Ok(Box::new(MinLengthFilter { min_length }))
42 }
43 Expr::Gt(left, right) | Expr::Gte(left, right) if matches!(**left, Expr::Column(ref name) if name == "score") =>
52 {
53 let min_score = extract_u64(right)? as f64;
54 Ok(Box::new(MinScoreFilter { min_score }))
55 }
56
57 Expr::InRegion(interval) => Ok(Box::new(RegionFilter {
59 chrom: interval.chrom.clone(),
60 start: interval.start,
61 end: interval.end,
62 })),
63
64 Expr::And(exprs) => {
66 if exprs.is_empty() {
67 return Err(Error::invalid_input("Empty AND expression"));
68 }
69
70 let mut result = exprs[0].compile()?;
71 for expr in &exprs[1..] {
72 let next = expr.compile()?;
73 result = Box::new(CompiledAndFilter {
74 left: result,
75 right: next,
76 });
77 }
78 Ok(result)
79 }
80
81 Expr::Or(exprs) => {
82 if exprs.is_empty() {
83 return Err(Error::invalid_input("Empty OR expression"));
84 }
85
86 let mut result = exprs[0].compile()?;
87 for expr in &exprs[1..] {
88 let next = expr.compile()?;
89 result = Box::new(CompiledOrFilter {
90 left: result,
91 right: next,
92 });
93 }
94 Ok(result)
95 }
96
97 Expr::Not(expr) => {
98 let inner = expr.compile()?;
99 Ok(Box::new(CompiledNotFilter { inner }))
100 }
101
102 _ => Err(Error::invalid_input(format!(
103 "Expression not supported for BED: {}",
104 self
105 ))),
106 }
107 }
108}