brk_interface/
lib.rs

1#![doc = include_str!("../README.md")]
2
3use std::collections::BTreeMap;
4
5use brk_computer::Computer;
6use brk_error::Result;
7use brk_indexer::Indexer;
8use brk_structs::Height;
9use tabled::settings::Style;
10use vecdb::{AnyCollectableVec, AnyStoredVec};
11
12mod deser;
13mod format;
14mod index;
15mod maybe_ids;
16mod output;
17mod pagination;
18mod params;
19mod table;
20mod vecs;
21
22pub use format::Format;
23pub use index::Index;
24pub use output::{Output, Value};
25pub use pagination::{PaginatedIndexParam, PaginationParam};
26pub use params::{IdParam, Params, ParamsOpt};
27pub use table::Tabled;
28use vecs::Vecs;
29
30use crate::vecs::{IdToVec, IndexToVec};
31
32#[allow(dead_code)]
33pub struct Interface<'a> {
34    vecs: Vecs<'a>,
35    indexer: &'a Indexer,
36    computer: &'a Computer,
37}
38
39impl<'a> Interface<'a> {
40    pub fn build(indexer: &Indexer, computer: &Computer) -> Self {
41        let indexer = indexer.static_clone();
42        let computer = computer.static_clone();
43        let vecs = Vecs::build(indexer, computer);
44
45        Self {
46            vecs,
47            indexer,
48            computer,
49        }
50    }
51
52    pub fn get_height(&self) -> Height {
53        Height::from(self.indexer.vecs.height_to_blockhash.stamp())
54    }
55
56    pub fn search(&self, params: &Params) -> Vec<(String, &&dyn AnyCollectableVec)> {
57        let tuples = params
58            .ids
59            .iter()
60            .flat_map(|s| {
61                s.to_lowercase()
62                    .replace("-", "_")
63                    .split_whitespace()
64                    .flat_map(|s| {
65                        s.split(',')
66                            .flat_map(|s| s.split('+').map(|s| s.to_string()))
67                    })
68                    .collect::<Vec<_>>()
69            })
70            .map(|mut id| {
71                let mut res = self.vecs.id_to_index_to_vec.get(id.as_str());
72                if res.is_none()
73                    && let Ok(index) = Index::try_from(id.as_str())
74                {
75                    id = index.possible_values().last().unwrap().to_string();
76                    res = self.vecs.id_to_index_to_vec.get(id.as_str())
77                }
78                (id, res)
79            })
80            .filter(|(_, opt)| opt.is_some())
81            .map(|(id, vec)| (id, vec.unwrap()))
82            .collect::<Vec<_>>();
83
84        tuples
85            .iter()
86            .flat_map(|(str, i_to_v)| i_to_v.get(&params.index).map(|vec| (str.to_owned(), vec)))
87            .collect::<Vec<_>>()
88    }
89
90    pub fn format(
91        &self,
92        vecs: Vec<(String, &&dyn AnyCollectableVec)>,
93        params: &ParamsOpt,
94    ) -> Result<Output> {
95        let from = params.from().map(|from| {
96            vecs.iter()
97                .map(|(_, v)| v.i64_to_usize(from))
98                .min()
99                .unwrap_or_default()
100        });
101
102        let to = params.to().map(|to| {
103            vecs.iter()
104                .map(|(_, v)| v.i64_to_usize(to))
105                .min()
106                .unwrap_or_default()
107        });
108
109        let mut values = vecs
110            .iter()
111            .map(|(_, vec)| -> Result<Vec<serde_json::Value>> {
112                Ok(vec.collect_range_serde_json(from, to)?)
113            })
114            .collect::<Result<Vec<_>>>()?;
115
116        let format = params.format();
117
118        if values.is_empty() {
119            return Ok(Output::default(format));
120        }
121
122        let ids_last_i = vecs.len() - 1;
123
124        Ok(match format {
125            Some(Format::CSV) | Some(Format::TSV) => {
126                let delimiter = if format == Some(Format::CSV) {
127                    ','
128                } else {
129                    '\t'
130                };
131
132                let mut text = vecs
133                    .iter()
134                    .map(|(id, _)| id.to_owned())
135                    .collect::<Vec<_>>()
136                    .join(&delimiter.to_string());
137
138                text.push('\n');
139
140                let values_len = values.first().unwrap().len();
141
142                (0..values_len).for_each(|i| {
143                    let mut line = "".to_string();
144                    values.iter().enumerate().for_each(|(id_i, v)| {
145                        line += &v.get(i).unwrap().to_string();
146                        if id_i == ids_last_i {
147                            line.push('\n');
148                        } else {
149                            line.push(delimiter);
150                        }
151                    });
152                    text += &line;
153                });
154
155                if format == Some(Format::CSV) {
156                    Output::CSV(text)
157                } else {
158                    Output::TSV(text)
159                }
160            }
161            Some(Format::MD) => {
162                let mut table =
163                    values.to_table(vecs.iter().map(|(s, _)| s.to_owned()).collect::<Vec<_>>());
164
165                table.with(Style::markdown());
166
167                Output::MD(table.to_string())
168            }
169            Some(Format::JSON) | None => {
170                if values.len() == 1 {
171                    let mut values = values.pop().unwrap();
172                    if values.len() == 1 {
173                        let value = values.pop().unwrap();
174                        Output::Json(Value::Single(value))
175                    } else {
176                        Output::Json(Value::List(values))
177                    }
178                } else {
179                    Output::Json(Value::Matrix(values))
180                }
181            }
182        })
183    }
184
185    pub fn search_and_format(&self, params: Params) -> Result<Output> {
186        self.format(self.search(&params), &params.rest)
187    }
188
189    pub fn id_to_index_to_vec(&self) -> &BTreeMap<&str, IndexToVec<'_>> {
190        &self.vecs.id_to_index_to_vec
191    }
192
193    pub fn index_to_id_to_vec(&self) -> &BTreeMap<Index, IdToVec<'_>> {
194        &self.vecs.index_to_id_to_vec
195    }
196
197    pub fn get_vecid_count(&self) -> usize {
198        self.vecs.id_count
199    }
200
201    pub fn get_index_count(&self) -> usize {
202        self.vecs.index_count
203    }
204
205    pub fn get_vec_count(&self) -> usize {
206        self.vecs.vec_count
207    }
208
209    pub fn get_indexes(&self) -> &[&'static str] {
210        &self.vecs.indexes
211    }
212
213    pub fn get_accepted_indexes(&self) -> &BTreeMap<&'static str, &'static [&'static str]> {
214        &self.vecs.accepted_indexes
215    }
216
217    pub fn get_vecids(&self, pagination: PaginationParam) -> &[&str] {
218        self.vecs.ids(pagination)
219    }
220
221    pub fn get_index_to_vecids(&self, paginated_index: PaginatedIndexParam) -> Vec<&str> {
222        self.vecs.index_to_ids(paginated_index)
223    }
224
225    pub fn get_vecid_to_indexes(&self, id: String) -> Option<&Vec<&'static str>> {
226        self.vecs.id_to_indexes(id)
227    }
228}