#![forbid(unsafe_code)]
#![warn(missing_docs)]
mod generated;
use std::fmt;
use std::str::FromStr;
pub const SCHEMA_VERSION: &str = "0.8.0";
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[non_exhaustive]
pub enum SchemaName {
AudioTranscription,
Classification,
DocumentExtraction,
Embedding,
EntityExtraction,
Generic,
Geolocation,
LlmOutput,
ObjectDetection,
Ranking,
Regression,
TemporalSegmentation,
}
impl SchemaName {
pub const ALL: &'static [SchemaName] = &[
SchemaName::AudioTranscription,
SchemaName::Classification,
SchemaName::DocumentExtraction,
SchemaName::Embedding,
SchemaName::EntityExtraction,
SchemaName::Generic,
SchemaName::Geolocation,
SchemaName::LlmOutput,
SchemaName::ObjectDetection,
SchemaName::Ranking,
SchemaName::Regression,
SchemaName::TemporalSegmentation,
];
pub const fn as_str(self) -> &'static str {
match self {
SchemaName::AudioTranscription => "audio-transcription",
SchemaName::Classification => "classification",
SchemaName::DocumentExtraction => "document-extraction",
SchemaName::Embedding => "embedding",
SchemaName::EntityExtraction => "entity-extraction",
SchemaName::Generic => "generic",
SchemaName::Geolocation => "geolocation",
SchemaName::LlmOutput => "llm-output",
SchemaName::ObjectDetection => "object-detection",
SchemaName::Ranking => "ranking",
SchemaName::Regression => "regression",
SchemaName::TemporalSegmentation => "temporal-segmentation",
}
}
}
impl fmt::Display for SchemaName {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.pad(self.as_str())
}
}
impl FromStr for SchemaName {
type Err = Error;
fn from_str(name: &str) -> Result<Self, Error> {
SchemaName::ALL
.iter()
.copied()
.find(|known| known.as_str() == name)
.ok_or_else(|| Error::UnknownName {
name: name.to_owned(),
})
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub enum Error {
UnknownName {
name: String,
},
UnknownVersion {
version: String,
},
NotInVersion {
name: SchemaName,
version: &'static str,
},
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Error::UnknownName { name } => {
write!(f, "unknown schema name {name:?}; expected one of ")?;
for (index, known) in SchemaName::ALL.iter().enumerate() {
if index > 0 {
f.write_str(", ")?;
}
f.write_str(known.as_str())?;
}
Ok(())
}
Error::UnknownVersion { version } => {
write!(
f,
"schema version {version:?} is not bundled; available: {}",
available_versions().join(", ")
)
}
Error::NotInVersion { name, version } => {
write!(
f,
"schema {:?} is not in schema version {version}",
name.as_str()
)
}
}
}
}
impl std::error::Error for Error {}
pub fn available_versions() -> &'static [&'static str] {
generated::VERSIONS
}
pub fn schema_json(name: SchemaName, version: Option<&str>) -> Result<&'static str, Error> {
let version = version.unwrap_or(SCHEMA_VERSION);
let Some(index) = generated::VERSIONS
.iter()
.position(|known| *known == version)
else {
return Err(Error::UnknownVersion {
version: version.to_owned(),
});
};
generated::SCHEMAS[index]
.iter()
.find(|(known, _)| *known == name)
.map(|(_, text)| *text)
.ok_or(Error::NotInVersion {
name,
version: generated::VERSIONS[index],
})
}
#[cfg(feature = "serde_json")]
pub fn schema(name: SchemaName, version: Option<&str>) -> Result<serde_json::Value, Error> {
let text = schema_json(name, version)?;
Ok(serde_json::from_str(text).expect("bundled schemas are valid JSON"))
}