arch_pkg_db/text/multi/
parse.rs1use super::MultiTextCollection;
2use crate::{MultiQueryDatabase, Text, multi::InsertError, value::RepositoryName};
3use arch_pkg_text::desc::{Query, QueryMut, misc::ShouldReuse};
4use core::error::Error;
5use derive_more::Display;
6use pipe_trait::Pipe;
7use rayon::prelude::*;
8
9#[derive(Debug, Display, Clone)]
11#[display(bound(ParseError: Display))]
12pub enum MultiTextCollectionParseError<'a, ParseError> {
13 Parse(ParseError),
14 Insert(InsertError<'a>),
15}
16
17impl<'a, ParseError: Error> Error for MultiTextCollectionParseError<'a, ParseError> {
20 fn source(&self) -> Option<&(dyn Error + 'static)> {
21 match self {
22 MultiTextCollectionParseError::Parse(error) => error.source(),
23 MultiTextCollectionParseError::Insert(error) => error.source(),
24 }
25 }
26}
27
28type ParseResult<'a, Querier> = Result<
30 MultiQueryDatabase<'a, Querier>,
31 MultiTextCollectionParseError<'a, <&'a str as TryInto<Querier>>::Error>,
32>;
33
34impl<'a> MultiTextCollection<'a> {
35 fn parse_with<Querier, Insert, InsertSuccess>(
37 &'a self,
38 mut insert: Insert,
39 ) -> ParseResult<'a, Querier>
40 where
41 &'a str: TryInto<Querier>,
42 Insert: FnMut(
43 &mut MultiQueryDatabase<'a, Querier>,
44 RepositoryName<'a>,
45 Querier,
46 ) -> Result<InsertSuccess, InsertError<'a>>,
47 {
48 let iter = self.iter();
49 let (lower_cap, _) = iter.size_hint();
50 let mut db = MultiQueryDatabase::with_capacity(lower_cap);
51
52 for (repository, text) in iter {
53 let querier = text
54 .as_str()
55 .try_into()
56 .map_err(MultiTextCollectionParseError::Parse)?;
57 insert(&mut db, repository, querier).map_err(MultiTextCollectionParseError::Insert)?;
58 }
59
60 Ok(db)
61 }
62
63 pub fn parse<Querier>(&'a self) -> ParseResult<'a, Querier>
65 where
66 &'a str: TryInto<Querier>,
67 Querier: Query<'a> + ShouldReuse,
68 {
69 self.parse_with(MultiQueryDatabase::insert)
70 }
71
72 pub fn parse_mut<Querier>(&'a self) -> ParseResult<'a, Querier>
74 where
75 &'a str: TryInto<Querier>,
76 Querier: QueryMut<'a> + ShouldReuse,
77 {
78 self.parse_with(MultiQueryDatabase::insert_mut)
79 }
80
81 fn par_parse_with<Querier, QueriersIntoDb>(
83 &'a self,
84 queriers_into_db: QueriersIntoDb,
85 ) -> ParseResult<'a, Querier>
86 where
87 &'a str: TryInto<Querier, Error: Send>,
88 Querier: Send,
89 QueriersIntoDb: FnOnce(
90 Vec<(RepositoryName<'a>, Querier)>,
91 ) -> Result<MultiQueryDatabase<'a, Querier>, InsertError>,
92 {
93 self.internal
94 .par_iter()
95 .flat_map(|(repository, collection)| {
96 collection
97 .iter()
98 .par_bridge() .map(Text::as_str)
100 .map(TryInto::<Querier>::try_into)
101 .map(move |querier| querier.map(|querier| (*repository, querier)))
102 })
103 .collect::<Result<Vec<_>, _>>()
104 .map_err(MultiTextCollectionParseError::Parse)?
105 .pipe(queriers_into_db)
106 .map_err(MultiTextCollectionParseError::Insert)
107 }
108
109 pub fn par_parse<Querier>(&'a self) -> ParseResult<'a, Querier>
111 where
112 &'a str: TryInto<Querier, Error: Send>,
113 Querier: Query<'a> + ShouldReuse + Send,
114 {
115 self.par_parse_with(MultiQueryDatabase::from_queriers)
116 }
117
118 pub fn par_parse_mut<Querier>(&'a self) -> ParseResult<'a, Querier>
120 where
121 &'a str: TryInto<Querier, Error: Send>,
122 Querier: QueryMut<'a> + ShouldReuse + Send,
123 {
124 self.par_parse_with(MultiQueryDatabase::from_queriers_mut)
125 }
126}