srdf/
query_srdf.rs

1use std::fmt::Display;
2
3use crate::Rdf;
4
5pub trait Sparql: Rdf {
6    fn query_select(&self, query: &str) -> Result<QuerySolutions<Self>, Self::Err>
7    where
8        Self: Sized;
9
10    fn query_ask(&self, query: &str) -> Result<bool, Self::Err>;
11}
12
13#[derive(PartialEq, Eq, Debug, Clone, Hash)]
14pub struct VarName {
15    str: String,
16}
17
18impl Display for VarName {
19    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
20        write!(f, "?{}", self.str)
21    }
22}
23
24impl VarName {
25    pub fn new(str: &str) -> VarName {
26        VarName {
27            str: str.to_string(),
28        }
29    }
30}
31
32impl From<String> for VarName {
33    fn from(value: String) -> Self {
34        VarName { str: value }
35    }
36}
37
38pub trait VariableSolutionIndex<S: Rdf> {
39    fn index(self, solution: &QuerySolution<S>) -> Option<usize>;
40}
41
42impl<S: Rdf> VariableSolutionIndex<S> for usize {
43    #[inline]
44    fn index(self, _: &QuerySolution<S>) -> Option<usize> {
45        Some(self)
46    }
47}
48
49impl<S: Rdf> VariableSolutionIndex<S> for &str {
50    #[inline]
51    fn index(self, solution: &QuerySolution<S>) -> Option<usize> {
52        solution.variables.iter().position(|v| v.str == self)
53    }
54}
55
56impl<S: Rdf> VariableSolutionIndex<S> for &VarName {
57    #[inline]
58    fn index(self, solution: &QuerySolution<S>) -> Option<usize> {
59        solution.variables.iter().position(|v| *v.str == self.str)
60    }
61}
62
63/// Represents one query solution
64#[derive(Debug, Clone)]
65pub struct QuerySolution<S: Rdf> {
66    variables: Vec<VarName>,
67    values: Vec<Option<S::Term>>,
68}
69
70impl<S: Rdf> QuerySolution<S> {
71    pub fn new(variables: Vec<VarName>, values: Vec<Option<S::Term>>) -> QuerySolution<S> {
72        QuerySolution { variables, values }
73    }
74
75    pub fn find_solution(&self, index: impl VariableSolutionIndex<S>) -> Option<&S::Term> {
76        match self.values.get(index.index(self)?) {
77            Some(value) => value.as_ref(),
78            None => None,
79        }
80    }
81
82    pub fn variables(&self) -> impl Iterator<Item = &VarName> {
83        self.variables.iter()
84    }
85
86    pub fn convert<T: Rdf, F>(&self, cnv_term: F) -> QuerySolution<T>
87    where
88        F: Fn(&S::Term) -> T::Term,
89    {
90        let cnv_values: Vec<Option<T::Term>> = self
91            .values
92            .iter()
93            .map(|s| s.as_ref().map(&cnv_term))
94            .collect();
95        QuerySolution {
96            variables: self.variables.clone(),
97            values: cnv_values,
98        }
99    }
100
101    pub fn show(&self) -> String {
102        let mut result = String::new();
103        for var in self.variables.iter() {
104            let value = match self.find_solution(var) {
105                None => "()".to_string(),
106                Some(v) => format!("{v}"),
107            };
108            result.push_str(format!("{} -> {}\n", var, value).as_str())
109        }
110        result
111    }
112}
113
114impl<S: Rdf, V: Into<Vec<VarName>>, T: Into<Vec<Option<S::Term>>>> From<(V, T)>
115    for QuerySolution<S>
116{
117    #[inline]
118    fn from((v, s): (V, T)) -> Self {
119        Self {
120            variables: v.into(),
121            values: s.into(),
122        }
123    }
124}
125
126/// Represent a list of query solutions
127#[derive(Debug, Clone)]
128pub struct QuerySolutions<S: Rdf> {
129    solutions: Vec<QuerySolution<S>>,
130}
131
132impl<S: Rdf> QuerySolutions<S> {
133    pub fn empty() -> QuerySolutions<S> {
134        QuerySolutions {
135            solutions: Vec::new(),
136        }
137    }
138
139    pub fn new(solutions: Vec<QuerySolution<S>>) -> QuerySolutions<S> {
140        QuerySolutions { solutions }
141    }
142
143    pub fn extend(&mut self, solutions: Vec<QuerySolution<S>>) {
144        self.solutions.extend(solutions)
145    }
146
147    pub fn iter(&self) -> impl Iterator<Item = &QuerySolution<S>> {
148        self.solutions.iter()
149    }
150
151    pub fn count(&self) -> usize {
152        self.solutions.len()
153    }
154}
155
156impl<S: Rdf> IntoIterator for QuerySolutions<S> {
157    type Item = QuerySolution<S>;
158    type IntoIter = std::vec::IntoIter<QuerySolution<S>>;
159
160    fn into_iter(self) -> Self::IntoIter {
161        self.solutions.into_iter()
162    }
163}