#![doc(
html_logo_url = "https://raw.githubusercontent.com/apache/datafusion/19fe44cf2f30cbdd63d4a4f52c74055163c6cc38/docs/logos/standalone_logo/logo_original.svg",
html_favicon_url = "https://raw.githubusercontent.com/apache/datafusion/19fe44cf2f30cbdd63d4a4f52c74055163c6cc38/docs/logos/standalone_logo/logo_original.svg"
)]
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
#[allow(rustdoc::broken_intra_doc_links)]
#[derive(Debug, Clone)]
pub struct Documentation {
pub doc_section: DocSection,
pub description: String,
pub syntax_example: String,
pub sql_example: Option<String>,
pub arguments: Option<Vec<(String, String)>>,
pub alternative_syntax: Option<Vec<String>>,
pub related_udfs: Option<Vec<String>>,
}
impl Documentation {
pub fn builder(
doc_section: DocSection,
description: impl Into<String>,
syntax_example: impl Into<String>,
) -> DocumentationBuilder {
DocumentationBuilder::new_with_details(doc_section, description, syntax_example)
}
pub fn to_doc_attribute(&self) -> String {
let mut result = String::new();
result.push_str("#[user_doc(");
result.push_str(
format!(
"\n doc_section({}label = \"{}\"{}),",
if !self.doc_section.include {
"include = \"false\", "
} else {
""
},
self.doc_section.label,
self.doc_section
.description
.map(|s| format!(", description = \"{s}\""))
.unwrap_or_default(),
)
.as_ref(),
);
result.push_str(format!("\n description=\"{}\",", self.description).as_ref());
result.push_str(
format!("\n syntax_example=\"{}\",", self.syntax_example).as_ref(),
);
result.push_str(
&self
.sql_example
.clone()
.map(|s| format!("\n sql_example = r#\"{s}\"#,"))
.unwrap_or_default(),
);
let st_arg_token = " expression to operate on. Can be a constant, column, or function, and any combination of operators.";
if let Some(args) = self.arguments.clone() {
args.iter().for_each(|(name, value)| {
if value.contains(st_arg_token) {
if name.starts_with("The ") {
result.push_str(format!("\n standard_argument(\n name = \"{name}\"),").as_ref());
} else {
result.push_str(format!("\n standard_argument(\n name = \"{}\",\n prefix = \"{}\"\n ),", name, value.replace(st_arg_token, "")).as_ref());
}
}
});
}
if let Some(args) = self.arguments.clone() {
args.iter().for_each(|(name, value)| {
if !value.contains(st_arg_token) {
result.push_str(format!("\n argument(\n name = \"{name}\",\n description = \"{value}\"\n ),").as_ref());
}
});
}
if let Some(alt_syntax) = self.alternative_syntax.clone() {
alt_syntax.iter().for_each(|syntax| {
result.push_str(
format!("\n alternative_syntax = \"{syntax}\",").as_ref(),
);
});
}
if let Some(related_udf) = self.related_udfs.clone() {
related_udf.iter().for_each(|udf| {
result.push_str(format!("\n related_udf(name = \"{udf}\"),").as_ref());
});
}
result.push_str("\n)]");
result
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct DocSection {
pub include: bool,
pub label: &'static str,
pub description: Option<&'static str>,
}
impl Default for DocSection {
fn default() -> Self {
Self {
include: true,
label: "Default",
description: None,
}
}
}
pub struct DocumentationBuilder {
pub doc_section: DocSection,
pub description: String,
pub syntax_example: String,
pub sql_example: Option<String>,
pub arguments: Option<Vec<(String, String)>>,
pub alternative_syntax: Option<Vec<String>>,
pub related_udfs: Option<Vec<String>>,
}
impl DocumentationBuilder {
#[allow(clippy::new_without_default)]
#[deprecated(
since = "44.0.0",
note = "please use `DocumentationBuilder::new_with_details` instead"
)]
pub fn new() -> Self {
Self::new_with_details(DocSection::default(), "<no description>", "<no example>")
}
pub fn new_with_details(
doc_section: DocSection,
description: impl Into<String>,
syntax_example: impl Into<String>,
) -> Self {
Self {
doc_section,
description: description.into(),
syntax_example: syntax_example.into(),
sql_example: None,
arguments: None,
alternative_syntax: None,
related_udfs: None,
}
}
pub fn with_doc_section(mut self, doc_section: DocSection) -> Self {
self.doc_section = doc_section;
self
}
pub fn with_description(mut self, description: impl Into<String>) -> Self {
self.description = description.into();
self
}
pub fn with_syntax_example(mut self, syntax_example: impl Into<String>) -> Self {
self.syntax_example = syntax_example.into();
self
}
pub fn with_sql_example(mut self, sql_example: impl Into<String>) -> Self {
self.sql_example = Some(sql_example.into());
self
}
pub fn with_argument(
mut self,
arg_name: impl Into<String>,
arg_description: impl Into<String>,
) -> Self {
let mut args = self.arguments.unwrap_or_default();
args.push((arg_name.into(), arg_description.into()));
self.arguments = Some(args);
self
}
pub fn with_standard_argument(
self,
arg_name: impl Into<String>,
expression_type: Option<&str>,
) -> Self {
let description = format!(
"{} expression to operate on. Can be a constant, column, or function, and any combination of operators.",
expression_type.unwrap_or("The")
);
self.with_argument(arg_name, description)
}
pub fn with_alternative_syntax(mut self, syntax_name: impl Into<String>) -> Self {
let mut alternative_syntax_array = self.alternative_syntax.unwrap_or_default();
alternative_syntax_array.push(syntax_name.into());
self.alternative_syntax = Some(alternative_syntax_array);
self
}
pub fn with_related_udf(mut self, related_udf: impl Into<String>) -> Self {
let mut related = self.related_udfs.unwrap_or_default();
related.push(related_udf.into());
self.related_udfs = Some(related);
self
}
pub fn build(self) -> Documentation {
let Self {
doc_section,
description,
syntax_example,
sql_example,
arguments,
alternative_syntax,
related_udfs,
} = self;
Documentation {
doc_section,
description,
syntax_example,
sql_example,
arguments,
alternative_syntax,
related_udfs,
}
}
}