pub(crate) mod authority;
mod database;
mod query;
#[cfg(test)]
mod tests;
use crate::Parameter;
use anyhow::{format_err, Result};
use authority::{authority, Authority};
use database::database;
use nom::{
branch::alt,
bytes::complete::tag,
character::complete::{alphanumeric1, one_of, space0},
combinator::{all_consuming, map, opt, recognize},
error::{context, VerboseError},
multi::{many1, separated_list1},
sequence::{delimited, preceded, terminated, tuple},
IResult,
};
use query::query;
type Res<I, O> = IResult<I, O, VerboseError<I>>;
#[derive(Debug, Default, PartialEq, Eq)]
pub(crate) struct ConnectionUri {
pub authority: Option<Authority>,
pub database: Option<String>,
pub parameters: Option<Vec<Parameter>>,
pub fragment: Option<String>,
}
pub(crate) fn multi_connection_string(
i: &str,
sep: &str,
) -> Result<Vec<ConnectionUri>> {
let (rem, res) =
all_consuming(separated_list1(tag(sep), connection_string))(i)
.map_err(|e| {
format_err!("error consuming multi connection string: {}", e)
})?;
eprintln!("input: {i:?}; rem: {rem:?}");
Ok(res)
}
pub(crate) fn consuming_connection_string(i: &str) -> Result<ConnectionUri> {
let (_, res) = all_consuming(connection_string)(i)
.map_err(|e| format_err!("error consuming connection string: {}", e))?;
Ok(res)
}
fn connection_string(i: &str) -> Res<&str, ConnectionUri> {
map(
preceded(
context("scheme", scheme),
tuple((
opt(authority),
context("database", database),
context("query", query),
opt(fragment),
)),
),
|(authority, database, parameters, fragment)| ConnectionUri {
authority,
database,
parameters,
fragment: fragment.map(std::convert::Into::into),
},
)(i)
}
fn fragment(i: &str) -> Res<&str, &str> {
delimited(
context("fragment #", tag("#")),
context(
"fragment body",
recognize(many1(alt((alphanumeric1, recognize(one_of("-_")))))),
),
space0,
)(i)
}
fn scheme(i: &str) -> Res<&str, &str> {
terminated(
alt((postgresql, postgres)),
context("scheme :// tag", tag("://")),
)(i)
}
fn postgres(i: &str) -> Res<&str, &str> {
tag("postgres")(i)
}
fn postgresql(i: &str) -> Res<&str, &str> {
tag("postgresql")(i)
}