pak_db/
query.rs

1#![doc = include_str!("../docs/queries.md")]
2
3use std::{collections::HashSet, ops::{BitAnd, BitOr}};
4use crate::{error::PakResult, pointer::PakTypedPointer};
5use super::{value::PakValue, Pak};
6
7//==============================================================================================
8//        Pak Query
9//==============================================================================================
10
11pub trait PakQueryExpression {
12    fn execute(&self, pak : &Pak) -> PakResult<HashSet<PakTypedPointer>>;
13}
14
15pub struct PakQueryUnion(Box<dyn PakQueryExpression>, Box<dyn PakQueryExpression>);
16
17impl PakQueryExpression for PakQueryUnion {
18    fn execute(&self, pak : &Pak) -> PakResult<HashSet<PakTypedPointer>> {
19        let results_a = self.0.execute(pak)?;
20        let results_b = self.1.execute(pak)?;
21        let results = results_a.into_iter().chain(results_b.into_iter()).collect::<HashSet<_>>();
22        Ok(results)
23    }
24}
25
26impl<B> BitOr<B> for PakQueryUnion where B : PakQueryExpression + 'static {
27    type Output = Self;
28
29    fn bitor(self, other: B) -> Self::Output {
30        PakQueryUnion(Box::new(self), Box::new(other))
31    }
32}
33
34impl <B> BitOr<B> for PakQueryIntersection where B : PakQueryExpression + 'static {
35    type Output = PakQueryUnion;
36
37    fn bitor(self, other: B) -> Self::Output {
38        PakQueryUnion(Box::new(self), Box::new(other))
39    }
40}
41
42impl <B> BitOr<B> for PakQuery where B : PakQueryExpression + 'static {
43    type Output = PakQueryUnion;
44
45    fn bitor(self, other: B) -> Self::Output {
46        PakQueryUnion(Box::new(self), Box::new(other))
47    }
48}
49
50//==============================================================================================
51//        Pak Query Intersection
52//==============================================================================================
53
54pub struct PakQueryIntersection(Box::<dyn PakQueryExpression>, Box::<dyn PakQueryExpression>);
55
56impl PakQueryExpression for PakQueryIntersection {
57    fn execute(&self, pak : &Pak) -> PakResult<HashSet<PakTypedPointer>> {
58        let results_a = self.0.execute(pak)?;
59        let results_b = self.1.execute(pak)?;
60        Ok(results_a.into_iter().filter(|e| results_b.contains(e)).collect())
61    }
62}
63
64impl <B> BitAnd<B> for PakQuery where B : PakQueryExpression + 'static {
65    type Output = PakQueryIntersection;
66
67    fn bitand(self, rhs: B) -> Self::Output {
68        PakQueryIntersection(Box::new(self), Box::new(rhs))
69    }
70}
71
72impl <B> BitAnd<B> for PakQueryUnion where B : PakQueryExpression + 'static {
73    type Output = PakQueryIntersection;
74
75    fn bitand(self, rhs: B) -> Self::Output {
76        PakQueryIntersection(Box::new(self), Box::new(rhs))
77    }
78}
79
80impl <B> BitAnd<B> for PakQueryIntersection where B : PakQueryExpression + 'static {
81    type Output = PakQueryIntersection;
82
83    fn bitand(self, rhs: B) -> Self::Output {
84        PakQueryIntersection(Box::new(self), Box::new(rhs))
85    }
86}
87
88
89//==============================================================================================
90//        Pak Query Expression
91//==============================================================================================
92
93pub enum PakQuery {
94    Equal(String, PakValue),
95    GreaterThan(String, PakValue),
96    LessThan(String, PakValue),
97    GreaterThanEqual(String, PakValue),
98    LessThanEqual(String, PakValue),
99    Contains(String, PakValue)
100}
101
102impl PakQuery {
103    pub fn equals(key : &str, value : impl Into<PakValue>) -> Self {
104        PakQuery::Equal(key.to_string(), value.into())
105    }
106
107    pub fn greater_than(key : &str, value : impl Into<PakValue>) -> Self {
108        PakQuery::GreaterThan(key.to_string(), value.into())
109    }
110
111    pub fn less_than(key : &str, value : impl Into<PakValue>) -> Self {
112        PakQuery::LessThan(key.to_string(), value.into())
113    }
114    
115    pub fn greater_than_or_equal(key : &str, value : impl Into<PakValue>) -> Self {
116        PakQuery::GreaterThanEqual(key.to_string(), value.into())
117    }
118    
119    pub fn less_than_or_equal(key : &str, value : impl Into<PakValue>) -> Self {
120        PakQuery::LessThanEqual(key.to_string(), value.into())
121    }
122    
123    pub fn contains(key : &str, value : impl Into<PakValue>) -> Self {
124        PakQuery::Contains(key.to_string(), value.into())
125    }
126}
127
128pub fn equals(key : &str, value : impl Into<PakValue>) -> PakQuery {
129    PakQuery::Equal(key.to_string(), value.into())
130}
131
132pub fn greater_than(key : &str, value : impl Into<PakValue>) -> PakQuery {
133    PakQuery::GreaterThan(key.to_string(), value.into())
134}
135
136pub fn less_than(key : &str, value : impl Into<PakValue>) -> PakQuery {
137    PakQuery::LessThan(key.to_string(), value.into())
138}
139
140pub fn greater_than_equal(key : &str, value : impl Into<PakValue>) -> PakQuery {
141    PakQuery::GreaterThanEqual(key.to_string(), value.into())
142}
143
144pub fn less_than_equal(key : &str, value : impl Into<PakValue>) -> PakQuery {
145    PakQuery::LessThanEqual(key.to_string(), value.into())
146}
147
148impl PakQueryExpression for PakQuery {
149    fn execute(&self, pak : &Pak) -> PakResult<HashSet<PakTypedPointer>> {
150        match self {
151            PakQuery::Equal(key, pak_value) => {
152                let tree = pak.get_tree(key)?;
153                tree.get(pak_value)
154            },
155            PakQuery::GreaterThan(key, pak_value) => {
156                let tree = pak.get_tree(key)?;
157                tree.get_greater(pak_value)
158            },
159            PakQuery::LessThan(key, pak_value) => {
160                let tree = pak.get_tree(key)?;
161                tree.get_less(pak_value)
162            },
163            PakQuery::GreaterThanEqual(key, pak_value) => {
164                let tree = pak.get_tree(key)?;
165                tree.get_greater_eq(pak_value)
166            },
167            PakQuery::LessThanEqual(key, pak_value) => {
168                let tree = pak.get_tree(key)?;
169                tree.get_less_eq(pak_value)
170            },
171            PakQuery::Contains(key, pak_value) => {
172                let tree = pak.get_tree(key)?;
173                tree.get_contains(pak_value)
174            }
175        }
176    }
177}