1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
// SPDX-License-Identifier: MIT
// Copyright 2026 Tom F. <https://github.com/tomtom215/>
// My way of giving something small back to the open source community
// and encouraging more Rust development!
//! Validation utilities for `DuckDB` community extension compliance.
//!
//! This module provides compile-time and runtime validators that enforce the
//! [`DuckDB` Community Extension](https://duckdb.org/community_extensions/development)
//! requirements. Extensions that pass these checks are ready for submission to the
//! `DuckDB` community extensions repository.
//!
//! # What is validated
//!
//! - **Extension name**: Must be lowercase alphanumeric with hyphens/underscores only
//! - **Function name**: Letters, digits and underscores — anything needing quotes in SQL is rejected
//! - **Semantic versioning**: `validate_semver` for strict semver; extension
//! versions are checked far more loosely, because `DuckDB` specifies no format
//! - **SPDX license**: Must be a recognized SPDX license identifier
//! - **Platform targets**: Exclusions must name real `DuckDB` build targets,
//! kept in sync with `extension-ci-tools`' distribution matrix by CI
//! - **Platform exclusion list**: Semicolon-separated string from `description.yml`
//! - **Cargo.toml**: Release profile settings for loadable extensions
//!
//! # Example
//!
//! ```rust
//! use quack_rs::validate::{
//! validate_extension_name, validate_extension_version,
//! validate_function_name, validate_semver, validate_spdx_license,
//! validate_platform, validate_excluded_platforms_str,
//! };
//!
//! assert!(validate_extension_name("my_extension").is_ok());
//! assert!(validate_extension_name("MyExt").is_err()); // uppercase not allowed
//!
//! assert!(validate_function_name("word_count").is_ok());
//! // Mixed case is fine — DuckDB ships `formatReadableSize`.
//! assert!(validate_function_name("wordCount").is_ok());
//! assert!(validate_function_name("word-count").is_err()); // would need quoting in SQL
//!
//! assert!(validate_semver("1.0.0").is_ok());
//! assert!(validate_semver("not-a-version").is_err());
//!
//! // Extension versions accept both semver and git hashes (unstable)
//! assert!(validate_extension_version("0.1.0").is_ok());
//! assert!(validate_extension_version("690bfc5").is_ok());
//!
//! assert!(validate_spdx_license("MIT").is_ok());
//! assert!(validate_spdx_license("FAKE-LICENSE").is_err());
//!
//! assert!(validate_platform("linux_amd64").is_ok());
//! assert!(validate_platform("freebsd_amd64").is_err());
//!
//! // Validate the semicolon-separated excluded_platforms field from description.yml
//! assert!(validate_excluded_platforms_str("wasm_mvp;wasm_eh;wasm_threads").is_ok());
//! assert!(validate_excluded_platforms_str("invalid_platform").is_err());
//! assert!(validate_excluded_platforms_str("").is_ok()); // empty means no exclusions
//! ```
pub use validate_extension_name;
pub use validate_function_name;
pub use ;
pub use ;
pub use ;
pub use validate_spdx_license;
/// Validates the `excluded_platforms` field from `description.yml` as a semicolon-separated string.
///
/// `DuckDB`'s `description.yml` stores excluded platforms as a semicolon-delimited string:
/// `"wasm_mvp;wasm_eh;wasm_threads"`. This function splits on `;` and validates each token.
///
/// An empty string is valid and means no platforms are excluded.
///
/// # Errors
///
/// Returns [`crate::error::ExtensionError`] if any token is not a known `DuckDB` build target,
/// or if the same platform appears more than once.
///
/// # Example
///
/// ```rust
/// use quack_rs::validate::validate_excluded_platforms_str;
///
/// assert!(validate_excluded_platforms_str("").is_ok());
/// assert!(validate_excluded_platforms_str("wasm_mvp;wasm_eh").is_ok());
/// assert!(validate_excluded_platforms_str("wasm_mvp;wasm_threads;wasm_eh").is_ok());
/// assert!(validate_excluded_platforms_str("invalid_platform").is_err());
/// assert!(validate_excluded_platforms_str("linux_amd64;linux_amd64").is_err()); // duplicate
/// ```