#![allow(dead_code)]
use std::collections::HashMap;
#[derive(Debug, Clone, PartialEq)]
pub struct InheritableMetadata {
pub keywords: Vec<String>,
pub description: Option<String>,
pub reel: Option<String>,
pub scene: Option<String>,
pub take: Option<u32>,
}
impl InheritableMetadata {
#[must_use]
pub fn new() -> Self {
Self {
keywords: Vec::new(),
description: None,
reel: None,
scene: None,
take: None,
}
}
pub fn merge_from(&mut self, other: &Self) {
for kw in &other.keywords {
if !self.keywords.contains(kw) {
self.keywords.push(kw.clone());
}
}
if other.description.is_some() {
self.description = other.description.clone();
}
if other.reel.is_some() {
self.reel = other.reel.clone();
}
if other.scene.is_some() {
self.scene = other.scene.clone();
}
if other.take.is_some() {
self.take = other.take;
}
}
}
impl Default for InheritableMetadata {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum InheritPolicy {
All,
None,
KeywordsOnly,
ProductionOnly,
}
#[must_use]
pub fn resolve_inherited(
parent: &InheritableMetadata,
subclip_override: &InheritableMetadata,
policy: InheritPolicy,
) -> InheritableMetadata {
let mut result = subclip_override.clone();
match policy {
InheritPolicy::None => {}
InheritPolicy::All => {
result.merge_from(parent);
}
InheritPolicy::KeywordsOnly => {
for kw in &parent.keywords {
if !result.keywords.contains(kw) {
result.keywords.push(kw.clone());
}
}
}
InheritPolicy::ProductionOnly => {
if result.reel.is_none() {
result.reel = parent.reel.clone();
}
if result.scene.is_none() {
result.scene = parent.scene.clone();
}
if result.take.is_none() {
result.take = parent.take;
}
}
}
result
}
pub struct InheritanceRegistry {
parents: HashMap<u64, InheritableMetadata>,
}
impl InheritanceRegistry {
#[must_use]
pub fn new() -> Self {
Self {
parents: HashMap::new(),
}
}
pub fn register_parent(&mut self, clip_id: u64, meta: InheritableMetadata) {
self.parents.insert(clip_id, meta);
}
#[must_use]
pub fn get_parent(&self, parent_id: u64) -> Option<&InheritableMetadata> {
self.parents.get(&parent_id)
}
#[must_use]
pub fn resolve(
&self,
parent_id: u64,
subclip_override: &InheritableMetadata,
policy: InheritPolicy,
) -> InheritableMetadata {
match self.parents.get(&parent_id) {
Some(parent) => resolve_inherited(parent, subclip_override, policy),
None => subclip_override.clone(),
}
}
#[must_use]
pub fn len(&self) -> usize {
self.parents.len()
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.parents.is_empty()
}
}
impl Default for InheritanceRegistry {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
fn make_parent() -> InheritableMetadata {
let mut m = InheritableMetadata::new();
m.keywords = vec!["interview".into(), "outdoors".into()];
m.reel = Some("A001".into());
m.scene = Some("5".into());
m.take = Some(3);
m.description = Some("Parent description".into());
m
}
fn make_override() -> InheritableMetadata {
let mut m = InheritableMetadata::new();
m.keywords = vec!["closeup".into()];
m
}
#[test]
fn test_inheritable_metadata_new() {
let m = InheritableMetadata::new();
assert!(m.keywords.is_empty());
assert!(m.description.is_none());
assert!(m.reel.is_none());
assert!(m.scene.is_none());
assert!(m.take.is_none());
}
#[test]
fn test_merge_from_keywords_union() {
let mut base = make_override();
let parent = make_parent();
base.merge_from(&parent);
assert!(base.keywords.contains(&"interview".to_string()));
assert!(base.keywords.contains(&"closeup".to_string()));
let count = base.keywords.iter().filter(|k| *k == "outdoors").count();
assert_eq!(count, 1);
}
#[test]
fn test_merge_from_overrides_description() {
let mut base = InheritableMetadata::new();
base.description = Some("Sub description".into());
let parent = make_parent();
base.merge_from(&parent);
assert_eq!(base.description.as_deref(), Some("Parent description"));
}
#[test]
fn test_resolve_inherit_none() {
let parent = make_parent();
let subclip = make_override();
let result = resolve_inherited(&parent, &subclip, InheritPolicy::None);
assert_eq!(result.keywords, vec!["closeup".to_string()]);
assert!(result.reel.is_none());
}
#[test]
fn test_resolve_inherit_all() {
let parent = make_parent();
let subclip = make_override();
let result = resolve_inherited(&parent, &subclip, InheritPolicy::All);
assert!(result.keywords.contains(&"interview".to_string()));
assert!(result.keywords.contains(&"closeup".to_string()));
assert_eq!(result.reel.as_deref(), Some("A001"));
}
#[test]
fn test_resolve_keywords_only() {
let parent = make_parent();
let subclip = make_override();
let result = resolve_inherited(&parent, &subclip, InheritPolicy::KeywordsOnly);
assert!(result.keywords.contains(&"interview".to_string()));
assert!(result.keywords.contains(&"closeup".to_string()));
assert!(result.reel.is_none());
}
#[test]
fn test_resolve_production_only() {
let parent = make_parent();
let subclip = make_override();
let result = resolve_inherited(&parent, &subclip, InheritPolicy::ProductionOnly);
assert_eq!(result.reel.as_deref(), Some("A001"));
assert_eq!(result.scene.as_deref(), Some("5"));
assert_eq!(result.take, Some(3));
assert_eq!(result.keywords, vec!["closeup".to_string()]);
}
#[test]
fn test_resolve_production_only_subclip_overrides() {
let parent = make_parent();
let mut subclip = make_override();
subclip.reel = Some("B002".into());
let result = resolve_inherited(&parent, &subclip, InheritPolicy::ProductionOnly);
assert_eq!(result.reel.as_deref(), Some("B002"));
}
#[test]
fn test_registry_register_and_resolve() {
let mut reg = InheritanceRegistry::new();
reg.register_parent(42, make_parent());
assert!(!reg.is_empty());
assert_eq!(reg.len(), 1);
let sub = make_override();
let result = reg.resolve(42, &sub, InheritPolicy::All);
assert!(result.keywords.contains(&"interview".to_string()));
}
#[test]
fn test_registry_unknown_parent() {
let reg = InheritanceRegistry::new();
let sub = make_override();
let result = reg.resolve(999, &sub, InheritPolicy::All);
assert_eq!(result.keywords, vec!["closeup".to_string()]);
}
#[test]
fn test_registry_get_parent() {
let mut reg = InheritanceRegistry::new();
reg.register_parent(1, make_parent());
let p = reg.get_parent(1);
assert!(p.is_some());
let p2 = reg.get_parent(99);
assert!(p2.is_none());
}
#[test]
fn test_default_trait() {
let m: InheritableMetadata = Default::default();
assert!(m.keywords.is_empty());
let r: InheritanceRegistry = Default::default();
assert!(r.is_empty());
}
}