|
| 1 | +// Licensed to the Apache Software Foundation (ASF) under one |
| 2 | +// or more contributor license agreements. See the NOTICE file |
| 3 | +// distributed with this work for additional information |
| 4 | +// regarding copyright ownership. The ASF licenses this file |
| 5 | +// to you under the Apache License, Version 2.0 (the |
| 6 | +// "License"); you may not use this file except in compliance |
| 7 | +// with the License. You may obtain a copy of the License at |
| 8 | +// |
| 9 | +// http://www.apache.org/licenses/LICENSE-2.0 |
| 10 | +// |
| 11 | +// Unless required by applicable law or agreed to in writing, |
| 12 | +// software distributed under the License is distributed on an |
| 13 | +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| 14 | +// KIND, either express or implied. See the License for the |
| 15 | +// specific language governing permissions and limitations |
| 16 | +// under the License. |
| 17 | + |
| 18 | +// #[derive(Debug, Clone)] |
| 19 | +// pub struct DocumentationTest { |
| 20 | +// /// the section in the documentation where the UDF will be documented |
| 21 | +// pub doc_section: DocSectionTest, |
| 22 | +// /// the description for the UDF |
| 23 | +// pub description: String, |
| 24 | +// /// a brief example of the syntax. For example "ascii(str)" |
| 25 | +// pub syntax_example: String, |
| 26 | +// /// a sql example for the UDF, usually in the form of a sql prompt |
| 27 | +// /// query and output. It is strongly recommended to provide an |
| 28 | +// /// example for anything but the most basic UDF's |
| 29 | +// pub sql_example: Option<String>, |
| 30 | +// /// arguments for the UDF which will be displayed in array order. |
| 31 | +// /// Left member of a pair is the argument name, right is a |
| 32 | +// /// description for the argument |
| 33 | +// pub arguments: Option<Vec<(String, String)>>, |
| 34 | +// /// related functions if any. Values should match the related |
| 35 | +// /// udf's name exactly. Related udf's must be of the same |
| 36 | +// /// UDF type (scalar, aggregate or window) for proper linking to |
| 37 | +// /// occur |
| 38 | +// pub related_udfs: Option<Vec<String>>, |
| 39 | +// } |
| 40 | +// |
| 41 | +// impl DocumentationTest { |
| 42 | +// /// Returns a new [`DocumentationBuilder`] with no options set. |
| 43 | +// pub fn builder() -> DocumentationBuilderTest { |
| 44 | +// DocumentationBuilderTest::new() |
| 45 | +// } |
| 46 | +// } |
| 47 | +// |
| 48 | +// #[derive(Debug, Clone, PartialEq)] |
| 49 | +// pub struct DocSectionTest { |
| 50 | +// /// true to include this doc section in the public |
| 51 | +// /// documentation, false otherwise |
| 52 | +// pub include: bool, |
| 53 | +// /// a display label for the doc section. For example: "Math Expressions" |
| 54 | +// pub label: &'static str, |
| 55 | +// /// an optional description for the doc section |
| 56 | +// pub description: Option<&'static str>, |
| 57 | +// } |
| 58 | +// |
| 59 | +// pub struct DocumentationBuilderTest { |
| 60 | +// pub doc_section: Option<DocSectionTest>, |
| 61 | +// pub description: Option<String>, |
| 62 | +// pub syntax_example: Option<String>, |
| 63 | +// pub sql_example: Option<String>, |
| 64 | +// pub arguments: Option<Vec<(String, String)>>, |
| 65 | +// pub related_udfs: Option<Vec<String>>, |
| 66 | +// } |
| 67 | +// |
| 68 | +// impl DocumentationBuilderTest { |
| 69 | +// pub fn new() -> Self { |
| 70 | +// Self { |
| 71 | +// doc_section: None, |
| 72 | +// description: None, |
| 73 | +// syntax_example: None, |
| 74 | +// sql_example: None, |
| 75 | +// arguments: None, |
| 76 | +// related_udfs: None, |
| 77 | +// } |
| 78 | +// } |
| 79 | +// |
| 80 | +// pub fn with_doc_section(mut self, doc_section: DocSectionTest) -> Self { |
| 81 | +// self.doc_section = Some(doc_section); |
| 82 | +// self |
| 83 | +// } |
| 84 | +// |
| 85 | +// pub fn with_description(mut self, description: impl Into<String>) -> Self { |
| 86 | +// self.description = Some(description.into()); |
| 87 | +// self |
| 88 | +// } |
| 89 | +// |
| 90 | +// pub fn with_syntax_example(mut self, syntax_example: impl Into<String>) -> Self { |
| 91 | +// self.syntax_example = Some(syntax_example.into()); |
| 92 | +// self |
| 93 | +// } |
| 94 | +// |
| 95 | +// pub fn with_sql_example(mut self, sql_example: impl Into<String>) -> Self { |
| 96 | +// self.sql_example = Some(sql_example.into()); |
| 97 | +// self |
| 98 | +// } |
| 99 | +// |
| 100 | +// /// Adds documentation for a specific argument to the documentation. |
| 101 | +// /// |
| 102 | +// /// Arguments are displayed in the order they are added. |
| 103 | +// pub fn with_argument( |
| 104 | +// mut self, |
| 105 | +// arg_name: impl Into<String>, |
| 106 | +// arg_description: impl Into<String>, |
| 107 | +// ) -> Self { |
| 108 | +// let mut args = self.arguments.unwrap_or_default(); |
| 109 | +// args.push((arg_name.into(), arg_description.into())); |
| 110 | +// self.arguments = Some(args); |
| 111 | +// self |
| 112 | +// } |
| 113 | +// |
| 114 | +// /// Add a standard "expression" argument to the documentation |
| 115 | +// /// |
| 116 | +// /// This is similar to [`Self::with_argument`] except that a standard |
| 117 | +// /// description is appended to the end: `"Can be a constant, column, or |
| 118 | +// /// function, and any combination of arithmetic operators."` |
| 119 | +// /// |
| 120 | +// /// The argument is rendered like |
| 121 | +// /// |
| 122 | +// /// ```text |
| 123 | +// /// <arg_name>: |
| 124 | +// /// <expression_type> expression to operate on. Can be a constant, column, or function, and any combination of arithmetic operators. |
| 125 | +// /// ``` |
| 126 | +// pub fn with_standard_argument( |
| 127 | +// self, |
| 128 | +// arg_name: impl Into<String>, |
| 129 | +// expression_type: impl AsRef<str>, |
| 130 | +// ) -> Self { |
| 131 | +// let expression_type = expression_type.as_ref(); |
| 132 | +// self.with_argument(arg_name, format!("{expression_type} expression to operate on. Can be a constant, column, or function, and any combination of operators.")) |
| 133 | +// } |
| 134 | +// |
| 135 | +// pub fn with_related_udf(mut self, related_udf: impl Into<String>) -> Self { |
| 136 | +// let mut related = self.related_udfs.unwrap_or_default(); |
| 137 | +// related.push(related_udf.into()); |
| 138 | +// self.related_udfs = Some(related); |
| 139 | +// self |
| 140 | +// } |
| 141 | +// |
| 142 | +// pub fn build(self) -> DocumentationTest { |
| 143 | +// let Self { |
| 144 | +// doc_section, |
| 145 | +// description, |
| 146 | +// syntax_example, |
| 147 | +// sql_example, |
| 148 | +// arguments, |
| 149 | +// related_udfs, |
| 150 | +// } = self; |
| 151 | +// |
| 152 | +// if doc_section.is_none() { |
| 153 | +// panic!("Documentation must have a doc section"); |
| 154 | +// } |
| 155 | +// |
| 156 | +// if description.is_none() { |
| 157 | +// panic!("Documentation must have a description"); |
| 158 | +// } |
| 159 | +// |
| 160 | +// if syntax_example.is_none() { |
| 161 | +// panic!("Documentation must have a syntax_example"); |
| 162 | +// } |
| 163 | +// |
| 164 | +// DocumentationTest { |
| 165 | +// doc_section: doc_section.unwrap(), |
| 166 | +// description: description.unwrap(), |
| 167 | +// syntax_example: syntax_example.unwrap(), |
| 168 | +// sql_example, |
| 169 | +// arguments, |
| 170 | +// related_udfs, |
| 171 | +// } |
| 172 | +// } |
| 173 | +// } |
| 174 | +// |
| 175 | +// impl Default for DocumentationBuilderTest { |
| 176 | +// fn default() -> Self { |
| 177 | +// Self::new() |
| 178 | +// } |
| 179 | +// } |
| 180 | + |
| 181 | +#[derive(Debug, Clone)] |
| 182 | +pub struct Documentation { |
| 183 | + /// The section in the documentation where the UDF will be documented |
| 184 | + pub doc_section: DocSection, |
| 185 | + /// The description for the UDF |
| 186 | + pub description: String, |
| 187 | + /// A brief example of the syntax. For example "ascii(str)" |
| 188 | + pub syntax_example: String, |
| 189 | + /// A sql example for the UDF, usually in the form of a sql prompt |
| 190 | + /// query and output. It is strongly recommended to provide an |
| 191 | + /// example for anything but the most basic UDF's |
| 192 | + pub sql_example: Option<String>, |
| 193 | + /// Arguments for the UDF which will be displayed in array order. |
| 194 | + /// Left member of a pair is the argument name, right is a |
| 195 | + /// description for the argument |
| 196 | + pub arguments: Option<Vec<(String, String)>>, |
| 197 | + /// A list of alternative syntax examples for a function |
| 198 | + pub alternative_syntax: Option<Vec<String>>, |
| 199 | + /// Related functions if any. Values should match the related |
| 200 | + /// udf's name exactly. Related udf's must be of the same |
| 201 | + /// UDF type (scalar, aggregate or window) for proper linking to |
| 202 | + /// occur |
| 203 | + pub related_udfs: Option<Vec<String>>, |
| 204 | +} |
| 205 | + |
| 206 | +impl Documentation { |
| 207 | + /// Returns a new [`DocumentationBuilder`] with no options set. |
| 208 | + pub fn builder() -> DocumentationBuilder { |
| 209 | + DocumentationBuilder::new() |
| 210 | + } |
| 211 | +} |
| 212 | + |
| 213 | +#[derive(Debug, Clone, PartialEq)] |
| 214 | +pub struct DocSection { |
| 215 | + /// True to include this doc section in the public |
| 216 | + /// documentation, false otherwise |
| 217 | + pub include: bool, |
| 218 | + /// A display label for the doc section. For example: "Math Expressions" |
| 219 | + pub label: &'static str, |
| 220 | + /// An optional description for the doc section |
| 221 | + pub description: Option<&'static str>, |
| 222 | +} |
| 223 | + |
| 224 | +/// A builder to be used for building [`Documentation`]'s. |
| 225 | +pub struct DocumentationBuilder { |
| 226 | + pub doc_section: Option<DocSection>, |
| 227 | + pub description: Option<String>, |
| 228 | + pub syntax_example: Option<String>, |
| 229 | + pub sql_example: Option<String>, |
| 230 | + pub arguments: Option<Vec<(String, String)>>, |
| 231 | + pub alternative_syntax: Option<Vec<String>>, |
| 232 | + pub related_udfs: Option<Vec<String>>, |
| 233 | +} |
| 234 | + |
| 235 | +impl DocumentationBuilder { |
| 236 | + pub fn new() -> Self { |
| 237 | + Self { |
| 238 | + doc_section: None, |
| 239 | + description: None, |
| 240 | + syntax_example: None, |
| 241 | + sql_example: None, |
| 242 | + arguments: None, |
| 243 | + alternative_syntax: None, |
| 244 | + related_udfs: None, |
| 245 | + } |
| 246 | + } |
| 247 | + |
| 248 | + pub fn with_doc_section(mut self, doc_section: DocSection) -> Self { |
| 249 | + self.doc_section = Some(doc_section); |
| 250 | + self |
| 251 | + } |
| 252 | + |
| 253 | + pub fn with_description(mut self, description: impl Into<String>) -> Self { |
| 254 | + self.description = Some(description.into()); |
| 255 | + self |
| 256 | + } |
| 257 | + |
| 258 | + pub fn with_syntax_example(mut self, syntax_example: impl Into<String>) -> Self { |
| 259 | + self.syntax_example = Some(syntax_example.into()); |
| 260 | + self |
| 261 | + } |
| 262 | + |
| 263 | + pub fn with_sql_example(mut self, sql_example: impl Into<String>) -> Self { |
| 264 | + self.sql_example = Some(sql_example.into()); |
| 265 | + self |
| 266 | + } |
| 267 | + |
| 268 | + /// Adds documentation for a specific argument to the documentation. |
| 269 | + /// |
| 270 | + /// Arguments are displayed in the order they are added. |
| 271 | + pub fn with_argument( |
| 272 | + mut self, |
| 273 | + arg_name: impl Into<String>, |
| 274 | + arg_description: impl Into<String>, |
| 275 | + ) -> Self { |
| 276 | + let mut args = self.arguments.unwrap_or_default(); |
| 277 | + args.push((arg_name.into(), arg_description.into())); |
| 278 | + self.arguments = Some(args); |
| 279 | + self |
| 280 | + } |
| 281 | + |
| 282 | + /// Add a standard "expression" argument to the documentation |
| 283 | + /// |
| 284 | + /// The argument is rendered like below if Some() is passed through: |
| 285 | + /// |
| 286 | + /// ```text |
| 287 | + /// <arg_name>: |
| 288 | + /// <expression_type> expression to operate on. Can be a constant, column, or function, and any combination of operators. |
| 289 | + /// ``` |
| 290 | + /// |
| 291 | + /// The argument is rendered like below if None is passed through: |
| 292 | + /// |
| 293 | + /// ```text |
| 294 | + /// <arg_name>: |
| 295 | + /// The expression to operate on. Can be a constant, column, or function, and any combination of operators. |
| 296 | + /// ``` |
| 297 | + pub fn with_standard_argument( |
| 298 | + self, |
| 299 | + arg_name: impl Into<String>, |
| 300 | + expression_type: Option<&str>, |
| 301 | + ) -> Self { |
| 302 | + let description = format!( |
| 303 | + "{} expression to operate on. Can be a constant, column, or function, and any combination of operators.", |
| 304 | + expression_type.unwrap_or("The") |
| 305 | + ); |
| 306 | + self.with_argument(arg_name, description) |
| 307 | + } |
| 308 | + |
| 309 | + pub fn with_alternative_syntax(mut self, syntax_name: impl Into<String>) -> Self { |
| 310 | + let mut alternative_syntax_array = self.alternative_syntax.unwrap_or_default(); |
| 311 | + alternative_syntax_array.push(syntax_name.into()); |
| 312 | + self.alternative_syntax = Some(alternative_syntax_array); |
| 313 | + self |
| 314 | + } |
| 315 | + |
| 316 | + pub fn with_related_udf(mut self, related_udf: impl Into<String>) -> Self { |
| 317 | + let mut related = self.related_udfs.unwrap_or_default(); |
| 318 | + related.push(related_udf.into()); |
| 319 | + self.related_udfs = Some(related); |
| 320 | + self |
| 321 | + } |
| 322 | + |
| 323 | + pub fn build(self) -> Documentation { |
| 324 | + let Self { |
| 325 | + doc_section, |
| 326 | + description, |
| 327 | + syntax_example, |
| 328 | + sql_example, |
| 329 | + arguments, |
| 330 | + alternative_syntax, |
| 331 | + related_udfs, |
| 332 | + } = self; |
| 333 | + |
| 334 | + if doc_section.is_none() { |
| 335 | + panic!("Documentation must have a doc section"); |
| 336 | + } |
| 337 | + if description.is_none() { |
| 338 | + panic!("Documentation must have a description"); |
| 339 | + } |
| 340 | + if syntax_example.is_none() { |
| 341 | + panic!("Documentation must have a syntax_example"); |
| 342 | + } |
| 343 | + |
| 344 | + Documentation { |
| 345 | + doc_section: doc_section.unwrap(), |
| 346 | + description: description.unwrap(), |
| 347 | + syntax_example: syntax_example.unwrap(), |
| 348 | + sql_example, |
| 349 | + arguments, |
| 350 | + alternative_syntax, |
| 351 | + related_udfs, |
| 352 | + } |
| 353 | + } |
| 354 | +} |
| 355 | + |
| 356 | +impl Default for DocumentationBuilder { |
| 357 | + fn default() -> Self { |
| 358 | + Self::new() |
| 359 | + } |
| 360 | +} |
0 commit comments