imferno_core/package/
codes.rs1pub use crate::diagnostics::codes::ValidationCode;
6
7pub use crate::assetmap::codes::St2067_2_2020;
8pub use crate::assetmap::volindex_codes::St429_9_2014;
9pub use crate::cpl::codes::St2067_3_2016;
10pub use crate::mxf::codes::St377_1_2011;
11pub use crate::scm::codes::St2067_9_2018;
12
13use crate::diagnostics::{Category, Severity};
14
15#[derive(Debug, Clone, Copy, PartialEq, Eq, strum::EnumIter)]
25pub enum ImfernoCode {
26 UnreferencedAsset,
30 UnlistedEssence,
34 ParseError,
36 PklParseError,
38 XmlAssetParseError,
40 XmlReadError,
42 ReadDirError,
44 DirEntryError,
46 PathTraversal,
48}
49
50impl ValidationCode for ImfernoCode {
51 fn code(&self) -> &'static str {
52 match self {
53 Self::UnreferencedAsset => "IMFERNO:Package/UnreferencedAsset",
54 Self::UnlistedEssence => "IMFERNO:Package/UnlistedEssence",
55 Self::ParseError => "IMFERNO:Package/ParseError",
56 Self::PklParseError => "IMFERNO:Package/PklParseError",
57 Self::XmlAssetParseError => "IMFERNO:Package/XmlAssetParseError",
58 Self::XmlReadError => "IMFERNO:Package/XmlReadError",
59 Self::ReadDirError => "IMFERNO:Package/ReadDirError",
60 Self::DirEntryError => "IMFERNO:Package/DirEntryError",
61 Self::PathTraversal => "IMFERNO:Package/PathTraversal",
62 }
63 }
64
65 fn description(&self) -> &'static str {
66 match self {
67 Self::UnreferencedAsset =>
68 "Asset is present in the AssetMap but not referenced by any CPL Virtual Track and has no SCM declaration. Likely a sidecar essence without an SCM.",
69 Self::UnlistedEssence =>
70 "File is present in the package directory but not listed in the AssetMap. The file is invisible to any conforming IMF reader.",
71 Self::ParseError =>
72 "IMF package failed to parse due to a structural error.",
73 Self::PklParseError =>
74 "A Packing List referenced by the AssetMap could not be parsed.",
75 Self::XmlAssetParseError =>
76 "An XML asset could not be parsed as CPL, OPL, or SCM.",
77 Self::XmlReadError =>
78 "An XML file could not be read from disk.",
79 Self::ReadDirError =>
80 "Could not scan the package directory.",
81 Self::DirEntryError =>
82 "Could not read a directory entry while scanning for unlisted essences.",
83 Self::PathTraversal =>
84 "An asset chunk path attempts to escape the package root directory (path traversal).",
85 }
86 }
87
88 fn default_severity(&self) -> Severity {
89 match self {
90 Self::UnreferencedAsset => Severity::Info,
91 Self::UnlistedEssence => Severity::Warning,
92 Self::ParseError => Severity::Critical,
93 Self::PklParseError => Severity::Error,
94 Self::XmlAssetParseError => Severity::Warning,
95 Self::XmlReadError => Severity::Warning,
96 Self::ReadDirError => Severity::Info,
97 Self::DirEntryError => Severity::Info,
98 Self::PathTraversal => Severity::Error,
99 }
100 }
101
102 fn category(&self) -> Category {
103 Category::Structure
104 }
105
106 fn example(&self) -> Option<&'static str> {
107 Some(match self {
108 Self::UnreferencedAsset =>
109 "ASSETMAP lists urn:uuid:abc… as an Asset, but no CPL Virtual Track resource and no SCM Asset entry references it.",
110 Self::UnlistedEssence =>
111 "BONUS_AUDIO.mxf sits next to ASSETMAP.xml on disk but does not appear in any <Asset> entry of ASSETMAP.xml.",
112 Self::ParseError =>
113 "Top-level error parsing ASSETMAP.xml — e.g. missing root <AssetMap> element or truncated stream.",
114 Self::PklParseError =>
115 "PKL_<uuid>.xml is referenced from ASSETMAP but is malformed XML or violates the PKL schema.",
116 Self::XmlAssetParseError =>
117 "An asset listed with a .xml suffix doesn't parse as CPL, OPL, or SCM (likely a misnamed file or a sidecar XML).",
118 Self::XmlReadError =>
119 "ASSETMAP.xml exists in the manifest but couldn't be opened (permission denied, network read failure, etc.).",
120 Self::ReadDirError =>
121 "The package root directory could not be enumerated (permission denied or path missing).",
122 Self::DirEntryError =>
123 "A specific directory entry returned an error during scanning (often a broken symlink).",
124 Self::PathTraversal =>
125 "<Chunk><Path>../../etc/passwd</Path></Chunk> — the asset path resolves outside the package root.",
126 })
127 }
128}
129
130impl ImfernoCode {
131 pub const ALL: &'static [Self] = &[
132 Self::UnreferencedAsset,
133 Self::UnlistedEssence,
134 Self::ParseError,
135 Self::PklParseError,
136 Self::XmlAssetParseError,
137 Self::XmlReadError,
138 Self::ReadDirError,
139 Self::DirEntryError,
140 Self::PathTraversal,
141 ];
142}
143
144impl From<ImfernoCode> for String {
145 fn from(c: ImfernoCode) -> String {
146 c.code().to_string()
147 }
148}