use fiftyone_pipeline_core::constants::DEFAULT_JSON_ENDPOINT;
use fiftyone_pipeline_core::{Error, Result};
use crate::constants::{
BUILDER_DEFAULT_ENABLE_COOKIES, BUILDER_DEFAULT_HOST, BUILDER_DEFAULT_MINIFY,
BUILDER_DEFAULT_OBJECT_NAME, BUILDER_DEFAULT_PROTOCOL,
};
use crate::element::JavaScriptBuilderElement;
#[derive(Debug, Clone)]
pub struct JavaScriptBuilderElementBuilder {
host: String,
endpoint: String,
protocol: String,
object_name: String,
enable_cookies: bool,
minify: bool,
}
impl JavaScriptBuilderElementBuilder {
pub fn new() -> Self {
JavaScriptBuilderElementBuilder {
host: BUILDER_DEFAULT_HOST.to_owned(),
endpoint: DEFAULT_JSON_ENDPOINT.to_owned(),
protocol: BUILDER_DEFAULT_PROTOCOL.to_owned(),
object_name: BUILDER_DEFAULT_OBJECT_NAME.to_owned(),
enable_cookies: BUILDER_DEFAULT_ENABLE_COOKIES,
minify: BUILDER_DEFAULT_MINIFY,
}
}
pub fn set_enable_cookies(mut self, enable_cookies: bool) -> Self {
self.enable_cookies = enable_cookies;
self
}
pub fn set_host(mut self, host: impl Into<String>) -> Self {
self.host = host.into();
self
}
pub fn set_endpoint(mut self, endpoint: impl Into<String>) -> Self {
self.endpoint = endpoint.into();
self
}
pub fn set_protocol(mut self, protocol: impl Into<String>) -> Result<Self> {
let protocol = protocol.into();
if protocol.eq_ignore_ascii_case("http") || protocol.eq_ignore_ascii_case("https") {
self.protocol = protocol;
Ok(self)
} else {
Err(Error::configuration(format!(
"Invalid protocol in configuration ({protocol}), must be 'http' or 'https'"
)))
}
}
pub fn set_object_name(mut self, object_name: impl Into<String>) -> Result<Self> {
let object_name = object_name.into();
if is_valid_object_name(&object_name) {
self.object_name = object_name;
Ok(self)
} else {
Err(Error::configuration(format!(
"The JavaScript object name '{object_name}' is not valid. It must \
be a valid JavaScript identifier."
)))
}
}
pub fn set_minify(mut self, minify: bool) -> Self {
self.minify = minify;
self
}
pub fn build(self) -> JavaScriptBuilderElement {
JavaScriptBuilderElement::from_parts(
self.host,
self.endpoint,
self.protocol,
self.object_name,
self.enable_cookies,
self.minify,
)
}
}
impl Default for JavaScriptBuilderElementBuilder {
fn default() -> Self {
JavaScriptBuilderElementBuilder::new()
}
}
fn is_valid_object_name(name: &str) -> bool {
let mut chars = name.chars();
match chars.next() {
Some(first) if is_identifier_start(first) => {}
_ => return false,
}
chars.all(is_identifier_part)
}
fn is_identifier_start(c: char) -> bool {
c.is_ascii_alphabetic() || c == '_' || c == '$'
}
fn is_identifier_part(c: char) -> bool {
is_identifier_start(c) || c.is_ascii_digit()
}