genomicframe_core/formats/fastq/
expression.rs1use crate::error::{Error, Result};
2use crate::expression::{extract_f64, extract_usize, ExprToFilter};
3use crate::expression::{CompiledAndFilter, CompiledNotFilter, CompiledOrFilter, Expr};
4use crate::filters::RecordFilter;
5use crate::formats::fastq::filters::*;
6use crate::formats::fastq::FastqRecord;
7
8impl ExprToFilter<FastqRecord> for Expr {
9 fn compile(&self) -> Result<Box<dyn RecordFilter<FastqRecord>>> {
10 match self {
11 Expr::Gt(left, right) | Expr::Gte(left, right) if matches!(**left, Expr::Column(ref name) if name == "quality" || name == "qual") =>
13 {
14 let min_mean_qual = extract_f64(right)?;
15 Ok(Box::new(QualityFilter { min_mean_qual }))
16 }
17
18 Expr::Gt(left, right) | Expr::Gte(left, right) if matches!(**left, Expr::Column(ref name) if name == "length") =>
20 {
21 let min_length = extract_usize(right)?;
22 Ok(Box::new(MinLengthFilter { min_length }))
23 }
24
25 Expr::Lt(left, right) | Expr::Lte(left, right) if matches!(**left, Expr::Column(ref name) if name == "length") =>
26 {
27 let max_length = extract_usize(right)?;
28 Ok(Box::new(LengthFilter {
29 min_length: 0,
30 max_length,
31 }))
32 }
33
34 Expr::Gt(left, right) | Expr::Gte(left, right) if matches!(**left, Expr::Column(ref name) if name == "gc_content") =>
36 {
37 let min_gc = extract_f64(right)?;
38 Ok(Box::new(GCContentFilter {
39 min_gc,
40 max_gc: 1.0,
41 }))
42 }
43
44 Expr::And(exprs) => {
46 if exprs.is_empty() {
47 return Err(Error::invalid_input("Empty AND expression"));
48 }
49
50 let mut result = exprs[0].compile()?;
51 for expr in &exprs[1..] {
52 let next = expr.compile()?;
53 result = Box::new(CompiledAndFilter {
54 left: result,
55 right: next,
56 });
57 }
58 Ok(result)
59 }
60
61 Expr::Or(exprs) => {
62 if exprs.is_empty() {
63 return Err(Error::invalid_input("Empty OR expression"));
64 }
65
66 let mut result = exprs[0].compile()?;
67 for expr in &exprs[1..] {
68 let next = expr.compile()?;
69 result = Box::new(CompiledOrFilter {
70 left: result,
71 right: next,
72 });
73 }
74 Ok(result)
75 }
76
77 Expr::Not(expr) => {
78 let inner = expr.compile()?;
79 Ok(Box::new(CompiledNotFilter { inner }))
80 }
81
82 _ => Err(Error::invalid_input(format!(
83 "Expression not supported for FASTQ: {}",
84 self
85 ))),
86 }
87 }
88}