ddex_builder/presets/mod.rs
1//! # DDEX Configuration Presets
2//!
3//! This module provides pre-configured settings for DDEX message generation.
4//! Presets are community-maintained configuration templates that help ensure
5//! DDEX compliance and reduce configuration complexity.
6//!
7//! ## Available Presets
8//!
9//! ### Generic Industry-Standard Presets
10//! - **audio_album**: DDEX-compliant audio album configuration
11//! - **audio_single**: DDEX-compliant single track configuration
12//! - **video_single**: DDEX-compliant video release configuration
13//! - **compilation**: DDEX-compliant compilation album configuration
14//!
15//! ### Platform Presets (Based on Public Documentation)
16//! - **YouTube Music**: Audio and video releases (based on public Partner docs)
17//!
18//! ## Architecture
19//!
20//! ```text
21//! Preset System
22//! ┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐
23//! │ Base Config │───▶│ Partner Rules │───▶│ Final Settings │
24//! │ (DDEX defaults) │ │ (customizations) │ │ (ready to use) │
25//! └─────────────────┘ └──────────────────┘ └─────────────────┘
26//! │ │ │
27//! ▼ ▼ ▼
28//! ┌─────────────┐ ┌─────────────────┐ ┌─────────────────┐
29//! │ • Version │ │ • Required │ │ • Validation │
30//! │ • Profile │ │ • Validation │ │ • Defaults │
31//! │ • Schema │ │ • Territories │ │ • Mappings │
32//! │ • Defaults │ │ • Quality │ │ • Overrides │
33//! └─────────────┘ └─────────────────┘ └─────────────────┘
34//! ```
35//!
36//! ## Usage Example
37//!
38//! ```rust
39//! use ddex_builder::presets::*;
40//! use ddex_builder::Builder;
41//!
42//! // Use generic audio album preset
43//! let mut builder = Builder::new();
44//! builder.apply_preset(&generic::audio_album())?;
45//!
46//! // Use YouTube preset for video content
47//! builder.apply_preset(&youtube::youtube_video())?;
48//!
49//! // Load by name
50//! let presets = all_presets();
51//! let audio_album = &presets["audio_album"];
52//! builder.apply_partner_preset(audio_album)?;
53//!
54//! // List available presets
55//! for (name, preset) in all_presets() {
56//! println!("{}: {}", name, preset.description);
57//! }
58//! ```
59//!
60//! ## Preset Features
61//!
62//! Each preset includes:
63//!
64//! - **Schema Version**: DDEX ERN version (3.8.2, 4.2, 4.3)
65//! - **Message Profile**: Audio, Video, or Mixed content
66//! - **Required Fields**: Mandatory metadata fields
67//! - **Validation Rules**: Data format and quality requirements
68//! - **Default Values**: Common field defaults
69//! - **Territory Codes**: Allowed distribution territories
70//! - **Quality Standards**: Audio/video quality minimums
71//!
72//! ## Custom Presets
73//!
74//! Create your own preset for internal standards:
75//!
76//! ```rust
77//! use ddex_builder::presets::*;
78//! use indexmap::IndexMap;
79//!
80//! // Start with a generic preset as base
81//! let mut custom_preset = generic::audio_album();
82//! custom_preset.name = "my_label_preset".to_string();
83//! custom_preset.description = "My Record Label Requirements".to_string();
84//!
85//! // Add custom validation rules
86//! custom_preset.validation_rules.insert(
87//! "Genre".to_string(),
88//! ValidationRule::OneOf(vec!["Rock".to_string(), "Pop".to_string()])
89//! );
90//!
91//! // Add custom territory restrictions
92//! custom_preset.config.territory_codes = vec!["US".to_string(), "CA".to_string()];
93//! ```
94//!
95//! ## Validation Rules
96//!
97//! Presets support comprehensive validation:
98//!
99//! - **Required**: Field must be present
100//! - **MinLength/MaxLength**: String length constraints
101//! - **Pattern**: Regex pattern matching
102//! - **OneOf**: Value must be from allowed list
103//! - **AudioQuality**: Minimum bit depth and sample rate
104//! - **TerritoryCode**: Allowed distribution territories
105//! - **Custom**: Partner-specific validation logic
106
107pub mod generic;
108pub mod youtube;
109
110use indexmap::IndexMap;
111use serde::{Deserialize, Serialize};
112
113/// DDEX version enum
114#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
115pub enum DdexVersion {
116 #[serde(rename = "ERN/3.8.2")]
117 Ern382,
118 #[serde(rename = "ERN/4.2")]
119 Ern42,
120 #[serde(rename = "ERN/4.3")]
121 Ern43,
122 #[serde(rename = "ERN/4.1")]
123 Ern41,
124}
125
126impl std::fmt::Display for DdexVersion {
127 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
128 match self {
129 DdexVersion::Ern382 => write!(f, "ERN/3.8.2"),
130 DdexVersion::Ern42 => write!(f, "ERN/4.2"),
131 DdexVersion::Ern43 => write!(f, "ERN/4.3"),
132 DdexVersion::Ern41 => write!(f, "ERN/4.1"),
133 }
134 }
135}
136
137/// Message profile enum
138#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
139pub enum MessageProfile {
140 AudioAlbum,
141 AudioSingle,
142 VideoAlbum,
143 VideoSingle,
144 Mixed,
145}
146
147/// Validation rule types
148#[derive(Debug, Clone, Serialize, Deserialize)]
149pub enum ValidationRule {
150 Required,
151 MinLength(usize),
152 MaxLength(usize),
153 Pattern(String),
154 OneOf(Vec<String>),
155 AudioQuality { min_bit_depth: u8, min_sample_rate: u32 },
156 TerritoryCode { allowed: Vec<String> },
157 Custom(String),
158}
159
160/// Enhanced preset configuration with validation rules
161#[derive(Debug, Clone, Serialize, Deserialize)]
162pub struct PresetConfig {
163 pub version: DdexVersion,
164 pub profile: MessageProfile,
165 pub required_fields: Vec<String>,
166 pub validation_rules: IndexMap<String, ValidationRule>,
167 pub default_values: IndexMap<String, String>,
168 pub custom_mappings: IndexMap<String, String>,
169 pub territory_codes: Vec<String>,
170 pub distribution_channels: Vec<String>,
171 pub release_types: Vec<String>,
172}
173
174/// Partner preset configuration (legacy structure, enhanced)
175#[derive(Debug, Clone, Serialize, Deserialize)]
176pub struct PartnerPreset {
177 pub name: String,
178 pub description: String,
179 pub source: PresetSource,
180 pub provenance_url: Option<String>,
181 pub version: String,
182 pub locked: bool,
183 pub disclaimer: String,
184 pub determinism: super::determinism::DeterminismConfig,
185 pub defaults: PresetDefaults,
186 pub required_fields: Vec<String>,
187 pub format_overrides: IndexMap<String, String>,
188 // Enhanced fields
189 pub config: PresetConfig,
190 pub validation_rules: IndexMap<String, ValidationRule>,
191 pub custom_mappings: IndexMap<String, String>,
192}
193
194/// Preset source
195#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
196pub enum PresetSource {
197 PublicDocs,
198 CustomerFeedback,
199 Community,
200}
201
202/// Preset defaults
203#[derive(Debug, Clone, Serialize, Deserialize)]
204pub struct PresetDefaults {
205 pub message_control_type: Option<String>,
206 pub territory_code: Vec<String>,
207 pub distribution_channel: Vec<String>,
208}
209
210
211
212/// Get all built-in presets
213///
214/// Returns a collection of community-maintained DDEX configuration presets.
215/// These presets provide baseline DDEX-compliant configurations and platform-specific
216/// templates based on publicly available documentation.
217pub fn all_presets() -> IndexMap<String, PartnerPreset> {
218 let mut presets = IndexMap::new();
219
220 // Generic industry-standard presets
221 presets.extend(generic::all_generic_presets());
222
223 // Platform presets (based on public documentation)
224 presets.extend(youtube::all_youtube_presets());
225
226 presets
227}