ddex_builder/versions/
ern_42.rs

1//! ERN 4.2 version specification and handling
2//!
3//! ERN 4.2 is an intermediate DDEX version that introduced many modern features
4//! while maintaining compatibility with legacy systems.
5
6use super::*;
7use crate::presets::DdexVersion;
8
9/// Get ERN 4.2 version specification
10pub fn get_version_spec() -> VersionSpec {
11    let mut element_mappings = IndexMap::new();
12    let mut namespace_prefixes = IndexMap::new();
13
14    // Modern namespace mappings
15    namespace_prefixes.insert("ern".to_string(), "http://ddex.net/xml/ern/42".to_string());
16    namespace_prefixes.insert("avs".to_string(), "http://ddex.net/xml/avs/avs".to_string());
17
18    // Enhanced element mappings for ERN 4.2
19    element_mappings.insert(
20        "NewReleaseMessage".to_string(),
21        "NewReleaseMessage".to_string(),
22    );
23    element_mappings.insert("MessageHeader".to_string(), "MessageHeader".to_string());
24    element_mappings.insert("MessageId".to_string(), "MessageId".to_string());
25    element_mappings.insert("MessageSender".to_string(), "MessageSender".to_string());
26    element_mappings.insert(
27        "MessageRecipient".to_string(),
28        "MessageRecipient".to_string(),
29    );
30    element_mappings.insert(
31        "MessageCreatedDateTime".to_string(),
32        "MessageCreatedDateTime".to_string(),
33    );
34    element_mappings.insert(
35        "MessageControlType".to_string(),
36        "MessageControlType".to_string(),
37    );
38
39    // Enhanced resource mappings
40    element_mappings.insert("ResourceList".to_string(), "ResourceList".to_string());
41    element_mappings.insert("SoundRecording".to_string(), "SoundRecording".to_string());
42    element_mappings.insert(
43        "ResourceReference".to_string(),
44        "ResourceReference".to_string(),
45    );
46    element_mappings.insert("ResourceId".to_string(), "ResourceId".to_string());
47    element_mappings.insert("ReferenceTitle".to_string(), "ReferenceTitle".to_string());
48    element_mappings.insert("DisplayArtist".to_string(), "DisplayArtist".to_string());
49    element_mappings.insert("ISRC".to_string(), "ISRC".to_string());
50    element_mappings.insert("Duration".to_string(), "Duration".to_string());
51    element_mappings.insert(
52        "TechnicalResourceDetails".to_string(),
53        "TechnicalResourceDetails".to_string(),
54    );
55    element_mappings.insert("AudioCodecType".to_string(), "AudioCodecType".to_string());
56    element_mappings.insert("BitRate".to_string(), "BitRate".to_string());
57    element_mappings.insert("FileName".to_string(), "FileName".to_string());
58
59    // Enhanced release mappings
60    element_mappings.insert("ReleaseList".to_string(), "ReleaseList".to_string());
61    element_mappings.insert("Release".to_string(), "Release".to_string());
62    element_mappings.insert(
63        "ReleaseReference".to_string(),
64        "ReleaseReference".to_string(),
65    );
66    element_mappings.insert("ReleaseId".to_string(), "ReleaseId".to_string());
67    element_mappings.insert("ReleaseType".to_string(), "ReleaseType".to_string());
68    element_mappings.insert("Title".to_string(), "Title".to_string());
69    element_mappings.insert("DisplayArtist".to_string(), "DisplayArtist".to_string());
70    element_mappings.insert("LabelName".to_string(), "LabelName".to_string());
71    element_mappings.insert("UPC".to_string(), "UPC".to_string());
72    element_mappings.insert("ReleaseDate".to_string(), "ReleaseDate".to_string());
73    element_mappings.insert("Genre".to_string(), "Genre".to_string());
74    element_mappings.insert("ResourceGroup".to_string(), "ResourceGroup".to_string());
75
76    // Enhanced deal mappings
77    element_mappings.insert("DealList".to_string(), "DealList".to_string());
78    element_mappings.insert("ReleaseDeal".to_string(), "ReleaseDeal".to_string());
79    element_mappings.insert("DealReference".to_string(), "DealReference".to_string());
80    element_mappings.insert("DealTerms".to_string(), "DealTerms".to_string());
81    element_mappings.insert(
82        "CommercialModelType".to_string(),
83        "CommercialModelType".to_string(),
84    );
85    element_mappings.insert("Territory".to_string(), "Territory".to_string());
86    element_mappings.insert("TerritoryCode".to_string(), "TerritoryCode".to_string());
87    element_mappings.insert("ValidityPeriod".to_string(), "ValidityPeriod".to_string());
88    element_mappings.insert("StartDate".to_string(), "StartDate".to_string());
89    element_mappings.insert("EndDate".to_string(), "EndDate".to_string());
90    element_mappings.insert("Price".to_string(), "Price".to_string());
91    element_mappings.insert("PriceAmount".to_string(), "PriceAmount".to_string());
92    element_mappings.insert(
93        "PriceCurrencyCode".to_string(),
94        "PriceCurrencyCode".to_string(),
95    );
96
97    // New elements in ERN 4.2
98    element_mappings.insert("PartyId".to_string(), "PartyId".to_string());
99    element_mappings.insert("PartyReference".to_string(), "PartyReference".to_string());
100    element_mappings.insert("DetailedHashSum".to_string(), "DetailedHashSum".to_string());
101    element_mappings.insert("PreviewDetails".to_string(), "PreviewDetails".to_string());
102    element_mappings.insert("UsageType".to_string(), "UsageType".to_string());
103
104    VersionSpec {
105        version: DdexVersion::Ern42,
106        namespace: "http://ddex.net/xml/ern/42".to_string(),
107        schema_location: Some(
108            "http://ddex.net/xml/ern/42 http://ddex.net/xml/ern/42/release-notification.xsd"
109                .to_string(),
110        ),
111        message_schema_version_id: "ern/42".to_string(),
112        supported_message_types: vec![
113            "NewReleaseMessage".to_string(),
114            "UpdateReleaseMessage".to_string(),
115            "CatalogTransferMessage".to_string(),
116            "PurgeReleaseMessage".to_string(),
117        ],
118        element_mappings,
119        required_elements: vec![
120            "MessageId".to_string(),
121            "MessageSender".to_string(),
122            "MessageRecipient".to_string(),
123            "MessageCreatedDateTime".to_string(),
124            "ResourceList".to_string(),
125            "ReleaseList".to_string(),
126        ],
127        deprecated_elements: vec![
128            // Elements deprecated in 4.2
129            "LegacyTechnicalDetails".to_string(),
130            "BasicPrice".to_string(),
131            "SimpleTerritory".to_string(),
132        ],
133        new_elements: vec![
134            // Elements new in 4.2 compared to 3.8.2
135            "MessageControlType".to_string(),
136            "PartyId".to_string(),
137            "PartyReference".to_string(),
138            "TechnicalResourceDetails".to_string(),
139            "AudioCodecType".to_string(),
140            "BitRate".to_string(),
141            "FileName".to_string(),
142            "DetailedHashSum".to_string(),
143            "PreviewDetails".to_string(),
144            "UsageType".to_string(),
145            "ReleaseReference".to_string(),
146            "DealReference".to_string(),
147            "Territory".to_string(),
148            "EndDate".to_string(),
149        ],
150        namespace_prefixes,
151    }
152}
153
154/// ERN 4.2 specific constraints and validation rules
155pub struct Ern42Constraints {
156    /// Maximum allowed resources per release
157    pub max_resources_per_release: usize,
158    /// Supported image formats
159    pub supported_image_formats: Vec<String>,
160    /// Supported audio formats
161    pub supported_audio_formats: Vec<String>,
162    /// Maximum deal complexity
163    pub max_deal_terms: usize,
164    /// Enhanced validation features
165    pub enhanced_validation: bool,
166}
167
168impl Default for Ern42Constraints {
169    fn default() -> Self {
170        Self {
171            max_resources_per_release: 500,
172            supported_image_formats: vec![
173                "JPEG".to_string(),
174                "PNG".to_string(),
175                "GIF".to_string(),
176                "TIFF".to_string(),
177            ],
178            supported_audio_formats: vec![
179                "MP3".to_string(),
180                "WAV".to_string(),
181                "FLAC".to_string(),
182                "AAC".to_string(),
183                "OGG".to_string(),
184            ],
185            max_deal_terms: 50,
186            enhanced_validation: true,
187        }
188    }
189}
190
191/// Get ERN 4.2 namespace mappings
192pub fn get_namespace_mappings() -> IndexMap<String, String> {
193    let mut mappings = IndexMap::new();
194
195    mappings.insert("ern".to_string(), "http://ddex.net/xml/ern/42".to_string());
196    mappings.insert("avs".to_string(), "http://ddex.net/xml/avs/avs".to_string());
197    mappings.insert("drm".to_string(), "http://ddex.net/xml/drm/drm".to_string());
198    mappings.insert("mv".to_string(), "http://ddex.net/xml/mv/mv".to_string());
199
200    mappings
201}
202
203/// Get ERN 4.2 specific XML template
204pub fn get_xml_template() -> &'static str {
205    r#"<?xml version="1.0" encoding="UTF-8"?>
206<NewReleaseMessage xmlns="http://ddex.net/xml/ern/42" 
207                  xmlns:avs="http://ddex.net/xml/avs/avs"
208                  MessageSchemaVersionId="ern/42">
209    <MessageHeader>
210        <MessageId>{message_id}</MessageId>
211        <MessageSender>
212            <PartyName>{sender_name}</PartyName>
213            <PartyId>{sender_id}</PartyId>
214        </MessageSender>
215        <MessageRecipient>
216            <PartyName>{recipient_name}</PartyName>
217            <PartyId>{recipient_id}</PartyId>
218        </MessageRecipient>
219        <MessageControlType>{control_type}</MessageControlType>
220        <MessageCreatedDateTime>{created_datetime}</MessageCreatedDateTime>
221    </MessageHeader>
222    
223    <ResourceList>
224        <!-- Enhanced resources will be populated here -->
225    </ResourceList>
226    
227    <ReleaseList>
228        <!-- Enhanced releases will be populated here -->
229    </ReleaseList>
230    
231    <DealList>
232        <!-- Enhanced deals will be populated here -->
233    </DealList>
234</NewReleaseMessage>"#
235}
236
237/// ERN 4.2 specific element builders
238pub mod builders {
239
240    use crate::ast::Element;
241
242    /// Build ERN 4.2 enhanced message header
243    pub fn build_enhanced_message_header(
244        message_id: &str,
245        sender_name: &str,
246        sender_id: Option<&str>,
247        recipient_name: &str,
248        recipient_id: Option<&str>,
249        control_type: Option<&str>,
250        created_datetime: &str,
251    ) -> Element {
252        let mut header = Element::new("MessageHeader");
253
254        // Message ID
255        let mut msg_id = Element::new("MessageId");
256        msg_id.add_text(message_id);
257        header.add_child(msg_id);
258
259        // Enhanced Message Sender
260        let mut sender = Element::new("MessageSender");
261        let mut sender_party = Element::new("PartyName");
262        sender_party.add_text(sender_name);
263        sender.add_child(sender_party);
264
265        if let Some(sid) = sender_id {
266            let mut sender_id_elem = Element::new("PartyId");
267            sender_id_elem.add_text(sid);
268            sender.add_child(sender_id_elem);
269        }
270        header.add_child(sender);
271
272        // Enhanced Message Recipient
273        let mut recipient = Element::new("MessageRecipient");
274        let mut recipient_party = Element::new("PartyName");
275        recipient_party.add_text(recipient_name);
276        recipient.add_child(recipient_party);
277
278        if let Some(rid) = recipient_id {
279            let mut recipient_id_elem = Element::new("PartyId");
280            recipient_id_elem.add_text(rid);
281            recipient.add_child(recipient_id_elem);
282        }
283        header.add_child(recipient);
284
285        // Message Control Type (new in 4.2)
286        if let Some(control) = control_type {
287            let mut control_elem = Element::new("MessageControlType");
288            control_elem.add_text(control);
289            header.add_child(control_elem);
290        }
291
292        // Created DateTime
293        let mut created = Element::new("MessageCreatedDateTime");
294        created.add_text(created_datetime);
295        header.add_child(created);
296
297        header
298    }
299
300    /// Build ERN 4.2 enhanced sound recording resource
301    pub fn build_enhanced_sound_recording(
302        resource_ref: &str,
303        resource_id: &str,
304        title: &str,
305        artist: &str,
306        isrc: &str,
307        duration: &str,
308        file_name: Option<&str>,
309        codec: Option<&str>,
310        bit_rate: Option<u32>,
311    ) -> Element {
312        let mut sound_recording = Element::new("SoundRecording");
313
314        // Resource Reference
315        let mut res_ref = Element::new("ResourceReference");
316        res_ref.add_text(resource_ref);
317        sound_recording.add_child(res_ref);
318
319        // Type
320        let mut res_type = Element::new("Type");
321        res_type.add_text("SoundRecording");
322        sound_recording.add_child(res_type);
323
324        // Resource ID
325        let mut res_id = Element::new("ResourceId");
326        res_id.add_text(resource_id);
327        sound_recording.add_child(res_id);
328
329        // Reference Title
330        let mut ref_title = Element::new("ReferenceTitle");
331        ref_title.add_text(title);
332        sound_recording.add_child(ref_title);
333
334        // Display Artist
335        let mut display_artist = Element::new("DisplayArtist");
336        display_artist.add_text(artist);
337        sound_recording.add_child(display_artist);
338
339        // ISRC
340        let mut isrc_elem = Element::new("ISRC");
341        isrc_elem.add_text(isrc);
342        sound_recording.add_child(isrc_elem);
343
344        // Duration
345        let mut duration_elem = Element::new("Duration");
346        duration_elem.add_text(duration);
347        sound_recording.add_child(duration_elem);
348
349        // Enhanced Technical Details (new in 4.2)
350        if file_name.is_some() || codec.is_some() || bit_rate.is_some() {
351            let mut tech_details = Element::new("TechnicalResourceDetails");
352
353            if let Some(fname) = file_name {
354                let mut file_elem = Element::new("FileName");
355                file_elem.add_text(fname);
356                tech_details.add_child(file_elem);
357            }
358
359            if let Some(codec_type) = codec {
360                let mut codec_elem = Element::new("AudioCodecType");
361                codec_elem.add_text(codec_type);
362                tech_details.add_child(codec_elem);
363            }
364
365            if let Some(bitrate) = bit_rate {
366                let mut bitrate_elem = Element::new("BitRate");
367                bitrate_elem.add_text(&bitrate.to_string());
368                tech_details.add_child(bitrate_elem);
369            }
370
371            sound_recording.add_child(tech_details);
372        }
373
374        sound_recording
375    }
376
377    /// Build ERN 4.2 enhanced release
378    pub fn build_enhanced_release(
379        release_ref: &str,
380        release_id: &str,
381        release_type: &str,
382        title: &str,
383        artist: &str,
384        label: &str,
385        upc: Option<&str>,
386        release_date: Option<&str>,
387        genre: Option<&str>,
388        resource_refs: &[String],
389    ) -> Element {
390        let mut release = Element::new("Release");
391
392        // Release Reference (enhanced in 4.2)
393        let mut rel_ref = Element::new("ReleaseReference");
394        rel_ref.add_text(release_ref);
395        release.add_child(rel_ref);
396
397        // Release ID
398        let mut rel_id = Element::new("ReleaseId");
399        rel_id.add_text(release_id);
400        release.add_child(rel_id);
401
402        // Release Type (more options in 4.2)
403        let mut rel_type = Element::new("ReleaseType");
404        rel_type.add_text(release_type);
405        release.add_child(rel_type);
406
407        // Title
408        let mut title_elem = Element::new("Title");
409        title_elem.add_text(title);
410        release.add_child(title_elem);
411
412        // Display Artist
413        let mut artist_elem = Element::new("DisplayArtist");
414        artist_elem.add_text(artist);
415        release.add_child(artist_elem);
416
417        // Label Name
418        let mut label_elem = Element::new("LabelName");
419        label_elem.add_text(label);
420        release.add_child(label_elem);
421
422        // UPC
423        if let Some(upc_val) = upc {
424            let mut upc_elem = Element::new("UPC");
425            upc_elem.add_text(upc_val);
426            release.add_child(upc_elem);
427        }
428
429        // Release Date
430        if let Some(date) = release_date {
431            let mut date_elem = Element::new("ReleaseDate");
432            date_elem.add_text(date);
433            release.add_child(date_elem);
434        }
435
436        // Genre
437        if let Some(genre_val) = genre {
438            let mut genre_elem = Element::new("Genre");
439            genre_elem.add_text(genre_val);
440            release.add_child(genre_elem);
441        }
442
443        // Enhanced Resource Group
444        if !resource_refs.is_empty() {
445            let mut resource_group = Element::new("ResourceGroup");
446            for res_ref in resource_refs {
447                let mut ref_elem = Element::new("ResourceReference");
448                ref_elem.add_text(res_ref);
449                resource_group.add_child(ref_elem);
450            }
451            release.add_child(resource_group);
452        }
453
454        release
455    }
456
457    /// Build ERN 4.2 enhanced deal
458    pub fn build_enhanced_deal(
459        deal_ref: &str,
460        commercial_model: &str,
461        territories: &[String],
462        start_date: Option<&str>,
463        end_date: Option<&str>,
464        price: Option<f64>,
465        currency: Option<&str>,
466        usage_type: Option<&str>,
467        release_refs: &[String],
468    ) -> Element {
469        let mut deal = Element::new("ReleaseDeal");
470
471        // Deal Reference (new in 4.2)
472        let mut deal_ref_elem = Element::new("DealReference");
473        deal_ref_elem.add_text(deal_ref);
474        deal.add_child(deal_ref_elem);
475
476        // Enhanced Deal Terms
477        let mut deal_terms = Element::new("DealTerms");
478
479        // Commercial Model Type
480        let mut model_elem = Element::new("CommercialModelType");
481        model_elem.add_text(commercial_model);
482        deal_terms.add_child(model_elem);
483
484        // Enhanced Territory handling
485        for territory_code in territories {
486            let mut territory = Element::new("Territory");
487            let mut territory_elem = Element::new("TerritoryCode");
488            territory_elem.add_text(territory_code);
489            territory.add_child(territory_elem);
490            deal_terms.add_child(territory);
491        }
492
493        // Enhanced Validity Period
494        if start_date.is_some() || end_date.is_some() {
495            let mut validity = Element::new("ValidityPeriod");
496
497            if let Some(start) = start_date {
498                let mut start_elem = Element::new("StartDate");
499                start_elem.add_text(start);
500                validity.add_child(start_elem);
501            }
502
503            if let Some(end) = end_date {
504                let mut end_elem = Element::new("EndDate");
505                end_elem.add_text(end);
506                validity.add_child(end_elem);
507            }
508
509            deal_terms.add_child(validity);
510        }
511
512        // Enhanced Price
513        if let Some(price_val) = price {
514            let mut price_elem = Element::new("Price");
515            let mut amount_elem = Element::new("PriceAmount");
516            amount_elem.add_text(&price_val.to_string());
517            price_elem.add_child(amount_elem);
518
519            if let Some(currency_code) = currency {
520                let mut currency_elem = Element::new("PriceCurrencyCode");
521                currency_elem.add_text(currency_code);
522                price_elem.add_child(currency_elem);
523            }
524
525            deal_terms.add_child(price_elem);
526        }
527
528        // Usage Type (new in 4.2)
529        if let Some(usage) = usage_type {
530            let mut usage_elem = Element::new("UsageType");
531            usage_elem.add_text(usage);
532            deal_terms.add_child(usage_elem);
533        }
534
535        deal.add_child(deal_terms);
536
537        // Release References
538        for rel_ref in release_refs {
539            let mut ref_elem = Element::new("ReleaseReference");
540            ref_elem.add_text(rel_ref);
541            deal.add_child(ref_elem);
542        }
543
544        deal
545    }
546}
547
548/// ERN 4.2 validation functions
549pub mod validation {
550
551    use once_cell::sync::Lazy;
552    use regex::Regex;
553
554    // Enhanced regex patterns for ERN 4.2
555    static ISRC_PATTERN_42: Lazy<Regex> =
556        Lazy::new(|| Regex::new(r"^[A-Z]{2}[A-Z0-9]{3}\d{7}$").unwrap());
557
558    static UPC_PATTERN_42: Lazy<Regex> = Lazy::new(|| Regex::new(r"^\d{12}$").unwrap());
559
560    static DURATION_PATTERN_42: Lazy<Regex> =
561        Lazy::new(|| Regex::new(r"^PT(?:\d+H)?(?:\d+M)?(?:\d+(?:\.\d+)?S)?$").unwrap());
562
563    static DATE_PATTERN_42: Lazy<Regex> = Lazy::new(|| Regex::new(r"^\d{4}-\d{2}-\d{2}$").unwrap());
564
565    static DATETIME_PATTERN_42: Lazy<Regex> = Lazy::new(|| {
566        Regex::new(r"^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})$").unwrap()
567    });
568
569    /// Enhanced validation for ERN 4.2
570    pub fn validate_isrc(isrc: &str) -> bool {
571        ISRC_PATTERN_42.is_match(isrc)
572    }
573
574    /// Enhanced UPC validation for ERN 4.2
575    pub fn validate_upc(upc: &str) -> bool {
576        UPC_PATTERN_42.is_match(upc)
577    }
578
579    /// Enhanced duration validation for ERN 4.2
580    pub fn validate_duration(duration: &str) -> bool {
581        DURATION_PATTERN_42.is_match(duration)
582    }
583
584    /// Enhanced date validation for ERN 4.2
585    pub fn validate_date(date: &str) -> bool {
586        DATE_PATTERN_42.is_match(date)
587    }
588
589    /// Enhanced datetime validation for ERN 4.2
590    pub fn validate_datetime(datetime: &str) -> bool {
591        DATETIME_PATTERN_42.is_match(datetime)
592    }
593
594    /// Enhanced territory code validation for ERN 4.2
595    pub fn validate_territory_code(territory: &str) -> bool {
596        // Extended territory list for 4.2
597        matches!(
598            territory,
599            "US" | "GB"
600                | "DE"
601                | "FR"
602                | "JP"
603                | "CA"
604                | "AU"
605                | "IT"
606                | "ES"
607                | "NL"
608                | "SE"
609                | "NO"
610                | "DK"
611                | "FI"
612                | "BR"
613                | "MX"
614                | "AR"
615                | "IN"
616                | "CN"
617                | "KR"
618                | "Worldwide"
619                | "WorldwideExceptUS"
620        )
621    }
622
623    /// Enhanced commercial model validation for ERN 4.2
624    pub fn validate_commercial_model(model: &str) -> bool {
625        matches!(
626            model,
627            "SubscriptionModel"
628                | "PurchaseModel"
629                | "AdSupportedModel"
630                | "FreeOfChargeModel"
631                | "StreamingModel"
632                | "DownloadModel"
633        )
634    }
635
636    /// Validate audio codec type for ERN 4.2
637    pub fn validate_audio_codec(codec: &str) -> bool {
638        matches!(
639            codec,
640            "MP3" | "AAC" | "FLAC" | "WAV" | "OGG" | "WMA" | "MP4" | "M4A"
641        )
642    }
643
644    /// Validate usage type for ERN 4.2
645    pub fn validate_usage_type(usage: &str) -> bool {
646        matches!(
647            usage,
648            "Stream"
649                | "Download"
650                | "Preview"
651                | "ConditionalDownload"
652                | "DigitalPhonogramDelivery"
653                | "UserMadeClip"
654        )
655    }
656
657    /// Get all validation errors for an ERN 4.2 message
658    pub fn validate_ern_42_message(xml_content: &str) -> Vec<String> {
659        let mut errors = Vec::new();
660
661        // Check required namespace
662        if !xml_content.contains("http://ddex.net/xml/ern/42") {
663            errors.push("Missing ERN 4.2 namespace".to_string());
664        }
665
666        // Check message schema version ID
667        if !xml_content.contains("ern/42") {
668            errors.push("Missing or incorrect MessageSchemaVersionId".to_string());
669        }
670
671        // Check for required elements
672        let required_elements = [
673            "MessageId",
674            "MessageSender",
675            "MessageRecipient",
676            "MessageCreatedDateTime",
677            "ResourceList",
678            "ReleaseList",
679        ];
680
681        for element in &required_elements {
682            if !xml_content.contains(&format!("<{}", element)) {
683                errors.push(format!("Missing required element: {}", element));
684            }
685        }
686
687        // Check for enhanced elements that should be present
688        if xml_content.contains("TechnicalResourceDetails") {
689            if !xml_content.contains("AudioCodecType") && !xml_content.contains("FileName") {
690                errors.push(
691                    "TechnicalResourceDetails should contain AudioCodecType or FileName"
692                        .to_string(),
693                );
694            }
695        }
696
697        errors
698    }
699}