use strum::VariantArray;
use super::ValueTypeName;
#[derive(Debug, Clone, Copy, VariantArray)]
pub enum FieldKey {
Active,
AllowedTokens,
ApiSchemas,
AssetInfo,
Clips,
ClipSets,
ColorConfiguration,
ColorManagementSystem,
ColorSpace,
Comment,
ConnectionPaths,
Custom,
CustomData,
CustomLayerData,
Default,
DefaultPrim,
DisplayGroup,
DisplayGroupOrder,
DisplayName,
DisplayUnit,
Documentation,
EndTimeCode,
ExpressionVariables,
FallbackPrimTypes,
FramePrecision,
FramesPerSecond,
Hidden,
HasOwnedSubLayers,
InheritPaths,
Instanceable,
Kind,
LayerRelocates,
PrimOrder,
NoLoadHint,
Owner,
Payload,
Permission,
Prefix,
PrefixSubstitutions,
PropertyOrder,
References,
Relocates,
SessionOwner,
Specializes,
Specifier,
StartTimeCode,
SubLayers,
SubLayerOffsets,
Suffix,
SuffixSubstitutions,
SymmetricPeer,
SymmetryArgs,
SymmetryArguments,
SymmetryFunction,
TargetPaths,
TimeSamples,
TimeCodesPerSecond,
TypeName,
VariantSelection,
Variability,
VariantSetNames,
EndFrame,
StartFrame,
}
impl From<FieldKey> for &'static str {
fn from(key: FieldKey) -> Self {
key.as_str()
}
}
impl AsRef<str> for FieldKey {
fn as_ref(&self) -> &str {
self.as_str()
}
}
impl FieldKey {
pub fn from_name(name: &str) -> Option<Self> {
FieldKey::VARIANTS.iter().copied().find(|key| key.as_str() == name)
}
pub const fn as_str(&self) -> &'static str {
match self {
FieldKey::Active => "active",
FieldKey::AllowedTokens => "allowedTokens",
FieldKey::ApiSchemas => "apiSchemas",
FieldKey::AssetInfo => "assetInfo",
FieldKey::Clips => "clips",
FieldKey::ClipSets => "clipSets",
FieldKey::ColorConfiguration => "colorConfiguration",
FieldKey::ColorManagementSystem => "colorManagementSystem",
FieldKey::ColorSpace => "colorSpace",
FieldKey::Comment => "comment",
FieldKey::ConnectionPaths => "connectionPaths",
FieldKey::Custom => "custom",
FieldKey::CustomData => "customData",
FieldKey::CustomLayerData => "customLayerData",
FieldKey::Default => "default",
FieldKey::DefaultPrim => "defaultPrim",
FieldKey::DisplayGroup => "displayGroup",
FieldKey::DisplayGroupOrder => "displayGroupOrder",
FieldKey::DisplayName => "displayName",
FieldKey::DisplayUnit => "displayUnit",
FieldKey::Documentation => "documentation",
FieldKey::EndTimeCode => "endTimeCode",
FieldKey::ExpressionVariables => "expressionVariables",
FieldKey::FallbackPrimTypes => "fallbackPrimTypes",
FieldKey::FramePrecision => "framePrecision",
FieldKey::FramesPerSecond => "framesPerSecond",
FieldKey::Hidden => "hidden",
FieldKey::HasOwnedSubLayers => "hasOwnedSubLayers",
FieldKey::InheritPaths => "inheritPaths",
FieldKey::Instanceable => "instanceable",
FieldKey::Kind => "kind",
FieldKey::LayerRelocates => "layerRelocates",
FieldKey::PrimOrder => "primOrder",
FieldKey::NoLoadHint => "noLoadHint",
FieldKey::Owner => "owner",
FieldKey::Payload => "payload",
FieldKey::Permission => "permission",
FieldKey::Prefix => "prefix",
FieldKey::PrefixSubstitutions => "prefixSubstitutions",
FieldKey::PropertyOrder => "propertyOrder",
FieldKey::References => "references",
FieldKey::Relocates => "relocates",
FieldKey::SessionOwner => "sessionOwner",
FieldKey::Specializes => "specializes",
FieldKey::Specifier => "specifier",
FieldKey::StartTimeCode => "startTimeCode",
FieldKey::SubLayers => "subLayers",
FieldKey::SubLayerOffsets => "subLayerOffsets",
FieldKey::Suffix => "suffix",
FieldKey::SuffixSubstitutions => "suffixSubstitutions",
FieldKey::SymmetricPeer => "symmetricPeer",
FieldKey::SymmetryArgs => "symmetryArgs",
FieldKey::SymmetryArguments => "symmetryArguments",
FieldKey::SymmetryFunction => "symmetryFunction",
FieldKey::TargetPaths => "targetPaths",
FieldKey::TimeSamples => "timeSamples",
FieldKey::TimeCodesPerSecond => "timeCodesPerSecond",
FieldKey::TypeName => "typeName",
FieldKey::VariantSelection => "variantSelection",
FieldKey::Variability => "variability",
FieldKey::VariantSetNames => "variantSetNames",
FieldKey::EndFrame => "endFrame",
FieldKey::StartFrame => "startFrame",
}
}
}
#[derive(Clone, Copy)]
pub enum ChildrenKey {
ConnectionChildren,
ExpressionChildren,
MapperArgChildren,
MapperChildren,
PrimChildren,
PropertyChildren,
RelationshipTargetChildren,
VariantChildren,
VariantSetChildren,
}
impl From<ChildrenKey> for &'static str {
fn from(key: ChildrenKey) -> Self {
key.as_str()
}
}
impl AsRef<str> for ChildrenKey {
fn as_ref(&self) -> &str {
self.as_str()
}
}
impl ChildrenKey {
pub const fn as_str(&self) -> &'static str {
match self {
ChildrenKey::ConnectionChildren => "connectionChildren",
ChildrenKey::ExpressionChildren => "expressionChildren",
ChildrenKey::MapperArgChildren => "mapperArgChildren",
ChildrenKey::MapperChildren => "mapperChildren",
ChildrenKey::PrimChildren => "primChildren",
ChildrenKey::PropertyChildren => "propertyChildren",
ChildrenKey::RelationshipTargetChildren => "targetChildren",
ChildrenKey::VariantChildren => "variantChildren",
ChildrenKey::VariantSetChildren => "variantSetChildren",
}
}
}
const SCHEMA_METADATA: [(&str, &str); 22] = [
("bindMaterialAs", "token"),
("connectability", "token"),
("constraintTargetIdentifier", "token"),
("elementSize", "int"),
("faceIndexPrimvar", "token"),
("faceOffsetPrimvar", "token"),
("inactiveIds", "int64listop"),
("interpolation", "token"),
("irIsInvertible", "bool"),
("irRole", "token"),
("kilogramsPerUnit", "double"),
("metersPerUnit", "double"),
("outputName", "token"),
("payloadAssetDependencies", "asset[]"),
("renderSettingsPrimPath", "string"),
("renderType", "token"),
("sdrMetadata", "dictionary"),
("uiHints", "dictionary"),
("unauthoredValuesIndex", "int"),
("upAxis", "token"),
("uvPrimvar", "token"),
("weight", "float"),
];
pub fn is_registered_field(name: &str) -> bool {
FieldKey::from_name(name).is_some() || schema_field_spelling(name).is_some()
}
pub fn schema_field_type(name: &str) -> Option<ValueTypeName> {
schema_field_spelling(name).map(ValueTypeName::from)
}
fn schema_field_spelling(name: &str) -> Option<&'static str> {
SCHEMA_METADATA
.iter()
.find(|(field, _)| *field == name)
.map(|(_, ty)| *ty)
}
pub fn is_vector_field(field: &str) -> bool {
const VECTORS: [&str; 9] = [
ChildrenKey::ExpressionChildren.as_str(),
ChildrenKey::MapperArgChildren.as_str(),
ChildrenKey::PrimChildren.as_str(),
ChildrenKey::PropertyChildren.as_str(),
ChildrenKey::VariantChildren.as_str(),
ChildrenKey::VariantSetChildren.as_str(),
FieldKey::PrimOrder.as_str(),
FieldKey::PropertyOrder.as_str(),
FieldKey::SubLayers.as_str(),
];
VECTORS.contains(&field)
}
pub fn folds_list_ops(field: &str) -> bool {
const DEDICATED: [FieldKey; 10] = [
FieldKey::References,
FieldKey::Payload,
FieldKey::InheritPaths,
FieldKey::Specializes,
FieldKey::VariantSetNames,
FieldKey::ConnectionPaths,
FieldKey::TargetPaths,
FieldKey::ClipSets,
FieldKey::Default,
FieldKey::TimeSamples,
];
!DEDICATED.iter().any(|key| key.as_str() == field)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn field_key_from_name() {
for key in FieldKey::VARIANTS {
assert_eq!(
FieldKey::from_name(key.as_str()).map(|k| k.as_str()),
Some(key.as_str())
);
}
assert!(FieldKey::from_name("madeUpField").is_none());
}
#[test]
fn vector_fields() {
assert!(is_vector_field(ChildrenKey::PrimChildren.as_str()));
assert!(is_vector_field(FieldKey::SubLayers.as_str()));
assert!(!is_vector_field(ChildrenKey::ConnectionChildren.as_str()));
assert!(!is_vector_field(FieldKey::AllowedTokens.as_str()));
}
#[test]
fn registered_fields() {
assert!(is_registered_field(FieldKey::DisplayUnit.as_str()));
assert!(is_registered_field("interpolation"));
assert!(!is_registered_field("hide_in_stage_window"));
}
#[test]
fn schema_field_types() {
assert_eq!(schema_field_type("interpolation"), Some(ValueTypeName::TOKEN));
assert_eq!(schema_field_type("elementSize"), Some(ValueTypeName::INT));
assert!(schema_field_type("sdrMetadata").is_some_and(|ty| ty.kind().is_none()));
assert_eq!(schema_field_type("hide_in_stage_window"), None);
assert_eq!(schema_field_type("uvPrimvar"), Some(ValueTypeName::TOKEN));
}
#[test]
fn child_key_str() {
assert_eq!(ChildrenKey::ConnectionChildren.as_str(), "connectionChildren");
assert_eq!(ChildrenKey::PrimChildren.as_str(), "primChildren");
assert_eq!(ChildrenKey::VariantSetChildren.as_str(), "variantSetChildren");
}
}