mirror of
https://github.com/storytold/artcraft.git
synced 2026-11-13 05:12:50 +00:00
forgot to commit this omg
This commit is contained in:
1 parent
d90d446643
commit
f50bfa9ee7
1 file changed
+155
@@ -0,0 +1,155 @@
|
||||
use std::collections::BTreeSet;
|
||||
|
||||
#[cfg(test)]
|
||||
use strum::EnumCount;
|
||||
#[cfg(test)]
|
||||
use strum::EnumIter;
|
||||
use utoipa::ToSchema;
|
||||
|
||||
/// Used in the `media_files` table in the nullable `maybe_project_type`
|
||||
/// VARCHAR(32) field.
|
||||
///
|
||||
/// Identifies which kind of internal Artcraft project document a media file is.
|
||||
/// Only set when `media_class = 'project'`. The file format lives in
|
||||
/// `media_type` (`json` / legacy `scene_json`); the JSON payload carries its
|
||||
/// own schema version.
|
||||
///
|
||||
/// DO NOT CHANGE VALUES WITHOUT A MIGRATION STRATEGY.
|
||||
#[cfg_attr(test, derive(EnumIter, EnumCount))]
|
||||
#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash, Deserialize, Serialize, ToSchema)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum MediaFileProjectType {
|
||||
/// 3D editor scene descriptor: objects with locations, skyboxes, animations,
|
||||
/// etc. — a full editable 3D scene.
|
||||
/// NB: serde's snake_case renames this to "scene3d" (no underscore before
|
||||
/// the digit), so the rename must be explicit.
|
||||
#[serde(rename = "scene_3d")]
|
||||
Scene3d,
|
||||
|
||||
/// Mood board: a collection of images on a lightweight graph.
|
||||
MoodBoard,
|
||||
|
||||
/// Graph workflow: a node-graph pipeline of image and video generation steps.
|
||||
Workflow,
|
||||
|
||||
/// Video editor project: a nonlinear video editing timeline.
|
||||
VideoTimeline,
|
||||
}
|
||||
|
||||
impl_enum_display_and_debug_using_to_str!(MediaFileProjectType);
|
||||
impl_mysql_enum_coders!(MediaFileProjectType);
|
||||
impl_mysql_from_row!(MediaFileProjectType);
|
||||
|
||||
impl MediaFileProjectType {
|
||||
pub const fn to_str(&self) -> &'static str {
|
||||
match self {
|
||||
Self::Scene3d => "scene_3d",
|
||||
Self::MoodBoard => "mood_board",
|
||||
Self::Workflow => "workflow",
|
||||
Self::VideoTimeline => "video_timeline",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_str(value: &str) -> Result<Self, String> {
|
||||
match value {
|
||||
"scene_3d" => Ok(Self::Scene3d),
|
||||
"mood_board" => Ok(Self::MoodBoard),
|
||||
"workflow" => Ok(Self::Workflow),
|
||||
"video_timeline" => Ok(Self::VideoTimeline),
|
||||
_ => Err(format!("invalid value: {:?}", value)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn all_variants() -> BTreeSet<Self> {
|
||||
// NB: BTreeSet is sorted
|
||||
BTreeSet::from([
|
||||
Self::Scene3d,
|
||||
Self::MoodBoard,
|
||||
Self::Workflow,
|
||||
Self::VideoTimeline,
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::by_table::media_files::media_file_project_type::MediaFileProjectType;
|
||||
use crate::test_helpers::assert_serialization;
|
||||
|
||||
mod serde {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_serialization() {
|
||||
assert_serialization(MediaFileProjectType::Scene3d, "scene_3d");
|
||||
assert_serialization(MediaFileProjectType::MoodBoard, "mood_board");
|
||||
assert_serialization(MediaFileProjectType::Workflow, "workflow");
|
||||
assert_serialization(MediaFileProjectType::VideoTimeline, "video_timeline");
|
||||
}
|
||||
}
|
||||
|
||||
mod impl_methods {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn to_str() {
|
||||
assert_eq!(MediaFileProjectType::Scene3d.to_str(), "scene_3d");
|
||||
assert_eq!(MediaFileProjectType::MoodBoard.to_str(), "mood_board");
|
||||
assert_eq!(MediaFileProjectType::Workflow.to_str(), "workflow");
|
||||
assert_eq!(MediaFileProjectType::VideoTimeline.to_str(), "video_timeline");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_str() {
|
||||
assert_eq!(MediaFileProjectType::from_str("scene_3d").unwrap(), MediaFileProjectType::Scene3d);
|
||||
assert_eq!(MediaFileProjectType::from_str("mood_board").unwrap(), MediaFileProjectType::MoodBoard);
|
||||
assert_eq!(MediaFileProjectType::from_str("workflow").unwrap(), MediaFileProjectType::Workflow);
|
||||
assert_eq!(MediaFileProjectType::from_str("video_timeline").unwrap(), MediaFileProjectType::VideoTimeline);
|
||||
assert!(MediaFileProjectType::from_str("foo").is_err());
|
||||
}
|
||||
}
|
||||
|
||||
mod manual_variant_checks {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn all_variants() {
|
||||
let mut variants = MediaFileProjectType::all_variants();
|
||||
assert_eq!(variants.len(), 4);
|
||||
assert_eq!(variants.pop_first(), Some(MediaFileProjectType::Scene3d));
|
||||
assert_eq!(variants.pop_first(), Some(MediaFileProjectType::MoodBoard));
|
||||
assert_eq!(variants.pop_first(), Some(MediaFileProjectType::Workflow));
|
||||
assert_eq!(variants.pop_first(), Some(MediaFileProjectType::VideoTimeline));
|
||||
assert_eq!(variants.pop_first(), None);
|
||||
}
|
||||
}
|
||||
|
||||
mod mechanical_checks {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn variant_length() {
|
||||
use strum::IntoEnumIterator;
|
||||
assert_eq!(MediaFileProjectType::all_variants().len(), MediaFileProjectType::iter().len());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn round_trip() {
|
||||
for variant in MediaFileProjectType::all_variants() {
|
||||
assert_eq!(variant, MediaFileProjectType::from_str(variant.to_str()).unwrap());
|
||||
assert_eq!(variant, MediaFileProjectType::from_str(&format!("{}", variant)).unwrap());
|
||||
assert_eq!(variant, MediaFileProjectType::from_str(&format!("{:?}", variant)).unwrap());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn serialized_length_ok_for_database() {
|
||||
const MAX_LENGTH : usize = 32;
|
||||
for variant in MediaFileProjectType::all_variants() {
|
||||
let serialized = variant.to_str();
|
||||
assert!(serialized.len() > 0, "variant {:?} is too short", variant);
|
||||
assert!(serialized.len() <= MAX_LENGTH, "variant {:?} is too long", variant);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user