use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)]
pub struct SchemaMetadata {
pub schema_version: Option<u32>,
pub schema_fingerprint: Option<String>,
}
impl SchemaMetadata {
pub fn new(
schema_version: Option<u32>,
schema_fingerprint: Option<String>,
) -> Result<Self, SchemaMetadataError> {
let metadata = Self {
schema_version,
schema_fingerprint,
};
metadata.validate()?;
Ok(metadata)
}
pub fn validate(&self) -> Result<(), SchemaMetadataError> {
if self.schema_version == Some(0) {
return Err(SchemaMetadataError::InvalidVersion);
}
let Some(fingerprint) = &self.schema_fingerprint else {
return Ok(());
};
if fingerprint.is_empty() {
return Err(SchemaMetadataError::EmptyFingerprint);
}
if fingerprint.len() > 256 {
return Err(SchemaMetadataError::FingerprintTooLong);
}
if !fingerprint.is_ascii() {
return Err(SchemaMetadataError::NonAsciiFingerprint);
}
if fingerprint.bytes().any(|byte| byte.is_ascii_control()) {
return Err(SchemaMetadataError::ControlCharacterFingerprint);
}
Ok(())
}
}
#[derive(Clone, Debug, Eq, thiserror::Error, PartialEq)]
pub enum SchemaMetadataError {
#[error("schema_version must be greater than zero when present")]
InvalidVersion,
#[error("schema_fingerprint must not be empty when present")]
EmptyFingerprint,
#[error("schema_fingerprint must be at most 256 bytes")]
FingerprintTooLong,
#[error("schema_fingerprint must be ASCII")]
NonAsciiFingerprint,
#[error("schema_fingerprint must not contain ASCII control characters")]
ControlCharacterFingerprint,
}