sql_fun_core/extensions/
extension_collection.rs1use std::{
2 fmt::{Display, Write},
3 path::{Path, PathBuf},
4 str::FromStr,
5};
6
7use combine::{
8 EasyParser, ParseError, Parser, Stream, eof,
9 parser::char::{char, spaces},
10 sep_end_by,
11};
12
13use crate::{ExtensionConfigError, ExtensionNameVersionPair, IVec};
14
15#[derive(Debug, serde::Deserialize, Clone, Default)]
17#[serde(transparent)]
18pub struct PostgresExtensionsCollection(IVec<ExtensionNameVersionPair>);
19
20impl Display for PostgresExtensionsCollection {
21 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
22 for (index, item) in self.0.iter().enumerate() {
23 if index == self.0.len() - 1 {
24 write!(f, "{item}")?;
25 } else {
26 write!(f, "{item},")?;
27 }
28 }
29 Ok(())
30 }
31}
32
33impl PostgresExtensionsCollection {
34 pub fn sql_files<P: AsRef<Path>>(
44 &mut self,
45 base_path: P,
46 ) -> Result<IVec<PathBuf>, ExtensionConfigError> {
47 let mut result = Vec::new();
48 for item in &mut self.0 {
49 result.push(item.resolve_version(&base_path)?);
50 }
51 Ok(IVec::from(result))
52 }
53
54 pub fn resolve_versions<P: AsRef<Path>>(
61 &mut self,
62 base_path: P,
63 ) -> Result<(), ExtensionConfigError> {
64 for item in &mut self.0 {
65 item.resolve_version(&base_path)?;
66 }
67 Ok(())
68 }
69
70 fn list_of_pair_parser<Input>()
71 -> impl Parser<Input, Output = Vec<Result<ExtensionNameVersionPair, ExtensionConfigError>>>
72 where
73 Input: Stream<Token = char>,
74 Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
75 {
76 spaces()
77 .with(sep_end_by(
78 ExtensionNameVersionPair::parser().skip(spaces()),
79 char(',').skip(spaces()),
80 ))
81 .skip(spaces())
82 }
83
84 fn list_of_pair_eof_parser<Input>()
85 -> impl Parser<Input, Output = Vec<Result<ExtensionNameVersionPair, ExtensionConfigError>>>
86 where
87 Input: Stream<Token = char>,
88 Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
89 {
90 Self::list_of_pair_parser().skip(eof())
91 }
92
93 fn parse(input: &str) -> Result<Vec<ExtensionNameVersionPair>, String> {
94 let parsed = Self::list_of_pair_eof_parser()
95 .easy_parse(input)
96 .map_err(|e| e.to_string())?;
97 let mut results = Vec::new();
98 let mut errors = String::new();
99 for item in parsed.0 {
100 match item {
101 Ok(v) => results.push(v),
102 Err(e) => writeln!(&mut errors, "{e}").expect("writing to string"),
103 }
104 }
105 if errors.is_empty() {
106 Ok(results)
107 } else {
108 Err(errors)
109 }
110 }
111}
112
113impl FromStr for PostgresExtensionsCollection {
114 type Err = (String, String);
115
116 fn from_str(s: &str) -> Result<Self, Self::Err> {
117 let parse_result = Self::parse(s);
118 match parse_result {
119 Ok(result) => Ok(Self(IVec::from(result))),
120 Err(msg) => Err((msg, s.to_string())),
121 }
122 }
123}