1use serde::{Deserialize, Serialize};
2
3#[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)]
13#[serde(deny_unknown_fields)]
14pub struct SchemaMetadata {
15 pub schema_version: Option<u32>,
17 pub schema_fingerprint: Option<String>,
19}
20
21impl SchemaMetadata {
22 pub fn new(
24 schema_version: Option<u32>,
25 schema_fingerprint: Option<String>,
26 ) -> Result<Self, SchemaMetadataError> {
27 let metadata = Self {
28 schema_version,
29 schema_fingerprint,
30 };
31 metadata.validate()?;
32 Ok(metadata)
33 }
34
35 pub fn validate(&self) -> Result<(), SchemaMetadataError> {
37 if self.schema_version == Some(0) {
38 return Err(SchemaMetadataError::InvalidVersion);
39 }
40
41 let Some(fingerprint) = &self.schema_fingerprint else {
42 return Ok(());
43 };
44
45 if fingerprint.is_empty() {
46 return Err(SchemaMetadataError::EmptyFingerprint);
47 }
48 if fingerprint.len() > 256 {
49 return Err(SchemaMetadataError::FingerprintTooLong);
50 }
51 if !fingerprint.is_ascii() {
52 return Err(SchemaMetadataError::NonAsciiFingerprint);
53 }
54 if fingerprint.bytes().any(|byte| byte.is_ascii_control()) {
55 return Err(SchemaMetadataError::ControlCharacterFingerprint);
56 }
57
58 Ok(())
59 }
60}
61
62#[derive(Clone, Debug, Eq, thiserror::Error, PartialEq)]
67pub enum SchemaMetadataError {
68 #[error("schema_version must be greater than zero when present")]
70 InvalidVersion,
71 #[error("schema_fingerprint must not be empty when present")]
73 EmptyFingerprint,
74 #[error("schema_fingerprint must be at most 256 bytes")]
76 FingerprintTooLong,
77 #[error("schema_fingerprint must be ASCII")]
79 NonAsciiFingerprint,
80 #[error("schema_fingerprint must not contain ASCII control characters")]
82 ControlCharacterFingerprint,
83}