use thiserror::Error;
#[derive(Default, Debug, PartialEq, Clone)]
pub struct FetchOptions {
pub(super) protocol: String,
pub(super) host: String,
pub(super) path: String,
pub(super) token: Option<String>,
}
impl FetchOptions {
pub fn new(url: &str, token: Option<String>) -> Result<Self, FetchOptionsError> {
let (protocol, host, path) =
Self::split_url(url).ok_or(FetchOptionsError::InvalidUrl(url.into()))?;
Ok(Self {
protocol,
host,
path,
token,
})
}
fn split_url(full_url: &str) -> Option<(String, String, String)> {
let (protocol, rest) = full_url.split_once("://").unwrap_or(("https", full_url));
let url_parts = rest.splitn(2, '/').collect::<Vec<_>>();
if url_parts.len() != 2 || !url_parts[1].contains('/') {
return None;
}
Some((protocol.into(), url_parts[0].into(), url_parts[1].into()))
}
}
#[derive(Debug, Error)]
pub enum FetchOptionsError {
#[error("Invalid URL: {0}")]
InvalidUrl(String),
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn create_new_fetch_options() {
let url = "https://gitlab.ost.ch/gitlab-time-report/gitlab-time-report";
let token = "MyAccessToken".to_string();
let result = FetchOptions {
protocol: "https".into(),
host: "gitlab.ost.ch".into(),
path: "gitlab-time-report/gitlab-time-report".into(),
token: Some(token.clone()),
};
let output = FetchOptions::new(url, Some(token)).unwrap();
assert_eq!(output, result);
}
#[test]
fn create_new_fetch_options_without_protocol() {
let url = "gitlab.ost.ch/gitlab-time-report/gitlab-time-report";
let token = "MyAccessToken".to_string();
let result = FetchOptions {
protocol: "https".into(),
host: "gitlab.ost.ch".into(),
path: "gitlab-time-report/gitlab-time-report".into(),
token: Some(token.clone()),
};
let output = FetchOptions::new(url, Some(token)).unwrap();
assert_eq!(output, result);
}
#[test]
fn split_url_correctly() {
let input = "https://gitlab.ost.ch/gitlab-time-report/gitlab-time-report";
let result = (
"https".into(),
"gitlab.ost.ch".into(),
"gitlab-time-report/gitlab-time-report".into(),
);
let output = FetchOptions::split_url(input).unwrap();
assert_eq!(output, result);
}
#[test]
fn split_url_one_slash() {
let input = "https://gitlab.com/gitlab-org";
let output = FetchOptions::split_url(input);
assert!(output.is_none());
}
}