From 83a8852cef3c8a8d01763fa7b186298e56283d4c Mon Sep 17 00:00:00 2001 From: Brandon Thomas Date: Sun, 22 Mar 2026 12:46:29 -0400 Subject: [PATCH] enums split - but just the enums (#1188) --- Cargo.lock | 57 ++ Cargo.toml | 8 + crates/schema/public/enums_api/Cargo.toml | 34 ++ ...ontend_failure_category_for_api_clients.rs | 109 ++++ ...ontend_failure_category_for_old_clients.rs | 65 +++ .../by_table/generic_inference_jobs/mod.rs | 2 + .../enums_api/src/api_safe/by_table/mod.rs | 1 + .../public/enums_api/src/api_safe/mod.rs | 1 + .../audit_logs/audit_log_entity_action.rs | 80 +++ .../audit_logs/audit_log_entity_type.rs | 68 +++ .../enums_api/src/by_table/audit_logs/mod.rs | 2 + .../batch_generation_entity_type.rs | 51 ++ .../src/by_table/batch_generations/mod.rs | 1 + .../by_table/beta_keys/beta_key_product.rs | 51 ++ .../enums_api/src/by_table/beta_keys/mod.rs | 1 + .../by_table/comments/comment_entity_type.rs | 86 +++ .../enums_api/src/by_table/comments/mod.rs | 1 + .../email_sender_jobs/email_category.rs | 60 +++ .../src/by_table/email_sender_jobs/mod.rs | 1 + .../src/by_table/entity_stats/mod.rs | 1 + .../entity_stats/stats_entity_type.rs | 62 +++ .../featured_item_entity_type.rs | 62 +++ .../src/by_table/featured_items/mod.rs | 1 + .../generic_download_type.rs | 107 ++++ .../src/by_table/generic_download_jobs/mod.rs | 1 + .../inference_category.rs | 159 ++++++ .../inference_input_source_token_type.rs | 55 ++ .../inference_job_external_third_party.rs | 66 +++ .../inference_job_product_category.rs | 215 ++++++++ .../inference_job_type.rs | 162 ++++++ .../inference_model_type.rs | 122 +++++ .../inference_result_type.rs | 78 +++ .../by_table/generic_inference_jobs/mod.rs | 7 + .../generic_synthetic_ids/id_category.rs | 139 +++++ .../src/by_table/generic_synthetic_ids/mod.rs | 1 + .../media_files/media_file_animation_type.rs | 125 +++++ .../by_table/media_files/media_file_class.rs | 73 +++ .../media_files/media_file_engine_category.rs | 109 ++++ .../media_files/media_file_origin_category.rs | 80 +++ .../media_file_origin_model_type.rs | 154 ++++++ .../media_file_origin_product_category.rs | 148 ++++++ .../media_files/media_file_subtype.rs | 114 ++++ .../by_table/media_files/media_file_type.rs | 248 +++++++++ .../enums_api/src/by_table/media_files/mod.rs | 8 + .../media_uploads/media_upload_source.rs | 64 +++ .../media_uploads/media_upload_type.rs | 67 +++ .../src/by_table/media_uploads/mod.rs | 2 + .../public/enums_api/src/by_table/mod.rs | 30 ++ .../src/by_table/model_categories/mod.rs | 1 + .../by_table/model_categories/model_type.rs | 55 ++ .../src/by_table/model_weights/mod.rs | 3 + .../model_weights/weights_category.rs | 64 +++ .../model_weights/weights_file_type.rs | 53 ++ .../by_table/model_weights/weights_types.rs | 93 ++++ .../src/by_table/prompt_context_items/mod.rs | 1 + .../prompt_context_semantic_type.rs | 102 ++++ .../enums_api/src/by_table/prompts/mod.rs | 1 + .../src/by_table/prompts/prompt_type.rs | 64 +++ .../enums_api/src/by_table/tag_uses/mod.rs | 1 + .../by_table/tag_uses/tag_use_entity_type.rs | 56 ++ .../by_table/trending_model_analytics/mod.rs | 2 + .../trending_model_analytics/model_type.rs | 55 ++ .../trending_model_analytics/window_name.rs | 66 +++ .../enums_api/src/by_table/tts_models/mod.rs | 1 + .../src/by_table/tts_models/tts_model_type.rs | 57 ++ .../src/by_table/tts_render_tasks/mod.rs | 1 + .../tts_render_tasks/tts_render_status.rs | 75 +++ .../enums_api/src/by_table/usages/mod.rs | 1 + .../src/by_table/usages/usages_type.rs | 57 ++ .../src/by_table/user_bookmarks/mod.rs | 1 + .../user_bookmark_entity_type.rs | 98 ++++ .../src/by_table/user_ratings/entity_type.rs | 80 +++ .../src/by_table/user_ratings/mod.rs | 2 + .../src/by_table/user_ratings/rating_value.rs | 72 +++ .../enums_api/src/by_table/users/mod.rs | 3 + .../src/by_table/users/user_feature_flag.rs | 69 +++ .../src/by_table/users/user_signup_method.rs | 64 +++ .../src/by_table/users/user_signup_source.rs | 93 ++++ .../by_table/voice_conversion_models/mod.rs | 1 + .../voice_conversion_model_type.rs | 63 +++ .../by_table/voice_conversion_results/mod.rs | 1 + .../voice_conversion_media_token_type.rs | 52 ++ .../src/by_table/wallet_ledger_entries/mod.rs | 1 + .../wallet_ledger_entry_type.rs | 103 ++++ .../src/by_table/web_rendition_targets/mod.rs | 1 + .../web_rendition_targets/rendition_status.rs | 69 +++ .../src/by_table/web_scraping_targets/mod.rs | 1 + .../web_scraping_targets/scraping_status.rs | 69 +++ .../src/by_table/zs_voices/encoding_type.rs | 54 ++ .../enums_api/src/by_table/zs_voices/mod.rs | 3 + .../src/by_table/zs_voices/model_category.rs | 54 ++ .../src/by_table/zs_voices/model_type.rs | 58 ++ .../src/common/artcraft_credits_pack_slug.rs | 71 +++ .../src/common/artcraft_subscription_slug.rs | 56 ++ .../common/generation/common_aspect_ratio.rs | 97 ++++ .../common/generation/common_image_model.rs | 90 ++++ .../common/generation/common_splat_model.rs | 55 ++ .../common/generation/common_video_model.rs | 135 +++++ .../generation/common_video_resolution.rs | 58 ++ .../common/generation/generation_provider.rs | 81 +++ .../enums_api/src/common/generation/mod.rs | 6 + .../public/enums_api/src/common/job_status.rs | 76 +++ .../enums_api/src/common/job_status_plus.rs | 78 +++ .../schema/public/enums_api/src/common/mod.rs | 12 + .../public/enums_api/src/common/model_type.rs | 280 ++++++++++ .../src/common/payments_namespace.rs | 55 ++ .../src/common/sqlite/awaitable_job_status.rs | 82 +++ .../src/common/sqlite/chatbot_job_status.rs | 71 +++ .../public/enums_api/src/common/sqlite/mod.rs | 4 + .../src/common/sqlite/skip_reason.rs | 77 +++ .../src/common/sqlite/web_content_type.rs | 98 ++++ .../src/common/stripe_subscription_status.rs | 69 +++ .../public/enums_api/src/common/view_as.rs | 60 +++ .../public/enums_api/src/common/visibility.rs | 76 +++ .../enums_api/src/common/vocoder_type.rs | 64 +++ crates/schema/public/enums_api/src/lib.rs | 26 + .../public/enums_api/src/no_table/mod.rs | 3 + .../src/no_table/premium_product/mod.rs | 1 + .../premium_product/premium_product_name.rs | 69 +++ .../src/no_table/style_transfer/mod.rs | 1 + .../style_transfer/style_transfer_name.rs | 191 +++++++ .../src/no_table/video_dimensions/mod.rs | 1 + .../video_dimensions/video_dimensions.rs | 56 ++ .../schema/public/enums_api/src/tauri/mod.rs | 2 + .../public/enums_api/src/tauri/tasks/mod.rs | 5 + .../src/tauri/tasks/task_failure_type.rs | 77 +++ .../src/tauri/tasks/task_media_file_class.rs | 65 +++ .../src/tauri/tasks/task_model_type.rs | 234 ++++++++ .../enums_api/src/tauri/tasks/task_status.rs | 73 +++ .../enums_api/src/tauri/tasks/task_type.rs | 64 +++ .../public/enums_api/src/tauri/ux/mod.rs | 2 + .../src/tauri/ux/tauri_command_caller.rs | 68 +++ .../src/tauri/ux/tauri_event_name.rs | 178 +++++++ crates/schema/public/enums_convert/Cargo.toml | 28 + ...ontend_failure_category_for_api_clients.rs | 35 ++ ...ontend_failure_category_for_old_clients.rs | 37 ++ .../by_table/generic_inference_jobs/mod.rs | 2 + .../src/api_safe/by_table/mod.rs | 1 + .../public/enums_convert/src/api_safe/mod.rs | 1 + .../audit_logs/audit_log_entity_action.rs | 50 ++ .../audit_logs/audit_log_entity_type.rs | 46 ++ .../src/by_table/audit_logs/mod.rs | 2 + .../batch_generation_entity_type.rs | 39 ++ .../src/by_table/batch_generations/mod.rs | 1 + .../by_table/beta_keys/beta_key_product.rs | 39 ++ .../src/by_table/beta_keys/mod.rs | 1 + .../by_table/comments/comment_entity_type.rs | 52 ++ .../src/by_table/comments/mod.rs | 1 + .../email_sender_jobs/email_category.rs | 41 ++ .../src/by_table/email_sender_jobs/mod.rs | 1 + .../src/by_table/entity_stats/mod.rs | 1 + .../entity_stats/stats_entity_type.rs | 43 ++ .../featured_item_entity_type.rs | 43 ++ .../src/by_table/featured_items/mod.rs | 1 + .../generic_download_type.rs | 53 ++ .../src/by_table/generic_download_jobs/mod.rs | 1 + .../inference_category.rs | 71 +++ .../inference_input_source_token_type.rs | 41 ++ .../inference_job_external_third_party.rs | 43 ++ .../inference_job_product_category.rs | 95 ++++ .../inference_job_type.rs | 93 ++++ .../inference_model_type.rs | 67 +++ .../inference_result_type.rs | 47 ++ .../by_table/generic_inference_jobs/mod.rs | 7 + .../generic_synthetic_ids/id_category.rs | 67 +++ .../src/by_table/generic_synthetic_ids/mod.rs | 1 + .../media_files/media_file_animation_type.rs | 63 +++ .../by_table/media_files/media_file_class.rs | 47 ++ .../media_files/media_file_engine_category.rs | 59 ++ .../media_files/media_file_origin_category.rs | 49 ++ .../media_file_origin_model_type.rs | 87 +++ .../media_file_origin_product_category.rs | 69 +++ .../media_files/media_file_subtype.rs | 59 ++ .../by_table/media_files/media_file_type.rs | 77 +++ .../src/by_table/media_files/mod.rs | 8 + .../media_uploads/media_upload_source.rs | 44 ++ .../media_uploads/media_upload_type.rs | 46 ++ .../src/by_table/media_uploads/mod.rs | 2 + .../public/enums_convert/src/by_table/mod.rs | 30 ++ .../src/by_table/model_categories/mod.rs | 1 + .../by_table/model_categories/model_type.rs | 42 ++ .../src/by_table/model_weights/mod.rs | 3 + .../model_weights/weights_category.rs | 47 ++ .../model_weights/weights_file_type.rs | 41 ++ .../by_table/model_weights/weights_types.rs | 65 +++ .../src/by_table/prompt_context_items/mod.rs | 1 + .../prompt_context_semantic_type.rs | 57 ++ .../enums_convert/src/by_table/prompts/mod.rs | 1 + .../src/by_table/prompts/prompt_type.rs | 43 ++ .../src/by_table/tag_uses/mod.rs | 1 + .../by_table/tag_uses/tag_use_entity_type.rs | 41 ++ .../by_table/trending_model_analytics/mod.rs | 2 + .../trending_model_analytics/model_type.rs | 40 ++ .../trending_model_analytics/window_name.rs | 44 ++ .../src/by_table/tts_models/mod.rs | 1 + .../src/by_table/tts_models/tts_model_type.rs | 42 ++ .../src/by_table/tts_render_tasks/mod.rs | 1 + .../tts_render_tasks/tts_render_status.rs | 50 ++ .../enums_convert/src/by_table/usages/mod.rs | 1 + .../src/by_table/usages/usages_type.rs | 41 ++ .../src/by_table/user_bookmarks/mod.rs | 1 + .../user_bookmark_entity_type.rs | 56 ++ .../src/by_table/user_ratings/entity_type.rs | 50 ++ .../src/by_table/user_ratings/mod.rs | 2 + .../src/by_table/user_ratings/rating_value.rs | 44 ++ .../enums_convert/src/by_table/users/mod.rs | 3 + .../src/by_table/users/user_feature_flag.rs | 45 ++ .../src/by_table/users/user_signup_method.rs | 43 ++ .../src/by_table/users/user_signup_source.rs | 53 ++ .../by_table/voice_conversion_models/mod.rs | 1 + .../voice_conversion_model_type.rs | 43 ++ .../by_table/voice_conversion_results/mod.rs | 1 + .../voice_conversion_media_token_type.rs | 40 ++ .../src/by_table/wallet_ledger_entries/mod.rs | 1 + .../wallet_ledger_entry_type.rs | 53 ++ .../src/by_table/web_rendition_targets/mod.rs | 1 + .../web_rendition_targets/rendition_status.rs | 48 ++ .../src/by_table/web_scraping_targets/mod.rs | 1 + .../web_scraping_targets/scraping_status.rs | 48 ++ .../src/by_table/zs_voices/encoding_type.rs | 39 ++ .../src/by_table/zs_voices/mod.rs | 3 + .../src/by_table/zs_voices/model_category.rs | 39 ++ .../src/by_table/zs_voices/model_type.rs | 41 ++ .../src/common/artcraft_credits_pack_slug.rs | 50 ++ .../src/common/artcraft_subscription_slug.rs | 44 ++ .../common/generation/generation_provider.rs | 50 ++ .../src/common/generation/mod.rs | 1 + .../enums_convert/src/common/job_status.rs | 50 ++ .../src/common/job_status_plus.rs | 54 ++ .../public/enums_convert/src/common/mod.rs | 12 + .../enums_convert/src/common/model_type.rs | 146 +++++ .../src/common/payments_namespace.rs | 42 ++ .../src/common/sqlite/awaitable_job_status.rs | 42 ++ .../src/common/sqlite/chatbot_job_status.rs | 38 ++ .../enums_convert/src/common/sqlite/mod.rs | 4 + .../src/common/sqlite/skip_reason.rs | 40 ++ .../src/common/sqlite/web_content_type.rs | 48 ++ .../src/common/stripe_subscription_status.rs | 44 ++ .../enums_convert/src/common/view_as.rs | 44 ++ .../enums_convert/src/common/visibility.rs | 44 ++ .../enums_convert/src/common/vocoder_type.rs | 34 ++ crates/schema/public/enums_convert/src/lib.rs | 5 + .../public/enums_convert/src/no_table/mod.rs | 2 + .../src/no_table/premium_product/mod.rs | 1 + .../premium_product/premium_product_name.rs | 36 ++ .../src/no_table/style_transfer/mod.rs | 1 + .../style_transfer/style_transfer_name.rs | 107 ++++ .../public/enums_convert/src/tauri/mod.rs | 2 + .../enums_convert/src/tauri/tasks/mod.rs | 5 + .../src/tauri/tasks/task_failure_type.rs | 56 ++ .../src/tauri/tasks/task_media_file_class.rs | 46 ++ .../src/tauri/tasks/task_model_type.rs | 128 +++++ .../src/tauri/tasks/task_status.rs | 56 ++ .../src/tauri/tasks/task_type.rs | 50 ++ .../public/enums_convert/src/tauri/ux/mod.rs | 2 + .../src/tauri/ux/tauri_command_caller.rs | 48 ++ .../src/tauri/ux/tauri_event_name.rs | 74 +++ crates/schema/public/enums_db/Cargo.toml | 50 ++ .../audit_logs/audit_log_entity_action.rs | 131 +++++ .../audit_logs/audit_log_entity_type.rs | 113 ++++ .../enums_db/src/by_table/audit_logs/mod.rs | 2 + .../batch_generation_entity_type.rs | 88 +++ .../src/by_table/batch_generations/mod.rs | 1 + .../by_table/beta_keys/beta_key_product.rs | 88 +++ .../enums_db/src/by_table/beta_keys/mod.rs | 1 + .../by_table/comments/comment_entity_type.rs | 140 +++++ .../enums_db/src/by_table/comments/mod.rs | 1 + .../email_sender_jobs/email_category.rs | 96 ++++ .../src/by_table/email_sender_jobs/mod.rs | 1 + .../enums_db/src/by_table/entity_stats/mod.rs | 1 + .../entity_stats/stats_entity_type.rs | 102 ++++ .../featured_item_entity_type.rs | 105 ++++ .../src/by_table/featured_items/mod.rs | 1 + .../generic_download_type.rs | 158 ++++++ .../src/by_table/generic_download_jobs/mod.rs | 1 + .../frontend_failure_category.rs | 228 ++++++++ .../inference_category.rs | 240 +++++++++ .../inference_input_source_token_type.rs | 86 +++ .../inference_job_external_third_party.rs | 105 ++++ .../inference_job_product_category.rs | 330 ++++++++++++ .../inference_job_type.rs | 233 ++++++++ .../inference_model_type.rs | 197 +++++++ .../inference_result_type.rs | 118 ++++ .../by_table/generic_inference_jobs/mod.rs | 8 + .../generic_synthetic_ids/id_category.rs | 214 ++++++++ .../src/by_table/generic_synthetic_ids/mod.rs | 1 + .../media_files/media_file_animation_type.rs | 195 +++++++ .../by_table/media_files/media_file_class.rs | 122 +++++ .../media_files/media_file_engine_category.rs | 173 ++++++ .../media_files/media_file_origin_category.rs | 129 +++++ .../media_file_origin_model_type.rs | 210 ++++++++ .../media_file_origin_product_category.rs | 226 ++++++++ .../media_files/media_file_subtype.rs | 178 +++++++ .../by_table/media_files/media_file_type.rs | 352 ++++++++++++ .../enums_db/src/by_table/media_files/mod.rs | 8 + .../media_uploads/media_upload_source.rs | 98 ++++ .../media_uploads/media_upload_type.rs | 104 ++++ .../src/by_table/media_uploads/mod.rs | 2 + .../public/enums_db/src/by_table/mod.rs | 30 ++ .../src/by_table/model_categories/mod.rs | 1 + .../by_table/model_categories/model_type.rs | 86 +++ .../src/by_table/model_weights/mod.rs | 3 + .../model_weights/weights_category.rs | 92 ++++ .../model_weights/weights_file_type.rs | 76 +++ .../by_table/model_weights/weights_types.rs | 131 +++++ .../src/by_table/prompt_context_items/mod.rs | 1 + .../prompt_context_semantic_type.rs | 167 ++++++ .../enums_db/src/by_table/prompts/mod.rs | 1 + .../src/by_table/prompts/prompt_type.rs | 107 ++++ .../enums_db/src/by_table/tag_uses/mod.rs | 1 + .../by_table/tag_uses/tag_use_entity_type.rs | 96 ++++ .../by_table/trending_model_analytics/mod.rs | 2 + .../trending_model_analytics/model_type.rs | 83 +++ .../trending_model_analytics/window_name.rs | 108 ++++ .../enums_db/src/by_table/tts_models/mod.rs | 1 + .../src/by_table/tts_models/tts_model_type.rs | 88 +++ .../src/by_table/tts_render_tasks/mod.rs | 1 + .../tts_render_tasks/tts_render_status.rs | 125 +++++ .../enums_db/src/by_table/usages/mod.rs | 1 + .../src/by_table/usages/usages_type.rs | 97 ++++ .../src/by_table/user_bookmarks/mod.rs | 1 + .../user_bookmark_entity_type.rs | 158 ++++++ .../src/by_table/user_ratings/entity_type.rs | 131 +++++ .../enums_db/src/by_table/user_ratings/mod.rs | 2 + .../src/by_table/user_ratings/rating_value.rs | 182 +++++++ .../public/enums_db/src/by_table/users/mod.rs | 3 + .../src/by_table/users/user_feature_flag.rs | 112 ++++ .../src/by_table/users/user_signup_method.rs | 107 ++++ .../src/by_table/users/user_signup_source.rs | 150 ++++++ .../by_table/voice_conversion_models/mod.rs | 1 + .../voice_conversion_model_type.rs | 97 ++++ .../by_table/voice_conversion_results/mod.rs | 1 + .../voice_conversion_media_token_type.rs | 80 +++ .../src/by_table/wallet_ledger_entries/mod.rs | 1 + .../wallet_ledger_entry_type.rs | 161 ++++++ .../src/by_table/web_rendition_targets/mod.rs | 1 + .../web_rendition_targets/rendition_status.rs | 116 ++++ .../src/by_table/web_scraping_targets/mod.rs | 1 + .../web_scraping_targets/scraping_status.rs | 116 ++++ .../src/by_table/zs_voices/encoding_type.rs | 91 ++++ .../enums_db/src/by_table/zs_voices/mod.rs | 3 + .../src/by_table/zs_voices/model_category.rs | 91 ++++ .../src/by_table/zs_voices/model_type.rs | 97 ++++ .../src/common/artcraft_credits_pack_slug.rs | 121 +++++ .../src/common/artcraft_subscription_slug.rs | 96 ++++ .../common/generation/generation_provider.rs | 135 +++++ .../enums_db/src/common/generation/mod.rs | 1 + .../public/enums_db/src/common/job_status.rs | 125 +++++ .../enums_db/src/common/job_status_plus.rs | 145 +++++ .../schema/public/enums_db/src/common/mod.rs | 12 + .../public/enums_db/src/common/model_type.rs | 503 ++++++++++++++++++ .../enums_db/src/common/payments_namespace.rs | 92 ++++ .../src/common/sqlite/awaitable_job_status.rs | 135 +++++ .../src/common/sqlite/chatbot_job_status.rs | 118 ++++ .../public/enums_db/src/common/sqlite/mod.rs | 4 + .../enums_db/src/common/sqlite/skip_reason.rs | 127 +++++ .../src/common/sqlite/web_content_type.rs | 160 ++++++ .../src/common/stripe_subscription_status.rs | 182 +++++++ .../public/enums_db/src/common/view_as.rs | 173 ++++++ .../public/enums_db/src/common/visibility.rs | 213 ++++++++ .../enums_db/src/common/vocoder_type.rs | 94 ++++ crates/schema/public/enums_db/src/lib.rs | 27 + ...mpl_enum_display_and_debug_using_to_str.rs | 43 ++ .../src/macros/impl_mysql_enum_coders.rs | 42 ++ .../src/macros/impl_mysql_from_row.rs | 47 ++ .../src/macros/impl_sqlite_enum_coders.rs | 6 + .../schema/public/enums_db/src/macros/mod.rs | 4 + .../public/enums_db/src/no_table/mod.rs | 2 + .../src/no_table/premium_product/mod.rs | 1 + .../premium_product/premium_product_name.rs | 76 +++ .../src/no_table/style_transfer/mod.rs | 1 + .../style_transfer/style_transfer_name.rs | 237 +++++++++ .../schema/public/enums_db/src/tauri/mod.rs | 2 + .../public/enums_db/src/tauri/tasks/mod.rs | 5 + .../src/tauri/tasks/task_failure_type.rs | 206 +++++++ .../src/tauri/tasks/task_media_file_class.rs | 120 +++++ .../src/tauri/tasks/task_model_type.rs | 427 +++++++++++++++ .../enums_db/src/tauri/tasks/task_status.rs | 154 ++++++ .../enums_db/src/tauri/tasks/task_type.rs | 125 +++++ .../public/enums_db/src/tauri/ux/mod.rs | 2 + .../src/tauri/ux/tauri_command_caller.rs | 115 ++++ .../enums_db/src/tauri/ux/tauri_event_name.rs | 251 +++++++++ .../schema/public/enums_db/src/traits/mod.rs | 1 + .../enums_db/src/traits/mysql_from_row.rs | 11 + crates/schema/public/enums_shared/Cargo.toml | 34 ++ .../enums_shared/src/error/enums_error.rs | 18 + .../public/enums_shared/src/error/mod.rs | 1 + crates/schema/public/enums_shared/src/lib.rs | 21 + .../public/enums_shared/src/macros/mod.rs | 1 + .../public/enums_shared/src/test_helpers.rs | 24 + 390 files changed, 24223 insertions(+) create mode 100644 crates/schema/public/enums_api/Cargo.toml create mode 100644 crates/schema/public/enums_api/src/api_safe/by_table/generic_inference_jobs/frontend_failure_category_for_api_clients.rs create mode 100644 crates/schema/public/enums_api/src/api_safe/by_table/generic_inference_jobs/frontend_failure_category_for_old_clients.rs create mode 100644 crates/schema/public/enums_api/src/api_safe/by_table/generic_inference_jobs/mod.rs create mode 100644 crates/schema/public/enums_api/src/api_safe/by_table/mod.rs create mode 100644 crates/schema/public/enums_api/src/api_safe/mod.rs create mode 100644 crates/schema/public/enums_api/src/by_table/audit_logs/audit_log_entity_action.rs create mode 100644 crates/schema/public/enums_api/src/by_table/audit_logs/audit_log_entity_type.rs create mode 100644 crates/schema/public/enums_api/src/by_table/audit_logs/mod.rs create mode 100644 crates/schema/public/enums_api/src/by_table/batch_generations/batch_generation_entity_type.rs create mode 100644 crates/schema/public/enums_api/src/by_table/batch_generations/mod.rs create mode 100644 crates/schema/public/enums_api/src/by_table/beta_keys/beta_key_product.rs create mode 100644 crates/schema/public/enums_api/src/by_table/beta_keys/mod.rs create mode 100644 crates/schema/public/enums_api/src/by_table/comments/comment_entity_type.rs create mode 100644 crates/schema/public/enums_api/src/by_table/comments/mod.rs create mode 100644 crates/schema/public/enums_api/src/by_table/email_sender_jobs/email_category.rs create mode 100644 crates/schema/public/enums_api/src/by_table/email_sender_jobs/mod.rs create mode 100644 crates/schema/public/enums_api/src/by_table/entity_stats/mod.rs create mode 100644 crates/schema/public/enums_api/src/by_table/entity_stats/stats_entity_type.rs create mode 100644 crates/schema/public/enums_api/src/by_table/featured_items/featured_item_entity_type.rs create mode 100644 crates/schema/public/enums_api/src/by_table/featured_items/mod.rs create mode 100644 crates/schema/public/enums_api/src/by_table/generic_download_jobs/generic_download_type.rs create mode 100644 crates/schema/public/enums_api/src/by_table/generic_download_jobs/mod.rs create mode 100644 crates/schema/public/enums_api/src/by_table/generic_inference_jobs/inference_category.rs create mode 100644 crates/schema/public/enums_api/src/by_table/generic_inference_jobs/inference_input_source_token_type.rs create mode 100644 crates/schema/public/enums_api/src/by_table/generic_inference_jobs/inference_job_external_third_party.rs create mode 100644 crates/schema/public/enums_api/src/by_table/generic_inference_jobs/inference_job_product_category.rs create mode 100644 crates/schema/public/enums_api/src/by_table/generic_inference_jobs/inference_job_type.rs create mode 100644 crates/schema/public/enums_api/src/by_table/generic_inference_jobs/inference_model_type.rs create mode 100644 crates/schema/public/enums_api/src/by_table/generic_inference_jobs/inference_result_type.rs create mode 100644 crates/schema/public/enums_api/src/by_table/generic_inference_jobs/mod.rs create mode 100644 crates/schema/public/enums_api/src/by_table/generic_synthetic_ids/id_category.rs create mode 100644 crates/schema/public/enums_api/src/by_table/generic_synthetic_ids/mod.rs create mode 100644 crates/schema/public/enums_api/src/by_table/media_files/media_file_animation_type.rs create mode 100644 crates/schema/public/enums_api/src/by_table/media_files/media_file_class.rs create mode 100644 crates/schema/public/enums_api/src/by_table/media_files/media_file_engine_category.rs create mode 100644 crates/schema/public/enums_api/src/by_table/media_files/media_file_origin_category.rs create mode 100644 crates/schema/public/enums_api/src/by_table/media_files/media_file_origin_model_type.rs create mode 100644 crates/schema/public/enums_api/src/by_table/media_files/media_file_origin_product_category.rs create mode 100644 crates/schema/public/enums_api/src/by_table/media_files/media_file_subtype.rs create mode 100644 crates/schema/public/enums_api/src/by_table/media_files/media_file_type.rs create mode 100644 crates/schema/public/enums_api/src/by_table/media_files/mod.rs create mode 100644 crates/schema/public/enums_api/src/by_table/media_uploads/media_upload_source.rs create mode 100644 crates/schema/public/enums_api/src/by_table/media_uploads/media_upload_type.rs create mode 100644 crates/schema/public/enums_api/src/by_table/media_uploads/mod.rs create mode 100644 crates/schema/public/enums_api/src/by_table/mod.rs create mode 100644 crates/schema/public/enums_api/src/by_table/model_categories/mod.rs create mode 100644 crates/schema/public/enums_api/src/by_table/model_categories/model_type.rs create mode 100644 crates/schema/public/enums_api/src/by_table/model_weights/mod.rs create mode 100644 crates/schema/public/enums_api/src/by_table/model_weights/weights_category.rs create mode 100644 crates/schema/public/enums_api/src/by_table/model_weights/weights_file_type.rs create mode 100644 crates/schema/public/enums_api/src/by_table/model_weights/weights_types.rs create mode 100644 crates/schema/public/enums_api/src/by_table/prompt_context_items/mod.rs create mode 100644 crates/schema/public/enums_api/src/by_table/prompt_context_items/prompt_context_semantic_type.rs create mode 100644 crates/schema/public/enums_api/src/by_table/prompts/mod.rs create mode 100644 crates/schema/public/enums_api/src/by_table/prompts/prompt_type.rs create mode 100644 crates/schema/public/enums_api/src/by_table/tag_uses/mod.rs create mode 100644 crates/schema/public/enums_api/src/by_table/tag_uses/tag_use_entity_type.rs create mode 100644 crates/schema/public/enums_api/src/by_table/trending_model_analytics/mod.rs create mode 100644 crates/schema/public/enums_api/src/by_table/trending_model_analytics/model_type.rs create mode 100644 crates/schema/public/enums_api/src/by_table/trending_model_analytics/window_name.rs create mode 100644 crates/schema/public/enums_api/src/by_table/tts_models/mod.rs create mode 100644 crates/schema/public/enums_api/src/by_table/tts_models/tts_model_type.rs create mode 100644 crates/schema/public/enums_api/src/by_table/tts_render_tasks/mod.rs create mode 100644 crates/schema/public/enums_api/src/by_table/tts_render_tasks/tts_render_status.rs create mode 100644 crates/schema/public/enums_api/src/by_table/usages/mod.rs create mode 100644 crates/schema/public/enums_api/src/by_table/usages/usages_type.rs create mode 100644 crates/schema/public/enums_api/src/by_table/user_bookmarks/mod.rs create mode 100644 crates/schema/public/enums_api/src/by_table/user_bookmarks/user_bookmark_entity_type.rs create mode 100644 crates/schema/public/enums_api/src/by_table/user_ratings/entity_type.rs create mode 100644 crates/schema/public/enums_api/src/by_table/user_ratings/mod.rs create mode 100644 crates/schema/public/enums_api/src/by_table/user_ratings/rating_value.rs create mode 100644 crates/schema/public/enums_api/src/by_table/users/mod.rs create mode 100644 crates/schema/public/enums_api/src/by_table/users/user_feature_flag.rs create mode 100644 crates/schema/public/enums_api/src/by_table/users/user_signup_method.rs create mode 100644 crates/schema/public/enums_api/src/by_table/users/user_signup_source.rs create mode 100644 crates/schema/public/enums_api/src/by_table/voice_conversion_models/mod.rs create mode 100644 crates/schema/public/enums_api/src/by_table/voice_conversion_models/voice_conversion_model_type.rs create mode 100644 crates/schema/public/enums_api/src/by_table/voice_conversion_results/mod.rs create mode 100644 crates/schema/public/enums_api/src/by_table/voice_conversion_results/voice_conversion_media_token_type.rs create mode 100644 crates/schema/public/enums_api/src/by_table/wallet_ledger_entries/mod.rs create mode 100644 crates/schema/public/enums_api/src/by_table/wallet_ledger_entries/wallet_ledger_entry_type.rs create mode 100644 crates/schema/public/enums_api/src/by_table/web_rendition_targets/mod.rs create mode 100644 crates/schema/public/enums_api/src/by_table/web_rendition_targets/rendition_status.rs create mode 100644 crates/schema/public/enums_api/src/by_table/web_scraping_targets/mod.rs create mode 100644 crates/schema/public/enums_api/src/by_table/web_scraping_targets/scraping_status.rs create mode 100644 crates/schema/public/enums_api/src/by_table/zs_voices/encoding_type.rs create mode 100644 crates/schema/public/enums_api/src/by_table/zs_voices/mod.rs create mode 100644 crates/schema/public/enums_api/src/by_table/zs_voices/model_category.rs create mode 100644 crates/schema/public/enums_api/src/by_table/zs_voices/model_type.rs create mode 100644 crates/schema/public/enums_api/src/common/artcraft_credits_pack_slug.rs create mode 100644 crates/schema/public/enums_api/src/common/artcraft_subscription_slug.rs create mode 100644 crates/schema/public/enums_api/src/common/generation/common_aspect_ratio.rs create mode 100644 crates/schema/public/enums_api/src/common/generation/common_image_model.rs create mode 100644 crates/schema/public/enums_api/src/common/generation/common_splat_model.rs create mode 100644 crates/schema/public/enums_api/src/common/generation/common_video_model.rs create mode 100644 crates/schema/public/enums_api/src/common/generation/common_video_resolution.rs create mode 100644 crates/schema/public/enums_api/src/common/generation/generation_provider.rs create mode 100644 crates/schema/public/enums_api/src/common/generation/mod.rs create mode 100644 crates/schema/public/enums_api/src/common/job_status.rs create mode 100644 crates/schema/public/enums_api/src/common/job_status_plus.rs create mode 100644 crates/schema/public/enums_api/src/common/mod.rs create mode 100644 crates/schema/public/enums_api/src/common/model_type.rs create mode 100644 crates/schema/public/enums_api/src/common/payments_namespace.rs create mode 100644 crates/schema/public/enums_api/src/common/sqlite/awaitable_job_status.rs create mode 100644 crates/schema/public/enums_api/src/common/sqlite/chatbot_job_status.rs create mode 100644 crates/schema/public/enums_api/src/common/sqlite/mod.rs create mode 100644 crates/schema/public/enums_api/src/common/sqlite/skip_reason.rs create mode 100644 crates/schema/public/enums_api/src/common/sqlite/web_content_type.rs create mode 100644 crates/schema/public/enums_api/src/common/stripe_subscription_status.rs create mode 100644 crates/schema/public/enums_api/src/common/view_as.rs create mode 100644 crates/schema/public/enums_api/src/common/visibility.rs create mode 100644 crates/schema/public/enums_api/src/common/vocoder_type.rs create mode 100644 crates/schema/public/enums_api/src/lib.rs create mode 100644 crates/schema/public/enums_api/src/no_table/mod.rs create mode 100644 crates/schema/public/enums_api/src/no_table/premium_product/mod.rs create mode 100644 crates/schema/public/enums_api/src/no_table/premium_product/premium_product_name.rs create mode 100644 crates/schema/public/enums_api/src/no_table/style_transfer/mod.rs create mode 100644 crates/schema/public/enums_api/src/no_table/style_transfer/style_transfer_name.rs create mode 100644 crates/schema/public/enums_api/src/no_table/video_dimensions/mod.rs create mode 100644 crates/schema/public/enums_api/src/no_table/video_dimensions/video_dimensions.rs create mode 100644 crates/schema/public/enums_api/src/tauri/mod.rs create mode 100644 crates/schema/public/enums_api/src/tauri/tasks/mod.rs create mode 100644 crates/schema/public/enums_api/src/tauri/tasks/task_failure_type.rs create mode 100644 crates/schema/public/enums_api/src/tauri/tasks/task_media_file_class.rs create mode 100644 crates/schema/public/enums_api/src/tauri/tasks/task_model_type.rs create mode 100644 crates/schema/public/enums_api/src/tauri/tasks/task_status.rs create mode 100644 crates/schema/public/enums_api/src/tauri/tasks/task_type.rs create mode 100644 crates/schema/public/enums_api/src/tauri/ux/mod.rs create mode 100644 crates/schema/public/enums_api/src/tauri/ux/tauri_command_caller.rs create mode 100644 crates/schema/public/enums_api/src/tauri/ux/tauri_event_name.rs create mode 100644 crates/schema/public/enums_convert/Cargo.toml create mode 100644 crates/schema/public/enums_convert/src/api_safe/by_table/generic_inference_jobs/frontend_failure_category_for_api_clients.rs create mode 100644 crates/schema/public/enums_convert/src/api_safe/by_table/generic_inference_jobs/frontend_failure_category_for_old_clients.rs create mode 100644 crates/schema/public/enums_convert/src/api_safe/by_table/generic_inference_jobs/mod.rs create mode 100644 crates/schema/public/enums_convert/src/api_safe/by_table/mod.rs create mode 100644 crates/schema/public/enums_convert/src/api_safe/mod.rs create mode 100644 crates/schema/public/enums_convert/src/by_table/audit_logs/audit_log_entity_action.rs create mode 100644 crates/schema/public/enums_convert/src/by_table/audit_logs/audit_log_entity_type.rs create mode 100644 crates/schema/public/enums_convert/src/by_table/audit_logs/mod.rs create mode 100644 crates/schema/public/enums_convert/src/by_table/batch_generations/batch_generation_entity_type.rs create mode 100644 crates/schema/public/enums_convert/src/by_table/batch_generations/mod.rs create mode 100644 crates/schema/public/enums_convert/src/by_table/beta_keys/beta_key_product.rs create mode 100644 crates/schema/public/enums_convert/src/by_table/beta_keys/mod.rs create mode 100644 crates/schema/public/enums_convert/src/by_table/comments/comment_entity_type.rs create mode 100644 crates/schema/public/enums_convert/src/by_table/comments/mod.rs create mode 100644 crates/schema/public/enums_convert/src/by_table/email_sender_jobs/email_category.rs create mode 100644 crates/schema/public/enums_convert/src/by_table/email_sender_jobs/mod.rs create mode 100644 crates/schema/public/enums_convert/src/by_table/entity_stats/mod.rs create mode 100644 crates/schema/public/enums_convert/src/by_table/entity_stats/stats_entity_type.rs create mode 100644 crates/schema/public/enums_convert/src/by_table/featured_items/featured_item_entity_type.rs create mode 100644 crates/schema/public/enums_convert/src/by_table/featured_items/mod.rs create mode 100644 crates/schema/public/enums_convert/src/by_table/generic_download_jobs/generic_download_type.rs create mode 100644 crates/schema/public/enums_convert/src/by_table/generic_download_jobs/mod.rs create mode 100644 crates/schema/public/enums_convert/src/by_table/generic_inference_jobs/inference_category.rs create mode 100644 crates/schema/public/enums_convert/src/by_table/generic_inference_jobs/inference_input_source_token_type.rs create mode 100644 crates/schema/public/enums_convert/src/by_table/generic_inference_jobs/inference_job_external_third_party.rs create mode 100644 crates/schema/public/enums_convert/src/by_table/generic_inference_jobs/inference_job_product_category.rs create mode 100644 crates/schema/public/enums_convert/src/by_table/generic_inference_jobs/inference_job_type.rs create mode 100644 crates/schema/public/enums_convert/src/by_table/generic_inference_jobs/inference_model_type.rs create mode 100644 crates/schema/public/enums_convert/src/by_table/generic_inference_jobs/inference_result_type.rs create mode 100644 crates/schema/public/enums_convert/src/by_table/generic_inference_jobs/mod.rs create mode 100644 crates/schema/public/enums_convert/src/by_table/generic_synthetic_ids/id_category.rs create mode 100644 crates/schema/public/enums_convert/src/by_table/generic_synthetic_ids/mod.rs create mode 100644 crates/schema/public/enums_convert/src/by_table/media_files/media_file_animation_type.rs create mode 100644 crates/schema/public/enums_convert/src/by_table/media_files/media_file_class.rs create mode 100644 crates/schema/public/enums_convert/src/by_table/media_files/media_file_engine_category.rs create mode 100644 crates/schema/public/enums_convert/src/by_table/media_files/media_file_origin_category.rs create mode 100644 crates/schema/public/enums_convert/src/by_table/media_files/media_file_origin_model_type.rs create mode 100644 crates/schema/public/enums_convert/src/by_table/media_files/media_file_origin_product_category.rs create mode 100644 crates/schema/public/enums_convert/src/by_table/media_files/media_file_subtype.rs create mode 100644 crates/schema/public/enums_convert/src/by_table/media_files/media_file_type.rs create mode 100644 crates/schema/public/enums_convert/src/by_table/media_files/mod.rs create mode 100644 crates/schema/public/enums_convert/src/by_table/media_uploads/media_upload_source.rs create mode 100644 crates/schema/public/enums_convert/src/by_table/media_uploads/media_upload_type.rs create mode 100644 crates/schema/public/enums_convert/src/by_table/media_uploads/mod.rs create mode 100644 crates/schema/public/enums_convert/src/by_table/mod.rs create mode 100644 crates/schema/public/enums_convert/src/by_table/model_categories/mod.rs create mode 100644 crates/schema/public/enums_convert/src/by_table/model_categories/model_type.rs create mode 100644 crates/schema/public/enums_convert/src/by_table/model_weights/mod.rs create mode 100644 crates/schema/public/enums_convert/src/by_table/model_weights/weights_category.rs create mode 100644 crates/schema/public/enums_convert/src/by_table/model_weights/weights_file_type.rs create mode 100644 crates/schema/public/enums_convert/src/by_table/model_weights/weights_types.rs create mode 100644 crates/schema/public/enums_convert/src/by_table/prompt_context_items/mod.rs create mode 100644 crates/schema/public/enums_convert/src/by_table/prompt_context_items/prompt_context_semantic_type.rs create mode 100644 crates/schema/public/enums_convert/src/by_table/prompts/mod.rs create mode 100644 crates/schema/public/enums_convert/src/by_table/prompts/prompt_type.rs create mode 100644 crates/schema/public/enums_convert/src/by_table/tag_uses/mod.rs create mode 100644 crates/schema/public/enums_convert/src/by_table/tag_uses/tag_use_entity_type.rs create mode 100644 crates/schema/public/enums_convert/src/by_table/trending_model_analytics/mod.rs create mode 100644 crates/schema/public/enums_convert/src/by_table/trending_model_analytics/model_type.rs create mode 100644 crates/schema/public/enums_convert/src/by_table/trending_model_analytics/window_name.rs create mode 100644 crates/schema/public/enums_convert/src/by_table/tts_models/mod.rs create mode 100644 crates/schema/public/enums_convert/src/by_table/tts_models/tts_model_type.rs create mode 100644 crates/schema/public/enums_convert/src/by_table/tts_render_tasks/mod.rs create mode 100644 crates/schema/public/enums_convert/src/by_table/tts_render_tasks/tts_render_status.rs create mode 100644 crates/schema/public/enums_convert/src/by_table/usages/mod.rs create mode 100644 crates/schema/public/enums_convert/src/by_table/usages/usages_type.rs create mode 100644 crates/schema/public/enums_convert/src/by_table/user_bookmarks/mod.rs create mode 100644 crates/schema/public/enums_convert/src/by_table/user_bookmarks/user_bookmark_entity_type.rs create mode 100644 crates/schema/public/enums_convert/src/by_table/user_ratings/entity_type.rs create mode 100644 crates/schema/public/enums_convert/src/by_table/user_ratings/mod.rs create mode 100644 crates/schema/public/enums_convert/src/by_table/user_ratings/rating_value.rs create mode 100644 crates/schema/public/enums_convert/src/by_table/users/mod.rs create mode 100644 crates/schema/public/enums_convert/src/by_table/users/user_feature_flag.rs create mode 100644 crates/schema/public/enums_convert/src/by_table/users/user_signup_method.rs create mode 100644 crates/schema/public/enums_convert/src/by_table/users/user_signup_source.rs create mode 100644 crates/schema/public/enums_convert/src/by_table/voice_conversion_models/mod.rs create mode 100644 crates/schema/public/enums_convert/src/by_table/voice_conversion_models/voice_conversion_model_type.rs create mode 100644 crates/schema/public/enums_convert/src/by_table/voice_conversion_results/mod.rs create mode 100644 crates/schema/public/enums_convert/src/by_table/voice_conversion_results/voice_conversion_media_token_type.rs create mode 100644 crates/schema/public/enums_convert/src/by_table/wallet_ledger_entries/mod.rs create mode 100644 crates/schema/public/enums_convert/src/by_table/wallet_ledger_entries/wallet_ledger_entry_type.rs create mode 100644 crates/schema/public/enums_convert/src/by_table/web_rendition_targets/mod.rs create mode 100644 crates/schema/public/enums_convert/src/by_table/web_rendition_targets/rendition_status.rs create mode 100644 crates/schema/public/enums_convert/src/by_table/web_scraping_targets/mod.rs create mode 100644 crates/schema/public/enums_convert/src/by_table/web_scraping_targets/scraping_status.rs create mode 100644 crates/schema/public/enums_convert/src/by_table/zs_voices/encoding_type.rs create mode 100644 crates/schema/public/enums_convert/src/by_table/zs_voices/mod.rs create mode 100644 crates/schema/public/enums_convert/src/by_table/zs_voices/model_category.rs create mode 100644 crates/schema/public/enums_convert/src/by_table/zs_voices/model_type.rs create mode 100644 crates/schema/public/enums_convert/src/common/artcraft_credits_pack_slug.rs create mode 100644 crates/schema/public/enums_convert/src/common/artcraft_subscription_slug.rs create mode 100644 crates/schema/public/enums_convert/src/common/generation/generation_provider.rs create mode 100644 crates/schema/public/enums_convert/src/common/generation/mod.rs create mode 100644 crates/schema/public/enums_convert/src/common/job_status.rs create mode 100644 crates/schema/public/enums_convert/src/common/job_status_plus.rs create mode 100644 crates/schema/public/enums_convert/src/common/mod.rs create mode 100644 crates/schema/public/enums_convert/src/common/model_type.rs create mode 100644 crates/schema/public/enums_convert/src/common/payments_namespace.rs create mode 100644 crates/schema/public/enums_convert/src/common/sqlite/awaitable_job_status.rs create mode 100644 crates/schema/public/enums_convert/src/common/sqlite/chatbot_job_status.rs create mode 100644 crates/schema/public/enums_convert/src/common/sqlite/mod.rs create mode 100644 crates/schema/public/enums_convert/src/common/sqlite/skip_reason.rs create mode 100644 crates/schema/public/enums_convert/src/common/sqlite/web_content_type.rs create mode 100644 crates/schema/public/enums_convert/src/common/stripe_subscription_status.rs create mode 100644 crates/schema/public/enums_convert/src/common/view_as.rs create mode 100644 crates/schema/public/enums_convert/src/common/visibility.rs create mode 100644 crates/schema/public/enums_convert/src/common/vocoder_type.rs create mode 100644 crates/schema/public/enums_convert/src/lib.rs create mode 100644 crates/schema/public/enums_convert/src/no_table/mod.rs create mode 100644 crates/schema/public/enums_convert/src/no_table/premium_product/mod.rs create mode 100644 crates/schema/public/enums_convert/src/no_table/premium_product/premium_product_name.rs create mode 100644 crates/schema/public/enums_convert/src/no_table/style_transfer/mod.rs create mode 100644 crates/schema/public/enums_convert/src/no_table/style_transfer/style_transfer_name.rs create mode 100644 crates/schema/public/enums_convert/src/tauri/mod.rs create mode 100644 crates/schema/public/enums_convert/src/tauri/tasks/mod.rs create mode 100644 crates/schema/public/enums_convert/src/tauri/tasks/task_failure_type.rs create mode 100644 crates/schema/public/enums_convert/src/tauri/tasks/task_media_file_class.rs create mode 100644 crates/schema/public/enums_convert/src/tauri/tasks/task_model_type.rs create mode 100644 crates/schema/public/enums_convert/src/tauri/tasks/task_status.rs create mode 100644 crates/schema/public/enums_convert/src/tauri/tasks/task_type.rs create mode 100644 crates/schema/public/enums_convert/src/tauri/ux/mod.rs create mode 100644 crates/schema/public/enums_convert/src/tauri/ux/tauri_command_caller.rs create mode 100644 crates/schema/public/enums_convert/src/tauri/ux/tauri_event_name.rs create mode 100644 crates/schema/public/enums_db/Cargo.toml create mode 100644 crates/schema/public/enums_db/src/by_table/audit_logs/audit_log_entity_action.rs create mode 100644 crates/schema/public/enums_db/src/by_table/audit_logs/audit_log_entity_type.rs create mode 100644 crates/schema/public/enums_db/src/by_table/audit_logs/mod.rs create mode 100644 crates/schema/public/enums_db/src/by_table/batch_generations/batch_generation_entity_type.rs create mode 100644 crates/schema/public/enums_db/src/by_table/batch_generations/mod.rs create mode 100644 crates/schema/public/enums_db/src/by_table/beta_keys/beta_key_product.rs create mode 100644 crates/schema/public/enums_db/src/by_table/beta_keys/mod.rs create mode 100644 crates/schema/public/enums_db/src/by_table/comments/comment_entity_type.rs create mode 100644 crates/schema/public/enums_db/src/by_table/comments/mod.rs create mode 100644 crates/schema/public/enums_db/src/by_table/email_sender_jobs/email_category.rs create mode 100644 crates/schema/public/enums_db/src/by_table/email_sender_jobs/mod.rs create mode 100644 crates/schema/public/enums_db/src/by_table/entity_stats/mod.rs create mode 100644 crates/schema/public/enums_db/src/by_table/entity_stats/stats_entity_type.rs create mode 100644 crates/schema/public/enums_db/src/by_table/featured_items/featured_item_entity_type.rs create mode 100644 crates/schema/public/enums_db/src/by_table/featured_items/mod.rs create mode 100644 crates/schema/public/enums_db/src/by_table/generic_download_jobs/generic_download_type.rs create mode 100644 crates/schema/public/enums_db/src/by_table/generic_download_jobs/mod.rs create mode 100644 crates/schema/public/enums_db/src/by_table/generic_inference_jobs/frontend_failure_category.rs create mode 100644 crates/schema/public/enums_db/src/by_table/generic_inference_jobs/inference_category.rs create mode 100644 crates/schema/public/enums_db/src/by_table/generic_inference_jobs/inference_input_source_token_type.rs create mode 100644 crates/schema/public/enums_db/src/by_table/generic_inference_jobs/inference_job_external_third_party.rs create mode 100644 crates/schema/public/enums_db/src/by_table/generic_inference_jobs/inference_job_product_category.rs create mode 100644 crates/schema/public/enums_db/src/by_table/generic_inference_jobs/inference_job_type.rs create mode 100644 crates/schema/public/enums_db/src/by_table/generic_inference_jobs/inference_model_type.rs create mode 100644 crates/schema/public/enums_db/src/by_table/generic_inference_jobs/inference_result_type.rs create mode 100644 crates/schema/public/enums_db/src/by_table/generic_inference_jobs/mod.rs create mode 100644 crates/schema/public/enums_db/src/by_table/generic_synthetic_ids/id_category.rs create mode 100644 crates/schema/public/enums_db/src/by_table/generic_synthetic_ids/mod.rs create mode 100644 crates/schema/public/enums_db/src/by_table/media_files/media_file_animation_type.rs create mode 100644 crates/schema/public/enums_db/src/by_table/media_files/media_file_class.rs create mode 100644 crates/schema/public/enums_db/src/by_table/media_files/media_file_engine_category.rs create mode 100644 crates/schema/public/enums_db/src/by_table/media_files/media_file_origin_category.rs create mode 100644 crates/schema/public/enums_db/src/by_table/media_files/media_file_origin_model_type.rs create mode 100644 crates/schema/public/enums_db/src/by_table/media_files/media_file_origin_product_category.rs create mode 100644 crates/schema/public/enums_db/src/by_table/media_files/media_file_subtype.rs create mode 100644 crates/schema/public/enums_db/src/by_table/media_files/media_file_type.rs create mode 100644 crates/schema/public/enums_db/src/by_table/media_files/mod.rs create mode 100644 crates/schema/public/enums_db/src/by_table/media_uploads/media_upload_source.rs create mode 100644 crates/schema/public/enums_db/src/by_table/media_uploads/media_upload_type.rs create mode 100644 crates/schema/public/enums_db/src/by_table/media_uploads/mod.rs create mode 100644 crates/schema/public/enums_db/src/by_table/mod.rs create mode 100644 crates/schema/public/enums_db/src/by_table/model_categories/mod.rs create mode 100644 crates/schema/public/enums_db/src/by_table/model_categories/model_type.rs create mode 100644 crates/schema/public/enums_db/src/by_table/model_weights/mod.rs create mode 100644 crates/schema/public/enums_db/src/by_table/model_weights/weights_category.rs create mode 100644 crates/schema/public/enums_db/src/by_table/model_weights/weights_file_type.rs create mode 100644 crates/schema/public/enums_db/src/by_table/model_weights/weights_types.rs create mode 100644 crates/schema/public/enums_db/src/by_table/prompt_context_items/mod.rs create mode 100644 crates/schema/public/enums_db/src/by_table/prompt_context_items/prompt_context_semantic_type.rs create mode 100644 crates/schema/public/enums_db/src/by_table/prompts/mod.rs create mode 100644 crates/schema/public/enums_db/src/by_table/prompts/prompt_type.rs create mode 100644 crates/schema/public/enums_db/src/by_table/tag_uses/mod.rs create mode 100644 crates/schema/public/enums_db/src/by_table/tag_uses/tag_use_entity_type.rs create mode 100644 crates/schema/public/enums_db/src/by_table/trending_model_analytics/mod.rs create mode 100644 crates/schema/public/enums_db/src/by_table/trending_model_analytics/model_type.rs create mode 100644 crates/schema/public/enums_db/src/by_table/trending_model_analytics/window_name.rs create mode 100644 crates/schema/public/enums_db/src/by_table/tts_models/mod.rs create mode 100644 crates/schema/public/enums_db/src/by_table/tts_models/tts_model_type.rs create mode 100644 crates/schema/public/enums_db/src/by_table/tts_render_tasks/mod.rs create mode 100644 crates/schema/public/enums_db/src/by_table/tts_render_tasks/tts_render_status.rs create mode 100644 crates/schema/public/enums_db/src/by_table/usages/mod.rs create mode 100644 crates/schema/public/enums_db/src/by_table/usages/usages_type.rs create mode 100644 crates/schema/public/enums_db/src/by_table/user_bookmarks/mod.rs create mode 100644 crates/schema/public/enums_db/src/by_table/user_bookmarks/user_bookmark_entity_type.rs create mode 100644 crates/schema/public/enums_db/src/by_table/user_ratings/entity_type.rs create mode 100644 crates/schema/public/enums_db/src/by_table/user_ratings/mod.rs create mode 100644 crates/schema/public/enums_db/src/by_table/user_ratings/rating_value.rs create mode 100644 crates/schema/public/enums_db/src/by_table/users/mod.rs create mode 100644 crates/schema/public/enums_db/src/by_table/users/user_feature_flag.rs create mode 100644 crates/schema/public/enums_db/src/by_table/users/user_signup_method.rs create mode 100644 crates/schema/public/enums_db/src/by_table/users/user_signup_source.rs create mode 100644 crates/schema/public/enums_db/src/by_table/voice_conversion_models/mod.rs create mode 100644 crates/schema/public/enums_db/src/by_table/voice_conversion_models/voice_conversion_model_type.rs create mode 100644 crates/schema/public/enums_db/src/by_table/voice_conversion_results/mod.rs create mode 100644 crates/schema/public/enums_db/src/by_table/voice_conversion_results/voice_conversion_media_token_type.rs create mode 100644 crates/schema/public/enums_db/src/by_table/wallet_ledger_entries/mod.rs create mode 100644 crates/schema/public/enums_db/src/by_table/wallet_ledger_entries/wallet_ledger_entry_type.rs create mode 100644 crates/schema/public/enums_db/src/by_table/web_rendition_targets/mod.rs create mode 100644 crates/schema/public/enums_db/src/by_table/web_rendition_targets/rendition_status.rs create mode 100644 crates/schema/public/enums_db/src/by_table/web_scraping_targets/mod.rs create mode 100644 crates/schema/public/enums_db/src/by_table/web_scraping_targets/scraping_status.rs create mode 100644 crates/schema/public/enums_db/src/by_table/zs_voices/encoding_type.rs create mode 100644 crates/schema/public/enums_db/src/by_table/zs_voices/mod.rs create mode 100644 crates/schema/public/enums_db/src/by_table/zs_voices/model_category.rs create mode 100644 crates/schema/public/enums_db/src/by_table/zs_voices/model_type.rs create mode 100644 crates/schema/public/enums_db/src/common/artcraft_credits_pack_slug.rs create mode 100644 crates/schema/public/enums_db/src/common/artcraft_subscription_slug.rs create mode 100644 crates/schema/public/enums_db/src/common/generation/generation_provider.rs create mode 100644 crates/schema/public/enums_db/src/common/generation/mod.rs create mode 100644 crates/schema/public/enums_db/src/common/job_status.rs create mode 100644 crates/schema/public/enums_db/src/common/job_status_plus.rs create mode 100644 crates/schema/public/enums_db/src/common/mod.rs create mode 100644 crates/schema/public/enums_db/src/common/model_type.rs create mode 100644 crates/schema/public/enums_db/src/common/payments_namespace.rs create mode 100644 crates/schema/public/enums_db/src/common/sqlite/awaitable_job_status.rs create mode 100644 crates/schema/public/enums_db/src/common/sqlite/chatbot_job_status.rs create mode 100644 crates/schema/public/enums_db/src/common/sqlite/mod.rs create mode 100644 crates/schema/public/enums_db/src/common/sqlite/skip_reason.rs create mode 100644 crates/schema/public/enums_db/src/common/sqlite/web_content_type.rs create mode 100644 crates/schema/public/enums_db/src/common/stripe_subscription_status.rs create mode 100644 crates/schema/public/enums_db/src/common/view_as.rs create mode 100644 crates/schema/public/enums_db/src/common/visibility.rs create mode 100644 crates/schema/public/enums_db/src/common/vocoder_type.rs create mode 100644 crates/schema/public/enums_db/src/lib.rs create mode 100644 crates/schema/public/enums_db/src/macros/impl_enum_display_and_debug_using_to_str.rs create mode 100644 crates/schema/public/enums_db/src/macros/impl_mysql_enum_coders.rs create mode 100644 crates/schema/public/enums_db/src/macros/impl_mysql_from_row.rs create mode 100644 crates/schema/public/enums_db/src/macros/impl_sqlite_enum_coders.rs create mode 100644 crates/schema/public/enums_db/src/macros/mod.rs create mode 100644 crates/schema/public/enums_db/src/no_table/mod.rs create mode 100644 crates/schema/public/enums_db/src/no_table/premium_product/mod.rs create mode 100644 crates/schema/public/enums_db/src/no_table/premium_product/premium_product_name.rs create mode 100644 crates/schema/public/enums_db/src/no_table/style_transfer/mod.rs create mode 100644 crates/schema/public/enums_db/src/no_table/style_transfer/style_transfer_name.rs create mode 100644 crates/schema/public/enums_db/src/tauri/mod.rs create mode 100644 crates/schema/public/enums_db/src/tauri/tasks/mod.rs create mode 100644 crates/schema/public/enums_db/src/tauri/tasks/task_failure_type.rs create mode 100644 crates/schema/public/enums_db/src/tauri/tasks/task_media_file_class.rs create mode 100644 crates/schema/public/enums_db/src/tauri/tasks/task_model_type.rs create mode 100644 crates/schema/public/enums_db/src/tauri/tasks/task_status.rs create mode 100644 crates/schema/public/enums_db/src/tauri/tasks/task_type.rs create mode 100644 crates/schema/public/enums_db/src/tauri/ux/mod.rs create mode 100644 crates/schema/public/enums_db/src/tauri/ux/tauri_command_caller.rs create mode 100644 crates/schema/public/enums_db/src/tauri/ux/tauri_event_name.rs create mode 100644 crates/schema/public/enums_db/src/traits/mod.rs create mode 100644 crates/schema/public/enums_db/src/traits/mysql_from_row.rs create mode 100644 crates/schema/public/enums_shared/Cargo.toml create mode 100644 crates/schema/public/enums_shared/src/error/enums_error.rs create mode 100644 crates/schema/public/enums_shared/src/error/mod.rs create mode 100644 crates/schema/public/enums_shared/src/lib.rs create mode 100644 crates/schema/public/enums_shared/src/macros/mod.rs create mode 100644 crates/schema/public/enums_shared/src/test_helpers.rs diff --git a/Cargo.lock b/Cargo.lock index 339993ab4b..400d353ddf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3793,6 +3793,50 @@ dependencies = [ "workspace-build-acceleration", ] +[[package]] +name = "enums_api" +version = "0.0.1" +dependencies = [ + "enums_shared", + "log", + "serde", + "serde_derive", + "serde_json", + "strum", + "toml 1.0.7+spec-1.1.0", + "utoipa", + "workspace-build-acceleration", +] + +[[package]] +name = "enums_convert" +version = "0.0.1" +dependencies = [ + "enums_api", + "enums_db", + "serde_json", + "strum", + "workspace-build-acceleration", +] + +[[package]] +name = "enums_db" +version = "0.0.1" +dependencies = [ + "enums_shared", + "log", + "serde", + "serde_derive", + "serde_json", + "sqlx", + "sqlx-core", + "sqlx-mysql", + "strum", + "toml 1.0.7+spec-1.1.0", + "utoipa", + "workspace-build-acceleration", +] + [[package]] name = "enums_public" version = "0.0.1" @@ -3807,6 +3851,19 @@ dependencies = [ "workspace-build-acceleration", ] +[[package]] +name = "enums_shared" +version = "0.0.1" +dependencies = [ + "log", + "serde", + "serde_derive", + "serde_json", + "strum", + "toml 1.0.7+spec-1.1.0", + "workspace-build-acceleration", +] + [[package]] name = "env" version = "1.0.1" diff --git a/Cargo.toml b/Cargo.toml index a40520a568..6d0aab4e80 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -111,7 +111,11 @@ members = [ # Schema (public): common strongly-typed tokens, ids, payloads, etc. "crates/schema/public/composite_identifiers", "crates/schema/public/enums", + "crates/schema/public/enums_api", + "crates/schema/public/enums_convert", + "crates/schema/public/enums_db", "crates/schema/public/enums_public", + "crates/schema/public/enums_shared", "crates/schema/public/reusable_types", # TODO(bt, 2022-12-21): Deprecate "crates/schema/public/tokens", @@ -233,6 +237,10 @@ crockford = { path = "crates/lib/data/crockford" } easyenv = { path = "crates/lib/easyenv" } enums = { path = "crates/schema/public/enums" } enums_public = { path = "crates/schema/public/enums_public" } +enums_db = { path = "crates/schema/public/enums_db" } +enums_api = { path = "crates/schema/public/enums_api" } +enums_shared = { path = "crates/schema/public/enums_shared" } +enums_convert = { path = "crates/schema/public/enums_convert" } errors = { path = "crates/lib/errors" } fal_client = { path = "crates/api_clients/fal_client" } ffmpeg_utils = { path = "crates/lib/ffmpeg_utils" } diff --git a/crates/schema/public/enums_api/Cargo.toml b/crates/schema/public/enums_api/Cargo.toml new file mode 100644 index 0000000000..53f746b811 --- /dev/null +++ b/crates/schema/public/enums_api/Cargo.toml @@ -0,0 +1,34 @@ +[package] +name = "enums_api" +edition = "2021" +version = "0.0.1" +authors = [ + "Brandon Thomas ", + "Brandon Thomas ", +] +publish = false + +[package.metadata.cargo-udeps.ignore] +normal = ["workspace-build-acceleration"] + +[lib] +name = "enums_api" +path = "src/lib.rs" + +[dependencies] +# Workspace hack (faster compile times) +workspace-build-acceleration.workspace = true + +# Internal +enums_shared.workspace = true + +# External +log.workspace = true +serde.workspace = true +serde_derive.workspace = true +strum.workspace = true +utoipa.workspace = true + +[dev-dependencies] +serde_json.workspace = true +toml.workspace = true diff --git a/crates/schema/public/enums_api/src/api_safe/by_table/generic_inference_jobs/frontend_failure_category_for_api_clients.rs b/crates/schema/public/enums_api/src/api_safe/by_table/generic_inference_jobs/frontend_failure_category_for_api_clients.rs new file mode 100644 index 0000000000..cd4bfe97db --- /dev/null +++ b/crates/schema/public/enums_api/src/api_safe/by_table/generic_inference_jobs/frontend_failure_category_for_api_clients.rs @@ -0,0 +1,109 @@ +use strum::EnumIter; +use utoipa::ToSchema; + +/// A forward-compatible version of `FrontendFailureCategory` for API clients. +/// +/// Contains all known variants plus an `Unknown(String)` catch-all so that +/// newer server-side values never cause deserialization failures on the client. +#[derive(Clone, Debug, Eq, PartialEq, Hash, Serialize, Deserialize, ToSchema, EnumIter)] +#[serde(rename_all = "snake_case")] +pub enum FrontendFailureCategoryForApiClients { + FaceNotDetected, + KeepAliveElapsed, + NotYetImplemented, + RetryableWorkerError, + ModelRulesViolation, + RuleBansUserImage, + RuleBansUserImageWithFaces, + RuleBansUserTextPrompt, + RuleBansUserContent, + RuleBansGeneratedVideo, + RuleBansGeneratedAudio, + RuleBansGeneratedContent, + GenerationFailed, + + /// Catch-all for values the client doesn't yet know about. + /// The contained string is the raw serialized value from the server. + #[serde(untagged)] + Unknown(String), +} + +#[cfg(test)] +mod tests { + use super::FrontendFailureCategoryForApiClients; + use enums_shared::test_helpers::{assert_deserialization, assert_serialization}; + + mod manual_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(FrontendFailureCategoryForApiClients::FaceNotDetected, "face_not_detected"); + assert_serialization(FrontendFailureCategoryForApiClients::KeepAliveElapsed, "keep_alive_elapsed"); + assert_serialization(FrontendFailureCategoryForApiClients::NotYetImplemented, "not_yet_implemented"); + assert_serialization(FrontendFailureCategoryForApiClients::RetryableWorkerError, "retryable_worker_error"); + assert_serialization(FrontendFailureCategoryForApiClients::ModelRulesViolation, "model_rules_violation"); + assert_serialization(FrontendFailureCategoryForApiClients::RuleBansUserImage, "rule_bans_user_image"); + assert_serialization(FrontendFailureCategoryForApiClients::RuleBansUserImageWithFaces, "rule_bans_user_image_with_faces"); + assert_serialization(FrontendFailureCategoryForApiClients::RuleBansUserTextPrompt, "rule_bans_user_text_prompt"); + assert_serialization(FrontendFailureCategoryForApiClients::RuleBansUserContent, "rule_bans_user_content"); + assert_serialization(FrontendFailureCategoryForApiClients::RuleBansGeneratedVideo, "rule_bans_generated_video"); + assert_serialization(FrontendFailureCategoryForApiClients::RuleBansGeneratedAudio, "rule_bans_generated_audio"); + assert_serialization(FrontendFailureCategoryForApiClients::RuleBansGeneratedContent, "rule_bans_generated_content"); + assert_serialization(FrontendFailureCategoryForApiClients::GenerationFailed, "generation_failed"); + } + + #[test] + fn test_deserialization() { + assert_deserialization("face_not_detected", FrontendFailureCategoryForApiClients::FaceNotDetected); + assert_deserialization("keep_alive_elapsed", FrontendFailureCategoryForApiClients::KeepAliveElapsed); + assert_deserialization("not_yet_implemented", FrontendFailureCategoryForApiClients::NotYetImplemented); + assert_deserialization("retryable_worker_error", FrontendFailureCategoryForApiClients::RetryableWorkerError); + assert_deserialization("model_rules_violation", FrontendFailureCategoryForApiClients::ModelRulesViolation); + assert_deserialization("rule_bans_user_image", FrontendFailureCategoryForApiClients::RuleBansUserImage); + assert_deserialization("rule_bans_user_image_with_faces", FrontendFailureCategoryForApiClients::RuleBansUserImageWithFaces); + assert_deserialization("rule_bans_user_text_prompt", FrontendFailureCategoryForApiClients::RuleBansUserTextPrompt); + assert_deserialization("rule_bans_user_content", FrontendFailureCategoryForApiClients::RuleBansUserContent); + assert_deserialization("rule_bans_generated_video", FrontendFailureCategoryForApiClients::RuleBansGeneratedVideo); + assert_deserialization("rule_bans_generated_audio", FrontendFailureCategoryForApiClients::RuleBansGeneratedAudio); + assert_deserialization("rule_bans_generated_content", FrontendFailureCategoryForApiClients::RuleBansGeneratedContent); + assert_deserialization("generation_failed", FrontendFailureCategoryForApiClients::GenerationFailed); + } + + #[test] + fn unknown_variant_deserializes() { + let json = "\"some_future_category\""; + let value: FrontendFailureCategoryForApiClients = serde_json::from_str(json).unwrap(); + assert_eq!(value, FrontendFailureCategoryForApiClients::Unknown("some_future_category".to_string())); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip_json() { + let known_variants = vec![ + FrontendFailureCategoryForApiClients::FaceNotDetected, + FrontendFailureCategoryForApiClients::KeepAliveElapsed, + FrontendFailureCategoryForApiClients::NotYetImplemented, + FrontendFailureCategoryForApiClients::RetryableWorkerError, + FrontendFailureCategoryForApiClients::ModelRulesViolation, + FrontendFailureCategoryForApiClients::RuleBansUserImage, + FrontendFailureCategoryForApiClients::RuleBansUserImageWithFaces, + FrontendFailureCategoryForApiClients::RuleBansUserTextPrompt, + FrontendFailureCategoryForApiClients::RuleBansUserContent, + FrontendFailureCategoryForApiClients::RuleBansGeneratedVideo, + FrontendFailureCategoryForApiClients::RuleBansGeneratedAudio, + FrontendFailureCategoryForApiClients::RuleBansGeneratedContent, + FrontendFailureCategoryForApiClients::GenerationFailed, + ]; + assert_eq!(known_variants.len(), 13); + for variant in known_variants { + let json = serde_json::to_string(&variant).unwrap(); + let back: FrontendFailureCategoryForApiClients = serde_json::from_str(&json).unwrap(); + assert_eq!(variant, back); + } + } + } +} diff --git a/crates/schema/public/enums_api/src/api_safe/by_table/generic_inference_jobs/frontend_failure_category_for_old_clients.rs b/crates/schema/public/enums_api/src/api_safe/by_table/generic_inference_jobs/frontend_failure_category_for_old_clients.rs new file mode 100644 index 0000000000..102c3aed7a --- /dev/null +++ b/crates/schema/public/enums_api/src/api_safe/by_table/generic_inference_jobs/frontend_failure_category_for_old_clients.rs @@ -0,0 +1,65 @@ +use strum::EnumIter; +use utoipa::ToSchema; + +/// A restricted subset of `FrontendFailureCategory` that only includes values +/// known to old deployed clients. New failure categories are omitted so that +/// old clients never receive an enum value they cannot deserialize. +#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Deserialize, Serialize, ToSchema, EnumIter)] +pub enum FrontendFailureCategoryForOldClients { + #[serde(rename = "face_not_detected")] + FaceNotDetected, + + #[serde(rename = "keep_alive_elapsed")] + KeepAliveElapsed, + + #[serde(rename = "not_yet_implemented")] + NotYetImplemented, + + #[serde(rename = "retryable_worker_error")] + RetryableWorkerError, +} + +#[cfg(test)] +mod tests { + use super::FrontendFailureCategoryForOldClients; + use enums_shared::test_helpers::{assert_deserialization, assert_serialization}; + use strum::IntoEnumIterator; + + mod manual_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(FrontendFailureCategoryForOldClients::FaceNotDetected, "face_not_detected"); + assert_serialization(FrontendFailureCategoryForOldClients::KeepAliveElapsed, "keep_alive_elapsed"); + assert_serialization(FrontendFailureCategoryForOldClients::NotYetImplemented, "not_yet_implemented"); + assert_serialization(FrontendFailureCategoryForOldClients::RetryableWorkerError, "retryable_worker_error"); + } + + #[test] + fn test_deserialization() { + assert_deserialization("face_not_detected", FrontendFailureCategoryForOldClients::FaceNotDetected); + assert_deserialization("keep_alive_elapsed", FrontendFailureCategoryForOldClients::KeepAliveElapsed); + assert_deserialization("not_yet_implemented", FrontendFailureCategoryForOldClients::NotYetImplemented); + assert_deserialization("retryable_worker_error", FrontendFailureCategoryForOldClients::RetryableWorkerError); + } + + #[test] + fn variants_count_check() { + assert_eq!(FrontendFailureCategoryForOldClients::iter().count(), 4); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip_json() { + for variant in FrontendFailureCategoryForOldClients::iter() { + let json = serde_json::to_string(&variant).unwrap(); + let back: FrontendFailureCategoryForOldClients = serde_json::from_str(&json).unwrap(); + assert_eq!(variant, back); + } + } + } +} diff --git a/crates/schema/public/enums_api/src/api_safe/by_table/generic_inference_jobs/mod.rs b/crates/schema/public/enums_api/src/api_safe/by_table/generic_inference_jobs/mod.rs new file mode 100644 index 0000000000..b442e76182 --- /dev/null +++ b/crates/schema/public/enums_api/src/api_safe/by_table/generic_inference_jobs/mod.rs @@ -0,0 +1,2 @@ +pub mod frontend_failure_category_for_api_clients; +pub mod frontend_failure_category_for_old_clients; diff --git a/crates/schema/public/enums_api/src/api_safe/by_table/mod.rs b/crates/schema/public/enums_api/src/api_safe/by_table/mod.rs new file mode 100644 index 0000000000..3f750197f4 --- /dev/null +++ b/crates/schema/public/enums_api/src/api_safe/by_table/mod.rs @@ -0,0 +1 @@ +pub mod generic_inference_jobs; diff --git a/crates/schema/public/enums_api/src/api_safe/mod.rs b/crates/schema/public/enums_api/src/api_safe/mod.rs new file mode 100644 index 0000000000..1935f8872f --- /dev/null +++ b/crates/schema/public/enums_api/src/api_safe/mod.rs @@ -0,0 +1 @@ +pub mod by_table; diff --git a/crates/schema/public/enums_api/src/by_table/audit_logs/audit_log_entity_action.rs b/crates/schema/public/enums_api/src/by_table/audit_logs/audit_log_entity_action.rs new file mode 100644 index 0000000000..3c6fa9d125 --- /dev/null +++ b/crates/schema/public/enums_api/src/by_table/audit_logs/audit_log_entity_action.rs @@ -0,0 +1,80 @@ +use strum::EnumIter; +use utoipa::ToSchema; + +/// Used in the `audit_logs` table in a `VARCHAR(32)` field named `entity_action`. +#[derive(Clone, Copy, Eq, PartialEq, Hash, Deserialize, Serialize, ToSchema, EnumIter, Debug)] + +pub enum AuditLogEntityAction { + /// Create action + #[serde(rename = "create")] + Create, + + /// Edit action + #[serde(rename = "edit")] + Edit, + + /// Edit features (eg. user feature flags) + #[serde(rename = "edit_features")] + EditFeatures, + + /// Delete action + #[serde(rename = "delete")] + Delete, + + /// Create featured item + #[serde(rename = "featured_item_create")] + FeaturedItemCreate, + + /// Delete featured item + #[serde(rename = "featured_item_delete")] + FeaturedItemDelete, +} + +#[cfg(test)] +mod tests { + use super::AuditLogEntityAction; + use enums_shared::test_helpers::{assert_deserialization, assert_serialization}; + use strum::IntoEnumIterator; + + mod manual_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(AuditLogEntityAction::Create, "create"); + assert_serialization(AuditLogEntityAction::Edit, "edit"); + assert_serialization(AuditLogEntityAction::EditFeatures, "edit_features"); + assert_serialization(AuditLogEntityAction::Delete, "delete"); + assert_serialization(AuditLogEntityAction::FeaturedItemCreate, "featured_item_create"); + assert_serialization(AuditLogEntityAction::FeaturedItemDelete, "featured_item_delete"); + } + + #[test] + fn test_deserialization() { + assert_deserialization("create", AuditLogEntityAction::Create); + assert_deserialization("edit", AuditLogEntityAction::Edit); + assert_deserialization("edit_features", AuditLogEntityAction::EditFeatures); + assert_deserialization("delete", AuditLogEntityAction::Delete); + assert_deserialization("featured_item_create", AuditLogEntityAction::FeaturedItemCreate); + assert_deserialization("featured_item_delete", AuditLogEntityAction::FeaturedItemDelete); + } + + #[test] + fn variants_count_check() { + assert_eq!(AuditLogEntityAction::iter().count(), 6); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip_json() { + for variant in AuditLogEntityAction::iter() { + let json = serde_json::to_string(&variant).unwrap(); + let back: AuditLogEntityAction = serde_json::from_str(&json).unwrap(); + assert_eq!(variant, back); + } + } + } +} diff --git a/crates/schema/public/enums_api/src/by_table/audit_logs/audit_log_entity_type.rs b/crates/schema/public/enums_api/src/by_table/audit_logs/audit_log_entity_type.rs new file mode 100644 index 0000000000..a6e8262a79 --- /dev/null +++ b/crates/schema/public/enums_api/src/by_table/audit_logs/audit_log_entity_type.rs @@ -0,0 +1,68 @@ +use strum::EnumIter; +use utoipa::ToSchema; + +/// Used in the `audit_logs` table in a `VARCHAR(32)` field named `entity_type`. +#[derive(Clone, Copy, Eq, PartialEq, Hash, Deserialize, Serialize, ToSchema, EnumIter, Debug)] + +pub enum AuditLogEntityType { + /// Comment system + #[serde(rename = "comment")] + Comment, + + /// Media file + #[serde(rename = "media_file")] + MediaFile, + + /// Model weight + #[serde(rename = "model_weight")] + ModelWeight, + + /// User + #[serde(rename = "user")] + User, +} + +#[cfg(test)] +mod tests { + use super::AuditLogEntityType; + use enums_shared::test_helpers::{assert_deserialization, assert_serialization}; + use strum::IntoEnumIterator; + + mod manual_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(AuditLogEntityType::Comment, "comment"); + assert_serialization(AuditLogEntityType::MediaFile, "media_file"); + assert_serialization(AuditLogEntityType::ModelWeight, "model_weight"); + assert_serialization(AuditLogEntityType::User, "user"); + } + + #[test] + fn test_deserialization() { + assert_deserialization("comment", AuditLogEntityType::Comment); + assert_deserialization("media_file", AuditLogEntityType::MediaFile); + assert_deserialization("model_weight", AuditLogEntityType::ModelWeight); + assert_deserialization("user", AuditLogEntityType::User); + } + + #[test] + fn variants_count_check() { + assert_eq!(AuditLogEntityType::iter().count(), 4); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip_json() { + for variant in AuditLogEntityType::iter() { + let json = serde_json::to_string(&variant).unwrap(); + let back: AuditLogEntityType = serde_json::from_str(&json).unwrap(); + assert_eq!(variant, back); + } + } + } +} diff --git a/crates/schema/public/enums_api/src/by_table/audit_logs/mod.rs b/crates/schema/public/enums_api/src/by_table/audit_logs/mod.rs new file mode 100644 index 0000000000..9de3fca75c --- /dev/null +++ b/crates/schema/public/enums_api/src/by_table/audit_logs/mod.rs @@ -0,0 +1,2 @@ +pub mod audit_log_entity_action; +pub mod audit_log_entity_type; diff --git a/crates/schema/public/enums_api/src/by_table/batch_generations/batch_generation_entity_type.rs b/crates/schema/public/enums_api/src/by_table/batch_generations/batch_generation_entity_type.rs new file mode 100644 index 0000000000..6be49242d3 --- /dev/null +++ b/crates/schema/public/enums_api/src/by_table/batch_generations/batch_generation_entity_type.rs @@ -0,0 +1,51 @@ +use strum::EnumIter; +use utoipa::ToSchema; + +/// Used in the `batch_generations` table in a `VARCHAR(32)` field named `entity_type`. +#[derive(Clone, Copy, Eq, PartialEq, Hash, Deserialize, Serialize, Ord, PartialOrd, ToSchema, EnumIter, Debug)] + +pub enum BatchGenerationEntityType { + /// Media files + /// This will probably be the only type supported, but we'll leave the possibility of future types. + #[serde(rename = "media_file")] + MediaFile, +} + +#[cfg(test)] +mod tests { + use super::BatchGenerationEntityType; + use enums_shared::test_helpers::{assert_deserialization, assert_serialization}; + use strum::IntoEnumIterator; + + mod manual_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(BatchGenerationEntityType::MediaFile, "media_file"); + } + + #[test] + fn test_deserialization() { + assert_deserialization("media_file", BatchGenerationEntityType::MediaFile); + } + + #[test] + fn variants_count_check() { + assert_eq!(BatchGenerationEntityType::iter().count(), 1); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip_json() { + for variant in BatchGenerationEntityType::iter() { + let json = serde_json::to_string(&variant).unwrap(); + let back: BatchGenerationEntityType = serde_json::from_str(&json).unwrap(); + assert_eq!(variant, back); + } + } + } +} diff --git a/crates/schema/public/enums_api/src/by_table/batch_generations/mod.rs b/crates/schema/public/enums_api/src/by_table/batch_generations/mod.rs new file mode 100644 index 0000000000..6feec4da5f --- /dev/null +++ b/crates/schema/public/enums_api/src/by_table/batch_generations/mod.rs @@ -0,0 +1 @@ +pub mod batch_generation_entity_type; diff --git a/crates/schema/public/enums_api/src/by_table/beta_keys/beta_key_product.rs b/crates/schema/public/enums_api/src/by_table/beta_keys/beta_key_product.rs new file mode 100644 index 0000000000..54b228eb5f --- /dev/null +++ b/crates/schema/public/enums_api/src/by_table/beta_keys/beta_key_product.rs @@ -0,0 +1,51 @@ +use strum::EnumIter; +use utoipa::ToSchema; + +/// Used in the `batch_generations` table in a `VARCHAR(32)` field named `entity_type`. +#[derive(Clone, Copy, Eq, PartialEq, Hash, Deserialize, Serialize, Ord, PartialOrd, ToSchema, EnumIter, Debug)] + +pub enum BetaKeyProduct { + /// Media files + /// This will probably be the only type supported, but we'll leave the possibility of future types. + #[serde(rename = "studio")] + Studio, +} + +#[cfg(test)] +mod tests { + use super::BetaKeyProduct; + use enums_shared::test_helpers::{assert_deserialization, assert_serialization}; + use strum::IntoEnumIterator; + + mod manual_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(BetaKeyProduct::Studio, "studio"); + } + + #[test] + fn test_deserialization() { + assert_deserialization("studio", BetaKeyProduct::Studio); + } + + #[test] + fn variants_count_check() { + assert_eq!(BetaKeyProduct::iter().count(), 1); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip_json() { + for variant in BetaKeyProduct::iter() { + let json = serde_json::to_string(&variant).unwrap(); + let back: BetaKeyProduct = serde_json::from_str(&json).unwrap(); + assert_eq!(variant, back); + } + } + } +} diff --git a/crates/schema/public/enums_api/src/by_table/beta_keys/mod.rs b/crates/schema/public/enums_api/src/by_table/beta_keys/mod.rs new file mode 100644 index 0000000000..1e30a227d3 --- /dev/null +++ b/crates/schema/public/enums_api/src/by_table/beta_keys/mod.rs @@ -0,0 +1 @@ +pub mod beta_key_product; diff --git a/crates/schema/public/enums_api/src/by_table/comments/comment_entity_type.rs b/crates/schema/public/enums_api/src/by_table/comments/comment_entity_type.rs new file mode 100644 index 0000000000..6a08feafb4 --- /dev/null +++ b/crates/schema/public/enums_api/src/by_table/comments/comment_entity_type.rs @@ -0,0 +1,86 @@ +use strum::EnumIter; +use utoipa::ToSchema; + +/// Used in the `comments` table in a `VARCHAR(32)` field named `entity_type`. +#[derive(Clone, Copy, Eq, PartialEq, Hash, Deserialize, Serialize, ToSchema, EnumIter, Debug)] + +pub enum CommentEntityType { + /// User + #[serde(rename = "user")] + User, + + /// Media files + #[serde(rename = "media_file")] + MediaFile, + + /// Model weights + #[serde(rename = "model_weight")] + ModelWeight, + + /// TTS model (architecture does not matter) + #[serde(rename = "tts_model")] + TtsModel, + + /// TTS result (architecture does not matter) + #[serde(rename = "tts_result")] + TtsResult, + + /// W2L template + #[serde(rename = "w2l_template")] + W2lTemplate, + + /// W2L result + #[serde(rename = "w2l_result")] + W2lResult, +} + +#[cfg(test)] +mod tests { + use super::CommentEntityType; + use enums_shared::test_helpers::{assert_deserialization, assert_serialization}; + use strum::IntoEnumIterator; + + mod manual_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(CommentEntityType::User, "user"); + assert_serialization(CommentEntityType::MediaFile, "media_file"); + assert_serialization(CommentEntityType::ModelWeight, "model_weight"); + assert_serialization(CommentEntityType::TtsModel, "tts_model"); + assert_serialization(CommentEntityType::TtsResult, "tts_result"); + assert_serialization(CommentEntityType::W2lTemplate, "w2l_template"); + assert_serialization(CommentEntityType::W2lResult, "w2l_result"); + } + + #[test] + fn test_deserialization() { + assert_deserialization("user", CommentEntityType::User); + assert_deserialization("media_file", CommentEntityType::MediaFile); + assert_deserialization("model_weight", CommentEntityType::ModelWeight); + assert_deserialization("tts_model", CommentEntityType::TtsModel); + assert_deserialization("tts_result", CommentEntityType::TtsResult); + assert_deserialization("w2l_template", CommentEntityType::W2lTemplate); + assert_deserialization("w2l_result", CommentEntityType::W2lResult); + } + + #[test] + fn variants_count_check() { + assert_eq!(CommentEntityType::iter().count(), 7); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip_json() { + for variant in CommentEntityType::iter() { + let json = serde_json::to_string(&variant).unwrap(); + let back: CommentEntityType = serde_json::from_str(&json).unwrap(); + assert_eq!(variant, back); + } + } + } +} diff --git a/crates/schema/public/enums_api/src/by_table/comments/mod.rs b/crates/schema/public/enums_api/src/by_table/comments/mod.rs new file mode 100644 index 0000000000..e30377b8e0 --- /dev/null +++ b/crates/schema/public/enums_api/src/by_table/comments/mod.rs @@ -0,0 +1 @@ +pub mod comment_entity_type; diff --git a/crates/schema/public/enums_api/src/by_table/email_sender_jobs/email_category.rs b/crates/schema/public/enums_api/src/by_table/email_sender_jobs/email_category.rs new file mode 100644 index 0000000000..f618dfd586 --- /dev/null +++ b/crates/schema/public/enums_api/src/by_table/email_sender_jobs/email_category.rs @@ -0,0 +1,60 @@ +use strum::EnumIter; +use utoipa::ToSchema; + +/// Used in the `email_sender_jobs` table in `VARCHAR(32)` field `id_category`. +/// +/// This denotes the type of email being sent. +/// +/// DO NOT CHANGE VALUES WITHOUT A MIGRATION STRATEGY. +#[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, Deserialize, Serialize, ToSchema, EnumIter, Debug)] + +pub enum EmailCategory { + /// User is recently registered + #[serde(rename = "welcome")] + Welcome, + + /// User is resetting their password + #[serde(rename = "password_reset")] + PasswordReset, +} + +#[cfg(test)] +mod tests { + use super::EmailCategory; + use enums_shared::test_helpers::{assert_deserialization, assert_serialization}; + use strum::IntoEnumIterator; + + mod manual_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(EmailCategory::Welcome, "welcome"); + assert_serialization(EmailCategory::PasswordReset, "password_reset"); + } + + #[test] + fn test_deserialization() { + assert_deserialization("welcome", EmailCategory::Welcome); + assert_deserialization("password_reset", EmailCategory::PasswordReset); + } + + #[test] + fn variants_count_check() { + assert_eq!(EmailCategory::iter().count(), 2); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip_json() { + for variant in EmailCategory::iter() { + let json = serde_json::to_string(&variant).unwrap(); + let back: EmailCategory = serde_json::from_str(&json).unwrap(); + assert_eq!(variant, back); + } + } + } +} diff --git a/crates/schema/public/enums_api/src/by_table/email_sender_jobs/mod.rs b/crates/schema/public/enums_api/src/by_table/email_sender_jobs/mod.rs new file mode 100644 index 0000000000..18d5731795 --- /dev/null +++ b/crates/schema/public/enums_api/src/by_table/email_sender_jobs/mod.rs @@ -0,0 +1 @@ +pub mod email_category; diff --git a/crates/schema/public/enums_api/src/by_table/entity_stats/mod.rs b/crates/schema/public/enums_api/src/by_table/entity_stats/mod.rs new file mode 100644 index 0000000000..58a4a07b90 --- /dev/null +++ b/crates/schema/public/enums_api/src/by_table/entity_stats/mod.rs @@ -0,0 +1 @@ +pub mod stats_entity_type; diff --git a/crates/schema/public/enums_api/src/by_table/entity_stats/stats_entity_type.rs b/crates/schema/public/enums_api/src/by_table/entity_stats/stats_entity_type.rs new file mode 100644 index 0000000000..52950db376 --- /dev/null +++ b/crates/schema/public/enums_api/src/by_table/entity_stats/stats_entity_type.rs @@ -0,0 +1,62 @@ +use strum::EnumIter; +use utoipa::ToSchema; + +/// Used in the `user_stats` table in a `VARCHAR(32)` field named `entity_type`. +#[derive(Clone, Copy, Eq, PartialEq, Hash, Deserialize, Serialize, ToSchema, Ord, PartialOrd, EnumIter, Debug)] + +pub enum StatsEntityType { + /// Comment + #[serde(rename = "comment")] + Comment, + + /// MediaFile + #[serde(rename = "media_file")] + MediaFile, + + /// ModelWeight (the new way to store models) + #[serde(rename = "model_weight")] + ModelWeight, +} + +#[cfg(test)] +mod tests { + use super::StatsEntityType; + use enums_shared::test_helpers::{assert_deserialization, assert_serialization}; + use strum::IntoEnumIterator; + + mod manual_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(StatsEntityType::Comment, "comment"); + assert_serialization(StatsEntityType::MediaFile, "media_file"); + assert_serialization(StatsEntityType::ModelWeight, "model_weight"); + } + + #[test] + fn test_deserialization() { + assert_deserialization("comment", StatsEntityType::Comment); + assert_deserialization("media_file", StatsEntityType::MediaFile); + assert_deserialization("model_weight", StatsEntityType::ModelWeight); + } + + #[test] + fn variants_count_check() { + assert_eq!(StatsEntityType::iter().count(), 3); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip_json() { + for variant in StatsEntityType::iter() { + let json = serde_json::to_string(&variant).unwrap(); + let back: StatsEntityType = serde_json::from_str(&json).unwrap(); + assert_eq!(variant, back); + } + } + } +} diff --git a/crates/schema/public/enums_api/src/by_table/featured_items/featured_item_entity_type.rs b/crates/schema/public/enums_api/src/by_table/featured_items/featured_item_entity_type.rs new file mode 100644 index 0000000000..577ab531b8 --- /dev/null +++ b/crates/schema/public/enums_api/src/by_table/featured_items/featured_item_entity_type.rs @@ -0,0 +1,62 @@ +use strum::EnumIter; +use utoipa::ToSchema; + +/// Used in the `user_bookmarks` table in a `VARCHAR(32)` field named `entity_type`. +#[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, Deserialize, Serialize, ToSchema, EnumIter, Debug)] + +pub enum FeaturedItemEntityType { + /// MediaFile + #[serde(rename = "media_file")] + MediaFile, + + /// ModelWeight (the new way to store models) + #[serde(rename = "model_weight")] + ModelWeight, + + /// User + #[serde(rename = "user")] + User, +} + +#[cfg(test)] +mod tests { + use super::FeaturedItemEntityType; + use enums_shared::test_helpers::{assert_deserialization, assert_serialization}; + use strum::IntoEnumIterator; + + mod manual_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(FeaturedItemEntityType::MediaFile, "media_file"); + assert_serialization(FeaturedItemEntityType::ModelWeight, "model_weight"); + assert_serialization(FeaturedItemEntityType::User, "user"); + } + + #[test] + fn test_deserialization() { + assert_deserialization("media_file", FeaturedItemEntityType::MediaFile); + assert_deserialization("model_weight", FeaturedItemEntityType::ModelWeight); + assert_deserialization("user", FeaturedItemEntityType::User); + } + + #[test] + fn variants_count_check() { + assert_eq!(FeaturedItemEntityType::iter().count(), 3); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip_json() { + for variant in FeaturedItemEntityType::iter() { + let json = serde_json::to_string(&variant).unwrap(); + let back: FeaturedItemEntityType = serde_json::from_str(&json).unwrap(); + assert_eq!(variant, back); + } + } + } +} diff --git a/crates/schema/public/enums_api/src/by_table/featured_items/mod.rs b/crates/schema/public/enums_api/src/by_table/featured_items/mod.rs new file mode 100644 index 0000000000..61e791bb90 --- /dev/null +++ b/crates/schema/public/enums_api/src/by_table/featured_items/mod.rs @@ -0,0 +1 @@ +pub mod featured_item_entity_type; diff --git a/crates/schema/public/enums_api/src/by_table/generic_download_jobs/generic_download_type.rs b/crates/schema/public/enums_api/src/by_table/generic_download_jobs/generic_download_type.rs new file mode 100644 index 0000000000..f44c420535 --- /dev/null +++ b/crates/schema/public/enums_api/src/by_table/generic_download_jobs/generic_download_type.rs @@ -0,0 +1,107 @@ +use strum::EnumIter; +use utoipa::ToSchema; + +// TODO: Use macro-derived impls + +/// Our "generic downloads" pipeline supports a wide variety of ML models and other media. +/// They are serialized in the database table `generic_download_jobs` as a VARCHAR(32). +/// +/// Each type of download is identified by the following enum variants. +/// These types are present in the HTTP API and database columns as serialized here. +/// +/// DO NOT CHANGE VALUES WITHOUT A MIGRATION STRATEGY. +#[derive(Clone, Copy, Eq, PartialEq, Debug, Deserialize, Serialize, ToSchema, EnumIter, Hash, Ord, PartialOrd)] +pub enum GenericDownloadType { + /// NB: Note - this is hifigan for Tacotron2. + /// Some work will be needed to unify this with other hifigan types. + #[serde(rename = "hifigan")] + HifiGan, + + /// NB: Note - this is hifigan for SoftVC (our internal codename is "rocketvc"). + /// Some work will need to be done to unify this with other hifigan types. + #[serde(rename = "hifigan_rocket_vc")] + HifiGanRocketVc, + + /// NB: Note - this is hifigan for SoVitsSvc + /// Some work will need to be done to unify this with other hifigan types. + #[serde(rename = "hifigan_so_vits_svc")] + HifiGanSoVitsSvc, + + //#[serde(rename = "melgan_vocodes")] + //#[sqlx(rename = "melgan_vocodes")] + //MelGanVocodes, + + /// NB: Our external-facing name for "softvc" is rocketvc. + /// I wish we could stop being stupid about this. + #[serde(rename = "rocket_vc")] + RocketVc, + + /// RVC (v2) voice conversion models + #[serde(rename = "rvc_v2")] + RvcV2, + + /// so-vits-svc voice conversion models + #[serde(rename = "so_vits_svc")] + SoVitsSvc, + + /// Tacotron TTS models. + #[serde(rename = "tacotron2")] + Tacotron2, + + /// VITS TTS models. + #[serde(rename = "vits")] + Vits, +} + +#[cfg(test)] +mod tests { + use super::GenericDownloadType; + use enums_shared::test_helpers::{assert_deserialization, assert_serialization}; + use strum::IntoEnumIterator; + + mod manual_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(GenericDownloadType::HifiGan, "hifigan"); + assert_serialization(GenericDownloadType::HifiGanRocketVc, "hifigan_rocket_vc"); + assert_serialization(GenericDownloadType::HifiGanSoVitsSvc, "hifigan_so_vits_svc"); + assert_serialization(GenericDownloadType::RocketVc, "rocket_vc"); + assert_serialization(GenericDownloadType::RvcV2, "rvc_v2"); + assert_serialization(GenericDownloadType::SoVitsSvc, "so_vits_svc"); + assert_serialization(GenericDownloadType::Tacotron2, "tacotron2"); + assert_serialization(GenericDownloadType::Vits, "vits"); + } + + #[test] + fn test_deserialization() { + assert_deserialization("hifigan", GenericDownloadType::HifiGan); + assert_deserialization("hifigan_rocket_vc", GenericDownloadType::HifiGanRocketVc); + assert_deserialization("hifigan_so_vits_svc", GenericDownloadType::HifiGanSoVitsSvc); + assert_deserialization("rocket_vc", GenericDownloadType::RocketVc); + assert_deserialization("rvc_v2", GenericDownloadType::RvcV2); + assert_deserialization("so_vits_svc", GenericDownloadType::SoVitsSvc); + assert_deserialization("tacotron2", GenericDownloadType::Tacotron2); + assert_deserialization("vits", GenericDownloadType::Vits); + } + + #[test] + fn variants_count_check() { + assert_eq!(GenericDownloadType::iter().count(), 8); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip_json() { + for variant in GenericDownloadType::iter() { + let json = serde_json::to_string(&variant).unwrap(); + let back: GenericDownloadType = serde_json::from_str(&json).unwrap(); + assert_eq!(variant, back); + } + } + } +} diff --git a/crates/schema/public/enums_api/src/by_table/generic_download_jobs/mod.rs b/crates/schema/public/enums_api/src/by_table/generic_download_jobs/mod.rs new file mode 100644 index 0000000000..40d1e08d44 --- /dev/null +++ b/crates/schema/public/enums_api/src/by_table/generic_download_jobs/mod.rs @@ -0,0 +1 @@ +pub mod generic_download_type; diff --git a/crates/schema/public/enums_api/src/by_table/generic_inference_jobs/inference_category.rs b/crates/schema/public/enums_api/src/by_table/generic_inference_jobs/inference_category.rs new file mode 100644 index 0000000000..e032566d09 --- /dev/null +++ b/crates/schema/public/enums_api/src/by_table/generic_inference_jobs/inference_category.rs @@ -0,0 +1,159 @@ +use strum::EnumIter; +use utoipa::ToSchema; + +/// Used in the `generic_inference_jobs` table in `VARCHAR(32)` field `inference_category`. +/// +/// Our "generic inference" pipeline supports a wide variety of ML models and other media. +/// Each "category" of inference is identified by the following enum variants. +/// These types are present in the HTTP API and database columns as serialized here. +/// +/// YOU CAN ADD NEW VALUES, BUT DO NOT CHANGE EXISTING VALUES WITHOUT A MIGRATION STRATEGY. +#[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, Deserialize, Serialize, Default, ToSchema, EnumIter, Debug)] + +pub enum InferenceCategory { + /// Deprecate this field !!! + /// We should drain all jobs from using this database field, then remove it. + #[deprecated(note = "NB(bt,2024-09-05): The frontend still needs this")] + #[serde(rename = "deprecated_field")] + DeprecatedField, + + /// Facial lipsync animation (eg. SadTalker, Wav2Lip, FaceFusion) + #[serde(rename = "lipsync_animation")] + #[default] + LipsyncAnimation, + + /// FakeYou's text to speech (eg. Tacotron2) + #[serde(rename = "text_to_speech")] + TextToSpeech, + + /// FakeYou's voice conversion (eg. svc, rvc) + #[serde(rename = "voice_conversion")] + VoiceConversion, + + /// Image generation (eg. Stable Diffusion 1.5), FAL-powered image generation, etc. + #[serde(rename = "image_generation")] + ImageGeneration, + + /// FAL-powered video generation + /// (Also Seedance2-Pro.com) + #[serde(rename = "video_generation")] + VideoGeneration, + + /// FAL-powered 3D object generation + #[serde(rename = "object_generation")] + ObjectGeneration, + + /// Gaussian Splat generation (eg. World Labs Marble) + #[serde(rename = "splat_generation")] + SplatGeneration, + + /// FAL-powered image background removal + #[serde(rename = "background_removal")] + BackgroundRemoval, + + /// Turn video into animation data with mocap processing (eg. Mocapnet). + #[serde(rename = "mocap")] + Mocap, + + /// ComfyUI workflows + /// This is what powers Storyteller Studio! + #[serde(rename = "workflow")] + Workflow, + + /// FBX to GLTF/GLB. + /// Still supported, but few people will use it. + #[serde(rename = "format_conversion")] + FormatConversion, + + /// Live portrait + #[serde(rename = "live_portrait")] + LivePortrait, + + #[serde(rename="seed_vc")] + SeedVc, + + /// DEPRECATED. Do not use. + /// This was for ReRenderAVideo, which we never productionized. + #[deprecated(note = "This was for ReRenderAVideo, which we never productionized.")] + #[serde(rename = "video_filter")] + VideoFilter, + + /// DEPRECATED. Bevy engine serverside rendering. + #[deprecated(note = "This was for Bevy engine's server side rendering.")] + #[serde(rename = "convert_bvh_to_workflow")] + ConvertBvhToWorkflow, + + #[serde(rename = "f5_tts")] + F5TTS, +} + +#[cfg(test)] +mod tests { + use super::InferenceCategory; + use enums_shared::test_helpers::{assert_deserialization, assert_serialization}; + use strum::IntoEnumIterator; + + mod manual_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(InferenceCategory::DeprecatedField, "deprecated_field"); + assert_serialization(InferenceCategory::LipsyncAnimation, "lipsync_animation"); + assert_serialization(InferenceCategory::TextToSpeech, "text_to_speech"); + assert_serialization(InferenceCategory::VoiceConversion, "voice_conversion"); + assert_serialization(InferenceCategory::ImageGeneration, "image_generation"); + assert_serialization(InferenceCategory::VideoGeneration, "video_generation"); + assert_serialization(InferenceCategory::ObjectGeneration, "object_generation"); + assert_serialization(InferenceCategory::SplatGeneration, "splat_generation"); + assert_serialization(InferenceCategory::BackgroundRemoval, "background_removal"); + assert_serialization(InferenceCategory::Mocap, "mocap"); + assert_serialization(InferenceCategory::Workflow, "workflow"); + assert_serialization(InferenceCategory::FormatConversion, "format_conversion"); + assert_serialization(InferenceCategory::LivePortrait, "live_portrait"); + assert_serialization(InferenceCategory::SeedVc, "seed_vc"); + assert_serialization(InferenceCategory::VideoFilter, "video_filter"); + assert_serialization(InferenceCategory::ConvertBvhToWorkflow, "convert_bvh_to_workflow"); + assert_serialization(InferenceCategory::F5TTS, "f5_tts"); + } + + #[test] + fn test_deserialization() { + assert_deserialization("deprecated_field", InferenceCategory::DeprecatedField); + assert_deserialization("lipsync_animation", InferenceCategory::LipsyncAnimation); + assert_deserialization("text_to_speech", InferenceCategory::TextToSpeech); + assert_deserialization("voice_conversion", InferenceCategory::VoiceConversion); + assert_deserialization("image_generation", InferenceCategory::ImageGeneration); + assert_deserialization("video_generation", InferenceCategory::VideoGeneration); + assert_deserialization("object_generation", InferenceCategory::ObjectGeneration); + assert_deserialization("splat_generation", InferenceCategory::SplatGeneration); + assert_deserialization("background_removal", InferenceCategory::BackgroundRemoval); + assert_deserialization("mocap", InferenceCategory::Mocap); + assert_deserialization("workflow", InferenceCategory::Workflow); + assert_deserialization("format_conversion", InferenceCategory::FormatConversion); + assert_deserialization("live_portrait", InferenceCategory::LivePortrait); + assert_deserialization("seed_vc", InferenceCategory::SeedVc); + assert_deserialization("video_filter", InferenceCategory::VideoFilter); + assert_deserialization("convert_bvh_to_workflow", InferenceCategory::ConvertBvhToWorkflow); + assert_deserialization("f5_tts", InferenceCategory::F5TTS); + } + + #[test] + fn variants_count_check() { + assert_eq!(InferenceCategory::iter().count(), 17); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip_json() { + for variant in InferenceCategory::iter() { + let json = serde_json::to_string(&variant).unwrap(); + let back: InferenceCategory = serde_json::from_str(&json).unwrap(); + assert_eq!(variant, back); + } + } + } +} diff --git a/crates/schema/public/enums_api/src/by_table/generic_inference_jobs/inference_input_source_token_type.rs b/crates/schema/public/enums_api/src/by_table/generic_inference_jobs/inference_input_source_token_type.rs new file mode 100644 index 0000000000..2b077067d9 --- /dev/null +++ b/crates/schema/public/enums_api/src/by_table/generic_inference_jobs/inference_input_source_token_type.rs @@ -0,0 +1,55 @@ +use strum::EnumIter; +use utoipa::ToSchema; + +/// Used in the `generic_inference_jobs` table in `VARCHAR(32)` field `maybe_input_source_token`. +/// +/// YOU CAN ADD NEW VALUES, BUT DO NOT CHANGE EXISTING VALUES WITHOUT A MIGRATION STRATEGY. +#[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, Deserialize, Serialize, ToSchema, EnumIter, Debug)] + +pub enum InferenceInputSourceTokenType { + #[serde(rename = "media_file")] + MediaFile, + #[serde(rename = "media_upload")] + MediaUpload, +} + +#[cfg(test)] +mod tests { + use super::InferenceInputSourceTokenType; + use enums_shared::test_helpers::{assert_deserialization, assert_serialization}; + use strum::IntoEnumIterator; + + mod manual_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(InferenceInputSourceTokenType::MediaFile, "media_file"); + assert_serialization(InferenceInputSourceTokenType::MediaUpload, "media_upload"); + } + + #[test] + fn test_deserialization() { + assert_deserialization("media_file", InferenceInputSourceTokenType::MediaFile); + assert_deserialization("media_upload", InferenceInputSourceTokenType::MediaUpload); + } + + #[test] + fn variants_count_check() { + assert_eq!(InferenceInputSourceTokenType::iter().count(), 2); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip_json() { + for variant in InferenceInputSourceTokenType::iter() { + let json = serde_json::to_string(&variant).unwrap(); + let back: InferenceInputSourceTokenType = serde_json::from_str(&json).unwrap(); + assert_eq!(variant, back); + } + } + } +} diff --git a/crates/schema/public/enums_api/src/by_table/generic_inference_jobs/inference_job_external_third_party.rs b/crates/schema/public/enums_api/src/by_table/generic_inference_jobs/inference_job_external_third_party.rs new file mode 100644 index 0000000000..b004776558 --- /dev/null +++ b/crates/schema/public/enums_api/src/by_table/generic_inference_jobs/inference_job_external_third_party.rs @@ -0,0 +1,66 @@ +use strum::EnumIter; +use utoipa::ToSchema; + +/// Used in the `generic_inference_jobs` table in `VARCHAR(16)` field `maybe_external_third_party`. +/// +/// YOU CAN ADD NEW VALUES, BUT DO NOT CHANGE EXISTING VALUES WITHOUT A MIGRATION STRATEGY. +#[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, Deserialize, Serialize, ToSchema, Default, EnumIter, Debug)] +#[serde(rename_all = "snake_case")] + +pub enum InferenceJobExternalThirdParty { + /// Fal jobs + #[serde(rename = "fal")] + #[default] + Fal, + + /// Seedance 2 Pro jobs + #[serde(rename = "seedance2pro")] + Seedance2Pro, + + /// World Labs jobs + #[serde(rename = "worldlabs")] + Worldlabs, +} + +#[cfg(test)] +mod tests { + use super::InferenceJobExternalThirdParty; + use enums_shared::test_helpers::{assert_deserialization, assert_serialization}; + use strum::IntoEnumIterator; + + mod manual_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(InferenceJobExternalThirdParty::Fal, "fal"); + assert_serialization(InferenceJobExternalThirdParty::Seedance2Pro, "seedance2pro"); + assert_serialization(InferenceJobExternalThirdParty::Worldlabs, "worldlabs"); + } + + #[test] + fn test_deserialization() { + assert_deserialization("fal", InferenceJobExternalThirdParty::Fal); + assert_deserialization("seedance2pro", InferenceJobExternalThirdParty::Seedance2Pro); + assert_deserialization("worldlabs", InferenceJobExternalThirdParty::Worldlabs); + } + + #[test] + fn variants_count_check() { + assert_eq!(InferenceJobExternalThirdParty::iter().count(), 3); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip_json() { + for variant in InferenceJobExternalThirdParty::iter() { + let json = serde_json::to_string(&variant).unwrap(); + let back: InferenceJobExternalThirdParty = serde_json::from_str(&json).unwrap(); + assert_eq!(variant, back); + } + } + } +} diff --git a/crates/schema/public/enums_api/src/by_table/generic_inference_jobs/inference_job_product_category.rs b/crates/schema/public/enums_api/src/by_table/generic_inference_jobs/inference_job_product_category.rs new file mode 100644 index 0000000000..1010662c7d --- /dev/null +++ b/crates/schema/public/enums_api/src/by_table/generic_inference_jobs/inference_job_product_category.rs @@ -0,0 +1,215 @@ +use strum::EnumIter; +use utoipa::ToSchema; + +/// Used in the `generic_inference_jobs` table in `VARCHAR(32)` field `product_category`. +/// +/// This is a user-facing and analytics-facing column that describes what product area the job +/// is attributed to. For example, this will help us separate "video style transfer" from +/// "storyteller studio" and also separate "live portrait" from "webcam live portrait". +/// +/// YOU CAN ADD NEW VALUES, BUT DO NOT CHANGE EXISTING VALUES WITHOUT A MIGRATION STRATEGY. +#[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, Deserialize, Serialize, ToSchema, Default, EnumIter, Debug)] +#[serde(rename_all = "snake_case")] + +pub enum InferenceJobProductCategory { + // =============== DOWNLOAD =============== + + /// Download: GptSoVits + #[default] + DownloadGptSoVits, + + // =============== FAL =============== + + FalImage, + FalVideo, + /// Fal: 3D Object Generation + FalObject, + FalBgRemoval, + + // =============== SEEDANCE 2 PRO =============== + + #[serde(rename = "seedance2pro_video")] + Seedance2ProVideo, + + // =============== WORLD LABS =============== + + /// World Labs: Gaussian Splat Generation + #[serde(rename = "worldlabs_splat")] + WorldlabsSplat, + + // =============== TEXT TO SPEECH =============== + + /// TTS: GptSoVits + TtsGptSoVits, + + /// TTS: F5Tts (Zero Shot) + TtsF5, + + /// TTS: StyleTts2 (Zero Shot) + TtsStyleTts2, + + /// TTS: Tacotron2 + TtsTacotron2, + + // =============== VOICE CONVERSION =============== + + /// Voice Conversion: RVC v2 + VcRvc2, + + /// Voice Conversion: SoVitsSvc + VcSvc, + + VcSeedVc, // Ugh + + // =============== VIDEO =============== + + /// Video: Face Fusion (Lipsync) + VidLipsyncFaceFusion, + + /// Video: Sad Talker (Lipsync) + VidLipsyncSadTalker, + + /// Live Portrait (normal interface) + VidLivePortrait, + + /// Live Portrait (webcam interface) + VidLivePortraitWebcam, + + /// Video: Studio + VidStudio, + + /// Video: Studio Gen 2 + VidStudioGen2, + + /// Video: Style Transfer + VidStyleTransfer, + + // =============== DEPRECATED =============== + + /// Lipsync: Face Fusion + #[deprecated(note = "Use `VidLipsyncFaceFusion` instead")] + LipsyncFaceFusion, + + /// Lipsync: SadTalker + #[deprecated(note = "Use `VidLipsyncSadTalker` instead")] + LipsyncSadTalker, + + /// Live Portrait (normal interface) + #[deprecated(note = "Use `VidLivePortrait` instead")] + LivePortrait, + + /// Live Portrait (webcam interface) + #[deprecated(note = "Use `VidLivePortraitWebcam` instead")] + LivePortraitWebcam, + + /// Stable Diffusion (deprecated) + #[deprecated(note = "unused")] + StableDiffusion, + + /// Storyteller Studio + #[deprecated(note = "Use `VidStudio` instead")] + Studio, + + /// Lipsync: Face Fusion + #[deprecated(note = "Use `VidLipsyncFaceFusion` instead")] + VidFaceFusion, + + /// Video Style Transfer + #[deprecated(note = "Use `VidStyleTransfer` instead")] + Vst, +} + +#[cfg(test)] +mod tests { + use super::InferenceJobProductCategory; + use enums_shared::test_helpers::{assert_deserialization, assert_serialization}; + use strum::IntoEnumIterator; + + mod manual_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(InferenceJobProductCategory::DownloadGptSoVits, "download_gpt_so_vits"); + assert_serialization(InferenceJobProductCategory::FalImage, "fal_image"); + assert_serialization(InferenceJobProductCategory::FalVideo, "fal_video"); + assert_serialization(InferenceJobProductCategory::FalObject, "fal_object"); + assert_serialization(InferenceJobProductCategory::FalBgRemoval, "fal_bg_removal"); + assert_serialization(InferenceJobProductCategory::Seedance2ProVideo, "seedance2pro_video"); + assert_serialization(InferenceJobProductCategory::WorldlabsSplat, "worldlabs_splat"); + assert_serialization(InferenceJobProductCategory::TtsGptSoVits, "tts_gpt_so_vits"); + assert_serialization(InferenceJobProductCategory::TtsF5, "tts_f5"); + assert_serialization(InferenceJobProductCategory::TtsStyleTts2, "tts_style_tts2"); + assert_serialization(InferenceJobProductCategory::TtsTacotron2, "tts_tacotron2"); + assert_serialization(InferenceJobProductCategory::VcRvc2, "vc_rvc2"); + assert_serialization(InferenceJobProductCategory::VcSvc, "vc_svc"); + assert_serialization(InferenceJobProductCategory::VcSeedVc, "vc_seed_vc"); + assert_serialization(InferenceJobProductCategory::VidLipsyncFaceFusion, "vid_lipsync_face_fusion"); + assert_serialization(InferenceJobProductCategory::VidLipsyncSadTalker, "vid_lipsync_sad_talker"); + assert_serialization(InferenceJobProductCategory::VidLivePortrait, "vid_live_portrait"); + assert_serialization(InferenceJobProductCategory::VidLivePortraitWebcam, "vid_live_portrait_webcam"); + assert_serialization(InferenceJobProductCategory::VidStudio, "vid_studio"); + assert_serialization(InferenceJobProductCategory::VidStudioGen2, "vid_studio_gen2"); + assert_serialization(InferenceJobProductCategory::VidStyleTransfer, "vid_style_transfer"); + assert_serialization(InferenceJobProductCategory::LipsyncFaceFusion, "lipsync_face_fusion"); + assert_serialization(InferenceJobProductCategory::LipsyncSadTalker, "lipsync_sad_talker"); + assert_serialization(InferenceJobProductCategory::LivePortrait, "live_portrait"); + assert_serialization(InferenceJobProductCategory::LivePortraitWebcam, "live_portrait_webcam"); + assert_serialization(InferenceJobProductCategory::StableDiffusion, "stable_diffusion"); + assert_serialization(InferenceJobProductCategory::Studio, "studio"); + assert_serialization(InferenceJobProductCategory::VidFaceFusion, "vid_face_fusion"); + assert_serialization(InferenceJobProductCategory::Vst, "vst"); + } + + #[test] + fn test_deserialization() { + assert_deserialization("download_gpt_so_vits", InferenceJobProductCategory::DownloadGptSoVits); + assert_deserialization("fal_image", InferenceJobProductCategory::FalImage); + assert_deserialization("fal_video", InferenceJobProductCategory::FalVideo); + assert_deserialization("fal_object", InferenceJobProductCategory::FalObject); + assert_deserialization("fal_bg_removal", InferenceJobProductCategory::FalBgRemoval); + assert_deserialization("seedance2pro_video", InferenceJobProductCategory::Seedance2ProVideo); + assert_deserialization("worldlabs_splat", InferenceJobProductCategory::WorldlabsSplat); + assert_deserialization("tts_gpt_so_vits", InferenceJobProductCategory::TtsGptSoVits); + assert_deserialization("tts_f5", InferenceJobProductCategory::TtsF5); + assert_deserialization("tts_style_tts2", InferenceJobProductCategory::TtsStyleTts2); + assert_deserialization("tts_tacotron2", InferenceJobProductCategory::TtsTacotron2); + assert_deserialization("vc_rvc2", InferenceJobProductCategory::VcRvc2); + assert_deserialization("vc_svc", InferenceJobProductCategory::VcSvc); + assert_deserialization("vc_seed_vc", InferenceJobProductCategory::VcSeedVc); + assert_deserialization("vid_lipsync_face_fusion", InferenceJobProductCategory::VidLipsyncFaceFusion); + assert_deserialization("vid_lipsync_sad_talker", InferenceJobProductCategory::VidLipsyncSadTalker); + assert_deserialization("vid_live_portrait", InferenceJobProductCategory::VidLivePortrait); + assert_deserialization("vid_live_portrait_webcam", InferenceJobProductCategory::VidLivePortraitWebcam); + assert_deserialization("vid_studio", InferenceJobProductCategory::VidStudio); + assert_deserialization("vid_studio_gen2", InferenceJobProductCategory::VidStudioGen2); + assert_deserialization("vid_style_transfer", InferenceJobProductCategory::VidStyleTransfer); + assert_deserialization("lipsync_face_fusion", InferenceJobProductCategory::LipsyncFaceFusion); + assert_deserialization("lipsync_sad_talker", InferenceJobProductCategory::LipsyncSadTalker); + assert_deserialization("live_portrait", InferenceJobProductCategory::LivePortrait); + assert_deserialization("live_portrait_webcam", InferenceJobProductCategory::LivePortraitWebcam); + assert_deserialization("stable_diffusion", InferenceJobProductCategory::StableDiffusion); + assert_deserialization("studio", InferenceJobProductCategory::Studio); + assert_deserialization("vid_face_fusion", InferenceJobProductCategory::VidFaceFusion); + assert_deserialization("vst", InferenceJobProductCategory::Vst); + } + + #[test] + fn variants_count_check() { + assert_eq!(InferenceJobProductCategory::iter().count(), 29); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip_json() { + for variant in InferenceJobProductCategory::iter() { + let json = serde_json::to_string(&variant).unwrap(); + let back: InferenceJobProductCategory = serde_json::from_str(&json).unwrap(); + assert_eq!(variant, back); + } + } + } +} diff --git a/crates/schema/public/enums_api/src/by_table/generic_inference_jobs/inference_job_type.rs b/crates/schema/public/enums_api/src/by_table/generic_inference_jobs/inference_job_type.rs new file mode 100644 index 0000000000..3d9ae41074 --- /dev/null +++ b/crates/schema/public/enums_api/src/by_table/generic_inference_jobs/inference_job_type.rs @@ -0,0 +1,162 @@ +use strum::EnumIter; +use utoipa::ToSchema; + +/// Report certain jobs publicly as different from what we actually run. +/// This is so we have an edge against the competition that might try to run +/// the same models or workflows. +/// +/// Previously named `PublicInferenceJobType` in the `enums_public` crate. +#[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, Deserialize, Serialize, Default, ToSchema, Debug, EnumIter)] +#[serde(rename_all = "snake_case")] +pub enum InferenceJobType { + // ======= Renamed enum variants ====== + + /// Instead of DB `InferenceJobType::LivePortrait` ("live_portrait") + ActingFace, + + /// Instead of DB `InferenceJobType::FaceFusion` ("face_fusion") + Lipsync, + + /// Storyteller Studio and Video Style Transfer Jobs. + VideoRender, + + GptSovits, + + #[serde(rename = "f5_tts")] + F5TTS, + + // ======= Everything else is the same ======= + + #[serde(rename = "fal_queue")] + FalQueue, + + #[deprecated(note = "Use VideoRender instead.")] + ComfyUi, + + #[serde(rename = "studio_gen2")] + StudioGen2, + + #[serde(rename = "convert_fbx_gltf")] + ConvertFbxToGltf, + + MocapNet, + + #[serde(rename = "rvc_v2")] + RvcV2, + + SadTalker, + + #[serde(rename = "seed_vc")] + SeedVc, + + SoVitsSvc, + + StableDiffusion, + + #[serde(rename = "styletts2")] + StyleTTS2, + + Tacotron2, + + #[default] + Unknown, + + #[deprecated(note = "This was for Bevy engine's server side rendering.")] + #[serde(rename = "bevy_to_workflow")] + BevyToWorkflow, + + #[deprecated(note = "This was for ReRenderAVideo, which we never productionized.")] + RerenderAVideo, + + #[serde(rename = "image_gen_api")] + ImageGenApi, + + #[serde(rename = "seedance2pro_queue")] + Seedance2ProQueue, + + #[serde(rename = "worldlabs_queue")] + WorldlabsQueue, +} + +#[cfg(test)] +mod tests { + use super::InferenceJobType; + use enums_shared::test_helpers::{assert_deserialization, assert_serialization}; + use strum::IntoEnumIterator; + + mod manual_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(InferenceJobType::ActingFace, "acting_face"); + assert_serialization(InferenceJobType::Lipsync, "lipsync"); + assert_serialization(InferenceJobType::VideoRender, "video_render"); + assert_serialization(InferenceJobType::GptSovits, "gpt_sovits"); + assert_serialization(InferenceJobType::F5TTS, "f5_tts"); + assert_serialization(InferenceJobType::FalQueue, "fal_queue"); + assert_serialization(InferenceJobType::ComfyUi, "comfy_ui"); + assert_serialization(InferenceJobType::StudioGen2, "studio_gen2"); + assert_serialization(InferenceJobType::ConvertFbxToGltf, "convert_fbx_gltf"); + assert_serialization(InferenceJobType::MocapNet, "mocap_net"); + assert_serialization(InferenceJobType::RvcV2, "rvc_v2"); + assert_serialization(InferenceJobType::SadTalker, "sad_talker"); + assert_serialization(InferenceJobType::SeedVc, "seed_vc"); + assert_serialization(InferenceJobType::SoVitsSvc, "so_vits_svc"); + assert_serialization(InferenceJobType::StableDiffusion, "stable_diffusion"); + assert_serialization(InferenceJobType::StyleTTS2, "styletts2"); + assert_serialization(InferenceJobType::Tacotron2, "tacotron2"); + assert_serialization(InferenceJobType::Unknown, "unknown"); + assert_serialization(InferenceJobType::BevyToWorkflow, "bevy_to_workflow"); + assert_serialization(InferenceJobType::RerenderAVideo, "rerender_a_video"); + assert_serialization(InferenceJobType::ImageGenApi, "image_gen_api"); + assert_serialization(InferenceJobType::Seedance2ProQueue, "seedance2pro_queue"); + assert_serialization(InferenceJobType::WorldlabsQueue, "worldlabs_queue"); + } + + #[test] + fn test_deserialization() { + assert_deserialization("acting_face", InferenceJobType::ActingFace); + assert_deserialization("lipsync", InferenceJobType::Lipsync); + assert_deserialization("video_render", InferenceJobType::VideoRender); + assert_deserialization("gpt_sovits", InferenceJobType::GptSovits); + assert_deserialization("f5_tts", InferenceJobType::F5TTS); + assert_deserialization("fal_queue", InferenceJobType::FalQueue); + assert_deserialization("comfy_ui", InferenceJobType::ComfyUi); + assert_deserialization("studio_gen2", InferenceJobType::StudioGen2); + assert_deserialization("convert_fbx_gltf", InferenceJobType::ConvertFbxToGltf); + assert_deserialization("mocap_net", InferenceJobType::MocapNet); + assert_deserialization("rvc_v2", InferenceJobType::RvcV2); + assert_deserialization("sad_talker", InferenceJobType::SadTalker); + assert_deserialization("seed_vc", InferenceJobType::SeedVc); + assert_deserialization("so_vits_svc", InferenceJobType::SoVitsSvc); + assert_deserialization("stable_diffusion", InferenceJobType::StableDiffusion); + assert_deserialization("styletts2", InferenceJobType::StyleTTS2); + assert_deserialization("tacotron2", InferenceJobType::Tacotron2); + assert_deserialization("unknown", InferenceJobType::Unknown); + assert_deserialization("bevy_to_workflow", InferenceJobType::BevyToWorkflow); + assert_deserialization("rerender_a_video", InferenceJobType::RerenderAVideo); + assert_deserialization("image_gen_api", InferenceJobType::ImageGenApi); + assert_deserialization("seedance2pro_queue", InferenceJobType::Seedance2ProQueue); + assert_deserialization("worldlabs_queue", InferenceJobType::WorldlabsQueue); + } + + #[test] + fn variants_count_check() { + assert_eq!(InferenceJobType::iter().count(), 23); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip_json() { + for variant in InferenceJobType::iter() { + let json = serde_json::to_string(&variant).unwrap(); + let back: InferenceJobType = serde_json::from_str(&json).unwrap(); + assert_eq!(variant, back); + } + } + } +} diff --git a/crates/schema/public/enums_api/src/by_table/generic_inference_jobs/inference_model_type.rs b/crates/schema/public/enums_api/src/by_table/generic_inference_jobs/inference_model_type.rs new file mode 100644 index 0000000000..3d07113f08 --- /dev/null +++ b/crates/schema/public/enums_api/src/by_table/generic_inference_jobs/inference_model_type.rs @@ -0,0 +1,122 @@ +use strum::EnumIter; +use utoipa::ToSchema; + +/// Used in the `generic_inference_jobs` table in `VARCHAR(32)` field `maybe_model_type`. +/// +/// Our "generic inference" pipeline supports a wide variety of ML models and other media. +/// Each inference "model type" identified by the following enum variants, though some pipelines +/// may use multiple models or no model (and may report NULL). +/// +/// These types are present in the HTTP API and database columns as serialized here. +/// +/// YOU CAN ADD NEW VALUES, BUT DO NOT CHANGE EXISTING VALUES WITHOUT A MIGRATION STRATEGY. +#[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, Deserialize, Serialize, ToSchema, EnumIter, Debug)] + +pub enum InferenceModelType { + // TODO(bt,2024-07-15): This is too generic. We probably need "StorytellerStudio", "LivePortrait", etc. + #[serde(rename = "comfy_ui")] + ComfyUi, + + #[serde(rename = "rvc_v2")] + RvcV2, + // NB: sad_talker does use user-supplied models, so there is no "model token" + #[serde(rename = "sad_talker")] + SadTalker, + #[serde(rename = "so_vits_svc")] + SoVitsSvc, + // TODO: Does this need to be "legacy_tacotron2" ? + + #[serde(rename = "seed_vc")] + SeedVc, + + /// NB: This is for Sora GPT 4o image gen + #[serde(rename = "image_gen_api")] + ImageGenApi, + + #[serde(rename = "tacotron2")] + Tacotron2, + #[serde(rename = "vits")] + Vits, + #[serde(rename = "vall_e_x")] + VallEX, + #[serde(rename = "rerender_a_video")] + RerenderAVideo, + #[serde(rename = "stable_diffusion")] + StableDiffusion, + #[serde(rename = "mocap_net")] + MocapNet, + #[serde(rename = "styletts2")] + StyleTTS2, + /// A job that turns "FBX" game engine files into "GLTF" files (Bevy-compatible). + #[serde(rename = "convert_fbx_gltf")] + ConvertFbxToGltf, + #[serde(rename = "bvh_to_workflow")] + BvhToWorkflow +} + +#[cfg(test)] +mod tests { + use super::InferenceModelType; + use enums_shared::test_helpers::{assert_deserialization, assert_serialization}; + use strum::IntoEnumIterator; + + mod manual_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(InferenceModelType::ComfyUi, "comfy_ui"); + assert_serialization(InferenceModelType::RvcV2, "rvc_v2"); + assert_serialization(InferenceModelType::SadTalker, "sad_talker"); + assert_serialization(InferenceModelType::SoVitsSvc, "so_vits_svc"); + assert_serialization(InferenceModelType::SeedVc, "seed_vc"); + assert_serialization(InferenceModelType::ImageGenApi, "image_gen_api"); + assert_serialization(InferenceModelType::Tacotron2, "tacotron2"); + assert_serialization(InferenceModelType::Vits, "vits"); + assert_serialization(InferenceModelType::VallEX, "vall_e_x"); + assert_serialization(InferenceModelType::RerenderAVideo, "rerender_a_video"); + assert_serialization(InferenceModelType::StableDiffusion, "stable_diffusion"); + assert_serialization(InferenceModelType::MocapNet, "mocap_net"); + assert_serialization(InferenceModelType::StyleTTS2, "styletts2"); + assert_serialization(InferenceModelType::ConvertFbxToGltf, "convert_fbx_gltf"); + assert_serialization(InferenceModelType::BvhToWorkflow, "bvh_to_workflow"); + } + + #[test] + fn test_deserialization() { + assert_deserialization("comfy_ui", InferenceModelType::ComfyUi); + assert_deserialization("rvc_v2", InferenceModelType::RvcV2); + assert_deserialization("sad_talker", InferenceModelType::SadTalker); + assert_deserialization("so_vits_svc", InferenceModelType::SoVitsSvc); + assert_deserialization("seed_vc", InferenceModelType::SeedVc); + assert_deserialization("image_gen_api", InferenceModelType::ImageGenApi); + assert_deserialization("tacotron2", InferenceModelType::Tacotron2); + assert_deserialization("vits", InferenceModelType::Vits); + assert_deserialization("vall_e_x", InferenceModelType::VallEX); + assert_deserialization("rerender_a_video", InferenceModelType::RerenderAVideo); + assert_deserialization("stable_diffusion", InferenceModelType::StableDiffusion); + assert_deserialization("mocap_net", InferenceModelType::MocapNet); + assert_deserialization("styletts2", InferenceModelType::StyleTTS2); + assert_deserialization("convert_fbx_gltf", InferenceModelType::ConvertFbxToGltf); + assert_deserialization("bvh_to_workflow", InferenceModelType::BvhToWorkflow); + } + + #[test] + fn variants_count_check() { + assert_eq!(InferenceModelType::iter().count(), 15); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip_json() { + for variant in InferenceModelType::iter() { + let json = serde_json::to_string(&variant).unwrap(); + let back: InferenceModelType = serde_json::from_str(&json).unwrap(); + assert_eq!(variant, back); + } + } + } +} diff --git a/crates/schema/public/enums_api/src/by_table/generic_inference_jobs/inference_result_type.rs b/crates/schema/public/enums_api/src/by_table/generic_inference_jobs/inference_result_type.rs new file mode 100644 index 0000000000..cf59dffa5e --- /dev/null +++ b/crates/schema/public/enums_api/src/by_table/generic_inference_jobs/inference_result_type.rs @@ -0,0 +1,78 @@ +use strum::EnumIter; +use utoipa::ToSchema; + +/// Used in the `generic_inference_jobs` table in `VARCHAR(32)` field `on_success_result_entity_type`. +/// +/// Our "generic inference" pipeline supports a wide variety of output types. +/// Each "result type" is identified by the following enum variants. +/// +/// These types are present in the HTTP API and database columns as serialized here. +/// +/// YOU CAN ADD NEW VALUES, BUT DO NOT CHANGE EXISTING VALUES WITHOUT A MIGRATION STRATEGY. +#[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, Deserialize, Serialize, ToSchema, EnumIter, Debug)] + +pub enum InferenceResultType { + /// Result is stored in the "media_files" table. + /// (The upstream model could have produced any type of media - image, video, audio. That is irrelevant.) + #[serde(rename = "media_file")] + MediaFile, + + #[serde(rename = "text_to_speech")] + TextToSpeech, + + #[serde(rename = "voice_conversion")] + VoiceConversion, + + #[serde(rename = "zs_voice_embedding")] + ZeroShotVoiceEmbedding, + + #[serde(rename = "upload_model")] + UploadModel +} + +#[cfg(test)] +mod tests { + use super::InferenceResultType; + use enums_shared::test_helpers::{assert_deserialization, assert_serialization}; + use strum::IntoEnumIterator; + + mod manual_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(InferenceResultType::MediaFile, "media_file"); + assert_serialization(InferenceResultType::TextToSpeech, "text_to_speech"); + assert_serialization(InferenceResultType::VoiceConversion, "voice_conversion"); + assert_serialization(InferenceResultType::ZeroShotVoiceEmbedding, "zs_voice_embedding"); + assert_serialization(InferenceResultType::UploadModel, "upload_model"); + } + + #[test] + fn test_deserialization() { + assert_deserialization("media_file", InferenceResultType::MediaFile); + assert_deserialization("text_to_speech", InferenceResultType::TextToSpeech); + assert_deserialization("voice_conversion", InferenceResultType::VoiceConversion); + assert_deserialization("zs_voice_embedding", InferenceResultType::ZeroShotVoiceEmbedding); + assert_deserialization("upload_model", InferenceResultType::UploadModel); + } + + #[test] + fn variants_count_check() { + assert_eq!(InferenceResultType::iter().count(), 5); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip_json() { + for variant in InferenceResultType::iter() { + let json = serde_json::to_string(&variant).unwrap(); + let back: InferenceResultType = serde_json::from_str(&json).unwrap(); + assert_eq!(variant, back); + } + } + } +} diff --git a/crates/schema/public/enums_api/src/by_table/generic_inference_jobs/mod.rs b/crates/schema/public/enums_api/src/by_table/generic_inference_jobs/mod.rs new file mode 100644 index 0000000000..df452ad0c6 --- /dev/null +++ b/crates/schema/public/enums_api/src/by_table/generic_inference_jobs/mod.rs @@ -0,0 +1,7 @@ +pub mod inference_category; +pub mod inference_input_source_token_type; +pub mod inference_job_external_third_party; +pub mod inference_job_product_category; +pub mod inference_job_type; +pub mod inference_model_type; +pub mod inference_result_type; diff --git a/crates/schema/public/enums_api/src/by_table/generic_synthetic_ids/id_category.rs b/crates/schema/public/enums_api/src/by_table/generic_synthetic_ids/id_category.rs new file mode 100644 index 0000000000..5c5126cf85 --- /dev/null +++ b/crates/schema/public/enums_api/src/by_table/generic_synthetic_ids/id_category.rs @@ -0,0 +1,139 @@ +use strum::EnumIter; +use utoipa::ToSchema; + +/// Used in the `generic_synthetic_ids` table in `VARCHAR(32)` field `id_category`. +/// +/// This lets us create synthetic increment IDs on a per-user, per-category basis. +/// +/// DO NOT CHANGE VALUES WITHOUT A MIGRATION STRATEGY. +#[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, Deserialize, Serialize, ToSchema, EnumIter, Debug)] + +pub enum IdCategory { + /// media_files table + #[serde(rename = "media_file")] + MediaFile, + + /// Results from lipsync animations (which may live in the media_files table) + #[serde(rename = "lipsync_animation")] + LipsyncAnimationResult, + + /// Results from face fusion + #[serde(rename = "face_fusion")] + FaceFusionResult, + + /// Results from video filters + #[serde(rename = "video_filter")] + VideoFilterResult, + + /// Results from Live Portrait + #[serde(rename = "live_portrait")] + LivePortraitResult, + + /// Studio Renders + #[serde(rename = "studio_render")] + StudioRender, + + /// Results from mocap + #[serde(rename = "mocap")] + MocapResult, + + /// Results from workflows + #[serde(rename = "workflow")] + WorkflowResult, + + /// Results from tacotron2 + /// Applies for RVC and SVC + #[serde(rename = "tts_result")] + TtsResult, + + /// Results from voice conversion (which may live in the media_files table) + /// Applies for RVC and SVC + #[serde(rename = "voice_conversion")] + VoiceConversionResult, + + /// Results from the zero shot tts (which may live in the media_files table) + #[serde(rename = "zs_tts_result")] + ZeroShotTtsResult, + + /// Zs dataset which lives in the zs_voice_datasets table + #[serde(rename = "zs_dataset")] + ZeroShotVoiceDataset, + + /// Zs voice which lives in the zs_voices table + #[serde(rename = "zs_voice")] + ZeroShotVoiceEmbedding, + + #[serde(rename = "model_weights")] + ModelWeights, + + /// Files that are uploaded with no general product area they belong to. (Eg. local dev testing) + #[serde(rename = "file_upload")] + FileUpload, +} + +#[cfg(test)] +mod tests { + use super::IdCategory; + use enums_shared::test_helpers::{assert_deserialization, assert_serialization}; + use strum::IntoEnumIterator; + + mod manual_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(IdCategory::MediaFile, "media_file"); + assert_serialization(IdCategory::LipsyncAnimationResult, "lipsync_animation"); + assert_serialization(IdCategory::FaceFusionResult, "face_fusion"); + assert_serialization(IdCategory::VideoFilterResult, "video_filter"); + assert_serialization(IdCategory::LivePortraitResult, "live_portrait"); + assert_serialization(IdCategory::StudioRender, "studio_render"); + assert_serialization(IdCategory::MocapResult, "mocap"); + assert_serialization(IdCategory::WorkflowResult, "workflow"); + assert_serialization(IdCategory::TtsResult, "tts_result"); + assert_serialization(IdCategory::VoiceConversionResult, "voice_conversion"); + assert_serialization(IdCategory::ZeroShotTtsResult, "zs_tts_result"); + assert_serialization(IdCategory::ZeroShotVoiceDataset, "zs_dataset"); + assert_serialization(IdCategory::ZeroShotVoiceEmbedding, "zs_voice"); + assert_serialization(IdCategory::ModelWeights, "model_weights"); + assert_serialization(IdCategory::FileUpload, "file_upload"); + } + + #[test] + fn test_deserialization() { + assert_deserialization("media_file", IdCategory::MediaFile); + assert_deserialization("lipsync_animation", IdCategory::LipsyncAnimationResult); + assert_deserialization("face_fusion", IdCategory::FaceFusionResult); + assert_deserialization("video_filter", IdCategory::VideoFilterResult); + assert_deserialization("live_portrait", IdCategory::LivePortraitResult); + assert_deserialization("studio_render", IdCategory::StudioRender); + assert_deserialization("mocap", IdCategory::MocapResult); + assert_deserialization("workflow", IdCategory::WorkflowResult); + assert_deserialization("tts_result", IdCategory::TtsResult); + assert_deserialization("voice_conversion", IdCategory::VoiceConversionResult); + assert_deserialization("zs_tts_result", IdCategory::ZeroShotTtsResult); + assert_deserialization("zs_dataset", IdCategory::ZeroShotVoiceDataset); + assert_deserialization("zs_voice", IdCategory::ZeroShotVoiceEmbedding); + assert_deserialization("model_weights", IdCategory::ModelWeights); + assert_deserialization("file_upload", IdCategory::FileUpload); + } + + #[test] + fn variants_count_check() { + assert_eq!(IdCategory::iter().count(), 15); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip_json() { + for variant in IdCategory::iter() { + let json = serde_json::to_string(&variant).unwrap(); + let back: IdCategory = serde_json::from_str(&json).unwrap(); + assert_eq!(variant, back); + } + } + } +} diff --git a/crates/schema/public/enums_api/src/by_table/generic_synthetic_ids/mod.rs b/crates/schema/public/enums_api/src/by_table/generic_synthetic_ids/mod.rs new file mode 100644 index 0000000000..f130b83c6e --- /dev/null +++ b/crates/schema/public/enums_api/src/by_table/generic_synthetic_ids/mod.rs @@ -0,0 +1 @@ +pub mod id_category; diff --git a/crates/schema/public/enums_api/src/by_table/media_files/media_file_animation_type.rs b/crates/schema/public/enums_api/src/by_table/media_files/media_file_animation_type.rs new file mode 100644 index 0000000000..74c93bff20 --- /dev/null +++ b/crates/schema/public/enums_api/src/by_table/media_files/media_file_animation_type.rs @@ -0,0 +1,125 @@ +use strum::EnumIter; +use utoipa::ToSchema; + +/// Used in the `media_files` table in a `VARCHAR` field. +/// +/// DO NOT CHANGE VALUES WITHOUT A MIGRATION STRATEGY. +#[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, Deserialize, Serialize, ToSchema, EnumIter, Debug)] +#[serde(rename_all = "snake_case")] + +pub enum MediaFileAnimationType { + /// Body: No body animation or rig. + /// Face: Rig supporting ARKit face blendshapes, or ARKit data + ArKit, + + /// Body: Animation or rig for MikuMikuDance (MMD). + /// Face: No face animation. + MikuMikuDance, + + /// Body: Animation or rig for MikuMikuDance (MMD). + /// Face: Animation blendshapes for ARKit. + MikuMikuDanceArKit, + + /// Body: Animation or rig for Mixamo + /// Face: No face animation. + Mixamo, + + /// Body: Animation or rig for Mixamo + /// Face: Animation blendshapes for ARKit. + MixamoArKit, + + /// Body: Animation or rig by MocapNet + /// Face: No face animation. + MocapNet, + + /// Body: Animation or rig for MocapNet + /// Face: Animation blendshapes for ARKit. + MocapNetArKit, + + /// Body: Animation or rig by Move.ai + /// Face: No face animation. + MoveAi, + + /// Body: Animation or rig for Move.ai + /// Face: Animation blendshapes for ARKit. + MoveAiArKit, + + /// Body: Animation or rig for Rigify. + /// Face: No face animation. + Rigify, + + /// Body: Animation or rig for Rigify. + /// Face: Animation blendshapes for ARKit. + RigifyArKit, + + /// Body: Animation or rig for Rokoko. + /// Face: No face animation. + Rokoko, + + /// Body: Animation or rig for Rokoko. + /// Face: Animation blendshapes for ARKit. + RokokoArKit, +} + +#[cfg(test)] +mod tests { + use super::MediaFileAnimationType; + use enums_shared::test_helpers::{assert_deserialization, assert_serialization}; + use strum::IntoEnumIterator; + + mod manual_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(MediaFileAnimationType::ArKit, "ar_kit"); + assert_serialization(MediaFileAnimationType::MikuMikuDance, "miku_miku_dance"); + assert_serialization(MediaFileAnimationType::MikuMikuDanceArKit, "miku_miku_dance_ar_kit"); + assert_serialization(MediaFileAnimationType::Mixamo, "mixamo"); + assert_serialization(MediaFileAnimationType::MixamoArKit, "mixamo_ar_kit"); + assert_serialization(MediaFileAnimationType::MocapNet, "mocap_net"); + assert_serialization(MediaFileAnimationType::MocapNetArKit, "mocap_net_ar_kit"); + assert_serialization(MediaFileAnimationType::MoveAi, "move_ai"); + assert_serialization(MediaFileAnimationType::MoveAiArKit, "move_ai_ar_kit"); + assert_serialization(MediaFileAnimationType::Rigify, "rigify"); + assert_serialization(MediaFileAnimationType::RigifyArKit, "rigify_ar_kit"); + assert_serialization(MediaFileAnimationType::Rokoko, "rokoko"); + assert_serialization(MediaFileAnimationType::RokokoArKit, "rokoko_ar_kit"); + } + + #[test] + fn test_deserialization() { + assert_deserialization("ar_kit", MediaFileAnimationType::ArKit); + assert_deserialization("miku_miku_dance", MediaFileAnimationType::MikuMikuDance); + assert_deserialization("miku_miku_dance_ar_kit", MediaFileAnimationType::MikuMikuDanceArKit); + assert_deserialization("mixamo", MediaFileAnimationType::Mixamo); + assert_deserialization("mixamo_ar_kit", MediaFileAnimationType::MixamoArKit); + assert_deserialization("mocap_net", MediaFileAnimationType::MocapNet); + assert_deserialization("mocap_net_ar_kit", MediaFileAnimationType::MocapNetArKit); + assert_deserialization("move_ai", MediaFileAnimationType::MoveAi); + assert_deserialization("move_ai_ar_kit", MediaFileAnimationType::MoveAiArKit); + assert_deserialization("rigify", MediaFileAnimationType::Rigify); + assert_deserialization("rigify_ar_kit", MediaFileAnimationType::RigifyArKit); + assert_deserialization("rokoko", MediaFileAnimationType::Rokoko); + assert_deserialization("rokoko_ar_kit", MediaFileAnimationType::RokokoArKit); + } + + #[test] + fn variants_count_check() { + assert_eq!(MediaFileAnimationType::iter().count(), 13); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip_json() { + for variant in MediaFileAnimationType::iter() { + let json = serde_json::to_string(&variant).unwrap(); + let back: MediaFileAnimationType = serde_json::from_str(&json).unwrap(); + assert_eq!(variant, back); + } + } + } +} diff --git a/crates/schema/public/enums_api/src/by_table/media_files/media_file_class.rs b/crates/schema/public/enums_api/src/by_table/media_files/media_file_class.rs new file mode 100644 index 0000000000..b2c1b4dee3 --- /dev/null +++ b/crates/schema/public/enums_api/src/by_table/media_files/media_file_class.rs @@ -0,0 +1,73 @@ +use strum::EnumIter; +use utoipa::ToSchema; + +/// Used in the `media_files` table in a `VARCHAR(16)` field. +/// +/// DO NOT CHANGE VALUES WITHOUT A MIGRATION STRATEGY. +#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash, Deserialize, Serialize, ToSchema, EnumIter, Debug)] +#[serde(rename_all = "snake_case")] + +pub enum MediaFileClass { + /// Unknown (default value) + /// This will be present until we migrate all old files. + Unknown, + + /// Audio files: wav, mp3, etc. + Audio, + + /// Image files: png, jpeg, etc. + Image, + + /// Video files: mp4, etc. + Video, + + /// 3D engine data: glb, gltf, etc. + Dimensional, +} + +#[cfg(test)] +mod tests { + use super::MediaFileClass; + use enums_shared::test_helpers::{assert_deserialization, assert_serialization}; + use strum::IntoEnumIterator; + + mod manual_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(MediaFileClass::Unknown, "unknown"); + assert_serialization(MediaFileClass::Audio, "audio"); + assert_serialization(MediaFileClass::Image, "image"); + assert_serialization(MediaFileClass::Video, "video"); + assert_serialization(MediaFileClass::Dimensional, "dimensional"); + } + + #[test] + fn test_deserialization() { + assert_deserialization("unknown", MediaFileClass::Unknown); + assert_deserialization("audio", MediaFileClass::Audio); + assert_deserialization("image", MediaFileClass::Image); + assert_deserialization("video", MediaFileClass::Video); + assert_deserialization("dimensional", MediaFileClass::Dimensional); + } + + #[test] + fn variants_count_check() { + assert_eq!(MediaFileClass::iter().count(), 5); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip_json() { + for variant in MediaFileClass::iter() { + let json = serde_json::to_string(&variant).unwrap(); + let back: MediaFileClass = serde_json::from_str(&json).unwrap(); + assert_eq!(variant, back); + } + } + } +} diff --git a/crates/schema/public/enums_api/src/by_table/media_files/media_file_engine_category.rs b/crates/schema/public/enums_api/src/by_table/media_files/media_file_engine_category.rs new file mode 100644 index 0000000000..c9d9fbc11f --- /dev/null +++ b/crates/schema/public/enums_api/src/by_table/media_files/media_file_engine_category.rs @@ -0,0 +1,109 @@ +use strum::EnumIter; +use utoipa::ToSchema; + +/// Used in the `media_files` table in a `VARCHAR` field. +/// +/// DO NOT CHANGE VALUES WITHOUT A MIGRATION STRATEGY. +#[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, Deserialize, Serialize, ToSchema, EnumIter, Debug)] +#[serde(rename_all = "snake_case")] + +pub enum MediaFileEngineCategory { + /// A 3D scene full of objects, characters, animations, etc. + Scene, + + /// A 3D character model. + Character, + + /// A 3D non-humanoid model, e.g. dragon, wolf, slime creature, etc. + /// These may or may not have a skeleton that can be animated with IK/FK. + Creature, + + /// A 3D skeletal animation sequence that can be applied to a character, + /// creature, etc. Typically, these use Mixamo or Move.ai. + Animation, + + /// A facial blend shape / shape key animation. Currently, these + /// are 100% ARKit. + Expression, + + /// A large 3D object that can be used as a backdrop for a scene, + /// a.k.a. "set", "stage", etc. These are typically self-contained + /// locations, buildings, or environments. + Location, + + /// All items used to add atmosphere to a scene, e.g. furniture, plants, + /// vehicles, radios, and certain props. (We'll reserve the word props for + /// "hand props" later.) + SetDressing, + + /// A 3D object that doesn't fit with the other types. + Object, + + /// A 3D skybox. + Skybox, + + /// An Image Plane (texture that spawns as an object) + ImagePlane, + + /// A Video Plane (texture that spawns as an object) + VideoPlane, +} + +#[cfg(test)] +mod tests { + use super::MediaFileEngineCategory; + use enums_shared::test_helpers::{assert_deserialization, assert_serialization}; + use strum::IntoEnumIterator; + + mod manual_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(MediaFileEngineCategory::Scene, "scene"); + assert_serialization(MediaFileEngineCategory::Character, "character"); + assert_serialization(MediaFileEngineCategory::Creature, "creature"); + assert_serialization(MediaFileEngineCategory::Animation, "animation"); + assert_serialization(MediaFileEngineCategory::Expression, "expression"); + assert_serialization(MediaFileEngineCategory::Location, "location"); + assert_serialization(MediaFileEngineCategory::SetDressing, "set_dressing"); + assert_serialization(MediaFileEngineCategory::Object, "object"); + assert_serialization(MediaFileEngineCategory::Skybox, "skybox"); + assert_serialization(MediaFileEngineCategory::ImagePlane, "image_plane"); + assert_serialization(MediaFileEngineCategory::VideoPlane, "video_plane"); + } + + #[test] + fn test_deserialization() { + assert_deserialization("scene", MediaFileEngineCategory::Scene); + assert_deserialization("character", MediaFileEngineCategory::Character); + assert_deserialization("creature", MediaFileEngineCategory::Creature); + assert_deserialization("animation", MediaFileEngineCategory::Animation); + assert_deserialization("expression", MediaFileEngineCategory::Expression); + assert_deserialization("location", MediaFileEngineCategory::Location); + assert_deserialization("set_dressing", MediaFileEngineCategory::SetDressing); + assert_deserialization("object", MediaFileEngineCategory::Object); + assert_deserialization("skybox", MediaFileEngineCategory::Skybox); + assert_deserialization("image_plane", MediaFileEngineCategory::ImagePlane); + assert_deserialization("video_plane", MediaFileEngineCategory::VideoPlane); + } + + #[test] + fn variants_count_check() { + assert_eq!(MediaFileEngineCategory::iter().count(), 11); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip_json() { + for variant in MediaFileEngineCategory::iter() { + let json = serde_json::to_string(&variant).unwrap(); + let back: MediaFileEngineCategory = serde_json::from_str(&json).unwrap(); + assert_eq!(variant, back); + } + } + } +} diff --git a/crates/schema/public/enums_api/src/by_table/media_files/media_file_origin_category.rs b/crates/schema/public/enums_api/src/by_table/media_files/media_file_origin_category.rs new file mode 100644 index 0000000000..976ee58c52 --- /dev/null +++ b/crates/schema/public/enums_api/src/by_table/media_files/media_file_origin_category.rs @@ -0,0 +1,80 @@ +use strum::EnumIter; +use utoipa::ToSchema; + +/// Used in the `media_files` table in a `VARCHAR` field. +/// +/// DO NOT CHANGE VALUES WITHOUT A MIGRATION STRATEGY. +#[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, Deserialize, Serialize, ToSchema, EnumIter, Debug)] +#[serde(rename_all = "snake_case")] + +pub enum MediaFileOriginCategory { + /// ML model inference output - uploaded models or zero shot. + Inference, + + /// Processed results - (we don't have these systems yet, but eg. trim, transcode, etc). + Processed, + + /// User uploaded files (from their filesystem) + Upload, + + /// User uploaded files recorded directly from their device (browser, mobile), typically using device APIs. + DeviceApi, + + /// From Storyteller Studio Engine + #[deprecated(note="This db field should only denote file provenance, not the product.")] + #[serde(rename = "studio")] + StorytellerStudio, + + /// From Storyteller Studio Engine + #[deprecated(note = "DO NOT USE. Originally deprecated in favor of `StorytellerStudio`.")] + StoryEngine, +} + +#[cfg(test)] +mod tests { + use super::MediaFileOriginCategory; + use enums_shared::test_helpers::{assert_deserialization, assert_serialization}; + use strum::IntoEnumIterator; + + mod manual_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(MediaFileOriginCategory::Inference, "inference"); + assert_serialization(MediaFileOriginCategory::Processed, "processed"); + assert_serialization(MediaFileOriginCategory::Upload, "upload"); + assert_serialization(MediaFileOriginCategory::DeviceApi, "device_api"); + assert_serialization(MediaFileOriginCategory::StorytellerStudio, "studio"); + assert_serialization(MediaFileOriginCategory::StoryEngine, "story_engine"); + } + + #[test] + fn test_deserialization() { + assert_deserialization("inference", MediaFileOriginCategory::Inference); + assert_deserialization("processed", MediaFileOriginCategory::Processed); + assert_deserialization("upload", MediaFileOriginCategory::Upload); + assert_deserialization("device_api", MediaFileOriginCategory::DeviceApi); + assert_deserialization("studio", MediaFileOriginCategory::StorytellerStudio); + assert_deserialization("story_engine", MediaFileOriginCategory::StoryEngine); + } + + #[test] + fn variants_count_check() { + assert_eq!(MediaFileOriginCategory::iter().count(), 6); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip_json() { + for variant in MediaFileOriginCategory::iter() { + let json = serde_json::to_string(&variant).unwrap(); + let back: MediaFileOriginCategory = serde_json::from_str(&json).unwrap(); + assert_eq!(variant, back); + } + } + } +} diff --git a/crates/schema/public/enums_api/src/by_table/media_files/media_file_origin_model_type.rs b/crates/schema/public/enums_api/src/by_table/media_files/media_file_origin_model_type.rs new file mode 100644 index 0000000000..551c4c15b2 --- /dev/null +++ b/crates/schema/public/enums_api/src/by_table/media_files/media_file_origin_model_type.rs @@ -0,0 +1,154 @@ +use serde::Deserialize; +use serde::Serialize; +use strum::EnumIter; +use utoipa::ToSchema; + +/// Report certain models publicly as different from what we actually use. +/// This is so we have an edge against the competition that might try to run +/// the same models. This won't always make sense, but in some cases it will. +/// +/// This was previously named `PublicMediaFileModelType` in the `enums_public` crate. +#[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, Deserialize, Serialize, ToSchema, Debug, EnumIter)] +#[serde(rename_all = "snake_case")] +pub enum MediaFileOriginModelType { + // Renamed enum variants + + /// Instead of DB `MediaFileOriginModelType::LivePortrait` ("live_portrait") + #[serde(rename = "face_mirror")] + FaceMirror, + + /// Instead of DB `MediaFileOriginModelType::SadTalker` ("sad_talker") + #[serde(rename = "face_animator")] + FaceAnimator, + + /// Instead of DB `MediaFileOriginModelType::FaceFusion` ("face_fusion") + #[serde(rename = "lipsync")] + Lipsync, + + /// Instead of DB `MediaFileOriginModelType::StyleTTS2` ("styletts2") + #[serde(rename = "voice_designer")] + VoiceDesigner, + + // Everything else is the same + + /// RVC (v2) voice conversion models + #[serde(rename = "rvc_v2")] + RvcV2, + + /// so-vits-svc voice conversion models + #[serde(rename = "so_vits_svc")] + SoVitsSvc, + + #[serde(rename = "tacotron2")] + Tacotron2, + + #[serde(rename = "mocap_net")] + MocapNet, + + #[serde(rename = "stable_diffusion_1_5")] + StableDiffusion15, + + #[serde(rename = "gpt_sovits")] + GptSovits, + + #[serde(rename = "f5_tts")] + F5TTS, + + #[serde(rename = "seed_vc")] + SeedVc, + + #[serde(rename = "studio")] + StorytellerStudio, + + /// NB: This is GPT4o image generation + #[serde(rename = "studio_ig")] + StorytellerStudioImageGen, + + #[serde(rename = "vst")] + VideoStyleTransfer, + + #[deprecated(note = "This is not a model type!")] + #[serde(rename = "comfy_ui")] + ComfyUi, + + #[deprecated(note = "We don't use this anymore")] + #[serde(rename = "vall_e_x")] + VallEX, + + #[deprecated(note = "We don't use this anymore")] + #[serde(rename = "rerender")] + Rerender, +} + +#[cfg(test)] +mod tests { + use super::MediaFileOriginModelType; + use enums_shared::test_helpers::{assert_deserialization, assert_serialization}; + use strum::IntoEnumIterator; + + mod manual_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(MediaFileOriginModelType::FaceMirror, "face_mirror"); + assert_serialization(MediaFileOriginModelType::FaceAnimator, "face_animator"); + assert_serialization(MediaFileOriginModelType::Lipsync, "lipsync"); + assert_serialization(MediaFileOriginModelType::VoiceDesigner, "voice_designer"); + assert_serialization(MediaFileOriginModelType::RvcV2, "rvc_v2"); + assert_serialization(MediaFileOriginModelType::SoVitsSvc, "so_vits_svc"); + assert_serialization(MediaFileOriginModelType::Tacotron2, "tacotron2"); + assert_serialization(MediaFileOriginModelType::MocapNet, "mocap_net"); + assert_serialization(MediaFileOriginModelType::StableDiffusion15, "stable_diffusion_1_5"); + assert_serialization(MediaFileOriginModelType::GptSovits, "gpt_sovits"); + assert_serialization(MediaFileOriginModelType::F5TTS, "f5_tts"); + assert_serialization(MediaFileOriginModelType::SeedVc, "seed_vc"); + assert_serialization(MediaFileOriginModelType::StorytellerStudio, "studio"); + assert_serialization(MediaFileOriginModelType::StorytellerStudioImageGen, "studio_ig"); + assert_serialization(MediaFileOriginModelType::VideoStyleTransfer, "vst"); + assert_serialization(MediaFileOriginModelType::ComfyUi, "comfy_ui"); + assert_serialization(MediaFileOriginModelType::VallEX, "vall_e_x"); + assert_serialization(MediaFileOriginModelType::Rerender, "rerender"); + } + + #[test] + fn test_deserialization() { + assert_deserialization("face_mirror", MediaFileOriginModelType::FaceMirror); + assert_deserialization("face_animator", MediaFileOriginModelType::FaceAnimator); + assert_deserialization("lipsync", MediaFileOriginModelType::Lipsync); + assert_deserialization("voice_designer", MediaFileOriginModelType::VoiceDesigner); + assert_deserialization("rvc_v2", MediaFileOriginModelType::RvcV2); + assert_deserialization("so_vits_svc", MediaFileOriginModelType::SoVitsSvc); + assert_deserialization("tacotron2", MediaFileOriginModelType::Tacotron2); + assert_deserialization("mocap_net", MediaFileOriginModelType::MocapNet); + assert_deserialization("stable_diffusion_1_5", MediaFileOriginModelType::StableDiffusion15); + assert_deserialization("gpt_sovits", MediaFileOriginModelType::GptSovits); + assert_deserialization("f5_tts", MediaFileOriginModelType::F5TTS); + assert_deserialization("seed_vc", MediaFileOriginModelType::SeedVc); + assert_deserialization("studio", MediaFileOriginModelType::StorytellerStudio); + assert_deserialization("studio_ig", MediaFileOriginModelType::StorytellerStudioImageGen); + assert_deserialization("vst", MediaFileOriginModelType::VideoStyleTransfer); + assert_deserialization("comfy_ui", MediaFileOriginModelType::ComfyUi); + assert_deserialization("vall_e_x", MediaFileOriginModelType::VallEX); + assert_deserialization("rerender", MediaFileOriginModelType::Rerender); + } + + #[test] + fn variants_count_check() { + assert_eq!(MediaFileOriginModelType::iter().count(), 18); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip_json() { + for variant in MediaFileOriginModelType::iter() { + let json = serde_json::to_string(&variant).unwrap(); + let back: MediaFileOriginModelType = serde_json::from_str(&json).unwrap(); + assert_eq!(variant, back); + } + } + } +} diff --git a/crates/schema/public/enums_api/src/by_table/media_files/media_file_origin_product_category.rs b/crates/schema/public/enums_api/src/by_table/media_files/media_file_origin_product_category.rs new file mode 100644 index 0000000000..452fd62047 --- /dev/null +++ b/crates/schema/public/enums_api/src/by_table/media_files/media_file_origin_product_category.rs @@ -0,0 +1,148 @@ +use strum::EnumIter; +use utoipa::ToSchema; + +/// Used in the `media_files` table in `VARCHAR(16)` field `origin_product_category`. +/// +/// This value indicates what product originally created the media file. (Not the ML model or +/// user upload process.) This will let us scope media files to the product that generated them +/// and filter them out of unrelated products if necessary (eg. a user probably doesn't want +/// "Voice Designer" dataset samples in a video generation flow.) +/// +/// DO NOT CHANGE VALUES WITHOUT A MIGRATION STRATEGY. +#[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, Deserialize, Serialize, ToSchema, EnumIter, Debug)] + +pub enum MediaFileOriginProductCategory { + /// Unknown which product is attached to the file (generated the file, the file was + /// uploaded on behalf of, etc.) + #[serde(rename = "unknown")] + Unknown, + + /// Media files created by (or uploaded for) the Face Animator product. + /// The underlying model could be SadTalker, Wav2Lip, or some future model + #[serde(rename = "face_animator")] + FaceAnimator, + + /// Media files created by Face Fusion (lipsync) + #[serde(rename = "face_fusion")] + FaceFusion, + + /// Media files created by Face Mirror (currently powered by Live Portrait) + #[serde(rename = "face_mirror")] + FaceMirror, + + /// Video style transfer + #[serde(rename = "vst")] + VideoStyleTransfer, + + /// Image Studio + #[serde(rename = "image_studio")] + ImageStudio, + + /// Storyteller Studio + #[serde(rename = "studio")] + StorytellerStudio, + + /// Text to speech (Tacotron2, not voice designer / VallE-X) + #[serde(rename = "tts")] + TextToSpeech, + + /// Voice conversion (either RVC or SVC) + #[serde(rename = "voice_conversion")] + VoiceConversion, + + /// Media files created by (or uploaded for) the Zero Shot voice product. + #[serde(rename = "zs_voice")] + ZeroShotVoice, + + // Mocap + #[serde(rename = "mocap")] + Mocap, + + #[serde(rename = "image_gen")] + ImageGeneration, + + #[serde(rename = "video_gen")] + VideoGeneration, + + #[serde(rename = "world_gen")] + WorldGeneration, + + // Media files for video filters + #[deprecated(note = "This isn't relevant product surface area anymore")] + #[serde(rename = "video_filter")] + VideoFilter, + + // Workflow + #[deprecated(note = "Use studio and VST instead.")] + #[serde(rename = "workflow")] + Workflow, +} + +#[cfg(test)] +mod tests { + use super::MediaFileOriginProductCategory; + use enums_shared::test_helpers::{assert_deserialization, assert_serialization}; + use strum::IntoEnumIterator; + + mod manual_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(MediaFileOriginProductCategory::Unknown, "unknown"); + assert_serialization(MediaFileOriginProductCategory::FaceAnimator, "face_animator"); + assert_serialization(MediaFileOriginProductCategory::FaceFusion, "face_fusion"); + assert_serialization(MediaFileOriginProductCategory::FaceMirror, "face_mirror"); + assert_serialization(MediaFileOriginProductCategory::VideoStyleTransfer, "vst"); + assert_serialization(MediaFileOriginProductCategory::ImageStudio, "image_studio"); + assert_serialization(MediaFileOriginProductCategory::StorytellerStudio, "studio"); + assert_serialization(MediaFileOriginProductCategory::TextToSpeech, "tts"); + assert_serialization(MediaFileOriginProductCategory::VoiceConversion, "voice_conversion"); + assert_serialization(MediaFileOriginProductCategory::ZeroShotVoice, "zs_voice"); + assert_serialization(MediaFileOriginProductCategory::Mocap, "mocap"); + assert_serialization(MediaFileOriginProductCategory::ImageGeneration, "image_gen"); + assert_serialization(MediaFileOriginProductCategory::VideoGeneration, "video_gen"); + assert_serialization(MediaFileOriginProductCategory::WorldGeneration, "world_gen"); + assert_serialization(MediaFileOriginProductCategory::VideoFilter, "video_filter"); + assert_serialization(MediaFileOriginProductCategory::Workflow, "workflow"); + } + + #[test] + fn test_deserialization() { + assert_deserialization("unknown", MediaFileOriginProductCategory::Unknown); + assert_deserialization("face_animator", MediaFileOriginProductCategory::FaceAnimator); + assert_deserialization("face_fusion", MediaFileOriginProductCategory::FaceFusion); + assert_deserialization("face_mirror", MediaFileOriginProductCategory::FaceMirror); + assert_deserialization("vst", MediaFileOriginProductCategory::VideoStyleTransfer); + assert_deserialization("image_studio", MediaFileOriginProductCategory::ImageStudio); + assert_deserialization("studio", MediaFileOriginProductCategory::StorytellerStudio); + assert_deserialization("tts", MediaFileOriginProductCategory::TextToSpeech); + assert_deserialization("voice_conversion", MediaFileOriginProductCategory::VoiceConversion); + assert_deserialization("zs_voice", MediaFileOriginProductCategory::ZeroShotVoice); + assert_deserialization("mocap", MediaFileOriginProductCategory::Mocap); + assert_deserialization("image_gen", MediaFileOriginProductCategory::ImageGeneration); + assert_deserialization("video_gen", MediaFileOriginProductCategory::VideoGeneration); + assert_deserialization("world_gen", MediaFileOriginProductCategory::WorldGeneration); + assert_deserialization("video_filter", MediaFileOriginProductCategory::VideoFilter); + assert_deserialization("workflow", MediaFileOriginProductCategory::Workflow); + } + + #[test] + fn variants_count_check() { + assert_eq!(MediaFileOriginProductCategory::iter().count(), 16); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip_json() { + for variant in MediaFileOriginProductCategory::iter() { + let json = serde_json::to_string(&variant).unwrap(); + let back: MediaFileOriginProductCategory = serde_json::from_str(&json).unwrap(); + assert_eq!(variant, back); + } + } + } +} diff --git a/crates/schema/public/enums_api/src/by_table/media_files/media_file_subtype.rs b/crates/schema/public/enums_api/src/by_table/media_files/media_file_subtype.rs new file mode 100644 index 0000000000..bbbae2952b --- /dev/null +++ b/crates/schema/public/enums_api/src/by_table/media_files/media_file_subtype.rs @@ -0,0 +1,114 @@ +use strum::EnumIter; +use utoipa::ToSchema; + +/// Used in the `media_files` table in a `VARCHAR` field. +/// +/// DO NOT CHANGE VALUES WITHOUT A MIGRATION STRATEGY. +#[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, Deserialize, Serialize, ToSchema, EnumIter, Debug)] +#[serde(rename_all = "snake_case")] +#[deprecated(note = "This was primarily for Bevy")] + +pub enum MediaFileSubtype { + /// NB: MediaFileSubtype is deprecated. + /// This should signal that the field / enum is fully deprecated. + Deprecated, + + // TODO(bt,2024-04-22): Deprecated (migrate) + /// Animation file from Mixamo + /// Primarily used for FBX and GLB. + Mixamo, + + // TODO(bt,2024-04-22): Deprecated (migrate) + /// Animation file from MocapNet + /// Primarily used for BVH. + MocapNet, + + // TODO(bt,2024-04-22): Deprecated + /// Generic animation case + /// Used for BVH files, but can also pertain to animation-only files of other types. + AnimationOnly, + + // TODO(bt,2024-04-22): Deprecated + /// Generic 3D scene file. + /// Can pertain to glTF, glB, FBX, etc. + SceneImport, + + // TODO(bt,2024-04-22): Deprecated + /// Native Storyteller scene format. + /// Typically stored in a `.scn.ron` file. + StorytellerScene, + + /// A 3D scene full of objects, characters, animations, etc. + Scene, + + /// A 3D character model. + Character, + + /// A 3D animation. + Animation, + + /// A 3D object that doesn't fit with the other types. + Object, + + /// A 3D skybox. + Skybox, +} + +#[cfg(test)] +mod tests { + use super::MediaFileSubtype; + use enums_shared::test_helpers::{assert_deserialization, assert_serialization}; + use strum::IntoEnumIterator; + + mod manual_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(MediaFileSubtype::Deprecated, "deprecated"); + assert_serialization(MediaFileSubtype::Mixamo, "mixamo"); + assert_serialization(MediaFileSubtype::MocapNet, "mocap_net"); + assert_serialization(MediaFileSubtype::AnimationOnly, "animation_only"); + assert_serialization(MediaFileSubtype::SceneImport, "scene_import"); + assert_serialization(MediaFileSubtype::StorytellerScene, "storyteller_scene"); + assert_serialization(MediaFileSubtype::Scene, "scene"); + assert_serialization(MediaFileSubtype::Character, "character"); + assert_serialization(MediaFileSubtype::Animation, "animation"); + assert_serialization(MediaFileSubtype::Object, "object"); + assert_serialization(MediaFileSubtype::Skybox, "skybox"); + } + + #[test] + fn test_deserialization() { + assert_deserialization("deprecated", MediaFileSubtype::Deprecated); + assert_deserialization("mixamo", MediaFileSubtype::Mixamo); + assert_deserialization("mocap_net", MediaFileSubtype::MocapNet); + assert_deserialization("animation_only", MediaFileSubtype::AnimationOnly); + assert_deserialization("scene_import", MediaFileSubtype::SceneImport); + assert_deserialization("storyteller_scene", MediaFileSubtype::StorytellerScene); + assert_deserialization("scene", MediaFileSubtype::Scene); + assert_deserialization("character", MediaFileSubtype::Character); + assert_deserialization("animation", MediaFileSubtype::Animation); + assert_deserialization("object", MediaFileSubtype::Object); + assert_deserialization("skybox", MediaFileSubtype::Skybox); + } + + #[test] + fn variants_count_check() { + assert_eq!(MediaFileSubtype::iter().count(), 11); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip_json() { + for variant in MediaFileSubtype::iter() { + let json = serde_json::to_string(&variant).unwrap(); + let back: MediaFileSubtype = serde_json::from_str(&json).unwrap(); + assert_eq!(variant, back); + } + } + } +} diff --git a/crates/schema/public/enums_api/src/by_table/media_files/media_file_type.rs b/crates/schema/public/enums_api/src/by_table/media_files/media_file_type.rs new file mode 100644 index 0000000000..3cdbc8140c --- /dev/null +++ b/crates/schema/public/enums_api/src/by_table/media_files/media_file_type.rs @@ -0,0 +1,248 @@ +use strum::EnumIter; +use utoipa::ToSchema; + +/// Used in the `media_files` table in a `VARCHAR(16)` field. +/// +/// DO NOT CHANGE VALUES WITHOUT A MIGRATION STRATEGY. +#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash, Deserialize, Serialize, ToSchema, EnumIter, Debug)] +#[serde(rename_all = "snake_case")] + +pub enum MediaFileType { + // TODO(bt): Deprecate and split into audio mime types; use media_class to represent broadly + /// Audio files: wav, mp3, etc. + #[deprecated] + Audio, + + // TODO(bt): Deprecate and split into image mime types; use media_class to represent broadly + /// Image files: png, jpeg, etc. + #[deprecated] + Image, + + // TODO(bt): Deprecate and split into video mime types; use media_class to represent broadly + /// Video files: mp4, etc. + #[deprecated] + Video, + + /// BVH files (for Bevy) + /// NB: This is the new type to migrate to. + Bvh, + + /// FBX files (for Bevy) + Fbx, + + /// glTF binary files (for Bevy) + Glb, + + /// glTF files (for Bevy) + Gltf, + + /// Spz Gaussian splats + /// This is a standard file format for Gaussian Splats, used by World Labs. + /// The mime type is application/gzip. + Spz, + + /// Bevy's scene files (in RON; Rusty Object Notation) + /// This will be replaced with another format in future versions of Bevy + SceneRon, + + /// Alternate scene files. + SceneJson, + + /// "Polygon Model Data", character data for MikuMikuDance + /// See: https://mikumikudance.fandom.com/wiki/MMD:Polygon_Model_Data + Pmd, + + /// "Vocaloid Motion Data", animation data for MikuMikuDance + /// See: https://mikumikudance.fandom.com/wiki/VMD_file_format + Vmd, + + /// "Polygon Model eXtend", character data from MikuMikuDance + /// NB: this is often associated with external files for textures, which + /// we'll store in the same bucket path. + /// See: https://mikumikudance.fandom.com/wiki/MMD:Polygon_Model_eXtend + Pmx, + + /// CSV format. (We use these for ArKit) + Csv, + + /// Jpeg images + Jpg, + + /// Png images + Png, + + /// Gif images + Gif, + + /// Mp4 videos + Mp4, + + /// Wav audio + Wav, + + /// Mp3 audio + Mp3, +} + +impl MediaFileType { + /// Jpeg and Png are the most widely supported static image formats for AI inference. + /// Webp, Webm, and Gif aren't as widely supported, so we don't include them here. + pub fn is_jpg_or_png(&self) -> bool { + matches!(self, Self::Jpg | Self::Png) + } + + /// A little bit less strict than `is_jpg_or_png`, this includes the legacy `Image` type. + pub fn is_jpg_or_png_or_legacy_image(&self) -> bool { + matches!(self, Self::Jpg | Self::Png | Self::Image) + } + + /// Returns the `MediaFileType` if the mime type matches one of the known types. + /// This is not exhaustive. + pub fn try_from_mime_type(mime_type: &str) -> Option { + match mime_type { + "image/jpeg" => Some(Self::Jpg), + "image/png" => Some(Self::Png), + "video/mp4" => Some(Self::Mp4), + "model/gltf-binary" => Some(Self::Glb), + _ => None, + } + } +} + +#[cfg(test)] +mod tests { + use super::MediaFileType; + use enums_shared::test_helpers::{assert_deserialization, assert_serialization}; + use strum::IntoEnumIterator; + + mod manual_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(MediaFileType::Audio, "audio"); + assert_serialization(MediaFileType::Image, "image"); + assert_serialization(MediaFileType::Video, "video"); + assert_serialization(MediaFileType::Bvh, "bvh"); + assert_serialization(MediaFileType::Fbx, "fbx"); + assert_serialization(MediaFileType::Glb, "glb"); + assert_serialization(MediaFileType::Gltf, "gltf"); + assert_serialization(MediaFileType::Spz, "spz"); + assert_serialization(MediaFileType::SceneRon, "scene_ron"); + assert_serialization(MediaFileType::SceneJson, "scene_json"); + assert_serialization(MediaFileType::Pmd, "pmd"); + assert_serialization(MediaFileType::Vmd, "vmd"); + assert_serialization(MediaFileType::Pmx, "pmx"); + assert_serialization(MediaFileType::Csv, "csv"); + assert_serialization(MediaFileType::Jpg, "jpg"); + assert_serialization(MediaFileType::Png, "png"); + assert_serialization(MediaFileType::Gif, "gif"); + assert_serialization(MediaFileType::Mp4, "mp4"); + assert_serialization(MediaFileType::Wav, "wav"); + assert_serialization(MediaFileType::Mp3, "mp3"); + } + + #[test] + fn test_deserialization() { + assert_deserialization("audio", MediaFileType::Audio); + assert_deserialization("image", MediaFileType::Image); + assert_deserialization("video", MediaFileType::Video); + assert_deserialization("bvh", MediaFileType::Bvh); + assert_deserialization("fbx", MediaFileType::Fbx); + assert_deserialization("glb", MediaFileType::Glb); + assert_deserialization("gltf", MediaFileType::Gltf); + assert_deserialization("spz", MediaFileType::Spz); + assert_deserialization("scene_ron", MediaFileType::SceneRon); + assert_deserialization("scene_json", MediaFileType::SceneJson); + assert_deserialization("pmd", MediaFileType::Pmd); + assert_deserialization("vmd", MediaFileType::Vmd); + assert_deserialization("pmx", MediaFileType::Pmx); + assert_deserialization("csv", MediaFileType::Csv); + assert_deserialization("jpg", MediaFileType::Jpg); + assert_deserialization("png", MediaFileType::Png); + assert_deserialization("gif", MediaFileType::Gif); + assert_deserialization("mp4", MediaFileType::Mp4); + assert_deserialization("wav", MediaFileType::Wav); + assert_deserialization("mp3", MediaFileType::Mp3); + } + + #[test] + fn variants_count_check() { + assert_eq!(MediaFileType::iter().count(), 20); + } + } + + mod test_is_jpg_or_png { + use super::*; + + #[test] + fn true_for_jpg_and_png() { + assert!(MediaFileType::Jpg.is_jpg_or_png()); + assert!(MediaFileType::Png.is_jpg_or_png()); + } + + #[test] + fn false_for_everything_else() { + for variant in MediaFileType::iter() { + if matches!(variant, MediaFileType::Jpg | MediaFileType::Png) { + continue; + } + assert!(!variant.is_jpg_or_png(), "Expected {:?} to be false", variant); + } + } + } + + mod test_is_jpg_or_png_or_legacy_image { + use super::*; + + #[test] + fn true_for_jpg_png_image() { + assert!(MediaFileType::Jpg.is_jpg_or_png_or_legacy_image()); + assert!(MediaFileType::Png.is_jpg_or_png_or_legacy_image()); + assert!(MediaFileType::Image.is_jpg_or_png_or_legacy_image()); + } + + #[test] + fn false_for_everything_else() { + for variant in MediaFileType::iter() { + if matches!(variant, MediaFileType::Jpg | MediaFileType::Png | MediaFileType::Image) { + continue; + } + assert!(!variant.is_jpg_or_png_or_legacy_image(), "Expected {:?} to be false", variant); + } + } + } + + mod test_try_from_mime_type { + use super::*; + + #[test] + fn known_mime_types() { + assert_eq!(MediaFileType::try_from_mime_type("image/jpeg"), Some(MediaFileType::Jpg)); + assert_eq!(MediaFileType::try_from_mime_type("image/png"), Some(MediaFileType::Png)); + assert_eq!(MediaFileType::try_from_mime_type("video/mp4"), Some(MediaFileType::Mp4)); + assert_eq!(MediaFileType::try_from_mime_type("model/gltf-binary"), Some(MediaFileType::Glb)); + } + + #[test] + fn unknown_mime_types_return_none() { + assert_eq!(MediaFileType::try_from_mime_type("audio/wav"), None); + assert_eq!(MediaFileType::try_from_mime_type("image/gif"), None); + assert_eq!(MediaFileType::try_from_mime_type("text/plain"), None); + assert_eq!(MediaFileType::try_from_mime_type(""), None); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip_json() { + for variant in MediaFileType::iter() { + let json = serde_json::to_string(&variant).unwrap(); + let back: MediaFileType = serde_json::from_str(&json).unwrap(); + assert_eq!(variant, back); + } + } + } +} diff --git a/crates/schema/public/enums_api/src/by_table/media_files/mod.rs b/crates/schema/public/enums_api/src/by_table/media_files/mod.rs new file mode 100644 index 0000000000..173082c091 --- /dev/null +++ b/crates/schema/public/enums_api/src/by_table/media_files/mod.rs @@ -0,0 +1,8 @@ +pub mod media_file_animation_type; +pub mod media_file_class; +pub mod media_file_engine_category; +pub mod media_file_origin_category; +pub mod media_file_origin_model_type; +pub mod media_file_origin_product_category; +pub mod media_file_subtype; +pub mod media_file_type; diff --git a/crates/schema/public/enums_api/src/by_table/media_uploads/media_upload_source.rs b/crates/schema/public/enums_api/src/by_table/media_uploads/media_upload_source.rs new file mode 100644 index 0000000000..36a485ad79 --- /dev/null +++ b/crates/schema/public/enums_api/src/by_table/media_uploads/media_upload_source.rs @@ -0,0 +1,64 @@ +use strum::EnumIter; +use utoipa::ToSchema; + +/// Used in the `media_uploads` table in a `VARCHAR` field `media_source`. +/// +/// DO NOT CHANGE VALUES WITHOUT A MIGRATION STRATEGY. +#[derive(Clone, Copy, Eq, PartialEq, Deserialize, Serialize, ToSchema, EnumIter, Debug)] + +pub enum MediaUploadSource { + /// Eg. browser javascript APIs to access the microphone, webcam, etc. + #[serde(rename = "device_api")] + DeviceApi, + + /// Uploaded files from the filesystem + #[serde(rename = "file")] + File, + + /// Unknown sources + #[serde(rename = "unknown")] + Unknown, +} + +#[cfg(test)] +mod tests { + use super::MediaUploadSource; + use enums_shared::test_helpers::{assert_deserialization, assert_serialization}; + use strum::IntoEnumIterator; + + mod manual_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(MediaUploadSource::DeviceApi, "device_api"); + assert_serialization(MediaUploadSource::File, "file"); + assert_serialization(MediaUploadSource::Unknown, "unknown"); + } + + #[test] + fn test_deserialization() { + assert_deserialization("device_api", MediaUploadSource::DeviceApi); + assert_deserialization("file", MediaUploadSource::File); + assert_deserialization("unknown", MediaUploadSource::Unknown); + } + + #[test] + fn variants_count_check() { + assert_eq!(MediaUploadSource::iter().count(), 3); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip_json() { + for variant in MediaUploadSource::iter() { + let json = serde_json::to_string(&variant).unwrap(); + let back: MediaUploadSource = serde_json::from_str(&json).unwrap(); + assert_eq!(variant, back); + } + } + } +} diff --git a/crates/schema/public/enums_api/src/by_table/media_uploads/media_upload_type.rs b/crates/schema/public/enums_api/src/by_table/media_uploads/media_upload_type.rs new file mode 100644 index 0000000000..afda14ab37 --- /dev/null +++ b/crates/schema/public/enums_api/src/by_table/media_uploads/media_upload_type.rs @@ -0,0 +1,67 @@ +use strum::EnumIter; +use utoipa::ToSchema; + +/// Used in the `media_uploads` table in a `VARCHAR` field. +/// +/// DO NOT CHANGE VALUES WITHOUT A MIGRATION STRATEGY. +#[derive(Clone, Copy, Eq, PartialEq, Deserialize, Serialize, ToSchema, EnumIter, Debug)] +#[serde(rename_all = "lowercase")] + +pub enum MediaUploadType { + /// Audio files: wav, mp3, etc. + Audio, + + /// Image files: png, jpeg, etc. + Image, + + /// Video files: mp4, etc. + Video, + + // Binary files: safetensors ... weights, etc. + Binary, +} + +#[cfg(test)] +mod tests { + use super::MediaUploadType; + use enums_shared::test_helpers::{assert_deserialization, assert_serialization}; + use strum::IntoEnumIterator; + + mod manual_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(MediaUploadType::Audio, "audio"); + assert_serialization(MediaUploadType::Image, "image"); + assert_serialization(MediaUploadType::Video, "video"); + assert_serialization(MediaUploadType::Binary, "binary"); + } + + #[test] + fn test_deserialization() { + assert_deserialization("audio", MediaUploadType::Audio); + assert_deserialization("image", MediaUploadType::Image); + assert_deserialization("video", MediaUploadType::Video); + assert_deserialization("binary", MediaUploadType::Binary); + } + + #[test] + fn variants_count_check() { + assert_eq!(MediaUploadType::iter().count(), 4); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip_json() { + for variant in MediaUploadType::iter() { + let json = serde_json::to_string(&variant).unwrap(); + let back: MediaUploadType = serde_json::from_str(&json).unwrap(); + assert_eq!(variant, back); + } + } + } +} diff --git a/crates/schema/public/enums_api/src/by_table/media_uploads/mod.rs b/crates/schema/public/enums_api/src/by_table/media_uploads/mod.rs new file mode 100644 index 0000000000..38dbfbff74 --- /dev/null +++ b/crates/schema/public/enums_api/src/by_table/media_uploads/mod.rs @@ -0,0 +1,2 @@ +pub mod media_upload_source; +pub mod media_upload_type; diff --git a/crates/schema/public/enums_api/src/by_table/mod.rs b/crates/schema/public/enums_api/src/by_table/mod.rs new file mode 100644 index 0000000000..f875036ef4 --- /dev/null +++ b/crates/schema/public/enums_api/src/by_table/mod.rs @@ -0,0 +1,30 @@ +pub mod audit_logs; +pub mod batch_generations; +pub mod beta_keys; +pub mod comments; +pub mod email_sender_jobs; +pub mod entity_stats; +pub mod featured_items; +pub mod generic_download_jobs; +pub mod generic_inference_jobs; +pub mod generic_synthetic_ids; +pub mod media_files; +pub mod media_uploads; +pub mod model_categories; +pub mod model_weights; +pub mod prompt_context_items; +pub mod prompts; +pub mod tag_uses; +pub mod trending_model_analytics; +pub mod tts_models; +pub mod tts_render_tasks; +pub mod usages; +pub mod user_bookmarks; +pub mod user_ratings; +pub mod users; +pub mod voice_conversion_models; +pub mod voice_conversion_results; +pub mod wallet_ledger_entries; +pub mod web_rendition_targets; +pub mod web_scraping_targets; +pub mod zs_voices; diff --git a/crates/schema/public/enums_api/src/by_table/model_categories/mod.rs b/crates/schema/public/enums_api/src/by_table/model_categories/mod.rs new file mode 100644 index 0000000000..3c5df49228 --- /dev/null +++ b/crates/schema/public/enums_api/src/by_table/model_categories/mod.rs @@ -0,0 +1 @@ +pub mod model_type; diff --git a/crates/schema/public/enums_api/src/by_table/model_categories/model_type.rs b/crates/schema/public/enums_api/src/by_table/model_categories/model_type.rs new file mode 100644 index 0000000000..b9d0caecfb --- /dev/null +++ b/crates/schema/public/enums_api/src/by_table/model_categories/model_type.rs @@ -0,0 +1,55 @@ +use strum::EnumIter; +use utoipa::ToSchema; + +/// Used in the `model_categories` table in an `ENUM` field. +/// (*WE WANT TO STOP USING ENUM FIELDS DUE TO MIGRATION ISSUES*) +/// +/// DO NOT CHANGE VALUES WITHOUT A MIGRATION STRATEGY. +#[derive(Clone, Copy, Eq, PartialEq, Hash, Deserialize, Serialize, ToSchema, EnumIter, Debug)] +#[serde(rename_all = "lowercase")] + +pub enum ModelType { + Tts, + W2l, +} + +#[cfg(test)] +mod tests { + use super::ModelType; + use enums_shared::test_helpers::{assert_deserialization, assert_serialization}; + use strum::IntoEnumIterator; + + mod manual_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(ModelType::Tts, "tts"); + assert_serialization(ModelType::W2l, "w2l"); + } + + #[test] + fn test_deserialization() { + assert_deserialization("tts", ModelType::Tts); + assert_deserialization("w2l", ModelType::W2l); + } + + #[test] + fn variants_count_check() { + assert_eq!(ModelType::iter().count(), 2); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip_json() { + for variant in ModelType::iter() { + let json = serde_json::to_string(&variant).unwrap(); + let back: ModelType = serde_json::from_str(&json).unwrap(); + assert_eq!(variant, back); + } + } + } +} diff --git a/crates/schema/public/enums_api/src/by_table/model_weights/mod.rs b/crates/schema/public/enums_api/src/by_table/model_weights/mod.rs new file mode 100644 index 0000000000..e98246b3d0 --- /dev/null +++ b/crates/schema/public/enums_api/src/by_table/model_weights/mod.rs @@ -0,0 +1,3 @@ +pub mod weights_category; +pub mod weights_file_type; +pub mod weights_types; diff --git a/crates/schema/public/enums_api/src/by_table/model_weights/weights_category.rs b/crates/schema/public/enums_api/src/by_table/model_weights/weights_category.rs new file mode 100644 index 0000000000..4a610bc5a0 --- /dev/null +++ b/crates/schema/public/enums_api/src/by_table/model_weights/weights_category.rs @@ -0,0 +1,64 @@ +use strum::EnumIter; +use utoipa::ToSchema; + +#[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, Deserialize, Serialize, ToSchema, EnumIter, Debug)] + +pub enum WeightsCategory { + #[serde(rename = "image_generation")] + ImageGeneration, + #[serde(rename = "text_to_speech")] + TextToSpeech, + #[serde(rename = "vocoder")] + Vocoder, + #[serde(rename = "voice_conversion")] + VoiceConversion, + #[serde(rename = "workflow_config")] + WorkflowConfig, +} + +#[cfg(test)] +mod tests { + use super::WeightsCategory; + use enums_shared::test_helpers::{assert_deserialization, assert_serialization}; + use strum::IntoEnumIterator; + + mod manual_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(WeightsCategory::ImageGeneration, "image_generation"); + assert_serialization(WeightsCategory::TextToSpeech, "text_to_speech"); + assert_serialization(WeightsCategory::Vocoder, "vocoder"); + assert_serialization(WeightsCategory::VoiceConversion, "voice_conversion"); + assert_serialization(WeightsCategory::WorkflowConfig, "workflow_config"); + } + + #[test] + fn test_deserialization() { + assert_deserialization("image_generation", WeightsCategory::ImageGeneration); + assert_deserialization("text_to_speech", WeightsCategory::TextToSpeech); + assert_deserialization("vocoder", WeightsCategory::Vocoder); + assert_deserialization("voice_conversion", WeightsCategory::VoiceConversion); + assert_deserialization("workflow_config", WeightsCategory::WorkflowConfig); + } + + #[test] + fn variants_count_check() { + assert_eq!(WeightsCategory::iter().count(), 5); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip_json() { + for variant in WeightsCategory::iter() { + let json = serde_json::to_string(&variant).unwrap(); + let back: WeightsCategory = serde_json::from_str(&json).unwrap(); + assert_eq!(variant, back); + } + } + } +} diff --git a/crates/schema/public/enums_api/src/by_table/model_weights/weights_file_type.rs b/crates/schema/public/enums_api/src/by_table/model_weights/weights_file_type.rs new file mode 100644 index 0000000000..c1026e67e4 --- /dev/null +++ b/crates/schema/public/enums_api/src/by_table/model_weights/weights_file_type.rs @@ -0,0 +1,53 @@ +use strum::EnumIter; +use utoipa::ToSchema; + +// TODO we will need to scan the checkpoints for malicious code. We can't just trust the file extension. +#[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, Deserialize, Serialize, ToSchema, EnumIter, Debug)] + +pub enum WeightsFileType { + #[serde(rename = "checkpoint")] + Checkpoint, + #[serde(rename = "safetensors")] + SafeTensors, +} + +#[cfg(test)] +mod tests { + use super::WeightsFileType; + use enums_shared::test_helpers::{assert_deserialization, assert_serialization}; + use strum::IntoEnumIterator; + + mod manual_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(WeightsFileType::Checkpoint, "checkpoint"); + assert_serialization(WeightsFileType::SafeTensors, "safetensors"); + } + + #[test] + fn test_deserialization() { + assert_deserialization("checkpoint", WeightsFileType::Checkpoint); + assert_deserialization("safetensors", WeightsFileType::SafeTensors); + } + + #[test] + fn variants_count_check() { + assert_eq!(WeightsFileType::iter().count(), 2); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip_json() { + for variant in WeightsFileType::iter() { + let json = serde_json::to_string(&variant).unwrap(); + let back: WeightsFileType = serde_json::from_str(&json).unwrap(); + assert_eq!(variant, back); + } + } + } +} diff --git a/crates/schema/public/enums_api/src/by_table/model_weights/weights_types.rs b/crates/schema/public/enums_api/src/by_table/model_weights/weights_types.rs new file mode 100644 index 0000000000..fc5f04a4fd --- /dev/null +++ b/crates/schema/public/enums_api/src/by_table/model_weights/weights_types.rs @@ -0,0 +1,93 @@ +use strum::EnumIter; +use utoipa::ToSchema; + +/// Report certain models publicly as different from what we actually use. +/// +/// Previously named `PublicWeightsType` in the `enums_public` crate. +#[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, Deserialize, Serialize, ToSchema, Debug, EnumIter)] + +pub enum WeightsType { + // Renamed enum variants + + /// Instead of DB `WeightsType::GptSoVits` ("gpt_so_vits") + #[serde(rename = "tacotron2.5")] + Tacotron2_5, + + // Everything else is the same + + #[serde(rename = "hifigan_tt2")] + HifiganTacotron2, + #[serde(rename = "rvc_v2")] + RvcV2, + #[serde(rename = "sd_1.5")] + StableDiffusion15, + #[serde(rename = "sdxl")] + StableDiffusionXL, + #[serde(rename = "so_vits_svc")] + SoVitsSvc, + #[serde(rename = "tt2")] + Tacotron2, + #[serde(rename = "loRA")] + LoRA, + #[serde(rename = "vall_e")] + VallE, + #[serde(rename = "comfy_ui")] + ComfyUi, +} + +#[cfg(test)] +mod tests { + use super::WeightsType; + use enums_shared::test_helpers::{assert_deserialization, assert_serialization}; + use strum::IntoEnumIterator; + + mod manual_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(WeightsType::Tacotron2_5, "tacotron2.5"); + assert_serialization(WeightsType::HifiganTacotron2, "hifigan_tt2"); + assert_serialization(WeightsType::RvcV2, "rvc_v2"); + assert_serialization(WeightsType::StableDiffusion15, "sd_1.5"); + assert_serialization(WeightsType::StableDiffusionXL, "sdxl"); + assert_serialization(WeightsType::SoVitsSvc, "so_vits_svc"); + assert_serialization(WeightsType::Tacotron2, "tt2"); + assert_serialization(WeightsType::LoRA, "loRA"); + assert_serialization(WeightsType::VallE, "vall_e"); + assert_serialization(WeightsType::ComfyUi, "comfy_ui"); + } + + #[test] + fn test_deserialization() { + assert_deserialization("tacotron2.5", WeightsType::Tacotron2_5); + assert_deserialization("hifigan_tt2", WeightsType::HifiganTacotron2); + assert_deserialization("rvc_v2", WeightsType::RvcV2); + assert_deserialization("sd_1.5", WeightsType::StableDiffusion15); + assert_deserialization("sdxl", WeightsType::StableDiffusionXL); + assert_deserialization("so_vits_svc", WeightsType::SoVitsSvc); + assert_deserialization("tt2", WeightsType::Tacotron2); + assert_deserialization("loRA", WeightsType::LoRA); + assert_deserialization("vall_e", WeightsType::VallE); + assert_deserialization("comfy_ui", WeightsType::ComfyUi); + } + + #[test] + fn variants_count_check() { + assert_eq!(WeightsType::iter().count(), 10); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip_json() { + for variant in WeightsType::iter() { + let json = serde_json::to_string(&variant).unwrap(); + let back: WeightsType = serde_json::from_str(&json).unwrap(); + assert_eq!(variant, back); + } + } + } +} diff --git a/crates/schema/public/enums_api/src/by_table/prompt_context_items/mod.rs b/crates/schema/public/enums_api/src/by_table/prompt_context_items/mod.rs new file mode 100644 index 0000000000..9a47938052 --- /dev/null +++ b/crates/schema/public/enums_api/src/by_table/prompt_context_items/mod.rs @@ -0,0 +1 @@ +pub mod prompt_context_semantic_type; diff --git a/crates/schema/public/enums_api/src/by_table/prompt_context_items/prompt_context_semantic_type.rs b/crates/schema/public/enums_api/src/by_table/prompt_context_items/prompt_context_semantic_type.rs new file mode 100644 index 0000000000..d98cd1f77c --- /dev/null +++ b/crates/schema/public/enums_api/src/by_table/prompt_context_items/prompt_context_semantic_type.rs @@ -0,0 +1,102 @@ +use strum::EnumIter; +use utoipa::ToSchema; + +/* +Current DB values - this is in conflict with API serializations. Need to fix! +imgref +imgsrc +imgmask +vid_start_frame +vid_end_frame +vidref +*/ + +/// Used in the `prompt_context_items` table in a `VARCHAR(16)` field. +/// +/// DO NOT CHANGE VALUES WITHOUT A MIGRATION STRATEGY. +#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Deserialize, Serialize, ToSchema, EnumIter, Debug)] +#[serde(rename_all = "snake_case")] + +pub enum PromptContextSemanticType { + /// Image-to-Video starting frame + VidStartFrame, + + /// Image-to-Video ending frame + VidEndFrame, + + /// Reference image for video generation (e.g. Seedance "vidref" mode) + VidRef, + + /// Source image, eg. for inpainting. + Imgsrc, + + /// Image mask, eg. for inpainting. + Imgmask, + + /// Standard image reference without a semantic type (e.g. Sora/ChatGPT 4o/gpt-image-1) + Imgref, + + ImgrefCharacter, + ImgrefStyle, + ImgrefBg, + + /// Audio reference (e.g. for audio-to-video generation) + Audioref, +} + +#[cfg(test)] +mod tests { + use super::PromptContextSemanticType; + use enums_shared::test_helpers::{assert_deserialization, assert_serialization}; + use strum::IntoEnumIterator; + + mod manual_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(PromptContextSemanticType::VidStartFrame, "vid_start_frame"); + assert_serialization(PromptContextSemanticType::VidEndFrame, "vid_end_frame"); + assert_serialization(PromptContextSemanticType::VidRef, "vid_ref"); + assert_serialization(PromptContextSemanticType::Imgsrc, "imgsrc"); + assert_serialization(PromptContextSemanticType::Imgmask, "imgmask"); + assert_serialization(PromptContextSemanticType::Imgref, "imgref"); + assert_serialization(PromptContextSemanticType::ImgrefCharacter, "imgref_character"); + assert_serialization(PromptContextSemanticType::ImgrefStyle, "imgref_style"); + assert_serialization(PromptContextSemanticType::ImgrefBg, "imgref_bg"); + assert_serialization(PromptContextSemanticType::Audioref, "audioref"); + } + + #[test] + fn test_deserialization() { + assert_deserialization("vid_start_frame", PromptContextSemanticType::VidStartFrame); + assert_deserialization("vid_end_frame", PromptContextSemanticType::VidEndFrame); + assert_deserialization("vid_ref", PromptContextSemanticType::VidRef); + assert_deserialization("imgsrc", PromptContextSemanticType::Imgsrc); + assert_deserialization("imgmask", PromptContextSemanticType::Imgmask); + assert_deserialization("imgref", PromptContextSemanticType::Imgref); + assert_deserialization("imgref_character", PromptContextSemanticType::ImgrefCharacter); + assert_deserialization("imgref_style", PromptContextSemanticType::ImgrefStyle); + assert_deserialization("imgref_bg", PromptContextSemanticType::ImgrefBg); + assert_deserialization("audioref", PromptContextSemanticType::Audioref); + } + + #[test] + fn variants_count_check() { + assert_eq!(PromptContextSemanticType::iter().count(), 10); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip_json() { + for variant in PromptContextSemanticType::iter() { + let json = serde_json::to_string(&variant).unwrap(); + let back: PromptContextSemanticType = serde_json::from_str(&json).unwrap(); + assert_eq!(variant, back); + } + } + } +} diff --git a/crates/schema/public/enums_api/src/by_table/prompts/mod.rs b/crates/schema/public/enums_api/src/by_table/prompts/mod.rs new file mode 100644 index 0000000000..1dd09b23cd --- /dev/null +++ b/crates/schema/public/enums_api/src/by_table/prompts/mod.rs @@ -0,0 +1 @@ +pub mod prompt_type; diff --git a/crates/schema/public/enums_api/src/by_table/prompts/prompt_type.rs b/crates/schema/public/enums_api/src/by_table/prompts/prompt_type.rs new file mode 100644 index 0000000000..f34a23b182 --- /dev/null +++ b/crates/schema/public/enums_api/src/by_table/prompts/prompt_type.rs @@ -0,0 +1,64 @@ +use strum::EnumIter; +use utoipa::ToSchema; + +/// Used in the `prompts` table in a `VARCHAR(16)` field. +/// +/// DO NOT CHANGE VALUES WITHOUT A MIGRATION STRATEGY. +#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Deserialize, Serialize, ToSchema, EnumIter, Debug)] +#[serde(rename_all = "snake_case")] + +pub enum PromptType { + /// Artcraft (App) + ArtcraftApp, + + /// Stable diffusion + #[deprecated] + StableDiffusion, + + /// Comfy UI + #[deprecated] + ComfyUi, +} + +#[cfg(test)] +mod tests { + use super::PromptType; + use enums_shared::test_helpers::{assert_deserialization, assert_serialization}; + use strum::IntoEnumIterator; + + mod manual_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(PromptType::ArtcraftApp, "artcraft_app"); + assert_serialization(PromptType::StableDiffusion, "stable_diffusion"); + assert_serialization(PromptType::ComfyUi, "comfy_ui"); + } + + #[test] + fn test_deserialization() { + assert_deserialization("artcraft_app", PromptType::ArtcraftApp); + assert_deserialization("stable_diffusion", PromptType::StableDiffusion); + assert_deserialization("comfy_ui", PromptType::ComfyUi); + } + + #[test] + fn variants_count_check() { + assert_eq!(PromptType::iter().count(), 3); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip_json() { + for variant in PromptType::iter() { + let json = serde_json::to_string(&variant).unwrap(); + let back: PromptType = serde_json::from_str(&json).unwrap(); + assert_eq!(variant, back); + } + } + } +} diff --git a/crates/schema/public/enums_api/src/by_table/tag_uses/mod.rs b/crates/schema/public/enums_api/src/by_table/tag_uses/mod.rs new file mode 100644 index 0000000000..08e9530e42 --- /dev/null +++ b/crates/schema/public/enums_api/src/by_table/tag_uses/mod.rs @@ -0,0 +1 @@ +pub mod tag_use_entity_type; diff --git a/crates/schema/public/enums_api/src/by_table/tag_uses/tag_use_entity_type.rs b/crates/schema/public/enums_api/src/by_table/tag_uses/tag_use_entity_type.rs new file mode 100644 index 0000000000..b56cc0f77a --- /dev/null +++ b/crates/schema/public/enums_api/src/by_table/tag_uses/tag_use_entity_type.rs @@ -0,0 +1,56 @@ +use strum::EnumIter; +use utoipa::ToSchema; + +/// Used in the `tag_uses` table in a `VARCHAR(32)` field named `entity_type`. +#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash, Deserialize, Serialize, ToSchema, EnumIter, Debug)] + +pub enum TagUseEntityType { + /// Media files + #[serde(rename = "media_file")] + MediaFile, + + /// Model weights + #[serde(rename = "model_weight")] + ModelWeight, +} + +#[cfg(test)] +mod tests { + use super::TagUseEntityType; + use enums_shared::test_helpers::{assert_deserialization, assert_serialization}; + use strum::IntoEnumIterator; + + mod manual_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(TagUseEntityType::MediaFile, "media_file"); + assert_serialization(TagUseEntityType::ModelWeight, "model_weight"); + } + + #[test] + fn test_deserialization() { + assert_deserialization("media_file", TagUseEntityType::MediaFile); + assert_deserialization("model_weight", TagUseEntityType::ModelWeight); + } + + #[test] + fn variants_count_check() { + assert_eq!(TagUseEntityType::iter().count(), 2); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip_json() { + for variant in TagUseEntityType::iter() { + let json = serde_json::to_string(&variant).unwrap(); + let back: TagUseEntityType = serde_json::from_str(&json).unwrap(); + assert_eq!(variant, back); + } + } + } +} diff --git a/crates/schema/public/enums_api/src/by_table/trending_model_analytics/mod.rs b/crates/schema/public/enums_api/src/by_table/trending_model_analytics/mod.rs new file mode 100644 index 0000000000..b7f654af7e --- /dev/null +++ b/crates/schema/public/enums_api/src/by_table/trending_model_analytics/mod.rs @@ -0,0 +1,2 @@ +pub mod model_type; +pub mod window_name; diff --git a/crates/schema/public/enums_api/src/by_table/trending_model_analytics/model_type.rs b/crates/schema/public/enums_api/src/by_table/trending_model_analytics/model_type.rs new file mode 100644 index 0000000000..af5a6cf800 --- /dev/null +++ b/crates/schema/public/enums_api/src/by_table/trending_model_analytics/model_type.rs @@ -0,0 +1,55 @@ +use strum::EnumIter; +use utoipa::ToSchema; + +/// Used in the `trending_model_analytics` table in a `VARCHAR` field. +/// +/// DO NOT CHANGE VALUES WITHOUT A MIGRATION STRATEGY. +#[derive(Clone, Copy, Eq, PartialEq, Deserialize, Serialize, ToSchema, EnumIter, Debug)] +#[serde(rename_all = "lowercase")] + +pub enum ModelType { + /// TTS models + Tts, + + // NB: It's assumed we'll use this same system to track + // trending VC models too, so the next type would be "VC". +} + +#[cfg(test)] +mod tests { + use super::ModelType; + use enums_shared::test_helpers::{assert_deserialization, assert_serialization}; + use strum::IntoEnumIterator; + + mod manual_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(ModelType::Tts, "tts"); + } + + #[test] + fn test_deserialization() { + assert_deserialization("tts", ModelType::Tts); + } + + #[test] + fn variants_count_check() { + assert_eq!(ModelType::iter().count(), 1); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip_json() { + for variant in ModelType::iter() { + let json = serde_json::to_string(&variant).unwrap(); + let back: ModelType = serde_json::from_str(&json).unwrap(); + assert_eq!(variant, back); + } + } + } +} diff --git a/crates/schema/public/enums_api/src/by_table/trending_model_analytics/window_name.rs b/crates/schema/public/enums_api/src/by_table/trending_model_analytics/window_name.rs new file mode 100644 index 0000000000..a9d6b829a3 --- /dev/null +++ b/crates/schema/public/enums_api/src/by_table/trending_model_analytics/window_name.rs @@ -0,0 +1,66 @@ +use strum::EnumIter; +use utoipa::ToSchema; + +/// Used in the `window_name` table in a `VARCHAR` field. +/// +/// Contrary to most of this crate and unlike most "enum"-types +/// that are inflexible, new window names can be added/removed +/// without breaking too much. +#[derive(Clone, Copy, Eq, PartialEq, Hash, Deserialize, Serialize, ToSchema, EnumIter, Debug)] + +pub enum WindowName { + /// Analytics over the last three hours + #[serde(rename = "last_3_hours")] + Last3Hours, + + /// Analytics over the last three hours + #[serde(rename = "last_3_days")] + Last3Days, + + /// Analytics over all historical records + #[serde(rename = "all_time")] + AllTime, +} + +#[cfg(test)] +mod tests { + use super::WindowName; + use enums_shared::test_helpers::{assert_deserialization, assert_serialization}; + use strum::IntoEnumIterator; + + mod manual_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(WindowName::Last3Hours, "last_3_hours"); + assert_serialization(WindowName::Last3Days, "last_3_days"); + assert_serialization(WindowName::AllTime, "all_time"); + } + + #[test] + fn test_deserialization() { + assert_deserialization("last_3_hours", WindowName::Last3Hours); + assert_deserialization("last_3_days", WindowName::Last3Days); + assert_deserialization("all_time", WindowName::AllTime); + } + + #[test] + fn variants_count_check() { + assert_eq!(WindowName::iter().count(), 3); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip_json() { + for variant in WindowName::iter() { + let json = serde_json::to_string(&variant).unwrap(); + let back: WindowName = serde_json::from_str(&json).unwrap(); + assert_eq!(variant, back); + } + } + } +} diff --git a/crates/schema/public/enums_api/src/by_table/tts_models/mod.rs b/crates/schema/public/enums_api/src/by_table/tts_models/mod.rs new file mode 100644 index 0000000000..f2bd5d5cae --- /dev/null +++ b/crates/schema/public/enums_api/src/by_table/tts_models/mod.rs @@ -0,0 +1 @@ +pub mod tts_model_type; diff --git a/crates/schema/public/enums_api/src/by_table/tts_models/tts_model_type.rs b/crates/schema/public/enums_api/src/by_table/tts_models/tts_model_type.rs new file mode 100644 index 0000000000..9a79674a6c --- /dev/null +++ b/crates/schema/public/enums_api/src/by_table/tts_models/tts_model_type.rs @@ -0,0 +1,57 @@ +use strum::EnumIter; +use utoipa::ToSchema; + +/// Used in the `tts_models` table in an `ENUM` field. +/// -- Furthermore -- not all enum values are represented !! +/// +/// DO NOT CHANGE VALUES WITHOUT A MIGRATION STRATEGY. +#[derive(Clone, Copy, Eq, PartialEq, Deserialize, Serialize, ToSchema, EnumIter, Debug)] + +pub enum TtsModelType { + #[serde(rename = "tacotron2")] + Tacotron2, + + #[serde(rename = "vits")] + Vits, +} + +#[cfg(test)] +mod tests { + use super::TtsModelType; + use enums_shared::test_helpers::{assert_deserialization, assert_serialization}; + use strum::IntoEnumIterator; + + mod manual_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(TtsModelType::Tacotron2, "tacotron2"); + assert_serialization(TtsModelType::Vits, "vits"); + } + + #[test] + fn test_deserialization() { + assert_deserialization("tacotron2", TtsModelType::Tacotron2); + assert_deserialization("vits", TtsModelType::Vits); + } + + #[test] + fn variants_count_check() { + assert_eq!(TtsModelType::iter().count(), 2); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip_json() { + for variant in TtsModelType::iter() { + let json = serde_json::to_string(&variant).unwrap(); + let back: TtsModelType = serde_json::from_str(&json).unwrap(); + assert_eq!(variant, back); + } + } + } +} diff --git a/crates/schema/public/enums_api/src/by_table/tts_render_tasks/mod.rs b/crates/schema/public/enums_api/src/by_table/tts_render_tasks/mod.rs new file mode 100644 index 0000000000..2fd09fffe5 --- /dev/null +++ b/crates/schema/public/enums_api/src/by_table/tts_render_tasks/mod.rs @@ -0,0 +1 @@ +pub mod tts_render_status; diff --git a/crates/schema/public/enums_api/src/by_table/tts_render_tasks/tts_render_status.rs b/crates/schema/public/enums_api/src/by_table/tts_render_tasks/tts_render_status.rs new file mode 100644 index 0000000000..62c110772b --- /dev/null +++ b/crates/schema/public/enums_api/src/by_table/tts_render_tasks/tts_render_status.rs @@ -0,0 +1,75 @@ +use strum::EnumIter; +use utoipa::ToSchema; + +/// Used in the SqLite `tts_render_tasks` table in a `TEXT` field named `tts_render_status`. +#[derive(Clone, Copy, Eq, PartialEq, Hash, Deserialize, Serialize, ToSchema, EnumIter, Debug)] + +pub enum TtsRenderStatus { + #[serde(rename = "new")] + New, + + // TODO: Added to fix a big. This whole enum should die. + #[serde(rename = "processing")] + Processing, + + #[serde(rename = "skipped")] + Skipped, + + #[serde(rename = "failed")] + Failed, + + #[serde(rename = "permanently_failed")] + PermanentlyFailed, + + #[serde(rename = "success")] + Success, +} + +#[cfg(test)] +mod tests { + use super::TtsRenderStatus; + use enums_shared::test_helpers::{assert_deserialization, assert_serialization}; + use strum::IntoEnumIterator; + + mod manual_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(TtsRenderStatus::New, "new"); + assert_serialization(TtsRenderStatus::Processing, "processing"); + assert_serialization(TtsRenderStatus::Skipped, "skipped"); + assert_serialization(TtsRenderStatus::Failed, "failed"); + assert_serialization(TtsRenderStatus::PermanentlyFailed, "permanently_failed"); + assert_serialization(TtsRenderStatus::Success, "success"); + } + + #[test] + fn test_deserialization() { + assert_deserialization("new", TtsRenderStatus::New); + assert_deserialization("processing", TtsRenderStatus::Processing); + assert_deserialization("skipped", TtsRenderStatus::Skipped); + assert_deserialization("failed", TtsRenderStatus::Failed); + assert_deserialization("permanently_failed", TtsRenderStatus::PermanentlyFailed); + assert_deserialization("success", TtsRenderStatus::Success); + } + + #[test] + fn variants_count_check() { + assert_eq!(TtsRenderStatus::iter().count(), 6); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip_json() { + for variant in TtsRenderStatus::iter() { + let json = serde_json::to_string(&variant).unwrap(); + let back: TtsRenderStatus = serde_json::from_str(&json).unwrap(); + assert_eq!(variant, back); + } + } + } +} diff --git a/crates/schema/public/enums_api/src/by_table/usages/mod.rs b/crates/schema/public/enums_api/src/by_table/usages/mod.rs new file mode 100644 index 0000000000..cd5a40cf1b --- /dev/null +++ b/crates/schema/public/enums_api/src/by_table/usages/mod.rs @@ -0,0 +1 @@ +pub mod usages_type; diff --git a/crates/schema/public/enums_api/src/by_table/usages/usages_type.rs b/crates/schema/public/enums_api/src/by_table/usages/usages_type.rs new file mode 100644 index 0000000000..c5cbdfa443 --- /dev/null +++ b/crates/schema/public/enums_api/src/by_table/usages/usages_type.rs @@ -0,0 +1,57 @@ +use strum::EnumIter; +use utoipa::ToSchema; + +/// Used in the `usages` table in a `VARCHAR(16)` field. (Two fields!) +/// +/// DO NOT CHANGE VALUES WITHOUT A MIGRATION STRATEGY. +#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Deserialize, Serialize, ToSchema, EnumIter, Debug)] +#[serde(rename_all = "snake_case")] + +pub enum UsagesType { + /// Represents a foreign key link against a model_weights record + ModelWeight, + + /// Represents a foreign key link against a media_files record + MediaFile, +} + +#[cfg(test)] +mod tests { + use super::UsagesType; + use enums_shared::test_helpers::{assert_deserialization, assert_serialization}; + use strum::IntoEnumIterator; + + mod manual_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(UsagesType::ModelWeight, "model_weight"); + assert_serialization(UsagesType::MediaFile, "media_file"); + } + + #[test] + fn test_deserialization() { + assert_deserialization("model_weight", UsagesType::ModelWeight); + assert_deserialization("media_file", UsagesType::MediaFile); + } + + #[test] + fn variants_count_check() { + assert_eq!(UsagesType::iter().count(), 2); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip_json() { + for variant in UsagesType::iter() { + let json = serde_json::to_string(&variant).unwrap(); + let back: UsagesType = serde_json::from_str(&json).unwrap(); + assert_eq!(variant, back); + } + } + } +} diff --git a/crates/schema/public/enums_api/src/by_table/user_bookmarks/mod.rs b/crates/schema/public/enums_api/src/by_table/user_bookmarks/mod.rs new file mode 100644 index 0000000000..49689232da --- /dev/null +++ b/crates/schema/public/enums_api/src/by_table/user_bookmarks/mod.rs @@ -0,0 +1 @@ +pub mod user_bookmark_entity_type; diff --git a/crates/schema/public/enums_api/src/by_table/user_bookmarks/user_bookmark_entity_type.rs b/crates/schema/public/enums_api/src/by_table/user_bookmarks/user_bookmark_entity_type.rs new file mode 100644 index 0000000000..763f24c7cf --- /dev/null +++ b/crates/schema/public/enums_api/src/by_table/user_bookmarks/user_bookmark_entity_type.rs @@ -0,0 +1,98 @@ +use strum::EnumIter; +use utoipa::ToSchema; + +/// Used in the `user_bookmarks` table in a `VARCHAR(32)` field named `entity_type`. +#[derive(Clone, Copy, Eq, PartialEq, Hash, Deserialize, Serialize, ToSchema, EnumIter, Debug)] + +pub enum UserBookmarkEntityType { + /// User + #[serde(rename = "user")] + User, + + /// TTS model (architecture does not matter) + #[serde(rename = "tts_model")] + TtsModel, + + /// TTS result (architecture does not matter) + #[serde(rename = "tts_result")] + TtsResult, + + /// W2L template + #[serde(rename = "w2l_template")] + W2lTemplate, + + /// W2L result + #[serde(rename = "w2l_result")] + W2lResult, + + /// MediaFile + #[serde(rename = "media_file")] + MediaFile, + + /// ModelWeight (the new way to store models) + #[serde(rename = "model_weight")] + ModelWeight, + + /// VoiceConversionModel + #[serde(rename = "voice_conversion_model")] + VoiceConversionModel, + + /// ZsVoice + #[serde(rename = "zs_voice")] + ZsVoice, +} + +#[cfg(test)] +mod tests { + use super::UserBookmarkEntityType; + use enums_shared::test_helpers::{assert_deserialization, assert_serialization}; + use strum::IntoEnumIterator; + + mod manual_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(UserBookmarkEntityType::User, "user"); + assert_serialization(UserBookmarkEntityType::TtsModel, "tts_model"); + assert_serialization(UserBookmarkEntityType::TtsResult, "tts_result"); + assert_serialization(UserBookmarkEntityType::W2lTemplate, "w2l_template"); + assert_serialization(UserBookmarkEntityType::W2lResult, "w2l_result"); + assert_serialization(UserBookmarkEntityType::MediaFile, "media_file"); + assert_serialization(UserBookmarkEntityType::ModelWeight, "model_weight"); + assert_serialization(UserBookmarkEntityType::VoiceConversionModel, "voice_conversion_model"); + assert_serialization(UserBookmarkEntityType::ZsVoice, "zs_voice"); + } + + #[test] + fn test_deserialization() { + assert_deserialization("user", UserBookmarkEntityType::User); + assert_deserialization("tts_model", UserBookmarkEntityType::TtsModel); + assert_deserialization("tts_result", UserBookmarkEntityType::TtsResult); + assert_deserialization("w2l_template", UserBookmarkEntityType::W2lTemplate); + assert_deserialization("w2l_result", UserBookmarkEntityType::W2lResult); + assert_deserialization("media_file", UserBookmarkEntityType::MediaFile); + assert_deserialization("model_weight", UserBookmarkEntityType::ModelWeight); + assert_deserialization("voice_conversion_model", UserBookmarkEntityType::VoiceConversionModel); + assert_deserialization("zs_voice", UserBookmarkEntityType::ZsVoice); + } + + #[test] + fn variants_count_check() { + assert_eq!(UserBookmarkEntityType::iter().count(), 9); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip_json() { + for variant in UserBookmarkEntityType::iter() { + let json = serde_json::to_string(&variant).unwrap(); + let back: UserBookmarkEntityType = serde_json::from_str(&json).unwrap(); + assert_eq!(variant, back); + } + } + } +} diff --git a/crates/schema/public/enums_api/src/by_table/user_ratings/entity_type.rs b/crates/schema/public/enums_api/src/by_table/user_ratings/entity_type.rs new file mode 100644 index 0000000000..19f3500a06 --- /dev/null +++ b/crates/schema/public/enums_api/src/by_table/user_ratings/entity_type.rs @@ -0,0 +1,80 @@ +use strum::EnumIter; +use utoipa::ToSchema; + +/// Used in the `user_ratings` table in a `VARCHAR(32)` field named `entity_type`. +#[derive(Clone, Copy, Eq, PartialEq, Hash, Deserialize, Serialize, ToSchema, EnumIter, Debug)] + +pub enum UserRatingEntityType { + /// Media files (inference results, uploads, etc.) + #[serde(rename = "media_file")] + MediaFile, + + /// Model weights (modern, polymorphic, type agnostic) + #[serde(rename = "model_weight")] + ModelWeight, + + /// TTS model (architecture does not matter) + #[serde(rename = "tts_model")] + TtsModel, + + /// TTS result (architecture does not matter) + #[serde(rename = "tts_result")] + TtsResult, + + /// W2L template + #[serde(rename = "w2l_template")] + W2lTemplate, + + /// W2L result + #[serde(rename = "w2l_result")] + W2lResult, +} + +#[cfg(test)] +mod tests { + use super::UserRatingEntityType; + use enums_shared::test_helpers::{assert_deserialization, assert_serialization}; + use strum::IntoEnumIterator; + + mod manual_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(UserRatingEntityType::MediaFile, "media_file"); + assert_serialization(UserRatingEntityType::ModelWeight, "model_weight"); + assert_serialization(UserRatingEntityType::TtsModel, "tts_model"); + assert_serialization(UserRatingEntityType::TtsResult, "tts_result"); + assert_serialization(UserRatingEntityType::W2lTemplate, "w2l_template"); + assert_serialization(UserRatingEntityType::W2lResult, "w2l_result"); + } + + #[test] + fn test_deserialization() { + assert_deserialization("media_file", UserRatingEntityType::MediaFile); + assert_deserialization("model_weight", UserRatingEntityType::ModelWeight); + assert_deserialization("tts_model", UserRatingEntityType::TtsModel); + assert_deserialization("tts_result", UserRatingEntityType::TtsResult); + assert_deserialization("w2l_template", UserRatingEntityType::W2lTemplate); + assert_deserialization("w2l_result", UserRatingEntityType::W2lResult); + } + + #[test] + fn variants_count_check() { + assert_eq!(UserRatingEntityType::iter().count(), 6); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip_json() { + for variant in UserRatingEntityType::iter() { + let json = serde_json::to_string(&variant).unwrap(); + let back: UserRatingEntityType = serde_json::from_str(&json).unwrap(); + assert_eq!(variant, back); + } + } + } +} diff --git a/crates/schema/public/enums_api/src/by_table/user_ratings/mod.rs b/crates/schema/public/enums_api/src/by_table/user_ratings/mod.rs new file mode 100644 index 0000000000..cd3855acfb --- /dev/null +++ b/crates/schema/public/enums_api/src/by_table/user_ratings/mod.rs @@ -0,0 +1,2 @@ +pub mod entity_type; +pub mod rating_value; diff --git a/crates/schema/public/enums_api/src/by_table/user_ratings/rating_value.rs b/crates/schema/public/enums_api/src/by_table/user_ratings/rating_value.rs new file mode 100644 index 0000000000..76eb194f80 --- /dev/null +++ b/crates/schema/public/enums_api/src/by_table/user_ratings/rating_value.rs @@ -0,0 +1,72 @@ +use strum::EnumIter; +use utoipa::ToSchema; + +/// UserRatingValue +/// +/// - Used in the `user_ratings` table as an `ENUM` field named `rating_type`. +/// - Used in the HTTP API. +/// +/// To use this in a query, the query must have type annotations. +/// See: https://www.gitmemory.com/issue/launchbadge/sqlx/1241/847154375 +/// eg. preferred_tts_result_visibility as `rating_type: enums::by_table::user_ratings::rating_type::UserRatingValue` +/// +/// See also: https://docs.rs/sqlx/0.4.0-beta.1/sqlx/trait.Type.html +/// +/// *DO NOT CHANGE VALUES WITHOUT A MIGRATION STRATEGY!* +/// +#[derive(Clone, Copy, Eq, PartialEq, Deserialize, Serialize, ToSchema, EnumIter, Debug)] +#[serde(rename_all = "lowercase")] + +pub enum UserRatingValue { + /// This is considered a ratings "soft deletion" and does not count towards a total score. + /// This is the default rating. + Neutral, + /// This is a positive vote / upvote / like. + /// They are available to non-logged-in users as long as they have the URL. + Positive, + /// This is a negative vote / downvote / dislike. + Negative, +} + +#[cfg(test)] +mod tests { + use super::UserRatingValue; + use enums_shared::test_helpers::{assert_deserialization, assert_serialization}; + use strum::IntoEnumIterator; + + mod manual_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(UserRatingValue::Neutral, "neutral"); + assert_serialization(UserRatingValue::Positive, "positive"); + assert_serialization(UserRatingValue::Negative, "negative"); + } + + #[test] + fn test_deserialization() { + assert_deserialization("neutral", UserRatingValue::Neutral); + assert_deserialization("positive", UserRatingValue::Positive); + assert_deserialization("negative", UserRatingValue::Negative); + } + + #[test] + fn variants_count_check() { + assert_eq!(UserRatingValue::iter().count(), 3); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip_json() { + for variant in UserRatingValue::iter() { + let json = serde_json::to_string(&variant).unwrap(); + let back: UserRatingValue = serde_json::from_str(&json).unwrap(); + assert_eq!(variant, back); + } + } + } +} diff --git a/crates/schema/public/enums_api/src/by_table/users/mod.rs b/crates/schema/public/enums_api/src/by_table/users/mod.rs new file mode 100644 index 0000000000..e4f4741f1b --- /dev/null +++ b/crates/schema/public/enums_api/src/by_table/users/mod.rs @@ -0,0 +1,3 @@ +pub mod user_feature_flag; +pub mod user_signup_method; +pub mod user_signup_source; diff --git a/crates/schema/public/enums_api/src/by_table/users/user_feature_flag.rs b/crates/schema/public/enums_api/src/by_table/users/user_feature_flag.rs new file mode 100644 index 0000000000..aba2ea3a0f --- /dev/null +++ b/crates/schema/public/enums_api/src/by_table/users/user_feature_flag.rs @@ -0,0 +1,69 @@ +use strum::EnumIter; +use utoipa::ToSchema; + +/// Used in the `users` table in a `VARCHAR` field (stored as comma separated set). +/// +/// DO NOT CHANGE VALUES WITHOUT A MIGRATION STRATEGY. +#[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, Deserialize, Serialize, ToSchema, EnumIter, Debug)] +#[serde(rename_all = "snake_case")] + +pub enum UserFeatureFlag { + /// Grants a user the ability to list media + /// (For now, it's hidden until we get an NSFW filter.) + ExploreMedia, + + /// Access to studio features + Studio, + + /// Whether users are allowed to upload 3D models + #[serde(rename = "upload_3d")] + Upload3d, + + /// Access to video style transfer + VideoStyleTransfer, +} + +#[cfg(test)] +mod tests { + use super::UserFeatureFlag; + use enums_shared::test_helpers::{assert_deserialization, assert_serialization}; + use strum::IntoEnumIterator; + + mod manual_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(UserFeatureFlag::ExploreMedia, "explore_media"); + assert_serialization(UserFeatureFlag::Studio, "studio"); + assert_serialization(UserFeatureFlag::Upload3d, "upload_3d"); + assert_serialization(UserFeatureFlag::VideoStyleTransfer, "video_style_transfer"); + } + + #[test] + fn test_deserialization() { + assert_deserialization("explore_media", UserFeatureFlag::ExploreMedia); + assert_deserialization("studio", UserFeatureFlag::Studio); + assert_deserialization("upload_3d", UserFeatureFlag::Upload3d); + assert_deserialization("video_style_transfer", UserFeatureFlag::VideoStyleTransfer); + } + + #[test] + fn variants_count_check() { + assert_eq!(UserFeatureFlag::iter().count(), 4); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip_json() { + for variant in UserFeatureFlag::iter() { + let json = serde_json::to_string(&variant).unwrap(); + let back: UserFeatureFlag = serde_json::from_str(&json).unwrap(); + assert_eq!(variant, back); + } + } + } +} diff --git a/crates/schema/public/enums_api/src/by_table/users/user_signup_method.rs b/crates/schema/public/enums_api/src/by_table/users/user_signup_method.rs new file mode 100644 index 0000000000..00ba123b0e --- /dev/null +++ b/crates/schema/public/enums_api/src/by_table/users/user_signup_method.rs @@ -0,0 +1,64 @@ +use strum::EnumIter; +use utoipa::ToSchema; + +/// Used in the `users` table in a `VARCHAR(16)` field. +/// +/// DO NOT CHANGE VALUES WITHOUT A MIGRATION STRATEGY. +#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Deserialize, Serialize, ToSchema, EnumIter, Debug)] +#[serde(rename_all = "snake_case")] + +pub enum UserSignupMethod { + /// Email + Password + EmailPassword, + + /// "Sign in With Google" SSO + GoogleSignIn, + + /// Stripe Checkout flow, where we provision user accounts for users with a + /// synthetic/fake email address and no password. After checkout completes, + /// the user gets a real email and password - or the user can set them. + StripeCheckout, +} + +#[cfg(test)] +mod tests { + use super::UserSignupMethod; + use enums_shared::test_helpers::{assert_deserialization, assert_serialization}; + use strum::IntoEnumIterator; + + mod manual_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(UserSignupMethod::EmailPassword, "email_password"); + assert_serialization(UserSignupMethod::GoogleSignIn, "google_sign_in"); + assert_serialization(UserSignupMethod::StripeCheckout, "stripe_checkout"); + } + + #[test] + fn test_deserialization() { + assert_deserialization("email_password", UserSignupMethod::EmailPassword); + assert_deserialization("google_sign_in", UserSignupMethod::GoogleSignIn); + assert_deserialization("stripe_checkout", UserSignupMethod::StripeCheckout); + } + + #[test] + fn variants_count_check() { + assert_eq!(UserSignupMethod::iter().count(), 3); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip_json() { + for variant in UserSignupMethod::iter() { + let json = serde_json::to_string(&variant).unwrap(); + let back: UserSignupMethod = serde_json::from_str(&json).unwrap(); + assert_eq!(variant, back); + } + } + } +} diff --git a/crates/schema/public/enums_api/src/by_table/users/user_signup_source.rs b/crates/schema/public/enums_api/src/by_table/users/user_signup_source.rs new file mode 100644 index 0000000000..df4542020d --- /dev/null +++ b/crates/schema/public/enums_api/src/by_table/users/user_signup_source.rs @@ -0,0 +1,93 @@ +use strum::EnumIter; +use utoipa::ToSchema; + +/// Used in the `users` table in a `VARCHAR(255)` (which should be a `VARCHAR(16)`) field, `maybe_source`. +/// +/// DO NOT CHANGE VALUES WITHOUT A MIGRATION STRATEGY. +#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Deserialize, Serialize, ToSchema, EnumIter, Debug)] +#[serde(rename_all = "snake_case")] + +pub enum UserSignupSource { + #[deprecated(since = "2026-01-30", note = "Use other Artcraft* enum variants instead")] + #[serde(rename = "artcraft")] + ArtCraft, + + /// ArtCraft Tauri App Onboard Flow + #[serde(rename = "artcraft_app")] + ArtCraftApp, + + /// artcraft.ai normal onboard flow + #[serde(rename = "artcraft_ai_web")] + ArtCraftAiWeb, + + /// artcraft.ai stripe checkout flow + #[serde(rename = "artcraft_ai_s")] + ArtCraftAiStripe, + + /// getartcraft.com normal onboard flow + #[serde(rename = "artcraft_get_web")] + ArtCraftGetWeb, + + /// getartcraft.com stripe checkout flow + #[serde(rename = "artcraft_get_s")] + ArtCraftGetStripe, + + #[serde(rename = "fakeyou")] + FakeYou, + + #[serde(rename = "storyteller")] + Storyteller, +} + +#[cfg(test)] +mod tests { + use super::UserSignupSource; + use enums_shared::test_helpers::{assert_deserialization, assert_serialization}; + use strum::IntoEnumIterator; + + mod manual_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(UserSignupSource::ArtCraft, "artcraft"); + assert_serialization(UserSignupSource::ArtCraftApp, "artcraft_app"); + assert_serialization(UserSignupSource::ArtCraftAiWeb, "artcraft_ai_web"); + assert_serialization(UserSignupSource::ArtCraftAiStripe, "artcraft_ai_s"); + assert_serialization(UserSignupSource::ArtCraftGetWeb, "artcraft_get_web"); + assert_serialization(UserSignupSource::ArtCraftGetStripe, "artcraft_get_s"); + assert_serialization(UserSignupSource::FakeYou, "fakeyou"); + assert_serialization(UserSignupSource::Storyteller, "storyteller"); + } + + #[test] + fn test_deserialization() { + assert_deserialization("artcraft", UserSignupSource::ArtCraft); + assert_deserialization("artcraft_app", UserSignupSource::ArtCraftApp); + assert_deserialization("artcraft_ai_web", UserSignupSource::ArtCraftAiWeb); + assert_deserialization("artcraft_ai_s", UserSignupSource::ArtCraftAiStripe); + assert_deserialization("artcraft_get_web", UserSignupSource::ArtCraftGetWeb); + assert_deserialization("artcraft_get_s", UserSignupSource::ArtCraftGetStripe); + assert_deserialization("fakeyou", UserSignupSource::FakeYou); + assert_deserialization("storyteller", UserSignupSource::Storyteller); + } + + #[test] + fn variants_count_check() { + assert_eq!(UserSignupSource::iter().count(), 8); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip_json() { + for variant in UserSignupSource::iter() { + let json = serde_json::to_string(&variant).unwrap(); + let back: UserSignupSource = serde_json::from_str(&json).unwrap(); + assert_eq!(variant, back); + } + } + } +} diff --git a/crates/schema/public/enums_api/src/by_table/voice_conversion_models/mod.rs b/crates/schema/public/enums_api/src/by_table/voice_conversion_models/mod.rs new file mode 100644 index 0000000000..25778ac3ec --- /dev/null +++ b/crates/schema/public/enums_api/src/by_table/voice_conversion_models/mod.rs @@ -0,0 +1 @@ +pub mod voice_conversion_model_type; diff --git a/crates/schema/public/enums_api/src/by_table/voice_conversion_models/voice_conversion_model_type.rs b/crates/schema/public/enums_api/src/by_table/voice_conversion_models/voice_conversion_model_type.rs new file mode 100644 index 0000000000..b58b89a46c --- /dev/null +++ b/crates/schema/public/enums_api/src/by_table/voice_conversion_models/voice_conversion_model_type.rs @@ -0,0 +1,63 @@ +use strum::EnumIter; +use utoipa::ToSchema; + +/// Used in the `voice_conversion_models` table in `VARCHAR(32)` field `model_type`. +/// +/// DO NOT CHANGE VALUES WITHOUT A MIGRATION STRATEGY. +#[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, Deserialize, Serialize, ToSchema, EnumIter, Debug)] + +pub enum VoiceConversionModelType { + // We're skipping RVC "v1" models as "v2" are much higher quality. + // Future incompatible upgrades may deserve a different enum variant. + #[serde(rename = "rvc_v2")] + RvcV2, + + #[serde(rename = "soft_vc")] + SoftVc, + + #[serde(rename = "so_vits_svc")] + SoVitsSvc, +} + +#[cfg(test)] +mod tests { + use super::VoiceConversionModelType; + use enums_shared::test_helpers::{assert_deserialization, assert_serialization}; + use strum::IntoEnumIterator; + + mod manual_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(VoiceConversionModelType::RvcV2, "rvc_v2"); + assert_serialization(VoiceConversionModelType::SoftVc, "soft_vc"); + assert_serialization(VoiceConversionModelType::SoVitsSvc, "so_vits_svc"); + } + + #[test] + fn test_deserialization() { + assert_deserialization("rvc_v2", VoiceConversionModelType::RvcV2); + assert_deserialization("soft_vc", VoiceConversionModelType::SoftVc); + assert_deserialization("so_vits_svc", VoiceConversionModelType::SoVitsSvc); + } + + #[test] + fn variants_count_check() { + assert_eq!(VoiceConversionModelType::iter().count(), 3); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip_json() { + for variant in VoiceConversionModelType::iter() { + let json = serde_json::to_string(&variant).unwrap(); + let back: VoiceConversionModelType = serde_json::from_str(&json).unwrap(); + assert_eq!(variant, back); + } + } + } +} diff --git a/crates/schema/public/enums_api/src/by_table/voice_conversion_results/mod.rs b/crates/schema/public/enums_api/src/by_table/voice_conversion_results/mod.rs new file mode 100644 index 0000000000..4568dc03ed --- /dev/null +++ b/crates/schema/public/enums_api/src/by_table/voice_conversion_results/mod.rs @@ -0,0 +1 @@ +pub mod voice_conversion_media_token_type; diff --git a/crates/schema/public/enums_api/src/by_table/voice_conversion_results/voice_conversion_media_token_type.rs b/crates/schema/public/enums_api/src/by_table/voice_conversion_results/voice_conversion_media_token_type.rs new file mode 100644 index 0000000000..fdb3b4d1a9 --- /dev/null +++ b/crates/schema/public/enums_api/src/by_table/voice_conversion_results/voice_conversion_media_token_type.rs @@ -0,0 +1,52 @@ +use strum::EnumIter; +use utoipa::ToSchema; + +/// Used in the `voice_conversion_results` table in a `VARCHAR` field. +/// +/// DO NOT CHANGE VALUES WITHOUT A MIGRATION STRATEGY. +#[derive(Clone, Copy, Eq, PartialEq, Deserialize, Serialize, ToSchema, EnumIter, Debug)] +#[serde(rename_all = "snake_case")] + +pub enum VoiceConversionMediaTokenType { + /// Media token refers to record in `media_uploads` table. + MediaUpload, +} + +#[cfg(test)] +mod tests { + use super::VoiceConversionMediaTokenType; + use enums_shared::test_helpers::{assert_deserialization, assert_serialization}; + use strum::IntoEnumIterator; + + mod manual_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(VoiceConversionMediaTokenType::MediaUpload, "media_upload"); + } + + #[test] + fn test_deserialization() { + assert_deserialization("media_upload", VoiceConversionMediaTokenType::MediaUpload); + } + + #[test] + fn variants_count_check() { + assert_eq!(VoiceConversionMediaTokenType::iter().count(), 1); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip_json() { + for variant in VoiceConversionMediaTokenType::iter() { + let json = serde_json::to_string(&variant).unwrap(); + let back: VoiceConversionMediaTokenType = serde_json::from_str(&json).unwrap(); + assert_eq!(variant, back); + } + } + } +} diff --git a/crates/schema/public/enums_api/src/by_table/wallet_ledger_entries/mod.rs b/crates/schema/public/enums_api/src/by_table/wallet_ledger_entries/mod.rs new file mode 100644 index 0000000000..385570f7f1 --- /dev/null +++ b/crates/schema/public/enums_api/src/by_table/wallet_ledger_entries/mod.rs @@ -0,0 +1 @@ +pub mod wallet_ledger_entry_type; diff --git a/crates/schema/public/enums_api/src/by_table/wallet_ledger_entries/wallet_ledger_entry_type.rs b/crates/schema/public/enums_api/src/by_table/wallet_ledger_entries/wallet_ledger_entry_type.rs new file mode 100644 index 0000000000..b0bd39691c --- /dev/null +++ b/crates/schema/public/enums_api/src/by_table/wallet_ledger_entries/wallet_ledger_entry_type.rs @@ -0,0 +1,103 @@ +use strum::EnumIter; +use utoipa::ToSchema; + +/// Used in the `wallet_ledger_entries` table in a `VARCHAR(16)` field. +/// +/// DO NOT CHANGE VALUES WITHOUT A MIGRATION STRATEGY. +#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash, Deserialize, Serialize, ToSchema, EnumIter, Debug)] +#[serde(rename_all = "snake_case")] + +pub enum WalletLedgerEntryType { + /// Wallet created + #[serde(rename = "create")] + Create, + + /// Credit durable banked balance + #[serde(rename = "credit_banked")] + CreditBanked, + + /// Credit monthly refill + #[serde(rename = "credit_monthly")] + CreditMonthly, + + /// Deduct credits (mixed durable and monthly deduction) + #[serde(rename = "deduct_mixed")] + DeductMixed, + + /// Deduct durable banked credits + #[serde(rename = "deduct_banked")] + DeductBanked, + + /// Deduct monthly credits + #[serde(rename = "deduct_monthly")] + DeductMonthly, + + /// Refund banked credits + #[serde(rename = "refund_banked")] + RefundBanked, + + /// Support staff manually credit account + #[serde(rename = "staff_add_banked")] + StaffAddBanked, + + // TODO: No clean way to do "mixed" refunds yet, and if we + // refund close to the cutoff it might be unfair. Let's + // just not do monthly refunds yet and instead credit our + // users with banked credits. + // /// Refund monthly credits + // #[serde(rename = "refund_monthly")] + // RefundMonthly, +} + +#[cfg(test)] +mod tests { + use super::WalletLedgerEntryType; + use enums_shared::test_helpers::{assert_deserialization, assert_serialization}; + use strum::IntoEnumIterator; + + mod manual_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(WalletLedgerEntryType::Create, "create"); + assert_serialization(WalletLedgerEntryType::CreditBanked, "credit_banked"); + assert_serialization(WalletLedgerEntryType::CreditMonthly, "credit_monthly"); + assert_serialization(WalletLedgerEntryType::DeductMixed, "deduct_mixed"); + assert_serialization(WalletLedgerEntryType::DeductBanked, "deduct_banked"); + assert_serialization(WalletLedgerEntryType::DeductMonthly, "deduct_monthly"); + assert_serialization(WalletLedgerEntryType::RefundBanked, "refund_banked"); + assert_serialization(WalletLedgerEntryType::StaffAddBanked, "staff_add_banked"); + } + + #[test] + fn test_deserialization() { + assert_deserialization("create", WalletLedgerEntryType::Create); + assert_deserialization("credit_banked", WalletLedgerEntryType::CreditBanked); + assert_deserialization("credit_monthly", WalletLedgerEntryType::CreditMonthly); + assert_deserialization("deduct_mixed", WalletLedgerEntryType::DeductMixed); + assert_deserialization("deduct_banked", WalletLedgerEntryType::DeductBanked); + assert_deserialization("deduct_monthly", WalletLedgerEntryType::DeductMonthly); + assert_deserialization("refund_banked", WalletLedgerEntryType::RefundBanked); + assert_deserialization("staff_add_banked", WalletLedgerEntryType::StaffAddBanked); + } + + #[test] + fn variants_count_check() { + assert_eq!(WalletLedgerEntryType::iter().count(), 8); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip_json() { + for variant in WalletLedgerEntryType::iter() { + let json = serde_json::to_string(&variant).unwrap(); + let back: WalletLedgerEntryType = serde_json::from_str(&json).unwrap(); + assert_eq!(variant, back); + } + } + } +} diff --git a/crates/schema/public/enums_api/src/by_table/web_rendition_targets/mod.rs b/crates/schema/public/enums_api/src/by_table/web_rendition_targets/mod.rs new file mode 100644 index 0000000000..371fe4d32f --- /dev/null +++ b/crates/schema/public/enums_api/src/by_table/web_rendition_targets/mod.rs @@ -0,0 +1 @@ +pub mod rendition_status; diff --git a/crates/schema/public/enums_api/src/by_table/web_rendition_targets/rendition_status.rs b/crates/schema/public/enums_api/src/by_table/web_rendition_targets/rendition_status.rs new file mode 100644 index 0000000000..960a7d2112 --- /dev/null +++ b/crates/schema/public/enums_api/src/by_table/web_rendition_targets/rendition_status.rs @@ -0,0 +1,69 @@ +use strum::EnumIter; +use utoipa::ToSchema; + +/// Used in the SqLite `web_scraping_targets` table in a `TEXT` field named `scraping_status`. +#[derive(Clone, Copy, Eq, PartialEq, Hash, Deserialize, Serialize, ToSchema, EnumIter, Debug)] + +pub enum RenditionStatus { + #[serde(rename = "new")] + New, + + #[serde(rename = "skipped")] + Skipped, + + #[serde(rename = "failed")] + Failed, + + #[serde(rename = "permanently_failed")] + PermanentlyFailed, + + #[serde(rename = "success")] + Success, +} + +#[cfg(test)] +mod tests { + use super::RenditionStatus; + use enums_shared::test_helpers::{assert_deserialization, assert_serialization}; + use strum::IntoEnumIterator; + + mod manual_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(RenditionStatus::New, "new"); + assert_serialization(RenditionStatus::Skipped, "skipped"); + assert_serialization(RenditionStatus::Failed, "failed"); + assert_serialization(RenditionStatus::PermanentlyFailed, "permanently_failed"); + assert_serialization(RenditionStatus::Success, "success"); + } + + #[test] + fn test_deserialization() { + assert_deserialization("new", RenditionStatus::New); + assert_deserialization("skipped", RenditionStatus::Skipped); + assert_deserialization("failed", RenditionStatus::Failed); + assert_deserialization("permanently_failed", RenditionStatus::PermanentlyFailed); + assert_deserialization("success", RenditionStatus::Success); + } + + #[test] + fn variants_count_check() { + assert_eq!(RenditionStatus::iter().count(), 5); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip_json() { + for variant in RenditionStatus::iter() { + let json = serde_json::to_string(&variant).unwrap(); + let back: RenditionStatus = serde_json::from_str(&json).unwrap(); + assert_eq!(variant, back); + } + } + } +} diff --git a/crates/schema/public/enums_api/src/by_table/web_scraping_targets/mod.rs b/crates/schema/public/enums_api/src/by_table/web_scraping_targets/mod.rs new file mode 100644 index 0000000000..2dea4d4509 --- /dev/null +++ b/crates/schema/public/enums_api/src/by_table/web_scraping_targets/mod.rs @@ -0,0 +1 @@ +pub mod scraping_status; diff --git a/crates/schema/public/enums_api/src/by_table/web_scraping_targets/scraping_status.rs b/crates/schema/public/enums_api/src/by_table/web_scraping_targets/scraping_status.rs new file mode 100644 index 0000000000..6eea0aafcb --- /dev/null +++ b/crates/schema/public/enums_api/src/by_table/web_scraping_targets/scraping_status.rs @@ -0,0 +1,69 @@ +use strum::EnumIter; +use utoipa::ToSchema; + +/// Used in the SqLite `web_scraping_targets` table in a `TEXT` field named `scraping_status`. +#[derive(Clone, Copy, Eq, PartialEq, Hash, Deserialize, Serialize, ToSchema, EnumIter, Debug)] + +pub enum ScrapingStatus { + #[serde(rename = "new")] + New, + + #[serde(rename = "skipped")] + Skipped, + + #[serde(rename = "failed")] + Failed, + + #[serde(rename = "permanently_failed")] + PermanentlyFailed, + + #[serde(rename = "success")] + Success, +} + +#[cfg(test)] +mod tests { + use super::ScrapingStatus; + use enums_shared::test_helpers::{assert_deserialization, assert_serialization}; + use strum::IntoEnumIterator; + + mod manual_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(ScrapingStatus::New, "new"); + assert_serialization(ScrapingStatus::Skipped, "skipped"); + assert_serialization(ScrapingStatus::Failed, "failed"); + assert_serialization(ScrapingStatus::PermanentlyFailed, "permanently_failed"); + assert_serialization(ScrapingStatus::Success, "success"); + } + + #[test] + fn test_deserialization() { + assert_deserialization("new", ScrapingStatus::New); + assert_deserialization("skipped", ScrapingStatus::Skipped); + assert_deserialization("failed", ScrapingStatus::Failed); + assert_deserialization("permanently_failed", ScrapingStatus::PermanentlyFailed); + assert_deserialization("success", ScrapingStatus::Success); + } + + #[test] + fn variants_count_check() { + assert_eq!(ScrapingStatus::iter().count(), 5); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip_json() { + for variant in ScrapingStatus::iter() { + let json = serde_json::to_string(&variant).unwrap(); + let back: ScrapingStatus = serde_json::from_str(&json).unwrap(); + assert_eq!(variant, back); + } + } + } +} diff --git a/crates/schema/public/enums_api/src/by_table/zs_voices/encoding_type.rs b/crates/schema/public/enums_api/src/by_table/zs_voices/encoding_type.rs new file mode 100644 index 0000000000..5d1fb108a0 --- /dev/null +++ b/crates/schema/public/enums_api/src/by_table/zs_voices/encoding_type.rs @@ -0,0 +1,54 @@ +use strum::EnumIter; +use utoipa::ToSchema; + +/// Used in the `zs_voices` table in a `VARCHAR(16)` field named `encoding_type`. +/// +/// This indicates what type of features are used in the embeddings. +/// +/// DO NOT CHANGE VALUES WITHOUT A MIGRATION STRATEGY. +#[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, Deserialize, Serialize, ToSchema, EnumIter, Debug)] + +pub enum ZsVoiceEncodingType { + /// Encodec features + #[serde(rename = "encodec")] + Encodec, +} + +#[cfg(test)] +mod tests { + use super::ZsVoiceEncodingType; + use enums_shared::test_helpers::{assert_deserialization, assert_serialization}; + use strum::IntoEnumIterator; + + mod manual_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(ZsVoiceEncodingType::Encodec, "encodec"); + } + + #[test] + fn test_deserialization() { + assert_deserialization("encodec", ZsVoiceEncodingType::Encodec); + } + + #[test] + fn variants_count_check() { + assert_eq!(ZsVoiceEncodingType::iter().count(), 1); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip_json() { + for variant in ZsVoiceEncodingType::iter() { + let json = serde_json::to_string(&variant).unwrap(); + let back: ZsVoiceEncodingType = serde_json::from_str(&json).unwrap(); + assert_eq!(variant, back); + } + } + } +} diff --git a/crates/schema/public/enums_api/src/by_table/zs_voices/mod.rs b/crates/schema/public/enums_api/src/by_table/zs_voices/mod.rs new file mode 100644 index 0000000000..45e42bce9c --- /dev/null +++ b/crates/schema/public/enums_api/src/by_table/zs_voices/mod.rs @@ -0,0 +1,3 @@ +pub mod encoding_type; +pub mod model_category; +pub mod model_type; diff --git a/crates/schema/public/enums_api/src/by_table/zs_voices/model_category.rs b/crates/schema/public/enums_api/src/by_table/zs_voices/model_category.rs new file mode 100644 index 0000000000..31eb19e68a --- /dev/null +++ b/crates/schema/public/enums_api/src/by_table/zs_voices/model_category.rs @@ -0,0 +1,54 @@ +use strum::EnumIter; +use utoipa::ToSchema; + +/// Used in the `zs_voices` table in a `VARCHAR(16)` field named `model_category`. +/// +/// This indicates what type of features are used in the embeddings. +/// +/// DO NOT CHANGE VALUES WITHOUT A MIGRATION STRATEGY. +#[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, Deserialize, Serialize, ToSchema, EnumIter, Debug)] + +pub enum ZsVoiceModelCategory { + /// TTS-type zero shot models + #[serde(rename = "tts")] + Tts, +} + +#[cfg(test)] +mod tests { + use super::ZsVoiceModelCategory; + use enums_shared::test_helpers::{assert_deserialization, assert_serialization}; + use strum::IntoEnumIterator; + + mod manual_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(ZsVoiceModelCategory::Tts, "tts"); + } + + #[test] + fn test_deserialization() { + assert_deserialization("tts", ZsVoiceModelCategory::Tts); + } + + #[test] + fn variants_count_check() { + assert_eq!(ZsVoiceModelCategory::iter().count(), 1); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip_json() { + for variant in ZsVoiceModelCategory::iter() { + let json = serde_json::to_string(&variant).unwrap(); + let back: ZsVoiceModelCategory = serde_json::from_str(&json).unwrap(); + assert_eq!(variant, back); + } + } + } +} diff --git a/crates/schema/public/enums_api/src/by_table/zs_voices/model_type.rs b/crates/schema/public/enums_api/src/by_table/zs_voices/model_type.rs new file mode 100644 index 0000000000..2864d4211d --- /dev/null +++ b/crates/schema/public/enums_api/src/by_table/zs_voices/model_type.rs @@ -0,0 +1,58 @@ +use strum::EnumIter; +use utoipa::ToSchema; + +/// Used in the `zs_voices` table in a `VARCHAR(16)` field named `model_type`. +/// +/// This indicates what type of features are used in the embeddings. +/// +/// DO NOT CHANGE VALUES WITHOUT A MIGRATION STRATEGY. +#[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, Deserialize, Serialize, ToSchema, EnumIter, Debug)] + +pub enum ZsVoiceModelType { + /// TTS-type zero shot models + #[serde(rename = "vall-e-x")] + VallEX, + #[serde(rename = "styletts2")] + StyleTTS2, +} + +#[cfg(test)] +mod tests { + use super::ZsVoiceModelType; + use enums_shared::test_helpers::{assert_deserialization, assert_serialization}; + use strum::IntoEnumIterator; + + mod manual_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(ZsVoiceModelType::VallEX, "vall-e-x"); + assert_serialization(ZsVoiceModelType::StyleTTS2, "styletts2"); + } + + #[test] + fn test_deserialization() { + assert_deserialization("vall-e-x", ZsVoiceModelType::VallEX); + assert_deserialization("styletts2", ZsVoiceModelType::StyleTTS2); + } + + #[test] + fn variants_count_check() { + assert_eq!(ZsVoiceModelType::iter().count(), 2); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip_json() { + for variant in ZsVoiceModelType::iter() { + let json = serde_json::to_string(&variant).unwrap(); + let back: ZsVoiceModelType = serde_json::from_str(&json).unwrap(); + assert_eq!(variant, back); + } + } + } +} diff --git a/crates/schema/public/enums_api/src/common/artcraft_credits_pack_slug.rs b/crates/schema/public/enums_api/src/common/artcraft_credits_pack_slug.rs new file mode 100644 index 0000000000..3f3d8e7acc --- /dev/null +++ b/crates/schema/public/enums_api/src/common/artcraft_credits_pack_slug.rs @@ -0,0 +1,71 @@ +use strum::EnumIter; +use utoipa::ToSchema; + +/// NB: This will be used by a variety of tables (MySQL and sqlite)! +/// Keep the max length to 16 characters. +#[derive(Clone, Debug, Copy, PartialEq, Eq, Hash, Ord, PartialOrd, Serialize, EnumIter, Deserialize, ToSchema)] +#[serde(rename_all = "snake_case")] + +pub enum ArtcraftCreditsPackSlug { + #[serde(rename= "artcraft_1000")] + Artcraft1000, + #[serde(rename= "artcraft_2500")] + Artcraft2500, + #[serde(rename= "artcraft_5000")] + Artcraft5000, + #[serde(rename= "artcraft_10000")] + Artcraft10000, + #[serde(rename= "artcraft_25000")] + Artcraft25000, + #[serde(rename= "artcraft_50000")] + Artcraft50000, +} + +#[cfg(test)] +mod tests { + use super::ArtcraftCreditsPackSlug; + use enums_shared::test_helpers::{assert_deserialization, assert_serialization}; + use strum::IntoEnumIterator; + + mod manual_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(ArtcraftCreditsPackSlug::Artcraft1000, "artcraft_1000"); + assert_serialization(ArtcraftCreditsPackSlug::Artcraft2500, "artcraft_2500"); + assert_serialization(ArtcraftCreditsPackSlug::Artcraft5000, "artcraft_5000"); + assert_serialization(ArtcraftCreditsPackSlug::Artcraft10000, "artcraft_10000"); + assert_serialization(ArtcraftCreditsPackSlug::Artcraft25000, "artcraft_25000"); + assert_serialization(ArtcraftCreditsPackSlug::Artcraft50000, "artcraft_50000"); + } + + #[test] + fn test_deserialization() { + assert_deserialization("artcraft_1000", ArtcraftCreditsPackSlug::Artcraft1000); + assert_deserialization("artcraft_2500", ArtcraftCreditsPackSlug::Artcraft2500); + assert_deserialization("artcraft_5000", ArtcraftCreditsPackSlug::Artcraft5000); + assert_deserialization("artcraft_10000", ArtcraftCreditsPackSlug::Artcraft10000); + assert_deserialization("artcraft_25000", ArtcraftCreditsPackSlug::Artcraft25000); + assert_deserialization("artcraft_50000", ArtcraftCreditsPackSlug::Artcraft50000); + } + + #[test] + fn variants_count_check() { + assert_eq!(ArtcraftCreditsPackSlug::iter().count(), 6); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip_json() { + for variant in ArtcraftCreditsPackSlug::iter() { + let json = serde_json::to_string(&variant).unwrap(); + let back: ArtcraftCreditsPackSlug = serde_json::from_str(&json).unwrap(); + assert_eq!(variant, back); + } + } + } +} diff --git a/crates/schema/public/enums_api/src/common/artcraft_subscription_slug.rs b/crates/schema/public/enums_api/src/common/artcraft_subscription_slug.rs new file mode 100644 index 0000000000..e4587ac0e4 --- /dev/null +++ b/crates/schema/public/enums_api/src/common/artcraft_subscription_slug.rs @@ -0,0 +1,56 @@ +use strum::EnumIter; +use utoipa::ToSchema; + +/// NB: This will be used by a variety of tables (MySQL and sqlite)! +/// Keep the max length to 16 characters. +#[derive(Clone, Debug, Copy, PartialEq, Eq, Hash, Ord, PartialOrd, Serialize, EnumIter, Deserialize, ToSchema)] +#[serde(rename_all = "snake_case")] + +pub enum ArtcraftSubscriptionSlug { + ArtcraftBasic, + ArtcraftPro, + ArtcraftMax, +} + +#[cfg(test)] +mod tests { + use super::ArtcraftSubscriptionSlug; + use enums_shared::test_helpers::{assert_deserialization, assert_serialization}; + use strum::IntoEnumIterator; + + mod manual_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(ArtcraftSubscriptionSlug::ArtcraftBasic, "artcraft_basic"); + assert_serialization(ArtcraftSubscriptionSlug::ArtcraftPro, "artcraft_pro"); + assert_serialization(ArtcraftSubscriptionSlug::ArtcraftMax, "artcraft_max"); + } + + #[test] + fn test_deserialization() { + assert_deserialization("artcraft_basic", ArtcraftSubscriptionSlug::ArtcraftBasic); + assert_deserialization("artcraft_pro", ArtcraftSubscriptionSlug::ArtcraftPro); + assert_deserialization("artcraft_max", ArtcraftSubscriptionSlug::ArtcraftMax); + } + + #[test] + fn variants_count_check() { + assert_eq!(ArtcraftSubscriptionSlug::iter().count(), 3); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip_json() { + for variant in ArtcraftSubscriptionSlug::iter() { + let json = serde_json::to_string(&variant).unwrap(); + let back: ArtcraftSubscriptionSlug = serde_json::from_str(&json).unwrap(); + assert_eq!(variant, back); + } + } + } +} diff --git a/crates/schema/public/enums_api/src/common/generation/common_aspect_ratio.rs b/crates/schema/public/enums_api/src/common/generation/common_aspect_ratio.rs new file mode 100644 index 0000000000..ca8e334e67 --- /dev/null +++ b/crates/schema/public/enums_api/src/common/generation/common_aspect_ratio.rs @@ -0,0 +1,97 @@ +use strum::EnumIter; +use utoipa::ToSchema; + +/// Common aspect ratios for video generation. +/// Mirrors artcraft_router::api::common_aspect_ratio::CommonAspectRatio. +#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize, ToSchema, EnumIter)] +#[serde(rename_all = "snake_case")] +pub enum CommonAspectRatio { + Auto, + Square, + WideThreeByTwo, + WideFourByThree, + WideFiveByFour, + WideSixteenByNine, + WideTwentyOneByNine, + TallTwoByThree, + TallThreeByFour, + TallFourByFive, + TallNineBySixteen, + TallNineByTwentyOne, + Wide, + Tall, + Auto2k, + Auto4k, + SquareHd, +} + +#[cfg(test)] +mod tests { + use super::CommonAspectRatio; + use enums_shared::test_helpers::{assert_deserialization, assert_serialization}; + use strum::IntoEnumIterator; + + mod manual_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(CommonAspectRatio::Auto, "auto"); + assert_serialization(CommonAspectRatio::Square, "square"); + assert_serialization(CommonAspectRatio::WideThreeByTwo, "wide_three_by_two"); + assert_serialization(CommonAspectRatio::WideFourByThree, "wide_four_by_three"); + assert_serialization(CommonAspectRatio::WideFiveByFour, "wide_five_by_four"); + assert_serialization(CommonAspectRatio::WideSixteenByNine, "wide_sixteen_by_nine"); + assert_serialization(CommonAspectRatio::WideTwentyOneByNine, "wide_twenty_one_by_nine"); + assert_serialization(CommonAspectRatio::TallTwoByThree, "tall_two_by_three"); + assert_serialization(CommonAspectRatio::TallThreeByFour, "tall_three_by_four"); + assert_serialization(CommonAspectRatio::TallFourByFive, "tall_four_by_five"); + assert_serialization(CommonAspectRatio::TallNineBySixteen, "tall_nine_by_sixteen"); + assert_serialization(CommonAspectRatio::TallNineByTwentyOne, "tall_nine_by_twenty_one"); + assert_serialization(CommonAspectRatio::Wide, "wide"); + assert_serialization(CommonAspectRatio::Tall, "tall"); + assert_serialization(CommonAspectRatio::Auto2k, "auto2k"); + assert_serialization(CommonAspectRatio::Auto4k, "auto4k"); + assert_serialization(CommonAspectRatio::SquareHd, "square_hd"); + } + + #[test] + fn test_deserialization() { + assert_deserialization("auto", CommonAspectRatio::Auto); + assert_deserialization("square", CommonAspectRatio::Square); + assert_deserialization("wide_three_by_two", CommonAspectRatio::WideThreeByTwo); + assert_deserialization("wide_four_by_three", CommonAspectRatio::WideFourByThree); + assert_deserialization("wide_five_by_four", CommonAspectRatio::WideFiveByFour); + assert_deserialization("wide_sixteen_by_nine", CommonAspectRatio::WideSixteenByNine); + assert_deserialization("wide_twenty_one_by_nine", CommonAspectRatio::WideTwentyOneByNine); + assert_deserialization("tall_two_by_three", CommonAspectRatio::TallTwoByThree); + assert_deserialization("tall_three_by_four", CommonAspectRatio::TallThreeByFour); + assert_deserialization("tall_four_by_five", CommonAspectRatio::TallFourByFive); + assert_deserialization("tall_nine_by_sixteen", CommonAspectRatio::TallNineBySixteen); + assert_deserialization("tall_nine_by_twenty_one", CommonAspectRatio::TallNineByTwentyOne); + assert_deserialization("wide", CommonAspectRatio::Wide); + assert_deserialization("tall", CommonAspectRatio::Tall); + assert_deserialization("auto2k", CommonAspectRatio::Auto2k); + assert_deserialization("auto4k", CommonAspectRatio::Auto4k); + assert_deserialization("square_hd", CommonAspectRatio::SquareHd); + } + + #[test] + fn variants_count_check() { + assert_eq!(CommonAspectRatio::iter().count(), 17); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip_json() { + for variant in CommonAspectRatio::iter() { + let json = serde_json::to_string(&variant).unwrap(); + let back: CommonAspectRatio = serde_json::from_str(&json).unwrap(); + assert_eq!(variant, back); + } + } + } +} diff --git a/crates/schema/public/enums_api/src/common/generation/common_image_model.rs b/crates/schema/public/enums_api/src/common/generation/common_image_model.rs new file mode 100644 index 0000000000..e842a44e65 --- /dev/null +++ b/crates/schema/public/enums_api/src/common/generation/common_image_model.rs @@ -0,0 +1,90 @@ +use strum::EnumIter; +use utoipa::ToSchema; + +/// Image models available for generation. +/// Mirrors artcraft_router::api::common_image_model::CommonImageModel. +#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize, ToSchema, EnumIter)] +#[serde(rename_all = "snake_case")] +pub enum CommonImageModel { + #[serde(rename = "flux_1_dev")] + Flux1Dev, + #[serde(rename = "flux_1_schnell")] + Flux1Schnell, + #[serde(rename = "flux_pro_1p1")] + FluxPro11, + #[serde(rename = "flux_pro_1p1_ultra")] + FluxPro11Ultra, + #[serde(rename = "gpt_image_1p5")] + GptImage1p5, + #[serde(rename = "nano_banana")] + NanaBanana, + #[serde(rename = "nano_banana_2")] + NanaBanana2, + #[serde(rename = "nano_banana_pro")] + NanaBananaPro, + #[serde(rename = "seedream_4")] + Seedream4, + #[serde(rename = "seedream_4p5")] + Seedream4p5, + #[serde(rename = "seedream_5_lite")] + Seedream5Lite, +} + +#[cfg(test)] +mod tests { + use super::CommonImageModel; + use enums_shared::test_helpers::{assert_deserialization, assert_serialization}; + use strum::IntoEnumIterator; + + mod manual_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(CommonImageModel::Flux1Dev, "flux_1_dev"); + assert_serialization(CommonImageModel::Flux1Schnell, "flux_1_schnell"); + assert_serialization(CommonImageModel::FluxPro11, "flux_pro_1p1"); + assert_serialization(CommonImageModel::FluxPro11Ultra, "flux_pro_1p1_ultra"); + assert_serialization(CommonImageModel::GptImage1p5, "gpt_image_1p5"); + assert_serialization(CommonImageModel::NanaBanana, "nano_banana"); + assert_serialization(CommonImageModel::NanaBanana2, "nano_banana_2"); + assert_serialization(CommonImageModel::NanaBananaPro, "nano_banana_pro"); + assert_serialization(CommonImageModel::Seedream4, "seedream_4"); + assert_serialization(CommonImageModel::Seedream4p5, "seedream_4p5"); + assert_serialization(CommonImageModel::Seedream5Lite, "seedream_5_lite"); + } + + #[test] + fn test_deserialization() { + assert_deserialization("flux_1_dev", CommonImageModel::Flux1Dev); + assert_deserialization("flux_1_schnell", CommonImageModel::Flux1Schnell); + assert_deserialization("flux_pro_1p1", CommonImageModel::FluxPro11); + assert_deserialization("flux_pro_1p1_ultra", CommonImageModel::FluxPro11Ultra); + assert_deserialization("gpt_image_1p5", CommonImageModel::GptImage1p5); + assert_deserialization("nano_banana", CommonImageModel::NanaBanana); + assert_deserialization("nano_banana_2", CommonImageModel::NanaBanana2); + assert_deserialization("nano_banana_pro", CommonImageModel::NanaBananaPro); + assert_deserialization("seedream_4", CommonImageModel::Seedream4); + assert_deserialization("seedream_4p5", CommonImageModel::Seedream4p5); + assert_deserialization("seedream_5_lite", CommonImageModel::Seedream5Lite); + } + + #[test] + fn variants_count_check() { + assert_eq!(CommonImageModel::iter().count(), 11); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip_json() { + for variant in CommonImageModel::iter() { + let json = serde_json::to_string(&variant).unwrap(); + let back: CommonImageModel = serde_json::from_str(&json).unwrap(); + assert_eq!(variant, back); + } + } + } +} diff --git a/crates/schema/public/enums_api/src/common/generation/common_splat_model.rs b/crates/schema/public/enums_api/src/common/generation/common_splat_model.rs new file mode 100644 index 0000000000..478b558e4c --- /dev/null +++ b/crates/schema/public/enums_api/src/common/generation/common_splat_model.rs @@ -0,0 +1,55 @@ +use strum::EnumIter; +use utoipa::ToSchema; + +/// Splat models available for generation. +/// Mirrors artcraft_router::api::common_splat_model::CommonSplatModel. +#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize, ToSchema, EnumIter)] +#[serde(rename_all = "snake_case")] +pub enum CommonSplatModel { + #[serde(rename = "marble_0p1_mini")] + Marble0p1Mini, + + #[serde(rename = "marble_0p1_plus")] + Marble0p1Plus, +} + +#[cfg(test)] +mod tests { + use super::CommonSplatModel; + use enums_shared::test_helpers::{assert_deserialization, assert_serialization}; + use strum::IntoEnumIterator; + + mod manual_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(CommonSplatModel::Marble0p1Mini, "marble_0p1_mini"); + assert_serialization(CommonSplatModel::Marble0p1Plus, "marble_0p1_plus"); + } + + #[test] + fn test_deserialization() { + assert_deserialization("marble_0p1_mini", CommonSplatModel::Marble0p1Mini); + assert_deserialization("marble_0p1_plus", CommonSplatModel::Marble0p1Plus); + } + + #[test] + fn variants_count_check() { + assert_eq!(CommonSplatModel::iter().count(), 2); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip_json() { + for variant in CommonSplatModel::iter() { + let json = serde_json::to_string(&variant).unwrap(); + let back: CommonSplatModel = serde_json::from_str(&json).unwrap(); + assert_eq!(variant, back); + } + } + } +} diff --git a/crates/schema/public/enums_api/src/common/generation/common_video_model.rs b/crates/schema/public/enums_api/src/common/generation/common_video_model.rs new file mode 100644 index 0000000000..6824ff212b --- /dev/null +++ b/crates/schema/public/enums_api/src/common/generation/common_video_model.rs @@ -0,0 +1,135 @@ +use strum::EnumIter; +use utoipa::ToSchema; + +/// Video models available for generation. +/// Mirrors artcraft_router::api::common_video_model::CommonVideoModel. +#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize, ToSchema, EnumIter)] +#[serde(rename_all = "snake_case")] +pub enum CommonVideoModel { + #[serde(rename = "grok_video")] + GrokVideo, + + #[serde(rename = "kling_1p6_pro")] + Kling16Pro, + + #[serde(rename = "kling_2p1_pro")] + Kling21Pro, + + #[serde(rename = "kling_2p1_master")] + Kling21Master, + + #[serde(rename = "kling_2p5_turbo_pro")] + Kling2p5TurboPro, + + #[serde(rename = "kling_2p6_pro")] + Kling2p6Pro, + + #[serde(rename = "kling_3p0_standard")] + Kling3p0Standard, + + #[serde(rename = "kling_3p0_pro")] + Kling3p0Pro, + + #[serde(rename = "seedance_1p0_lite")] + Seedance10Lite, + + #[serde(rename = "seedance_1p5_pro")] + Seedance1p5Pro, + + #[serde(rename = "seedance_2p0")] + Seedance2p0, + + #[serde(rename = "sora_2")] + Sora2, + + #[serde(rename = "sora_2_pro")] + Sora2Pro, + + #[serde(rename = "veo_2")] + Veo2, + + #[serde(rename = "veo_3")] + Veo3, + + #[serde(rename = "veo_3_fast")] + Veo3Fast, + + #[serde(rename = "veo_3p1")] + Veo3p1, + + #[serde(rename = "veo_3p1_fast")] + Veo3p1Fast, +} + +#[cfg(test)] +mod tests { + use super::CommonVideoModel; + use enums_shared::test_helpers::{assert_deserialization, assert_serialization}; + use strum::IntoEnumIterator; + + mod manual_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(CommonVideoModel::GrokVideo, "grok_video"); + assert_serialization(CommonVideoModel::Kling16Pro, "kling_1p6_pro"); + assert_serialization(CommonVideoModel::Kling21Pro, "kling_2p1_pro"); + assert_serialization(CommonVideoModel::Kling21Master, "kling_2p1_master"); + assert_serialization(CommonVideoModel::Kling2p5TurboPro, "kling_2p5_turbo_pro"); + assert_serialization(CommonVideoModel::Kling2p6Pro, "kling_2p6_pro"); + assert_serialization(CommonVideoModel::Kling3p0Standard, "kling_3p0_standard"); + assert_serialization(CommonVideoModel::Kling3p0Pro, "kling_3p0_pro"); + assert_serialization(CommonVideoModel::Seedance10Lite, "seedance_1p0_lite"); + assert_serialization(CommonVideoModel::Seedance1p5Pro, "seedance_1p5_pro"); + assert_serialization(CommonVideoModel::Seedance2p0, "seedance_2p0"); + assert_serialization(CommonVideoModel::Sora2, "sora_2"); + assert_serialization(CommonVideoModel::Sora2Pro, "sora_2_pro"); + assert_serialization(CommonVideoModel::Veo2, "veo_2"); + assert_serialization(CommonVideoModel::Veo3, "veo_3"); + assert_serialization(CommonVideoModel::Veo3Fast, "veo_3_fast"); + assert_serialization(CommonVideoModel::Veo3p1, "veo_3p1"); + assert_serialization(CommonVideoModel::Veo3p1Fast, "veo_3p1_fast"); + } + + #[test] + fn test_deserialization() { + assert_deserialization("grok_video", CommonVideoModel::GrokVideo); + assert_deserialization("kling_1p6_pro", CommonVideoModel::Kling16Pro); + assert_deserialization("kling_2p1_pro", CommonVideoModel::Kling21Pro); + assert_deserialization("kling_2p1_master", CommonVideoModel::Kling21Master); + assert_deserialization("kling_2p5_turbo_pro", CommonVideoModel::Kling2p5TurboPro); + assert_deserialization("kling_2p6_pro", CommonVideoModel::Kling2p6Pro); + assert_deserialization("kling_3p0_standard", CommonVideoModel::Kling3p0Standard); + assert_deserialization("kling_3p0_pro", CommonVideoModel::Kling3p0Pro); + assert_deserialization("seedance_1p0_lite", CommonVideoModel::Seedance10Lite); + assert_deserialization("seedance_1p5_pro", CommonVideoModel::Seedance1p5Pro); + assert_deserialization("seedance_2p0", CommonVideoModel::Seedance2p0); + assert_deserialization("sora_2", CommonVideoModel::Sora2); + assert_deserialization("sora_2_pro", CommonVideoModel::Sora2Pro); + assert_deserialization("veo_2", CommonVideoModel::Veo2); + assert_deserialization("veo_3", CommonVideoModel::Veo3); + assert_deserialization("veo_3_fast", CommonVideoModel::Veo3Fast); + assert_deserialization("veo_3p1", CommonVideoModel::Veo3p1); + assert_deserialization("veo_3p1_fast", CommonVideoModel::Veo3p1Fast); + } + + #[test] + fn variants_count_check() { + assert_eq!(CommonVideoModel::iter().count(), 18); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip_json() { + for variant in CommonVideoModel::iter() { + let json = serde_json::to_string(&variant).unwrap(); + let back: CommonVideoModel = serde_json::from_str(&json).unwrap(); + assert_eq!(variant, back); + } + } + } +} diff --git a/crates/schema/public/enums_api/src/common/generation/common_video_resolution.rs b/crates/schema/public/enums_api/src/common/generation/common_video_resolution.rs new file mode 100644 index 0000000000..335fa268e1 --- /dev/null +++ b/crates/schema/public/enums_api/src/common/generation/common_video_resolution.rs @@ -0,0 +1,58 @@ +use strum::EnumIter; +use utoipa::ToSchema; + +/// Common video resolutions. +/// Mirrors artcraft_router::api::common_resolution::CommonResolution. +#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize, ToSchema, EnumIter)] +#[serde(rename_all = "snake_case")] +pub enum CommonVideoResolution { + OneK, + TwoK, + ThreeK, + FourK, +} + +#[cfg(test)] +mod tests { + use super::CommonVideoResolution; + use enums_shared::test_helpers::{assert_deserialization, assert_serialization}; + use strum::IntoEnumIterator; + + mod manual_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(CommonVideoResolution::OneK, "one_k"); + assert_serialization(CommonVideoResolution::TwoK, "two_k"); + assert_serialization(CommonVideoResolution::ThreeK, "three_k"); + assert_serialization(CommonVideoResolution::FourK, "four_k"); + } + + #[test] + fn test_deserialization() { + assert_deserialization("one_k", CommonVideoResolution::OneK); + assert_deserialization("two_k", CommonVideoResolution::TwoK); + assert_deserialization("three_k", CommonVideoResolution::ThreeK); + assert_deserialization("four_k", CommonVideoResolution::FourK); + } + + #[test] + fn variants_count_check() { + assert_eq!(CommonVideoResolution::iter().count(), 4); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip_json() { + for variant in CommonVideoResolution::iter() { + let json = serde_json::to_string(&variant).unwrap(); + let back: CommonVideoResolution = serde_json::from_str(&json).unwrap(); + assert_eq!(variant, back); + } + } + } +} diff --git a/crates/schema/public/enums_api/src/common/generation/generation_provider.rs b/crates/schema/public/enums_api/src/common/generation/generation_provider.rs new file mode 100644 index 0000000000..24db14e8dd --- /dev/null +++ b/crates/schema/public/enums_api/src/common/generation/generation_provider.rs @@ -0,0 +1,81 @@ +//! This is an important enum. +//! +//! It's used in storyteller-web inference generation, the cost estimate handler, +//! the ArtCraft Tauri app, and more. +//! +//! Do not change the values here without cause or care. + +use strum::EnumCount; +use strum::EnumIter; +use utoipa::ToSchema; + +/// NB: Keep the max length to 16 characters. +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Ord, PartialOrd, Serialize, Deserialize, ToSchema, EnumIter, EnumCount)] +#[serde(rename_all = "snake_case")] +pub enum GenerationProvider { + Artcraft, + Fal, + Grok, + Midjourney, + Sora, + WorldLabs, + + // /// Catch-all for values the client doesn't yet know about. + // /// + // /// We need this to help prevent old versions of deployed-in-the-field + // /// apps from breaking, eg. Tauri Desktop, when new enum variants are added. + // /// This will stop deserialization from failing, but the client still has + // /// to behave intelligently. + // /// + // /// The contained string is the raw serialized value from the server. + // #[serde(untagged)] + // Unknown(String), +} + +#[cfg(test)] +mod tests { + use super::GenerationProvider; + use enums_shared::test_helpers::{assert_deserialization, assert_serialization}; + use strum::IntoEnumIterator; + + mod manual_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(GenerationProvider::Artcraft, "artcraft"); + assert_serialization(GenerationProvider::Fal, "fal"); + assert_serialization(GenerationProvider::Grok, "grok"); + assert_serialization(GenerationProvider::Midjourney, "midjourney"); + assert_serialization(GenerationProvider::Sora, "sora"); + assert_serialization(GenerationProvider::WorldLabs, "world_labs"); + } + + #[test] + fn test_deserialization() { + assert_deserialization("artcraft", GenerationProvider::Artcraft); + assert_deserialization("fal", GenerationProvider::Fal); + assert_deserialization("grok", GenerationProvider::Grok); + assert_deserialization("midjourney", GenerationProvider::Midjourney); + assert_deserialization("sora", GenerationProvider::Sora); + assert_deserialization("world_labs", GenerationProvider::WorldLabs); + } + #[test] + fn variants_count_check() { + assert_eq!(GenerationProvider::iter().count(), 6); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip_json() { + for variant in GenerationProvider::iter() { + let json = serde_json::to_string(&variant).unwrap(); + let back: GenerationProvider = serde_json::from_str(&json).unwrap(); + assert_eq!(variant, back); + } + } + } +} diff --git a/crates/schema/public/enums_api/src/common/generation/mod.rs b/crates/schema/public/enums_api/src/common/generation/mod.rs new file mode 100644 index 0000000000..e74d5744d6 --- /dev/null +++ b/crates/schema/public/enums_api/src/common/generation/mod.rs @@ -0,0 +1,6 @@ +pub mod common_aspect_ratio; +pub mod common_image_model; +pub mod common_splat_model; +pub mod common_video_model; +pub mod common_video_resolution; +pub mod generation_provider; diff --git a/crates/schema/public/enums_api/src/common/job_status.rs b/crates/schema/public/enums_api/src/common/job_status.rs new file mode 100644 index 0000000000..d2d65d2122 --- /dev/null +++ b/crates/schema/public/enums_api/src/common/job_status.rs @@ -0,0 +1,76 @@ +use strum::EnumIter; +use utoipa::ToSchema; + +/// This is used in nearly every job system as an actual MySQL ENUM value: +/// +/// - tts_download_job +/// - tts_inference_job +/// - w2l_download_job +/// - w2l_inference_job +/// - generic_download_job +/// - (NOT generic_inference_job, which uses JobStatusPlus) +/// +/// See the documentation on the table for usage. +/// +/// DO NOT CHANGE VALUES WITHOUT A MIGRATION STRATEGY. + +#[derive(Clone, Debug, Copy, PartialEq, Eq, Hash, Ord, PartialOrd, Serialize, ToSchema, EnumIter, Deserialize)] +#[serde(rename_all = "snake_case")] + +pub enum JobStatus { + Pending, + Started, + CompleteSuccess, + CompleteFailure, + AttemptFailed, + Dead, +} + +#[cfg(test)] +mod tests { + use super::JobStatus; + use enums_shared::test_helpers::{assert_deserialization, assert_serialization}; + use strum::IntoEnumIterator; + + mod manual_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(JobStatus::Pending, "pending"); + assert_serialization(JobStatus::Started, "started"); + assert_serialization(JobStatus::CompleteSuccess, "complete_success"); + assert_serialization(JobStatus::CompleteFailure, "complete_failure"); + assert_serialization(JobStatus::AttemptFailed, "attempt_failed"); + assert_serialization(JobStatus::Dead, "dead"); + } + + #[test] + fn test_deserialization() { + assert_deserialization("pending", JobStatus::Pending); + assert_deserialization("started", JobStatus::Started); + assert_deserialization("complete_success", JobStatus::CompleteSuccess); + assert_deserialization("complete_failure", JobStatus::CompleteFailure); + assert_deserialization("attempt_failed", JobStatus::AttemptFailed); + assert_deserialization("dead", JobStatus::Dead); + } + + #[test] + fn variants_count_check() { + assert_eq!(JobStatus::iter().count(), 6); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip_json() { + for variant in JobStatus::iter() { + let json = serde_json::to_string(&variant).unwrap(); + let back: JobStatus = serde_json::from_str(&json).unwrap(); + assert_eq!(variant, back); + } + } + } +} diff --git a/crates/schema/public/enums_api/src/common/job_status_plus.rs b/crates/schema/public/enums_api/src/common/job_status_plus.rs new file mode 100644 index 0000000000..b730e18246 --- /dev/null +++ b/crates/schema/public/enums_api/src/common/job_status_plus.rs @@ -0,0 +1,78 @@ +use strum::EnumIter; +use utoipa::ToSchema; + +/// This is used in newer jobs (that add additional enum states) +/// +/// - generic_inference_job +/// - (no other jobs yet) +/// +/// See the documentation on the table for usage. +/// +/// DO NOT CHANGE VALUES WITHOUT A MIGRATION STRATEGY. + +#[derive(Clone, Debug, Copy, PartialEq, Eq, Hash, Ord, PartialOrd, Serialize, EnumIter, Deserialize, ToSchema)] +#[serde(rename_all = "snake_case")] + +pub enum JobStatusPlus { + Pending, + Started, + CompleteSuccess, + CompleteFailure, + AttemptFailed, + Dead, + CancelledByUser, + CancelledBySystem, +} + +#[cfg(test)] +mod tests { + use super::JobStatusPlus; + use enums_shared::test_helpers::{assert_deserialization, assert_serialization}; + use strum::IntoEnumIterator; + + mod manual_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(JobStatusPlus::Pending, "pending"); + assert_serialization(JobStatusPlus::Started, "started"); + assert_serialization(JobStatusPlus::CompleteSuccess, "complete_success"); + assert_serialization(JobStatusPlus::CompleteFailure, "complete_failure"); + assert_serialization(JobStatusPlus::AttemptFailed, "attempt_failed"); + assert_serialization(JobStatusPlus::Dead, "dead"); + assert_serialization(JobStatusPlus::CancelledByUser, "cancelled_by_user"); + assert_serialization(JobStatusPlus::CancelledBySystem, "cancelled_by_system"); + } + + #[test] + fn test_deserialization() { + assert_deserialization("pending", JobStatusPlus::Pending); + assert_deserialization("started", JobStatusPlus::Started); + assert_deserialization("complete_success", JobStatusPlus::CompleteSuccess); + assert_deserialization("complete_failure", JobStatusPlus::CompleteFailure); + assert_deserialization("attempt_failed", JobStatusPlus::AttemptFailed); + assert_deserialization("dead", JobStatusPlus::Dead); + assert_deserialization("cancelled_by_user", JobStatusPlus::CancelledByUser); + assert_deserialization("cancelled_by_system", JobStatusPlus::CancelledBySystem); + } + + #[test] + fn variants_count_check() { + assert_eq!(JobStatusPlus::iter().count(), 8); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip_json() { + for variant in JobStatusPlus::iter() { + let json = serde_json::to_string(&variant).unwrap(); + let back: JobStatusPlus = serde_json::from_str(&json).unwrap(); + assert_eq!(variant, back); + } + } + } +} diff --git a/crates/schema/public/enums_api/src/common/mod.rs b/crates/schema/public/enums_api/src/common/mod.rs new file mode 100644 index 0000000000..972e0c2ae4 --- /dev/null +++ b/crates/schema/public/enums_api/src/common/mod.rs @@ -0,0 +1,12 @@ +pub mod artcraft_credits_pack_slug; +pub mod artcraft_subscription_slug; +pub mod generation; +pub mod job_status; +pub mod job_status_plus; +pub mod model_type; +pub mod payments_namespace; +pub mod sqlite; +pub mod stripe_subscription_status; +pub mod view_as; +pub mod visibility; +pub mod vocoder_type; diff --git a/crates/schema/public/enums_api/src/common/model_type.rs b/crates/schema/public/enums_api/src/common/model_type.rs new file mode 100644 index 0000000000..25892c07db --- /dev/null +++ b/crates/schema/public/enums_api/src/common/model_type.rs @@ -0,0 +1,280 @@ +use strum::EnumIter; +use utoipa::ToSchema; + +/// NB: This will be used by a variety of tables (MySQL and sqlite)! +/// Keep the max length to 24 characters. +#[derive(Clone, Debug, Copy, PartialEq, Eq, Hash, Ord, PartialOrd, Serialize, EnumIter, Deserialize, ToSchema)] +#[serde(rename_all = "snake_case")] + +pub enum ModelType { + // Image models + #[serde(rename = "flux_1_dev")] + Flux1Dev, + #[serde(rename = "flux_1_schnell")] + Flux1Schnell, + #[serde(rename = "flux_dev_juggernaut")] + FluxDevJuggernaut, + #[serde(rename = "flux_pro_1")] + FluxPro1, + #[serde(rename = "flux_pro_1p1")] + FluxPro11, + #[serde(rename = "flux_pro_1p1_ultra")] + FluxPro11Ultra, + #[serde(rename = "flux_pro_kontext_max")] + FluxProKontextMax, + #[serde(rename = "flux_2_lora_angles")] + Flux2LoraAngles, + #[serde(rename = "gpt_image_1")] + GptImage1, + #[serde(rename = "gpt_image_1p5")] + GptImage1p5, + // Generic grok image model without a version + #[serde(rename = "grok_image")] + GrokImage, + #[serde(rename = "recraft_3")] + Recraft3, + #[serde(rename = "seededit_3")] + SeedEdit3, + #[serde(rename = "qwen")] + Qwen, + #[serde(rename = "qwen_edit_2511_angles")] + QwenEdit2511Angles, + /// Gemini 2.5 Flash, AKA "Nano Banana" + #[serde(rename = "gemini_25_flash")] + Gemini25Flash, + #[serde(rename = "nano_banana")] + NanoBanana, + #[serde(rename = "nano_banana_2")] + NanoBanana2, + #[serde(rename = "nano_banana_pro")] + NanoBananaPro, + #[serde(rename = "seedream_4")] + Seedream4, + #[serde(rename = "seedream_4p5")] + Seedream4p5, + #[serde(rename = "seedream_5_lite")] + Seedream5Lite, + + /// Midjourney without distinguishing a model type or version + #[serde(rename = "midjourney")] + Midjourney, + #[serde(rename = "midjourney_v6")] + MidjourneyV6, + #[serde(rename = "midjourney_v6p1")] + MidjourneyV6p1, + #[serde(rename = "midjourney_v6p1_raw")] + MidjourneyV6p1Raw, + #[serde(rename = "midjourney_v7")] + MidjourneyV7, + #[serde(rename = "midjourney_v7_draft")] + MidjourneyV7Draft, + #[serde(rename = "midjourney_v7_draft_raw")] + MidjourneyV7DraftRaw, + #[serde(rename = "midjourney_v7_raw")] + MidjourneyV7Raw, + + //// Image Infill models + //#[serde(rename = "flux_pro_1_infill")] + //FluxPro1Infill, + + // Video models + + // Generic grok video model without a version + #[serde(rename = "grok_video")] + GrokVideo, + #[serde(rename = "kling_1p6_pro")] + Kling16Pro, + #[serde(rename = "kling_2p1_pro")] + Kling21Pro, + #[serde(rename = "kling_2p1_master")] + Kling21Master, + #[serde(rename = "kling_2p5_turbo_pro")] + Kling2p5TurboPro, + #[serde(rename = "kling_2p6_pro")] + Kling2p6Pro, + #[serde(rename = "kling_3p0_standard")] + Kling3p0Standard, + #[serde(rename = "kling_3p0_pro")] + Kling3p0Pro, + #[serde(rename = "seedance_1p0_lite")] + Seedance10Lite, + #[serde(rename = "seedance_1p0_pro")] + Seedance10Pro, + #[serde(rename = "seedance_1p5_pro")] + Seedance1p5Pro, + #[serde(rename = "seedance_2p0")] + Seedance2p0, + #[serde(rename = "sora_2")] + Sora2, + #[serde(rename = "sora_2_pro")] + Sora2Pro, + #[serde(rename = "veo_2")] + Veo2, + #[serde(rename = "veo_3")] + Veo3, + #[serde(rename = "veo_3_fast")] + Veo3Fast, + #[serde(rename = "veo_3p1")] + Veo3p1, + #[serde(rename = "veo_3p1_fast")] + Veo3p1Fast, + + // 3D Object generation models + #[serde(rename = "hunyuan_3d_2p0")] + Hunyuan3d2_0, + #[serde(rename = "hunyuan_3d_2p1")] + Hunyuan3d2_1, + #[serde(rename = "hunyuan_3d_3")] + Hunyuan3d3, + + // Splat generation models (World Labs) + #[serde(rename = "marble_0p1_mini")] + Marble0p1Mini, + #[serde(rename = "marble_0p1_plus")] + Marble0p1Plus, +} + +#[cfg(test)] +mod tests { + use super::ModelType; + use enums_shared::test_helpers::{assert_deserialization, assert_serialization}; + use strum::IntoEnumIterator; + + mod manual_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(ModelType::Flux1Dev, "flux_1_dev"); + assert_serialization(ModelType::Flux1Schnell, "flux_1_schnell"); + assert_serialization(ModelType::FluxDevJuggernaut, "flux_dev_juggernaut"); + assert_serialization(ModelType::FluxPro1, "flux_pro_1"); + assert_serialization(ModelType::FluxPro11, "flux_pro_1p1"); + assert_serialization(ModelType::FluxPro11Ultra, "flux_pro_1p1_ultra"); + assert_serialization(ModelType::FluxProKontextMax, "flux_pro_kontext_max"); + assert_serialization(ModelType::Flux2LoraAngles, "flux_2_lora_angles"); + assert_serialization(ModelType::GptImage1, "gpt_image_1"); + assert_serialization(ModelType::GptImage1p5, "gpt_image_1p5"); + assert_serialization(ModelType::GrokImage, "grok_image"); + assert_serialization(ModelType::Recraft3, "recraft_3"); + assert_serialization(ModelType::SeedEdit3, "seededit_3"); + assert_serialization(ModelType::Qwen, "qwen"); + assert_serialization(ModelType::QwenEdit2511Angles, "qwen_edit_2511_angles"); + assert_serialization(ModelType::Gemini25Flash, "gemini_25_flash"); + assert_serialization(ModelType::NanoBanana, "nano_banana"); + assert_serialization(ModelType::NanoBanana2, "nano_banana_2"); + assert_serialization(ModelType::NanoBananaPro, "nano_banana_pro"); + assert_serialization(ModelType::Seedream4, "seedream_4"); + assert_serialization(ModelType::Seedream4p5, "seedream_4p5"); + assert_serialization(ModelType::Seedream5Lite, "seedream_5_lite"); + assert_serialization(ModelType::Midjourney, "midjourney"); + assert_serialization(ModelType::MidjourneyV6, "midjourney_v6"); + assert_serialization(ModelType::MidjourneyV6p1, "midjourney_v6p1"); + assert_serialization(ModelType::MidjourneyV6p1Raw, "midjourney_v6p1_raw"); + assert_serialization(ModelType::MidjourneyV7, "midjourney_v7"); + assert_serialization(ModelType::MidjourneyV7Draft, "midjourney_v7_draft"); + assert_serialization(ModelType::MidjourneyV7DraftRaw, "midjourney_v7_draft_raw"); + assert_serialization(ModelType::MidjourneyV7Raw, "midjourney_v7_raw"); + assert_serialization(ModelType::GrokVideo, "grok_video"); + assert_serialization(ModelType::Kling16Pro, "kling_1p6_pro"); + assert_serialization(ModelType::Kling21Pro, "kling_2p1_pro"); + assert_serialization(ModelType::Kling21Master, "kling_2p1_master"); + assert_serialization(ModelType::Kling2p5TurboPro, "kling_2p5_turbo_pro"); + assert_serialization(ModelType::Kling2p6Pro, "kling_2p6_pro"); + assert_serialization(ModelType::Kling3p0Standard, "kling_3p0_standard"); + assert_serialization(ModelType::Kling3p0Pro, "kling_3p0_pro"); + assert_serialization(ModelType::Seedance10Lite, "seedance_1p0_lite"); + assert_serialization(ModelType::Seedance10Pro, "seedance_1p0_pro"); + assert_serialization(ModelType::Seedance1p5Pro, "seedance_1p5_pro"); + assert_serialization(ModelType::Seedance2p0, "seedance_2p0"); + assert_serialization(ModelType::Sora2, "sora_2"); + assert_serialization(ModelType::Sora2Pro, "sora_2_pro"); + assert_serialization(ModelType::Veo2, "veo_2"); + assert_serialization(ModelType::Veo3, "veo_3"); + assert_serialization(ModelType::Veo3Fast, "veo_3_fast"); + assert_serialization(ModelType::Veo3p1, "veo_3p1"); + assert_serialization(ModelType::Veo3p1Fast, "veo_3p1_fast"); + assert_serialization(ModelType::Hunyuan3d2_0, "hunyuan_3d_2p0"); + assert_serialization(ModelType::Hunyuan3d2_1, "hunyuan_3d_2p1"); + assert_serialization(ModelType::Hunyuan3d3, "hunyuan_3d_3"); + assert_serialization(ModelType::Marble0p1Mini, "marble_0p1_mini"); + assert_serialization(ModelType::Marble0p1Plus, "marble_0p1_plus"); + } + + #[test] + fn test_deserialization() { + assert_deserialization("flux_1_dev", ModelType::Flux1Dev); + assert_deserialization("flux_1_schnell", ModelType::Flux1Schnell); + assert_deserialization("flux_dev_juggernaut", ModelType::FluxDevJuggernaut); + assert_deserialization("flux_pro_1", ModelType::FluxPro1); + assert_deserialization("flux_pro_1p1", ModelType::FluxPro11); + assert_deserialization("flux_pro_1p1_ultra", ModelType::FluxPro11Ultra); + assert_deserialization("flux_pro_kontext_max", ModelType::FluxProKontextMax); + assert_deserialization("flux_2_lora_angles", ModelType::Flux2LoraAngles); + assert_deserialization("gpt_image_1", ModelType::GptImage1); + assert_deserialization("gpt_image_1p5", ModelType::GptImage1p5); + assert_deserialization("grok_image", ModelType::GrokImage); + assert_deserialization("recraft_3", ModelType::Recraft3); + assert_deserialization("seededit_3", ModelType::SeedEdit3); + assert_deserialization("qwen", ModelType::Qwen); + assert_deserialization("qwen_edit_2511_angles", ModelType::QwenEdit2511Angles); + assert_deserialization("gemini_25_flash", ModelType::Gemini25Flash); + assert_deserialization("nano_banana", ModelType::NanoBanana); + assert_deserialization("nano_banana_2", ModelType::NanoBanana2); + assert_deserialization("nano_banana_pro", ModelType::NanoBananaPro); + assert_deserialization("seedream_4", ModelType::Seedream4); + assert_deserialization("seedream_4p5", ModelType::Seedream4p5); + assert_deserialization("seedream_5_lite", ModelType::Seedream5Lite); + assert_deserialization("midjourney", ModelType::Midjourney); + assert_deserialization("midjourney_v6", ModelType::MidjourneyV6); + assert_deserialization("midjourney_v6p1", ModelType::MidjourneyV6p1); + assert_deserialization("midjourney_v6p1_raw", ModelType::MidjourneyV6p1Raw); + assert_deserialization("midjourney_v7", ModelType::MidjourneyV7); + assert_deserialization("midjourney_v7_draft", ModelType::MidjourneyV7Draft); + assert_deserialization("midjourney_v7_draft_raw", ModelType::MidjourneyV7DraftRaw); + assert_deserialization("midjourney_v7_raw", ModelType::MidjourneyV7Raw); + assert_deserialization("grok_video", ModelType::GrokVideo); + assert_deserialization("kling_1p6_pro", ModelType::Kling16Pro); + assert_deserialization("kling_2p1_pro", ModelType::Kling21Pro); + assert_deserialization("kling_2p1_master", ModelType::Kling21Master); + assert_deserialization("kling_2p5_turbo_pro", ModelType::Kling2p5TurboPro); + assert_deserialization("kling_2p6_pro", ModelType::Kling2p6Pro); + assert_deserialization("kling_3p0_standard", ModelType::Kling3p0Standard); + assert_deserialization("kling_3p0_pro", ModelType::Kling3p0Pro); + assert_deserialization("seedance_1p0_lite", ModelType::Seedance10Lite); + assert_deserialization("seedance_1p0_pro", ModelType::Seedance10Pro); + assert_deserialization("seedance_1p5_pro", ModelType::Seedance1p5Pro); + assert_deserialization("seedance_2p0", ModelType::Seedance2p0); + assert_deserialization("sora_2", ModelType::Sora2); + assert_deserialization("sora_2_pro", ModelType::Sora2Pro); + assert_deserialization("veo_2", ModelType::Veo2); + assert_deserialization("veo_3", ModelType::Veo3); + assert_deserialization("veo_3_fast", ModelType::Veo3Fast); + assert_deserialization("veo_3p1", ModelType::Veo3p1); + assert_deserialization("veo_3p1_fast", ModelType::Veo3p1Fast); + assert_deserialization("hunyuan_3d_2p0", ModelType::Hunyuan3d2_0); + assert_deserialization("hunyuan_3d_2p1", ModelType::Hunyuan3d2_1); + assert_deserialization("hunyuan_3d_3", ModelType::Hunyuan3d3); + assert_deserialization("marble_0p1_mini", ModelType::Marble0p1Mini); + assert_deserialization("marble_0p1_plus", ModelType::Marble0p1Plus); + } + + #[test] + fn variants_count_check() { + assert_eq!(ModelType::iter().count(), 54); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip_json() { + for variant in ModelType::iter() { + let json = serde_json::to_string(&variant).unwrap(); + let back: ModelType = serde_json::from_str(&json).unwrap(); + assert_eq!(variant, back); + } + } + } +} diff --git a/crates/schema/public/enums_api/src/common/payments_namespace.rs b/crates/schema/public/enums_api/src/common/payments_namespace.rs new file mode 100644 index 0000000000..f81d280028 --- /dev/null +++ b/crates/schema/public/enums_api/src/common/payments_namespace.rs @@ -0,0 +1,55 @@ +use strum::EnumIter; +use utoipa::ToSchema; + +/// NB: This will be used by a variety of tables (MySQL and sqlite)! +/// Keep the max length to 16 characters. +#[derive(Clone, Debug, Copy, PartialEq, Eq, Hash, Ord, PartialOrd, Serialize, EnumIter, Deserialize, ToSchema)] +#[serde(rename_all = "snake_case")] + +pub enum PaymentsNamespace { + #[serde(rename = "artcraft")] + Artcraft, + #[serde(rename = "fakeyou")] + FakeYou, +} + +#[cfg(test)] +mod tests { + use super::PaymentsNamespace; + use enums_shared::test_helpers::{assert_deserialization, assert_serialization}; + use strum::IntoEnumIterator; + + mod manual_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(PaymentsNamespace::Artcraft, "artcraft"); + assert_serialization(PaymentsNamespace::FakeYou, "fakeyou"); + } + + #[test] + fn test_deserialization() { + assert_deserialization("artcraft", PaymentsNamespace::Artcraft); + assert_deserialization("fakeyou", PaymentsNamespace::FakeYou); + } + + #[test] + fn variants_count_check() { + assert_eq!(PaymentsNamespace::iter().count(), 2); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip_json() { + for variant in PaymentsNamespace::iter() { + let json = serde_json::to_string(&variant).unwrap(); + let back: PaymentsNamespace = serde_json::from_str(&json).unwrap(); + assert_eq!(variant, back); + } + } + } +} diff --git a/crates/schema/public/enums_api/src/common/sqlite/awaitable_job_status.rs b/crates/schema/public/enums_api/src/common/sqlite/awaitable_job_status.rs new file mode 100644 index 0000000000..41b1d2a670 --- /dev/null +++ b/crates/schema/public/enums_api/src/common/sqlite/awaitable_job_status.rs @@ -0,0 +1,82 @@ +use serde::Deserialize; +use serde::Serialize; +use strum::EnumIter; +use utoipa::ToSchema; + +/// Used in the following SqLite tables and columns: +/// `web_scraping_targets` . `maybe_skip_reason`. +#[derive(Clone, Debug, Copy, Eq, PartialEq, Hash, Deserialize, Serialize, EnumIter, ToSchema)] + +pub enum AwaitableJobStatus { + #[serde(rename = "not_ready")] + NotReady, + + #[serde(rename = "ready_waiting")] + ReadyWaiting, + + #[serde(rename = "processing")] + Processing, + + #[serde(rename = "retryably_failed")] + RetryablyFailed, + + #[serde(rename = "permanently_failed")] + PermanentlyFailed, + + #[serde(rename = "skipped")] + Skipped, + + #[serde(rename = "done")] + Done, +} + +#[cfg(test)] +mod tests { + use super::AwaitableJobStatus; + use enums_shared::test_helpers::{assert_deserialization, assert_serialization}; + use strum::IntoEnumIterator; + + mod manual_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(AwaitableJobStatus::NotReady, "not_ready"); + assert_serialization(AwaitableJobStatus::ReadyWaiting, "ready_waiting"); + assert_serialization(AwaitableJobStatus::Processing, "processing"); + assert_serialization(AwaitableJobStatus::RetryablyFailed, "retryably_failed"); + assert_serialization(AwaitableJobStatus::PermanentlyFailed, "permanently_failed"); + assert_serialization(AwaitableJobStatus::Skipped, "skipped"); + assert_serialization(AwaitableJobStatus::Done, "done"); + } + + #[test] + fn test_deserialization() { + assert_deserialization("not_ready", AwaitableJobStatus::NotReady); + assert_deserialization("ready_waiting", AwaitableJobStatus::ReadyWaiting); + assert_deserialization("processing", AwaitableJobStatus::Processing); + assert_deserialization("retryably_failed", AwaitableJobStatus::RetryablyFailed); + assert_deserialization("permanently_failed", AwaitableJobStatus::PermanentlyFailed); + assert_deserialization("skipped", AwaitableJobStatus::Skipped); + assert_deserialization("done", AwaitableJobStatus::Done); + } + + #[test] + fn variants_count_check() { + assert_eq!(AwaitableJobStatus::iter().count(), 7); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip_json() { + for variant in AwaitableJobStatus::iter() { + let json = serde_json::to_string(&variant).unwrap(); + let back: AwaitableJobStatus = serde_json::from_str(&json).unwrap(); + assert_eq!(variant, back); + } + } + } +} diff --git a/crates/schema/public/enums_api/src/common/sqlite/chatbot_job_status.rs b/crates/schema/public/enums_api/src/common/sqlite/chatbot_job_status.rs new file mode 100644 index 0000000000..41975b4028 --- /dev/null +++ b/crates/schema/public/enums_api/src/common/sqlite/chatbot_job_status.rs @@ -0,0 +1,71 @@ +use serde::Deserialize; +use serde::Serialize; +use strum::EnumIter; +use utoipa::ToSchema; + +/// Used in the SqLite `web_scraping_targets` table in a `TEXT` field named `scraping_status`. +#[derive(Clone, Debug, Copy, Eq, PartialEq, Hash, Deserialize, Serialize, EnumIter, ToSchema)] + +pub enum ChatbotJobStatus { + #[serde(rename = "new")] + New, + + #[serde(rename = "skipped")] + Skipped, + + #[serde(rename = "failed")] + Failed, + + #[serde(rename = "permanently_failed")] + PermanentlyFailed, + + #[serde(rename = "success")] + Success, +} + +#[cfg(test)] +mod tests { + use super::ChatbotJobStatus; + use enums_shared::test_helpers::{assert_deserialization, assert_serialization}; + use strum::IntoEnumIterator; + + mod manual_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(ChatbotJobStatus::New, "new"); + assert_serialization(ChatbotJobStatus::Skipped, "skipped"); + assert_serialization(ChatbotJobStatus::Failed, "failed"); + assert_serialization(ChatbotJobStatus::PermanentlyFailed, "permanently_failed"); + assert_serialization(ChatbotJobStatus::Success, "success"); + } + + #[test] + fn test_deserialization() { + assert_deserialization("new", ChatbotJobStatus::New); + assert_deserialization("skipped", ChatbotJobStatus::Skipped); + assert_deserialization("failed", ChatbotJobStatus::Failed); + assert_deserialization("permanently_failed", ChatbotJobStatus::PermanentlyFailed); + assert_deserialization("success", ChatbotJobStatus::Success); + } + + #[test] + fn variants_count_check() { + assert_eq!(ChatbotJobStatus::iter().count(), 5); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip_json() { + for variant in ChatbotJobStatus::iter() { + let json = serde_json::to_string(&variant).unwrap(); + let back: ChatbotJobStatus = serde_json::from_str(&json).unwrap(); + assert_eq!(variant, back); + } + } + } +} diff --git a/crates/schema/public/enums_api/src/common/sqlite/mod.rs b/crates/schema/public/enums_api/src/common/sqlite/mod.rs new file mode 100644 index 0000000000..7659a1e044 --- /dev/null +++ b/crates/schema/public/enums_api/src/common/sqlite/mod.rs @@ -0,0 +1,4 @@ +pub mod awaitable_job_status; +pub mod chatbot_job_status; +pub mod skip_reason; +pub mod web_content_type; diff --git a/crates/schema/public/enums_api/src/common/sqlite/skip_reason.rs b/crates/schema/public/enums_api/src/common/sqlite/skip_reason.rs new file mode 100644 index 0000000000..e88fec355e --- /dev/null +++ b/crates/schema/public/enums_api/src/common/sqlite/skip_reason.rs @@ -0,0 +1,77 @@ +use serde::Deserialize; +use serde::Serialize; +use strum::EnumIter; +use utoipa::ToSchema; + +/// Used in the following SqLite tables and columns: +/// `web_scraping_targets` . `maybe_skip_reason`. +#[derive(Clone, Debug, Copy, Eq, PartialEq, Hash, Deserialize, Serialize, EnumIter, ToSchema)] + +pub enum SkipReason { + #[serde(rename = "empty_content")] + EmptyContent, + + #[serde(rename = "advertisement")] + Advertisement, + + #[serde(rename = "video_content")] + VideoContent, + + #[serde(rename = "filtered_topic")] + FilteredTopic, + + #[serde(rename = "filtered_topic_politics")] + FilteredTopicPolitics, + + #[serde(rename = "nobody_cares")] + NobodyCares, +} + +#[cfg(test)] +mod tests { + use super::SkipReason; + use enums_shared::test_helpers::{assert_deserialization, assert_serialization}; + use strum::IntoEnumIterator; + + mod manual_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(SkipReason::EmptyContent, "empty_content"); + assert_serialization(SkipReason::Advertisement, "advertisement"); + assert_serialization(SkipReason::VideoContent, "video_content"); + assert_serialization(SkipReason::FilteredTopic, "filtered_topic"); + assert_serialization(SkipReason::FilteredTopicPolitics, "filtered_topic_politics"); + assert_serialization(SkipReason::NobodyCares, "nobody_cares"); + } + + #[test] + fn test_deserialization() { + assert_deserialization("empty_content", SkipReason::EmptyContent); + assert_deserialization("advertisement", SkipReason::Advertisement); + assert_deserialization("video_content", SkipReason::VideoContent); + assert_deserialization("filtered_topic", SkipReason::FilteredTopic); + assert_deserialization("filtered_topic_politics", SkipReason::FilteredTopicPolitics); + assert_deserialization("nobody_cares", SkipReason::NobodyCares); + } + + #[test] + fn variants_count_check() { + assert_eq!(SkipReason::iter().count(), 6); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip_json() { + for variant in SkipReason::iter() { + let json = serde_json::to_string(&variant).unwrap(); + let back: SkipReason = serde_json::from_str(&json).unwrap(); + assert_eq!(variant, back); + } + } + } +} diff --git a/crates/schema/public/enums_api/src/common/sqlite/web_content_type.rs b/crates/schema/public/enums_api/src/common/sqlite/web_content_type.rs new file mode 100644 index 0000000000..cda4a929fb --- /dev/null +++ b/crates/schema/public/enums_api/src/common/sqlite/web_content_type.rs @@ -0,0 +1,98 @@ +use serde::Deserialize; +use serde::Serialize; +use strum::EnumIter; +use utoipa::ToSchema; + +/// Used in the SqLite `web_scraping_targets` table in a `TEXT` field named `web_content_type`. +/// Used in the SqLite `news_story_productions` table in a `TEXT` field named `web_content_type`. +/// Used in the SqLite `news_stories` table in a `TEXT` field named `web_content_type`. +#[derive(Clone, Debug, Copy, Eq, PartialEq, Hash, Deserialize, Serialize, EnumIter, ToSchema)] + +pub enum WebContentType { + #[serde(rename = "cbs_news_article")] + CbsNewsArticle, + + #[serde(rename = "cnn_article")] + CnnArticle, + + #[serde(rename = "gizmodo_article")] + GizmodoArticle, + + #[serde(rename = "hacker_news_thread")] + HackerNewsThread, + + #[serde(rename = "kotaku_article")] + KotakuArticle, + + #[serde(rename = "reddit_thread")] + RedditThread, + + #[serde(rename = "slashdot_article")] + SlashdotArticle, + + #[serde(rename = "substack_post")] + SubstackPost, + + #[serde(rename = "techcrunch_article")] + TechCrunchArticle, + + #[serde(rename = "the_guardian_article")] + TheGuardianArticle, +} + +#[cfg(test)] +mod tests { + use super::WebContentType; + use enums_shared::test_helpers::{assert_deserialization, assert_serialization}; + use strum::IntoEnumIterator; + + mod manual_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(WebContentType::CbsNewsArticle, "cbs_news_article"); + assert_serialization(WebContentType::CnnArticle, "cnn_article"); + assert_serialization(WebContentType::GizmodoArticle, "gizmodo_article"); + assert_serialization(WebContentType::HackerNewsThread, "hacker_news_thread"); + assert_serialization(WebContentType::KotakuArticle, "kotaku_article"); + assert_serialization(WebContentType::RedditThread, "reddit_thread"); + assert_serialization(WebContentType::SlashdotArticle, "slashdot_article"); + assert_serialization(WebContentType::SubstackPost, "substack_post"); + assert_serialization(WebContentType::TechCrunchArticle, "techcrunch_article"); + assert_serialization(WebContentType::TheGuardianArticle, "the_guardian_article"); + } + + #[test] + fn test_deserialization() { + assert_deserialization("cbs_news_article", WebContentType::CbsNewsArticle); + assert_deserialization("cnn_article", WebContentType::CnnArticle); + assert_deserialization("gizmodo_article", WebContentType::GizmodoArticle); + assert_deserialization("hacker_news_thread", WebContentType::HackerNewsThread); + assert_deserialization("kotaku_article", WebContentType::KotakuArticle); + assert_deserialization("reddit_thread", WebContentType::RedditThread); + assert_deserialization("slashdot_article", WebContentType::SlashdotArticle); + assert_deserialization("substack_post", WebContentType::SubstackPost); + assert_deserialization("techcrunch_article", WebContentType::TechCrunchArticle); + assert_deserialization("the_guardian_article", WebContentType::TheGuardianArticle); + } + + #[test] + fn variants_count_check() { + assert_eq!(WebContentType::iter().count(), 10); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip_json() { + for variant in WebContentType::iter() { + let json = serde_json::to_string(&variant).unwrap(); + let back: WebContentType = serde_json::from_str(&json).unwrap(); + assert_eq!(variant, back); + } + } + } +} diff --git a/crates/schema/public/enums_api/src/common/stripe_subscription_status.rs b/crates/schema/public/enums_api/src/common/stripe_subscription_status.rs new file mode 100644 index 0000000000..79fa8a2a35 --- /dev/null +++ b/crates/schema/public/enums_api/src/common/stripe_subscription_status.rs @@ -0,0 +1,69 @@ +use strum::EnumIter; +use utoipa::ToSchema; + +#[derive(Clone, Debug, Copy, PartialEq, Eq, Hash, Ord, PartialOrd, Serialize, EnumIter, Deserialize, ToSchema)] +#[serde(rename_all = "snake_case")] + +pub enum StripeSubscriptionStatus { + Active, + Canceled, + Incomplete, + IncompleteExpired, + PastDue, + Trialing, + Unpaid, + Paused, +} + +#[cfg(test)] +mod tests { + use super::StripeSubscriptionStatus; + use enums_shared::test_helpers::{assert_deserialization, assert_serialization}; + use strum::IntoEnumIterator; + + mod manual_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(StripeSubscriptionStatus::Active, "active"); + assert_serialization(StripeSubscriptionStatus::Canceled, "canceled"); + assert_serialization(StripeSubscriptionStatus::Incomplete, "incomplete"); + assert_serialization(StripeSubscriptionStatus::IncompleteExpired, "incomplete_expired"); + assert_serialization(StripeSubscriptionStatus::PastDue, "past_due"); + assert_serialization(StripeSubscriptionStatus::Trialing, "trialing"); + assert_serialization(StripeSubscriptionStatus::Unpaid, "unpaid"); + assert_serialization(StripeSubscriptionStatus::Paused, "paused"); + } + + #[test] + fn test_deserialization() { + assert_deserialization("active", StripeSubscriptionStatus::Active); + assert_deserialization("canceled", StripeSubscriptionStatus::Canceled); + assert_deserialization("incomplete", StripeSubscriptionStatus::Incomplete); + assert_deserialization("incomplete_expired", StripeSubscriptionStatus::IncompleteExpired); + assert_deserialization("past_due", StripeSubscriptionStatus::PastDue); + assert_deserialization("trialing", StripeSubscriptionStatus::Trialing); + assert_deserialization("unpaid", StripeSubscriptionStatus::Unpaid); + assert_deserialization("paused", StripeSubscriptionStatus::Paused); + } + + #[test] + fn variants_count_check() { + assert_eq!(StripeSubscriptionStatus::iter().count(), 8); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip_json() { + for variant in StripeSubscriptionStatus::iter() { + let json = serde_json::to_string(&variant).unwrap(); + let back: StripeSubscriptionStatus = serde_json::from_str(&json).unwrap(); + assert_eq!(variant, back); + } + } + } +} diff --git a/crates/schema/public/enums_api/src/common/view_as.rs b/crates/schema/public/enums_api/src/common/view_as.rs new file mode 100644 index 0000000000..8f9f0ab4f8 --- /dev/null +++ b/crates/schema/public/enums_api/src/common/view_as.rs @@ -0,0 +1,60 @@ +use strum::EnumIter; +use utoipa::ToSchema; + +#[derive(Clone, Debug, Copy, Eq, PartialEq, Deserialize, Serialize, EnumIter, ToSchema)] +#[serde(rename_all = "snake_case")] + +pub enum ViewAs { + /// Public entities are able to be listed in public lists. + /// It does not mean that they necessarily will be (eg. they could be "mod unapproved" or deleted). + Author, + /// Hidden entities are not shown in public lists, but the URL to them may be given out freely. + /// They are available to non-logged-in users as long as they have the URL. + Moderator, + /// Private entities should only be available to the creator, a list of approved users, and + /// website moderation staff. + AnotherUser, +} + +#[cfg(test)] +mod tests { + use super::ViewAs; + use enums_shared::test_helpers::{assert_deserialization, assert_serialization}; + use strum::IntoEnumIterator; + + mod manual_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(ViewAs::Author, "author"); + assert_serialization(ViewAs::Moderator, "moderator"); + assert_serialization(ViewAs::AnotherUser, "another_user"); + } + + #[test] + fn test_deserialization() { + assert_deserialization("author", ViewAs::Author); + assert_deserialization("moderator", ViewAs::Moderator); + assert_deserialization("another_user", ViewAs::AnotherUser); + } + + #[test] + fn variants_count_check() { + assert_eq!(ViewAs::iter().count(), 3); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip_json() { + for variant in ViewAs::iter() { + let json = serde_json::to_string(&variant).unwrap(); + let back: ViewAs = serde_json::from_str(&json).unwrap(); + assert_eq!(variant, back); + } + } + } +} diff --git a/crates/schema/public/enums_api/src/common/visibility.rs b/crates/schema/public/enums_api/src/common/visibility.rs new file mode 100644 index 0000000000..fd783e13d8 --- /dev/null +++ b/crates/schema/public/enums_api/src/common/visibility.rs @@ -0,0 +1,76 @@ +use strum::EnumIter; +/// Visibility +/// +/// Used in various database tables (as enums! careful!) and the HTTP API to convey +/// how the associated entity should be made visible to the public. +/// +/// To use this in a query, the query must have type annotations. +/// See: https://www.gitmemory.com/issue/launchbadge/sqlx/1241/847154375 +/// eg. preferred_tts_result_visibility as `preferred_tts_result_visibility: enums::common::visibility::Visibility` +/// +/// See also: https://docs.rs/sqlx/0.4.0-beta.1/sqlx/trait.Type.html +/// +/// *DO NOT CHANGE VALUES WITHOUT A MIGRATION STRATEGY!* + +use utoipa::ToSchema; + +#[derive(Clone, Debug, Copy, Eq, PartialEq, Deserialize, Serialize, EnumIter, ToSchema)] +#[serde(rename_all = "lowercase")] +pub enum Visibility { + /// Public entities are able to be listed in public lists. + /// It does not mean that they necessarily will be (eg. they could be "mod unapproved" or deleted). + Public, + /// Hidden entities are not shown in public lists, but the URL to them may be given out freely. + /// They are available to non-logged-in users as long as they have the URL. + Hidden, + /// Private entities should only be available to the creator, a list of approved users, and + /// website moderation staff. + Private, + + // TODO(bt, 2022-12-20): We need a "Shared" option where users can share it with a specified group. + // This should perhaps be its own type, eg. VisibilityV2., so that we don't use it in tables that + // have not yet been migrated to this scheme. +} + +#[cfg(test)] +mod tests { + use super::Visibility; + use enums_shared::test_helpers::{assert_deserialization, assert_serialization}; + use strum::IntoEnumIterator; + + mod manual_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(Visibility::Public, "public"); + assert_serialization(Visibility::Hidden, "hidden"); + assert_serialization(Visibility::Private, "private"); + } + + #[test] + fn test_deserialization() { + assert_deserialization("public", Visibility::Public); + assert_deserialization("hidden", Visibility::Hidden); + assert_deserialization("private", Visibility::Private); + } + + #[test] + fn variants_count_check() { + assert_eq!(Visibility::iter().count(), 3); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip_json() { + for variant in Visibility::iter() { + let json = serde_json::to_string(&variant).unwrap(); + let back: Visibility = serde_json::from_str(&json).unwrap(); + assert_eq!(variant, back); + } + } + } +} diff --git a/crates/schema/public/enums_api/src/common/vocoder_type.rs b/crates/schema/public/enums_api/src/common/vocoder_type.rs new file mode 100644 index 0000000000..e732f1e1e4 --- /dev/null +++ b/crates/schema/public/enums_api/src/common/vocoder_type.rs @@ -0,0 +1,64 @@ +use strum::EnumIter; +use utoipa::ToSchema; + +#[derive(Clone, Copy, Eq, PartialEq, Debug, Deserialize, Serialize, EnumIter, ToSchema)] + +pub enum VocoderType { + /// NB: Note - this is hifigan for Tacotron2. + /// Some work will be needed to unify this with other hifigan types. + #[serde(rename = "hifigan")] + HifiGan, + + #[serde(rename = "hifigan-superres")] + HifiGanSuperResolution, + + /// NB: Note - this is hifigan for SoftVC (our internal codename is "rocketvc"). + /// Some work will need to be done to unify this with other hifigan types. + /// NB(bt, 2025-07-09): It was so silly to try to obscure this. Both FakeYou and Uberduck are irrelevant now. + #[serde(rename = "hifigan_rocket_vc")] + HifiGanRocketVc, + +} + +#[cfg(test)] +mod tests { + use super::VocoderType; + use enums_shared::test_helpers::{assert_deserialization, assert_serialization}; + use strum::IntoEnumIterator; + + mod manual_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(VocoderType::HifiGan, "hifigan"); + assert_serialization(VocoderType::HifiGanSuperResolution, "hifigan-superres"); + assert_serialization(VocoderType::HifiGanRocketVc, "hifigan_rocket_vc"); + } + + #[test] + fn test_deserialization() { + assert_deserialization("hifigan", VocoderType::HifiGan); + assert_deserialization("hifigan-superres", VocoderType::HifiGanSuperResolution); + assert_deserialization("hifigan_rocket_vc", VocoderType::HifiGanRocketVc); + } + + #[test] + fn variants_count_check() { + assert_eq!(VocoderType::iter().count(), 3); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip_json() { + for variant in VocoderType::iter() { + let json = serde_json::to_string(&variant).unwrap(); + let back: VocoderType = serde_json::from_str(&json).unwrap(); + assert_eq!(variant, back); + } + } + } +} diff --git a/crates/schema/public/enums_api/src/lib.rs b/crates/schema/public/enums_api/src/lib.rs new file mode 100644 index 0000000000..7c71da2b31 --- /dev/null +++ b/crates/schema/public/enums_api/src/lib.rs @@ -0,0 +1,26 @@ +// Never allow these +#![forbid(private_bounds)] +#![forbid(private_interfaces)] +#![forbid(unused_must_use)] // NB: It's unsafe to not close/check some things + +// Okay to toggle +#![deny(unused_imports)] +#![forbid(unreachable_patterns)] +#![forbid(unused_mut)] +#![forbid(unused_variables)] + +// Always allow +#![allow(dead_code)] +#![allow(non_snake_case)] + +#[allow(unused_imports)] +#[macro_use] extern crate serde_derive; + +pub mod api_safe; +pub mod by_table; +pub mod common; +pub mod no_table; +pub mod tauri; + +// Re-export shared types +pub use enums_shared::error; diff --git a/crates/schema/public/enums_api/src/no_table/mod.rs b/crates/schema/public/enums_api/src/no_table/mod.rs new file mode 100644 index 0000000000..977ace7de9 --- /dev/null +++ b/crates/schema/public/enums_api/src/no_table/mod.rs @@ -0,0 +1,3 @@ +pub mod premium_product; +pub mod style_transfer; +pub mod video_dimensions; \ No newline at end of file diff --git a/crates/schema/public/enums_api/src/no_table/premium_product/mod.rs b/crates/schema/public/enums_api/src/no_table/premium_product/mod.rs new file mode 100644 index 0000000000..c6890ee97f --- /dev/null +++ b/crates/schema/public/enums_api/src/no_table/premium_product/mod.rs @@ -0,0 +1 @@ +pub mod premium_product_name; \ No newline at end of file diff --git a/crates/schema/public/enums_api/src/no_table/premium_product/premium_product_name.rs b/crates/schema/public/enums_api/src/no_table/premium_product/premium_product_name.rs new file mode 100644 index 0000000000..4aee1d58f9 --- /dev/null +++ b/crates/schema/public/enums_api/src/no_table/premium_product/premium_product_name.rs @@ -0,0 +1,69 @@ +use strum::EnumIter; +use utoipa::ToSchema; + +/// This enum is not backed by a particular database table. +/// This is used to count premium product uses for free and paid users. +/// +/// DO NOT CHANGE VALUES WITHOUT A MIGRATION STRATEGY. +#[derive(Clone, Debug, Copy, Eq, PartialEq, Ord, PartialOrd, Hash, Deserialize, Serialize, EnumIter, ToSchema)] +#[serde(rename_all = "snake_case")] + +pub enum PremiumProductName { + // NB: These keys are kept short to preserve space + #[serde(rename = "fa")] + FaceAnimator, + // NB: These keys are kept short to preserve space + #[serde(rename = "fm")] + FaceMirror, + // NB: These keys are kept short to preserve space + #[serde(rename = "lip")] + Lipsync, + // NB: These keys are kept short to preserve space + #[serde(rename = "vst")] + VideoStyleTransfer, +} + +#[cfg(test)] +mod tests { + use super::PremiumProductName; + use enums_shared::test_helpers::{assert_deserialization, assert_serialization}; + use strum::IntoEnumIterator; + + mod manual_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(PremiumProductName::FaceAnimator, "fa"); + assert_serialization(PremiumProductName::FaceMirror, "fm"); + assert_serialization(PremiumProductName::Lipsync, "lip"); + assert_serialization(PremiumProductName::VideoStyleTransfer, "vst"); + } + + #[test] + fn test_deserialization() { + assert_deserialization("fa", PremiumProductName::FaceAnimator); + assert_deserialization("fm", PremiumProductName::FaceMirror); + assert_deserialization("lip", PremiumProductName::Lipsync); + assert_deserialization("vst", PremiumProductName::VideoStyleTransfer); + } + + #[test] + fn variants_count_check() { + assert_eq!(PremiumProductName::iter().count(), 4); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip_json() { + for variant in PremiumProductName::iter() { + let json = serde_json::to_string(&variant).unwrap(); + let back: PremiumProductName = serde_json::from_str(&json).unwrap(); + assert_eq!(variant, back); + } + } + } +} diff --git a/crates/schema/public/enums_api/src/no_table/style_transfer/mod.rs b/crates/schema/public/enums_api/src/no_table/style_transfer/mod.rs new file mode 100644 index 0000000000..84c0a980bc --- /dev/null +++ b/crates/schema/public/enums_api/src/no_table/style_transfer/mod.rs @@ -0,0 +1 @@ +pub mod style_transfer_name; \ No newline at end of file diff --git a/crates/schema/public/enums_api/src/no_table/style_transfer/style_transfer_name.rs b/crates/schema/public/enums_api/src/no_table/style_transfer/style_transfer_name.rs new file mode 100644 index 0000000000..af930d75ec --- /dev/null +++ b/crates/schema/public/enums_api/src/no_table/style_transfer/style_transfer_name.rs @@ -0,0 +1,191 @@ +use strum::EnumIter; +use utoipa::ToSchema; + +/// This enum is not backed by a particular database table. +/// It's used in APIs and Jobs to agree upon ComfyUI style transfer style configurations. +/// +/// DO NOT CHANGE VALUES WITHOUT A MIGRATION STRATEGY. +#[derive(Clone, Debug, Copy, Eq, PartialEq, Ord, PartialOrd, Hash, Deserialize, Serialize, EnumIter, ToSchema)] +#[serde(rename_all = "snake_case")] + +pub enum StyleTransferName { + #[serde(rename = "anime_2_5d")] + Anime2_5D, + #[serde(rename = "anime_2d_flat")] + Anime2DFlat, + #[serde(rename = "cartoon_3d")] + Cartoon3D, + #[serde(rename = "comic_book")] + ComicBook, + #[serde(rename = "anime_ghibli")] + AnimeGhibli, + #[serde(rename = "ink_punk")] + InkPunk, + #[serde(rename = "ink_splash")] + InkSplash, + #[serde(rename = "ink_bw_style")] + InkBWStyle, + #[serde(rename = "jojo_style")] + JojoStyle, + #[serde(rename = "paper_origami")] + PaperOrigami, + #[serde(rename = "pixel_art")] + PixelArt, + #[serde(rename = "pop_art")] + PopArt, + #[serde(rename = "realistic_1")] + Realistic1, + #[serde(rename = "realistic_2")] + Realistic2, + #[serde(rename = "anime_retro_neon")] + AnimeRetroNeon, + #[serde(rename = "anime_standard")] + AnimeStandard, + + // New Styles (2024-05-03) + + #[serde(rename = "hr_giger")] + HrGiger, + #[serde(rename = "simpsons")] + Simpsons, + #[serde(rename = "carnage")] + Carnage, + #[serde(rename = "pastel_cute_anime")] // TODO: Rename + AnimePastelCute, + #[serde(rename = "bloom_lighting")] + BloomLighting, + #[serde(rename = "25d_horror")] // TODO: Rename + Horror2_5D, + #[serde(rename = "creepy")] + Creepy, + #[serde(rename = "creepy_vhs")] + CreepyVhs, + #[serde(rename = "trail_cam_footage")] + TrailCamFootage, + #[serde(rename = "old_black_white_movie")] + OldBlackWhiteMovie, + #[serde(rename = "horror_noir_black_white")] + HorrorNoirBlackWhite, + #[serde(rename = "techno_noir_black_white")] + TechnoNoirBlackWhite, + #[serde(rename = "black_white_20s")] + BlackWhite20s, + #[serde(rename = "cyberpunk_anime")] + CyberpunkAnime, + #[serde(rename = "dragonball")] + Dragonball, + #[serde(rename = "realistic_matrix")] + RealisticMatrix, + #[serde(rename = "realistic_cyberpunk")] + RealisticCyberpunk, + + // New Styles (2024-06-27) + + #[serde(rename = "dreamer")] // TODO: Land this in Gitub + Dreamer, +} + +#[cfg(test)] +mod tests { + use super::StyleTransferName; + use enums_shared::test_helpers::{assert_deserialization, assert_serialization}; + use strum::IntoEnumIterator; + + mod manual_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(StyleTransferName::Anime2_5D, "anime_2_5d"); + assert_serialization(StyleTransferName::Anime2DFlat, "anime_2d_flat"); + assert_serialization(StyleTransferName::Cartoon3D, "cartoon_3d"); + assert_serialization(StyleTransferName::ComicBook, "comic_book"); + assert_serialization(StyleTransferName::AnimeGhibli, "anime_ghibli"); + assert_serialization(StyleTransferName::InkPunk, "ink_punk"); + assert_serialization(StyleTransferName::InkSplash, "ink_splash"); + assert_serialization(StyleTransferName::InkBWStyle, "ink_bw_style"); + assert_serialization(StyleTransferName::JojoStyle, "jojo_style"); + assert_serialization(StyleTransferName::PaperOrigami, "paper_origami"); + assert_serialization(StyleTransferName::PixelArt, "pixel_art"); + assert_serialization(StyleTransferName::PopArt, "pop_art"); + assert_serialization(StyleTransferName::Realistic1, "realistic_1"); + assert_serialization(StyleTransferName::Realistic2, "realistic_2"); + assert_serialization(StyleTransferName::AnimeRetroNeon, "anime_retro_neon"); + assert_serialization(StyleTransferName::AnimeStandard, "anime_standard"); + assert_serialization(StyleTransferName::HrGiger, "hr_giger"); + assert_serialization(StyleTransferName::Simpsons, "simpsons"); + assert_serialization(StyleTransferName::Carnage, "carnage"); + assert_serialization(StyleTransferName::AnimePastelCute, "pastel_cute_anime"); + assert_serialization(StyleTransferName::BloomLighting, "bloom_lighting"); + assert_serialization(StyleTransferName::Horror2_5D, "25d_horror"); + assert_serialization(StyleTransferName::Creepy, "creepy"); + assert_serialization(StyleTransferName::CreepyVhs, "creepy_vhs"); + assert_serialization(StyleTransferName::TrailCamFootage, "trail_cam_footage"); + assert_serialization(StyleTransferName::OldBlackWhiteMovie, "old_black_white_movie"); + assert_serialization(StyleTransferName::HorrorNoirBlackWhite, "horror_noir_black_white"); + assert_serialization(StyleTransferName::TechnoNoirBlackWhite, "techno_noir_black_white"); + assert_serialization(StyleTransferName::BlackWhite20s, "black_white_20s"); + assert_serialization(StyleTransferName::CyberpunkAnime, "cyberpunk_anime"); + assert_serialization(StyleTransferName::Dragonball, "dragonball"); + assert_serialization(StyleTransferName::RealisticMatrix, "realistic_matrix"); + assert_serialization(StyleTransferName::RealisticCyberpunk, "realistic_cyberpunk"); + assert_serialization(StyleTransferName::Dreamer, "dreamer"); + } + + #[test] + fn test_deserialization() { + assert_deserialization("anime_2_5d", StyleTransferName::Anime2_5D); + assert_deserialization("anime_2d_flat", StyleTransferName::Anime2DFlat); + assert_deserialization("cartoon_3d", StyleTransferName::Cartoon3D); + assert_deserialization("comic_book", StyleTransferName::ComicBook); + assert_deserialization("anime_ghibli", StyleTransferName::AnimeGhibli); + assert_deserialization("ink_punk", StyleTransferName::InkPunk); + assert_deserialization("ink_splash", StyleTransferName::InkSplash); + assert_deserialization("ink_bw_style", StyleTransferName::InkBWStyle); + assert_deserialization("jojo_style", StyleTransferName::JojoStyle); + assert_deserialization("paper_origami", StyleTransferName::PaperOrigami); + assert_deserialization("pixel_art", StyleTransferName::PixelArt); + assert_deserialization("pop_art", StyleTransferName::PopArt); + assert_deserialization("realistic_1", StyleTransferName::Realistic1); + assert_deserialization("realistic_2", StyleTransferName::Realistic2); + assert_deserialization("anime_retro_neon", StyleTransferName::AnimeRetroNeon); + assert_deserialization("anime_standard", StyleTransferName::AnimeStandard); + assert_deserialization("hr_giger", StyleTransferName::HrGiger); + assert_deserialization("simpsons", StyleTransferName::Simpsons); + assert_deserialization("carnage", StyleTransferName::Carnage); + assert_deserialization("pastel_cute_anime", StyleTransferName::AnimePastelCute); + assert_deserialization("bloom_lighting", StyleTransferName::BloomLighting); + assert_deserialization("25d_horror", StyleTransferName::Horror2_5D); + assert_deserialization("creepy", StyleTransferName::Creepy); + assert_deserialization("creepy_vhs", StyleTransferName::CreepyVhs); + assert_deserialization("trail_cam_footage", StyleTransferName::TrailCamFootage); + assert_deserialization("old_black_white_movie", StyleTransferName::OldBlackWhiteMovie); + assert_deserialization("horror_noir_black_white", StyleTransferName::HorrorNoirBlackWhite); + assert_deserialization("techno_noir_black_white", StyleTransferName::TechnoNoirBlackWhite); + assert_deserialization("black_white_20s", StyleTransferName::BlackWhite20s); + assert_deserialization("cyberpunk_anime", StyleTransferName::CyberpunkAnime); + assert_deserialization("dragonball", StyleTransferName::Dragonball); + assert_deserialization("realistic_matrix", StyleTransferName::RealisticMatrix); + assert_deserialization("realistic_cyberpunk", StyleTransferName::RealisticCyberpunk); + assert_deserialization("dreamer", StyleTransferName::Dreamer); + } + + #[test] + fn variants_count_check() { + assert_eq!(StyleTransferName::iter().count(), 34); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip_json() { + for variant in StyleTransferName::iter() { + let json = serde_json::to_string(&variant).unwrap(); + let back: StyleTransferName = serde_json::from_str(&json).unwrap(); + assert_eq!(variant, back); + } + } + } +} diff --git a/crates/schema/public/enums_api/src/no_table/video_dimensions/mod.rs b/crates/schema/public/enums_api/src/no_table/video_dimensions/mod.rs new file mode 100644 index 0000000000..6f8ed8967c --- /dev/null +++ b/crates/schema/public/enums_api/src/no_table/video_dimensions/mod.rs @@ -0,0 +1 @@ +mod video_dimensions; \ No newline at end of file diff --git a/crates/schema/public/enums_api/src/no_table/video_dimensions/video_dimensions.rs b/crates/schema/public/enums_api/src/no_table/video_dimensions/video_dimensions.rs new file mode 100644 index 0000000000..b9e8fbe26d --- /dev/null +++ b/crates/schema/public/enums_api/src/no_table/video_dimensions/video_dimensions.rs @@ -0,0 +1,56 @@ +use strum::EnumIter; +use utoipa::ToSchema; + +/// This enum is not backed by a particular database table. +/// This is used to determine the video generation size. +#[derive(Clone, Debug, Copy, Eq, PartialEq, Ord, PartialOrd, Hash, Deserialize, Serialize, EnumIter, ToSchema)] +#[serde(rename_all = "snake_case")] + +pub enum VideoDimensions { + Landscape, + Portrait, + Square, +} + +#[cfg(test)] +mod tests { + use super::VideoDimensions; + use enums_shared::test_helpers::{assert_deserialization, assert_serialization}; + use strum::IntoEnumIterator; + + mod manual_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(VideoDimensions::Landscape, "landscape"); + assert_serialization(VideoDimensions::Portrait, "portrait"); + assert_serialization(VideoDimensions::Square, "square"); + } + + #[test] + fn test_deserialization() { + assert_deserialization("landscape", VideoDimensions::Landscape); + assert_deserialization("portrait", VideoDimensions::Portrait); + assert_deserialization("square", VideoDimensions::Square); + } + + #[test] + fn variants_count_check() { + assert_eq!(VideoDimensions::iter().count(), 3); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip_json() { + for variant in VideoDimensions::iter() { + let json = serde_json::to_string(&variant).unwrap(); + let back: VideoDimensions = serde_json::from_str(&json).unwrap(); + assert_eq!(variant, back); + } + } + } +} diff --git a/crates/schema/public/enums_api/src/tauri/mod.rs b/crates/schema/public/enums_api/src/tauri/mod.rs new file mode 100644 index 0000000000..c687f0ee1b --- /dev/null +++ b/crates/schema/public/enums_api/src/tauri/mod.rs @@ -0,0 +1,2 @@ +pub mod tasks; +pub mod ux; diff --git a/crates/schema/public/enums_api/src/tauri/tasks/mod.rs b/crates/schema/public/enums_api/src/tauri/tasks/mod.rs new file mode 100644 index 0000000000..ef469ecb21 --- /dev/null +++ b/crates/schema/public/enums_api/src/tauri/tasks/mod.rs @@ -0,0 +1,5 @@ +pub mod task_failure_type; +pub mod task_media_file_class; +pub mod task_model_type; +pub mod task_status; +pub mod task_type; diff --git a/crates/schema/public/enums_api/src/tauri/tasks/task_failure_type.rs b/crates/schema/public/enums_api/src/tauri/tasks/task_failure_type.rs new file mode 100644 index 0000000000..c2b65c8f72 --- /dev/null +++ b/crates/schema/public/enums_api/src/tauri/tasks/task_failure_type.rs @@ -0,0 +1,77 @@ +use strum::EnumIter; +use utoipa::ToSchema; + +/// Failure type for tasks in the Tauri desktop app. +#[derive(Clone, Debug, Copy, PartialEq, Eq, Hash, Ord, PartialOrd, Serialize, EnumIter, Deserialize, ToSchema)] +#[serde(rename_all = "snake_case")] +pub enum TaskFailureType { + /// Catch-all for unknown failures. + Unknown, + + RuleBansUserImage, + RuleBansUserImageWithFaces, + RuleBansUserTextPrompt, + RuleBansUserContent, + + RuleBansGeneratedVideo, + RuleBansGeneratedAudio, + RuleBansGeneratedContent, + + /// No reason given for generation failure, but this matches what we were told. + GenerationFailed, +} + +#[cfg(test)] +mod tests { + use super::TaskFailureType; + use enums_shared::test_helpers::{assert_deserialization, assert_serialization}; + use strum::IntoEnumIterator; + + mod manual_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(TaskFailureType::Unknown, "unknown"); + assert_serialization(TaskFailureType::RuleBansUserImage, "rule_bans_user_image"); + assert_serialization(TaskFailureType::RuleBansUserImageWithFaces, "rule_bans_user_image_with_faces"); + assert_serialization(TaskFailureType::RuleBansUserTextPrompt, "rule_bans_user_text_prompt"); + assert_serialization(TaskFailureType::RuleBansUserContent, "rule_bans_user_content"); + assert_serialization(TaskFailureType::RuleBansGeneratedVideo, "rule_bans_generated_video"); + assert_serialization(TaskFailureType::RuleBansGeneratedAudio, "rule_bans_generated_audio"); + assert_serialization(TaskFailureType::RuleBansGeneratedContent, "rule_bans_generated_content"); + assert_serialization(TaskFailureType::GenerationFailed, "generation_failed"); + } + + #[test] + fn test_deserialization() { + assert_deserialization("unknown", TaskFailureType::Unknown); + assert_deserialization("rule_bans_user_image", TaskFailureType::RuleBansUserImage); + assert_deserialization("rule_bans_user_image_with_faces", TaskFailureType::RuleBansUserImageWithFaces); + assert_deserialization("rule_bans_user_text_prompt", TaskFailureType::RuleBansUserTextPrompt); + assert_deserialization("rule_bans_user_content", TaskFailureType::RuleBansUserContent); + assert_deserialization("rule_bans_generated_video", TaskFailureType::RuleBansGeneratedVideo); + assert_deserialization("rule_bans_generated_audio", TaskFailureType::RuleBansGeneratedAudio); + assert_deserialization("rule_bans_generated_content", TaskFailureType::RuleBansGeneratedContent); + assert_deserialization("generation_failed", TaskFailureType::GenerationFailed); + } + + #[test] + fn variants_count_check() { + assert_eq!(TaskFailureType::iter().count(), 9); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip_json() { + for variant in TaskFailureType::iter() { + let json = serde_json::to_string(&variant).unwrap(); + let back: TaskFailureType = serde_json::from_str(&json).unwrap(); + assert_eq!(variant, back); + } + } + } +} diff --git a/crates/schema/public/enums_api/src/tauri/tasks/task_media_file_class.rs b/crates/schema/public/enums_api/src/tauri/tasks/task_media_file_class.rs new file mode 100644 index 0000000000..10244908ea --- /dev/null +++ b/crates/schema/public/enums_api/src/tauri/tasks/task_media_file_class.rs @@ -0,0 +1,65 @@ + +use strum::EnumIter; +use utoipa::ToSchema; + +#[derive(Clone, Debug, Copy, PartialEq, Eq, Hash, Ord, PartialOrd, Serialize, EnumIter, Deserialize, ToSchema)] +#[serde(rename_all = "snake_case")] + +pub enum TaskMediaFileClass { + /// Audio files: wav, mp3, etc. + Audio, + + /// Image files: png, jpeg, etc. + Image, + + /// Video files: mp4, etc. + Video, + + /// 3D engine data: glb, gltf, etc. + Dimensional, +} + +#[cfg(test)] +mod tests { + use super::TaskMediaFileClass; + use enums_shared::test_helpers::{assert_deserialization, assert_serialization}; + use strum::IntoEnumIterator; + + mod manual_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(TaskMediaFileClass::Audio, "audio"); + assert_serialization(TaskMediaFileClass::Image, "image"); + assert_serialization(TaskMediaFileClass::Video, "video"); + assert_serialization(TaskMediaFileClass::Dimensional, "dimensional"); + } + + #[test] + fn test_deserialization() { + assert_deserialization("audio", TaskMediaFileClass::Audio); + assert_deserialization("image", TaskMediaFileClass::Image); + assert_deserialization("video", TaskMediaFileClass::Video); + assert_deserialization("dimensional", TaskMediaFileClass::Dimensional); + } + + #[test] + fn variants_count_check() { + assert_eq!(TaskMediaFileClass::iter().count(), 4); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip_json() { + for variant in TaskMediaFileClass::iter() { + let json = serde_json::to_string(&variant).unwrap(); + let back: TaskMediaFileClass = serde_json::from_str(&json).unwrap(); + assert_eq!(variant, back); + } + } + } +} diff --git a/crates/schema/public/enums_api/src/tauri/tasks/task_model_type.rs b/crates/schema/public/enums_api/src/tauri/tasks/task_model_type.rs new file mode 100644 index 0000000000..a91d65658d --- /dev/null +++ b/crates/schema/public/enums_api/src/tauri/tasks/task_model_type.rs @@ -0,0 +1,234 @@ + +use strum::EnumIter; +use utoipa::ToSchema; + +#[derive(Clone, Debug, Copy, PartialEq, Eq, Hash, Ord, PartialOrd, Serialize, EnumIter, Deserialize, ToSchema)] +#[serde(rename_all = "snake_case")] + +pub enum TaskModelType { + // Image models + #[serde(rename = "flux_1_dev")] + Flux1Dev, + #[serde(rename = "flux_1_schnell")] + Flux1Schnell, + #[serde(rename = "flux_dev_juggernaut")] + FluxDevJuggernaut, + // NB: For inpainting for now + #[serde(rename = "flux_pro_1")] + FluxPro1, + #[serde(rename = "flux_pro_1.1")] + FluxPro11, + #[serde(rename = "flux_pro_1.1_ultra")] + FluxPro11Ultra, + #[serde(rename = "flux_pro_kontext_max")] + FluxProKontextMax, + #[serde(rename = "gemini_25_flash")] + Gemini25Flash, + #[serde(rename = "nano_banana")] + NanoBanana, + #[serde(rename = "nano_banana_2")] + NanoBanana2, + #[serde(rename = "nano_banana_pro")] + NanoBananaPro, + #[serde(rename = "gpt_image_1")] + GptImage1, + #[serde(rename = "gpt_image_1p5")] + GptImage1p5, + #[serde(rename = "seedream_4")] + Seedream4, + #[serde(rename = "seedream_4p5")] + Seedream4p5, + #[serde(rename = "seedream_5_lite")] + Seedream5Lite, + #[serde(rename = "qwen_edit_2511_angles")] + QwenEdit2511Angles, + #[serde(rename = "flux_2_lora_angles")] + Flux2LoraAngles, + #[serde(rename = "grok_image")] + GrokImage, + #[serde(rename = "recraft_3")] + Recraft3, + + // Generic Midjourney model, version unknown. + #[serde(rename = "midjourney")] + Midjourney, + + // Video models + #[serde(rename = "grok_video")] + GrokVideo, // Video version unspecified/unknown + #[serde(rename = "kling_1.6_pro")] + Kling16Pro, + #[serde(rename = "kling_2.1_pro")] + Kling21Pro, + #[serde(rename = "kling_2.1_master")] + Kling21Master, + #[serde(rename = "kling_2p5_turbo_pro")] + Kling2p5TurboPro, + #[serde(rename = "kling_2p6_pro")] + Kling2p6Pro, + #[serde(rename = "kling_3p0_standard")] + Kling3p0Standard, + #[serde(rename = "kling_3p0_pro")] + Kling3p0Pro, + #[serde(rename = "seedance_1.0_lite")] + Seedance10Lite, + #[serde(rename = "seedance_1p5_pro")] + Seedance1p5Pro, + #[serde(rename = "seedance_2p0")] + Seedance2p0, + #[serde(rename = "sora_2")] + Sora2, + #[serde(rename = "sora_2_pro")] + Sora2Pro, + #[serde(rename = "veo_2")] + Veo2, + #[serde(rename = "veo_3")] + Veo3, + #[serde(rename = "veo_3_fast")] + Veo3Fast, + #[serde(rename = "veo_3p1")] + Veo3p1, + #[serde(rename = "veo_3p1_fast")] + Veo3p1Fast, + + // 3D Object generation models + #[serde(rename = "hunyuan_3d_2.0")] + Hunyuan3d2_0, + #[serde(rename = "hunyuan_3d_2.1")] + Hunyuan3d2_1, + #[serde(rename = "hunyuan_3d_3")] + Hunyuan3d3, + #[serde(rename = "worldlabs_marble")] + WorldlabsMarble, + #[serde(rename = "marble_0p1_mini")] + WorldlabsMarble0p1Mini, + #[serde(rename = "marble_0p1_plus")] + WorldlabsMarble0p1Plus, +} + +#[cfg(test)] +mod tests { + use super::TaskModelType; + use enums_shared::test_helpers::{assert_deserialization, assert_serialization}; + use strum::IntoEnumIterator; + + mod manual_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(TaskModelType::Flux1Dev, "flux_1_dev"); + assert_serialization(TaskModelType::Flux1Schnell, "flux_1_schnell"); + assert_serialization(TaskModelType::FluxDevJuggernaut, "flux_dev_juggernaut"); + assert_serialization(TaskModelType::FluxPro1, "flux_pro_1"); + assert_serialization(TaskModelType::FluxPro11, "flux_pro_1.1"); + assert_serialization(TaskModelType::FluxPro11Ultra, "flux_pro_1.1_ultra"); + assert_serialization(TaskModelType::FluxProKontextMax, "flux_pro_kontext_max"); + assert_serialization(TaskModelType::Gemini25Flash, "gemini_25_flash"); + assert_serialization(TaskModelType::NanoBanana, "nano_banana"); + assert_serialization(TaskModelType::NanoBanana2, "nano_banana_2"); + assert_serialization(TaskModelType::NanoBananaPro, "nano_banana_pro"); + assert_serialization(TaskModelType::GptImage1, "gpt_image_1"); + assert_serialization(TaskModelType::GptImage1p5, "gpt_image_1p5"); + assert_serialization(TaskModelType::Seedream4, "seedream_4"); + assert_serialization(TaskModelType::Seedream4p5, "seedream_4p5"); + assert_serialization(TaskModelType::Seedream5Lite, "seedream_5_lite"); + assert_serialization(TaskModelType::QwenEdit2511Angles, "qwen_edit_2511_angles"); + assert_serialization(TaskModelType::Flux2LoraAngles, "flux_2_lora_angles"); + assert_serialization(TaskModelType::GrokImage, "grok_image"); + assert_serialization(TaskModelType::Recraft3, "recraft_3"); + assert_serialization(TaskModelType::Midjourney, "midjourney"); + assert_serialization(TaskModelType::GrokVideo, "grok_video"); + assert_serialization(TaskModelType::Kling16Pro, "kling_1.6_pro"); + assert_serialization(TaskModelType::Kling21Pro, "kling_2.1_pro"); + assert_serialization(TaskModelType::Kling21Master, "kling_2.1_master"); + assert_serialization(TaskModelType::Kling2p5TurboPro, "kling_2p5_turbo_pro"); + assert_serialization(TaskModelType::Kling2p6Pro, "kling_2p6_pro"); + assert_serialization(TaskModelType::Kling3p0Standard, "kling_3p0_standard"); + assert_serialization(TaskModelType::Kling3p0Pro, "kling_3p0_pro"); + assert_serialization(TaskModelType::Seedance10Lite, "seedance_1.0_lite"); + assert_serialization(TaskModelType::Seedance1p5Pro, "seedance_1p5_pro"); + assert_serialization(TaskModelType::Seedance2p0, "seedance_2p0"); + assert_serialization(TaskModelType::Sora2, "sora_2"); + assert_serialization(TaskModelType::Sora2Pro, "sora_2_pro"); + assert_serialization(TaskModelType::Veo2, "veo_2"); + assert_serialization(TaskModelType::Veo3, "veo_3"); + assert_serialization(TaskModelType::Veo3Fast, "veo_3_fast"); + assert_serialization(TaskModelType::Veo3p1, "veo_3p1"); + assert_serialization(TaskModelType::Veo3p1Fast, "veo_3p1_fast"); + assert_serialization(TaskModelType::Hunyuan3d2_0, "hunyuan_3d_2.0"); + assert_serialization(TaskModelType::Hunyuan3d2_1, "hunyuan_3d_2.1"); + assert_serialization(TaskModelType::Hunyuan3d3, "hunyuan_3d_3"); + assert_serialization(TaskModelType::WorldlabsMarble, "worldlabs_marble"); + assert_serialization(TaskModelType::WorldlabsMarble0p1Mini, "marble_0p1_mini"); + assert_serialization(TaskModelType::WorldlabsMarble0p1Plus, "marble_0p1_plus"); + } + + #[test] + fn test_deserialization() { + assert_deserialization("flux_1_dev", TaskModelType::Flux1Dev); + assert_deserialization("flux_1_schnell", TaskModelType::Flux1Schnell); + assert_deserialization("flux_dev_juggernaut", TaskModelType::FluxDevJuggernaut); + assert_deserialization("flux_pro_1", TaskModelType::FluxPro1); + assert_deserialization("flux_pro_1.1", TaskModelType::FluxPro11); + assert_deserialization("flux_pro_1.1_ultra", TaskModelType::FluxPro11Ultra); + assert_deserialization("flux_pro_kontext_max", TaskModelType::FluxProKontextMax); + assert_deserialization("gemini_25_flash", TaskModelType::Gemini25Flash); + assert_deserialization("nano_banana", TaskModelType::NanoBanana); + assert_deserialization("nano_banana_2", TaskModelType::NanoBanana2); + assert_deserialization("nano_banana_pro", TaskModelType::NanoBananaPro); + assert_deserialization("gpt_image_1", TaskModelType::GptImage1); + assert_deserialization("gpt_image_1p5", TaskModelType::GptImage1p5); + assert_deserialization("seedream_4", TaskModelType::Seedream4); + assert_deserialization("seedream_4p5", TaskModelType::Seedream4p5); + assert_deserialization("seedream_5_lite", TaskModelType::Seedream5Lite); + assert_deserialization("qwen_edit_2511_angles", TaskModelType::QwenEdit2511Angles); + assert_deserialization("flux_2_lora_angles", TaskModelType::Flux2LoraAngles); + assert_deserialization("grok_image", TaskModelType::GrokImage); + assert_deserialization("recraft_3", TaskModelType::Recraft3); + assert_deserialization("midjourney", TaskModelType::Midjourney); + assert_deserialization("grok_video", TaskModelType::GrokVideo); + assert_deserialization("kling_1.6_pro", TaskModelType::Kling16Pro); + assert_deserialization("kling_2.1_pro", TaskModelType::Kling21Pro); + assert_deserialization("kling_2.1_master", TaskModelType::Kling21Master); + assert_deserialization("kling_2p5_turbo_pro", TaskModelType::Kling2p5TurboPro); + assert_deserialization("kling_2p6_pro", TaskModelType::Kling2p6Pro); + assert_deserialization("kling_3p0_standard", TaskModelType::Kling3p0Standard); + assert_deserialization("kling_3p0_pro", TaskModelType::Kling3p0Pro); + assert_deserialization("seedance_1.0_lite", TaskModelType::Seedance10Lite); + assert_deserialization("seedance_1p5_pro", TaskModelType::Seedance1p5Pro); + assert_deserialization("seedance_2p0", TaskModelType::Seedance2p0); + assert_deserialization("sora_2", TaskModelType::Sora2); + assert_deserialization("sora_2_pro", TaskModelType::Sora2Pro); + assert_deserialization("veo_2", TaskModelType::Veo2); + assert_deserialization("veo_3", TaskModelType::Veo3); + assert_deserialization("veo_3_fast", TaskModelType::Veo3Fast); + assert_deserialization("veo_3p1", TaskModelType::Veo3p1); + assert_deserialization("veo_3p1_fast", TaskModelType::Veo3p1Fast); + assert_deserialization("hunyuan_3d_2.0", TaskModelType::Hunyuan3d2_0); + assert_deserialization("hunyuan_3d_2.1", TaskModelType::Hunyuan3d2_1); + assert_deserialization("hunyuan_3d_3", TaskModelType::Hunyuan3d3); + assert_deserialization("worldlabs_marble", TaskModelType::WorldlabsMarble); + assert_deserialization("marble_0p1_mini", TaskModelType::WorldlabsMarble0p1Mini); + assert_deserialization("marble_0p1_plus", TaskModelType::WorldlabsMarble0p1Plus); + } + + #[test] + fn variants_count_check() { + assert_eq!(TaskModelType::iter().count(), 45); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip_json() { + for variant in TaskModelType::iter() { + let json = serde_json::to_string(&variant).unwrap(); + let back: TaskModelType = serde_json::from_str(&json).unwrap(); + assert_eq!(variant, back); + } + } + } +} diff --git a/crates/schema/public/enums_api/src/tauri/tasks/task_status.rs b/crates/schema/public/enums_api/src/tauri/tasks/task_status.rs new file mode 100644 index 0000000000..fa2cd00bb2 --- /dev/null +++ b/crates/schema/public/enums_api/src/tauri/tasks/task_status.rs @@ -0,0 +1,73 @@ + +use strum::EnumIter; +use utoipa::ToSchema; + +#[derive(Clone, Debug, Copy, PartialEq, Eq, Hash, Ord, PartialOrd, Serialize, EnumIter, Deserialize, ToSchema)] +#[serde(rename_all = "snake_case")] + +pub enum TaskStatus { + Pending, + Started, + CompleteSuccess, + CompleteFailure, + AttemptFailed, + Dead, + CancelledByUser, + CancelledByProvider, + CancelledByUs, +} + +#[cfg(test)] +mod tests { + use super::TaskStatus; + use enums_shared::test_helpers::{assert_deserialization, assert_serialization}; + use strum::IntoEnumIterator; + + mod manual_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(TaskStatus::Pending, "pending"); + assert_serialization(TaskStatus::Started, "started"); + assert_serialization(TaskStatus::CompleteSuccess, "complete_success"); + assert_serialization(TaskStatus::CompleteFailure, "complete_failure"); + assert_serialization(TaskStatus::AttemptFailed, "attempt_failed"); + assert_serialization(TaskStatus::Dead, "dead"); + assert_serialization(TaskStatus::CancelledByUser, "cancelled_by_user"); + assert_serialization(TaskStatus::CancelledByProvider, "cancelled_by_provider"); + assert_serialization(TaskStatus::CancelledByUs, "cancelled_by_us"); + } + + #[test] + fn test_deserialization() { + assert_deserialization("pending", TaskStatus::Pending); + assert_deserialization("started", TaskStatus::Started); + assert_deserialization("complete_success", TaskStatus::CompleteSuccess); + assert_deserialization("complete_failure", TaskStatus::CompleteFailure); + assert_deserialization("attempt_failed", TaskStatus::AttemptFailed); + assert_deserialization("dead", TaskStatus::Dead); + assert_deserialization("cancelled_by_user", TaskStatus::CancelledByUser); + assert_deserialization("cancelled_by_provider", TaskStatus::CancelledByProvider); + assert_deserialization("cancelled_by_us", TaskStatus::CancelledByUs); + } + + #[test] + fn variants_count_check() { + assert_eq!(TaskStatus::iter().count(), 9); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip_json() { + for variant in TaskStatus::iter() { + let json = serde_json::to_string(&variant).unwrap(); + let back: TaskStatus = serde_json::from_str(&json).unwrap(); + assert_eq!(variant, back); + } + } + } +} diff --git a/crates/schema/public/enums_api/src/tauri/tasks/task_type.rs b/crates/schema/public/enums_api/src/tauri/tasks/task_type.rs new file mode 100644 index 0000000000..9c9d8fc0e1 --- /dev/null +++ b/crates/schema/public/enums_api/src/tauri/tasks/task_type.rs @@ -0,0 +1,64 @@ + +use strum::EnumIter; +use utoipa::ToSchema; + +#[derive(Clone, Debug, Copy, PartialEq, Eq, Hash, Ord, PartialOrd, Serialize, EnumIter, Deserialize, ToSchema)] +#[serde(rename_all = "snake_case")] + +pub enum TaskType { + ImageGeneration, + ImageInpaintEdit, + VideoGeneration, + ObjectGeneration, + GaussianGeneration, + BackgroundRemoval, +} + +#[cfg(test)] +mod tests { + use super::TaskType; + use enums_shared::test_helpers::{assert_deserialization, assert_serialization}; + use strum::IntoEnumIterator; + + mod manual_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(TaskType::ImageGeneration, "image_generation"); + assert_serialization(TaskType::ImageInpaintEdit, "image_inpaint_edit"); + assert_serialization(TaskType::VideoGeneration, "video_generation"); + assert_serialization(TaskType::ObjectGeneration, "object_generation"); + assert_serialization(TaskType::GaussianGeneration, "gaussian_generation"); + assert_serialization(TaskType::BackgroundRemoval, "background_removal"); + } + + #[test] + fn test_deserialization() { + assert_deserialization("image_generation", TaskType::ImageGeneration); + assert_deserialization("image_inpaint_edit", TaskType::ImageInpaintEdit); + assert_deserialization("video_generation", TaskType::VideoGeneration); + assert_deserialization("object_generation", TaskType::ObjectGeneration); + assert_deserialization("gaussian_generation", TaskType::GaussianGeneration); + assert_deserialization("background_removal", TaskType::BackgroundRemoval); + } + + #[test] + fn variants_count_check() { + assert_eq!(TaskType::iter().count(), 6); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip_json() { + for variant in TaskType::iter() { + let json = serde_json::to_string(&variant).unwrap(); + let back: TaskType = serde_json::from_str(&json).unwrap(); + assert_eq!(variant, back); + } + } + } +} diff --git a/crates/schema/public/enums_api/src/tauri/ux/mod.rs b/crates/schema/public/enums_api/src/tauri/ux/mod.rs new file mode 100644 index 0000000000..40215426d6 --- /dev/null +++ b/crates/schema/public/enums_api/src/tauri/ux/mod.rs @@ -0,0 +1,2 @@ +pub mod tauri_command_caller; +pub mod tauri_event_name; diff --git a/crates/schema/public/enums_api/src/tauri/ux/tauri_command_caller.rs b/crates/schema/public/enums_api/src/tauri/ux/tauri_command_caller.rs new file mode 100644 index 0000000000..a95fb3a51b --- /dev/null +++ b/crates/schema/public/enums_api/src/tauri/ux/tauri_command_caller.rs @@ -0,0 +1,68 @@ + +use strum::EnumIter; +use utoipa::ToSchema; + +/// Defines the names of the Tauri-sent events that the frontend subscribes to. +/// These event names are also stored in the database, so keep them short-ish. +#[derive(Clone, Debug, Copy, PartialEq, Eq, Hash, Ord, PartialOrd, Serialize, EnumIter, Deserialize, ToSchema)] +#[serde(rename_all = "snake_case")] + +pub enum TauriCommandCaller { + /// The 2D canvas + Canvas, + /// The inpainting editor + ImageEditor, + /// The text-to-image page + TextToImage, + /// The image-to-video page + ImageToVideo, + /// A mini-app (doesn't specify which one) + MiniApp, +} + +#[cfg(test)] +mod tests { + use super::TauriCommandCaller; + use enums_shared::test_helpers::{assert_deserialization, assert_serialization}; + use strum::IntoEnumIterator; + + mod manual_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(TauriCommandCaller::Canvas, "canvas"); + assert_serialization(TauriCommandCaller::ImageEditor, "image_editor"); + assert_serialization(TauriCommandCaller::TextToImage, "text_to_image"); + assert_serialization(TauriCommandCaller::ImageToVideo, "image_to_video"); + assert_serialization(TauriCommandCaller::MiniApp, "mini_app"); + } + + #[test] + fn test_deserialization() { + assert_deserialization("canvas", TauriCommandCaller::Canvas); + assert_deserialization("image_editor", TauriCommandCaller::ImageEditor); + assert_deserialization("text_to_image", TauriCommandCaller::TextToImage); + assert_deserialization("image_to_video", TauriCommandCaller::ImageToVideo); + assert_deserialization("mini_app", TauriCommandCaller::MiniApp); + } + + #[test] + fn variants_count_check() { + assert_eq!(TauriCommandCaller::iter().count(), 5); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip_json() { + for variant in TauriCommandCaller::iter() { + let json = serde_json::to_string(&variant).unwrap(); + let back: TauriCommandCaller = serde_json::from_str(&json).unwrap(); + assert_eq!(variant, back); + } + } + } +} diff --git a/crates/schema/public/enums_api/src/tauri/ux/tauri_event_name.rs b/crates/schema/public/enums_api/src/tauri/ux/tauri_event_name.rs new file mode 100644 index 0000000000..f34e031c3c --- /dev/null +++ b/crates/schema/public/enums_api/src/tauri/ux/tauri_event_name.rs @@ -0,0 +1,178 @@ +use strum::EnumIter; +use utoipa::ToSchema; + +/// Defines the names of the Tauri-sent events that the frontend subscribes to. +/// These event names are also stored in the database, so keep them short-ish. +/// +/// NB: Events should end in "_event" so they're easy to grep for in Javascript. +#[derive(Clone, Debug, Copy, PartialEq, Eq, Hash, Ord, PartialOrd, Serialize, EnumIter, Deserialize, ToSchema)] +#[serde(rename_all = "snake_case")] + +pub enum TauriEventName { + // TODO: Get rid of kebab case. + /// General purpose event: + /// Generation enqueued + #[serde(rename = "generation-enqueue-success-event")] + GenerationEnqueueSuccessEvent, + + // TODO: Get rid of kebab case. + /// General purpose event: + /// Generation failed to enqueue + #[serde(rename = "generation-enqueue-failure-event")] + GenerationEnqueueFailureEvent, + + // TODO: Get rid of kebab case. + /// General purpose event: + /// Generation completed successfully + #[serde(rename = "generation-complete-event")] + GenerationCompleteEvent, + + // TODO: Get rid of kebab case. + /// General purpose event: + /// Generation failed + #[serde(rename = "generation-failed-event")] + GenerationFailedEvent, + + /// Informational event: + /// Credits were purchased or spent (but we don't know how much) + #[serde(rename = "credits_balance_changed_event")] + CreditsBalanceChangedEvent, + + /// Informational event: + /// Subscription was changed (but we don't know the details - upgrade, cancel, etc.) + #[serde(rename = "subscription_plan_changed_event")] + SubscriptionPlanChangedEvent, + + /// Informational event: + /// A media file was deleted (and we'll send the token) + #[serde(rename = "media_file_deleted_event")] + MediaFileDeletedEvent, + + /// Special event: + /// Background removal is complete + #[serde(rename = "canvas_bg_removed_event")] + CanvasBgRemovedEvent, + + /// Special event: + /// Image generation is complete + #[serde(rename = "text_to_image_generation_complete_event")] + TextToImageGenerationCompleteEvent, + + /// Special event: + /// Image edit is complete + #[serde(rename = "image_edit_complete_event")] + ImageEditCompleteEvent, + + /// Special event: + /// Object (3D mesh) generation is complete + #[serde(rename = "object_generation_complete_event")] + ObjectGenerationCompleteEvent, + + /// Special event: + /// Gaussian generation is complete + #[serde(rename = "gaussian_generation_complete_event")] + GaussianGenerationCompleteEvent, + + /// Special event: + /// Video generation is complete + #[serde(rename = "video_generation_complete_event")] + VideoGenerationCompleteEvent, + + /// Special event: + /// Refresh account states + #[serde(rename = "refresh_account_state_event")] + RefreshAccountStateEvent, + + /// Special event: + /// Show a billing modal (a suggestion to pay, etc. for a specific provider) + #[serde(rename = "show_provider_billing_modal_event")] + ShowProviderBillingModalEvent, + + /// Special event: + /// Show a login modal (or a suggestion to login) + #[serde(rename = "show_provider_login_modal_event")] + ShowProviderLoginModalEvent, + + /// Warning event: + /// Flash a user input error message + #[serde(rename = "flash_user_input_error_event")] + FlashUserInputErrorEvent, + + /// Warning event: + /// File with that name was already downloaded + #[serde(rename = "flash_file_download_error_event")] + FlashFileDownloadErrorEvent, +} + +#[cfg(test)] +mod tests { + use super::TauriEventName; + use enums_shared::test_helpers::{assert_deserialization, assert_serialization}; + use strum::IntoEnumIterator; + + mod manual_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(TauriEventName::GenerationEnqueueSuccessEvent, "generation-enqueue-success-event"); + assert_serialization(TauriEventName::GenerationEnqueueFailureEvent, "generation-enqueue-failure-event"); + assert_serialization(TauriEventName::GenerationCompleteEvent, "generation-complete-event"); + assert_serialization(TauriEventName::GenerationFailedEvent, "generation-failed-event"); + assert_serialization(TauriEventName::CreditsBalanceChangedEvent, "credits_balance_changed_event"); + assert_serialization(TauriEventName::SubscriptionPlanChangedEvent, "subscription_plan_changed_event"); + assert_serialization(TauriEventName::MediaFileDeletedEvent, "media_file_deleted_event"); + assert_serialization(TauriEventName::CanvasBgRemovedEvent, "canvas_bg_removed_event"); + assert_serialization(TauriEventName::TextToImageGenerationCompleteEvent, "text_to_image_generation_complete_event"); + assert_serialization(TauriEventName::ImageEditCompleteEvent, "image_edit_complete_event"); + assert_serialization(TauriEventName::ObjectGenerationCompleteEvent, "object_generation_complete_event"); + assert_serialization(TauriEventName::GaussianGenerationCompleteEvent, "gaussian_generation_complete_event"); + assert_serialization(TauriEventName::VideoGenerationCompleteEvent, "video_generation_complete_event"); + assert_serialization(TauriEventName::RefreshAccountStateEvent, "refresh_account_state_event"); + assert_serialization(TauriEventName::ShowProviderBillingModalEvent, "show_provider_billing_modal_event"); + assert_serialization(TauriEventName::ShowProviderLoginModalEvent, "show_provider_login_modal_event"); + assert_serialization(TauriEventName::FlashUserInputErrorEvent, "flash_user_input_error_event"); + assert_serialization(TauriEventName::FlashFileDownloadErrorEvent, "flash_file_download_error_event"); + } + + #[test] + fn test_deserialization() { + assert_deserialization("generation-enqueue-success-event", TauriEventName::GenerationEnqueueSuccessEvent); + assert_deserialization("generation-enqueue-failure-event", TauriEventName::GenerationEnqueueFailureEvent); + assert_deserialization("generation-complete-event", TauriEventName::GenerationCompleteEvent); + assert_deserialization("generation-failed-event", TauriEventName::GenerationFailedEvent); + assert_deserialization("credits_balance_changed_event", TauriEventName::CreditsBalanceChangedEvent); + assert_deserialization("subscription_plan_changed_event", TauriEventName::SubscriptionPlanChangedEvent); + assert_deserialization("media_file_deleted_event", TauriEventName::MediaFileDeletedEvent); + assert_deserialization("canvas_bg_removed_event", TauriEventName::CanvasBgRemovedEvent); + assert_deserialization("text_to_image_generation_complete_event", TauriEventName::TextToImageGenerationCompleteEvent); + assert_deserialization("image_edit_complete_event", TauriEventName::ImageEditCompleteEvent); + assert_deserialization("object_generation_complete_event", TauriEventName::ObjectGenerationCompleteEvent); + assert_deserialization("gaussian_generation_complete_event", TauriEventName::GaussianGenerationCompleteEvent); + assert_deserialization("video_generation_complete_event", TauriEventName::VideoGenerationCompleteEvent); + assert_deserialization("refresh_account_state_event", TauriEventName::RefreshAccountStateEvent); + assert_deserialization("show_provider_billing_modal_event", TauriEventName::ShowProviderBillingModalEvent); + assert_deserialization("show_provider_login_modal_event", TauriEventName::ShowProviderLoginModalEvent); + assert_deserialization("flash_user_input_error_event", TauriEventName::FlashUserInputErrorEvent); + assert_deserialization("flash_file_download_error_event", TauriEventName::FlashFileDownloadErrorEvent); + } + + #[test] + fn variants_count_check() { + assert_eq!(TauriEventName::iter().count(), 18); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip_json() { + for variant in TauriEventName::iter() { + let json = serde_json::to_string(&variant).unwrap(); + let back: TauriEventName = serde_json::from_str(&json).unwrap(); + assert_eq!(variant, back); + } + } + } +} diff --git a/crates/schema/public/enums_convert/Cargo.toml b/crates/schema/public/enums_convert/Cargo.toml new file mode 100644 index 0000000000..f63ef0bcbd --- /dev/null +++ b/crates/schema/public/enums_convert/Cargo.toml @@ -0,0 +1,28 @@ +[package] +name = "enums_convert" +edition = "2021" +version = "0.0.1" +authors = [ + "Brandon Thomas ", + "Brandon Thomas ", +] +publish = false + +[package.metadata.cargo-udeps.ignore] +normal = ["workspace-build-acceleration"] + +[lib] +name = "enums_convert" +path = "src/lib.rs" + +[dependencies] +# Workspace hack (faster compile times) +workspace-build-acceleration.workspace = true + +# Internal +enums_api.workspace = true +enums_db.workspace = true + +[dev-dependencies] +serde_json.workspace = true +strum.workspace = true diff --git a/crates/schema/public/enums_convert/src/api_safe/by_table/generic_inference_jobs/frontend_failure_category_for_api_clients.rs b/crates/schema/public/enums_convert/src/api_safe/by_table/generic_inference_jobs/frontend_failure_category_for_api_clients.rs new file mode 100644 index 0000000000..4dda9119cb --- /dev/null +++ b/crates/schema/public/enums_convert/src/api_safe/by_table/generic_inference_jobs/frontend_failure_category_for_api_clients.rs @@ -0,0 +1,35 @@ +use enums_api::api_safe::by_table::generic_inference_jobs::frontend_failure_category_for_api_clients::FrontendFailureCategoryForApiClients; +use enums_db::by_table::generic_inference_jobs::frontend_failure_category::FrontendFailureCategory; + +/// Convert a DB `FrontendFailureCategory` to the API-client-facing type. +pub fn frontend_failure_category_to_api_clients(db_value: &FrontendFailureCategory) -> FrontendFailureCategoryForApiClients { + match db_value { + FrontendFailureCategory::FaceNotDetected => FrontendFailureCategoryForApiClients::FaceNotDetected, + FrontendFailureCategory::KeepAliveElapsed => FrontendFailureCategoryForApiClients::KeepAliveElapsed, + FrontendFailureCategory::NotYetImplemented => FrontendFailureCategoryForApiClients::NotYetImplemented, + FrontendFailureCategory::RetryableWorkerError => FrontendFailureCategoryForApiClients::RetryableWorkerError, + FrontendFailureCategory::ModelRulesViolation => FrontendFailureCategoryForApiClients::ModelRulesViolation, + FrontendFailureCategory::RuleBansUserImage => FrontendFailureCategoryForApiClients::RuleBansUserImage, + FrontendFailureCategory::RuleBansUserImageWithFaces => FrontendFailureCategoryForApiClients::RuleBansUserImageWithFaces, + FrontendFailureCategory::RuleBansUserTextPrompt => FrontendFailureCategoryForApiClients::RuleBansUserTextPrompt, + FrontendFailureCategory::RuleBansUserContent => FrontendFailureCategoryForApiClients::RuleBansUserContent, + FrontendFailureCategory::RuleBansGeneratedVideo => FrontendFailureCategoryForApiClients::RuleBansGeneratedVideo, + FrontendFailureCategory::RuleBansGeneratedAudio => FrontendFailureCategoryForApiClients::RuleBansGeneratedAudio, + FrontendFailureCategory::RuleBansGeneratedContent => FrontendFailureCategoryForApiClients::RuleBansGeneratedContent, + FrontendFailureCategory::GenerationFailed => FrontendFailureCategoryForApiClients::GenerationFailed, + } +} + +#[cfg(test)] +mod tests { + use super::*; + use strum::IntoEnumIterator; + + #[test] + fn all_db_variants_convert() { + use strum::IntoEnumIterator; + for variant in FrontendFailureCategory::iter() { + let _ = frontend_failure_category_to_api_clients(&variant); + } + } +} diff --git a/crates/schema/public/enums_convert/src/api_safe/by_table/generic_inference_jobs/frontend_failure_category_for_old_clients.rs b/crates/schema/public/enums_convert/src/api_safe/by_table/generic_inference_jobs/frontend_failure_category_for_old_clients.rs new file mode 100644 index 0000000000..6c05b9137f --- /dev/null +++ b/crates/schema/public/enums_convert/src/api_safe/by_table/generic_inference_jobs/frontend_failure_category_for_old_clients.rs @@ -0,0 +1,37 @@ +use enums_api::api_safe::by_table::generic_inference_jobs::frontend_failure_category_for_old_clients::FrontendFailureCategoryForOldClients; +use enums_db::by_table::generic_inference_jobs::frontend_failure_category::FrontendFailureCategory; + +/// Convert a DB `FrontendFailureCategory` to the restricted old-client type. +/// Returns `None` for categories that old clients do not understand. +pub fn try_frontend_failure_category_to_old_clients(db_value: &FrontendFailureCategory) -> Option { + match db_value { + FrontendFailureCategory::FaceNotDetected => Some(FrontendFailureCategoryForOldClients::FaceNotDetected), + FrontendFailureCategory::KeepAliveElapsed => Some(FrontendFailureCategoryForOldClients::KeepAliveElapsed), + FrontendFailureCategory::NotYetImplemented => Some(FrontendFailureCategoryForOldClients::NotYetImplemented), + FrontendFailureCategory::RetryableWorkerError => Some(FrontendFailureCategoryForOldClients::RetryableWorkerError), + _ => None, + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn known_variants_convert() { + assert_eq!( + try_frontend_failure_category_to_old_clients(&FrontendFailureCategory::FaceNotDetected), + Some(FrontendFailureCategoryForOldClients::FaceNotDetected) + ); + assert_eq!( + try_frontend_failure_category_to_old_clients(&FrontendFailureCategory::KeepAliveElapsed), + Some(FrontendFailureCategoryForOldClients::KeepAliveElapsed) + ); + } + + #[test] + fn new_variants_return_none() { + assert_eq!(try_frontend_failure_category_to_old_clients(&FrontendFailureCategory::ModelRulesViolation), None); + assert_eq!(try_frontend_failure_category_to_old_clients(&FrontendFailureCategory::GenerationFailed), None); + } +} diff --git a/crates/schema/public/enums_convert/src/api_safe/by_table/generic_inference_jobs/mod.rs b/crates/schema/public/enums_convert/src/api_safe/by_table/generic_inference_jobs/mod.rs new file mode 100644 index 0000000000..b442e76182 --- /dev/null +++ b/crates/schema/public/enums_convert/src/api_safe/by_table/generic_inference_jobs/mod.rs @@ -0,0 +1,2 @@ +pub mod frontend_failure_category_for_api_clients; +pub mod frontend_failure_category_for_old_clients; diff --git a/crates/schema/public/enums_convert/src/api_safe/by_table/mod.rs b/crates/schema/public/enums_convert/src/api_safe/by_table/mod.rs new file mode 100644 index 0000000000..3f750197f4 --- /dev/null +++ b/crates/schema/public/enums_convert/src/api_safe/by_table/mod.rs @@ -0,0 +1 @@ +pub mod generic_inference_jobs; diff --git a/crates/schema/public/enums_convert/src/api_safe/mod.rs b/crates/schema/public/enums_convert/src/api_safe/mod.rs new file mode 100644 index 0000000000..1935f8872f --- /dev/null +++ b/crates/schema/public/enums_convert/src/api_safe/mod.rs @@ -0,0 +1 @@ +pub mod by_table; diff --git a/crates/schema/public/enums_convert/src/by_table/audit_logs/audit_log_entity_action.rs b/crates/schema/public/enums_convert/src/by_table/audit_logs/audit_log_entity_action.rs new file mode 100644 index 0000000000..8e2cbee246 --- /dev/null +++ b/crates/schema/public/enums_convert/src/by_table/audit_logs/audit_log_entity_action.rs @@ -0,0 +1,50 @@ +use enums_api::by_table::audit_logs::audit_log_entity_action::AuditLogEntityAction as Api; +use enums_db::by_table::audit_logs::audit_log_entity_action::AuditLogEntityAction as Db; + +pub fn audit_log_entity_action_to_db(api_value: &Api) -> Db { + match api_value { + Api::Create => Db::Create, + Api::Edit => Db::Edit, + Api::EditFeatures => Db::EditFeatures, + Api::Delete => Db::Delete, + Api::FeaturedItemCreate => Db::FeaturedItemCreate, + Api::FeaturedItemDelete => Db::FeaturedItemDelete, + } +} + +pub fn audit_log_entity_action_to_api(db_value: &Db) -> Api { + match db_value { + Db::Create => Api::Create, + Db::Edit => Api::Edit, + Db::EditFeatures => Api::EditFeatures, + Db::Delete => Api::Delete, + Db::FeaturedItemCreate => Api::FeaturedItemCreate, + Db::FeaturedItemDelete => Api::FeaturedItemDelete, + } +} + +#[cfg(test)] +mod tests { + use super::*; + use strum::IntoEnumIterator; + + #[test] + fn round_trip_api_to_db() { + use strum::IntoEnumIterator; + for api_variant in Api::iter() { + let db = audit_log_entity_action_to_db(&api_variant); + let back = audit_log_entity_action_to_api(&db); + assert_eq!(api_variant, back); + } + } + + #[test] + fn round_trip_db_to_api() { + use strum::IntoEnumIterator; + for api_variant in Api::iter() { + let db = audit_log_entity_action_to_db(&api_variant); + let back = audit_log_entity_action_to_api(&db); + assert_eq!(api_variant, back); + } + } +} diff --git a/crates/schema/public/enums_convert/src/by_table/audit_logs/audit_log_entity_type.rs b/crates/schema/public/enums_convert/src/by_table/audit_logs/audit_log_entity_type.rs new file mode 100644 index 0000000000..9f3759720f --- /dev/null +++ b/crates/schema/public/enums_convert/src/by_table/audit_logs/audit_log_entity_type.rs @@ -0,0 +1,46 @@ +use enums_api::by_table::audit_logs::audit_log_entity_type::AuditLogEntityType as Api; +use enums_db::by_table::audit_logs::audit_log_entity_type::AuditLogEntityType as Db; + +pub fn audit_log_entity_type_to_db(api_value: &Api) -> Db { + match api_value { + Api::Comment => Db::Comment, + Api::MediaFile => Db::MediaFile, + Api::ModelWeight => Db::ModelWeight, + Api::User => Db::User, + } +} + +pub fn audit_log_entity_type_to_api(db_value: &Db) -> Api { + match db_value { + Db::Comment => Api::Comment, + Db::MediaFile => Api::MediaFile, + Db::ModelWeight => Api::ModelWeight, + Db::User => Api::User, + } +} + +#[cfg(test)] +mod tests { + use super::*; + use strum::IntoEnumIterator; + + #[test] + fn round_trip_api_to_db() { + use strum::IntoEnumIterator; + for api_variant in Api::iter() { + let db = audit_log_entity_type_to_db(&api_variant); + let back = audit_log_entity_type_to_api(&db); + assert_eq!(api_variant, back); + } + } + + #[test] + fn round_trip_db_to_api() { + use strum::IntoEnumIterator; + for api_variant in Api::iter() { + let db = audit_log_entity_type_to_db(&api_variant); + let back = audit_log_entity_type_to_api(&db); + assert_eq!(api_variant, back); + } + } +} diff --git a/crates/schema/public/enums_convert/src/by_table/audit_logs/mod.rs b/crates/schema/public/enums_convert/src/by_table/audit_logs/mod.rs new file mode 100644 index 0000000000..9de3fca75c --- /dev/null +++ b/crates/schema/public/enums_convert/src/by_table/audit_logs/mod.rs @@ -0,0 +1,2 @@ +pub mod audit_log_entity_action; +pub mod audit_log_entity_type; diff --git a/crates/schema/public/enums_convert/src/by_table/batch_generations/batch_generation_entity_type.rs b/crates/schema/public/enums_convert/src/by_table/batch_generations/batch_generation_entity_type.rs new file mode 100644 index 0000000000..4b452ab820 --- /dev/null +++ b/crates/schema/public/enums_convert/src/by_table/batch_generations/batch_generation_entity_type.rs @@ -0,0 +1,39 @@ +use enums_api::by_table::batch_generations::batch_generation_entity_type::BatchGenerationEntityType as Api; +use enums_db::by_table::batch_generations::batch_generation_entity_type::BatchGenerationEntityType as Db; + +pub fn batch_generation_entity_type_to_db(api_value: &Api) -> Db { + match api_value { + Api::MediaFile => Db::MediaFile, + } +} + +pub fn batch_generation_entity_type_to_api(db_value: &Db) -> Api { + match db_value { + Db::MediaFile => Api::MediaFile, + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn round_trip_api_to_db() { + use strum::IntoEnumIterator; + for api_variant in Api::iter() { + let db = batch_generation_entity_type_to_db(&api_variant); + let back = batch_generation_entity_type_to_api(&db); + assert_eq!(api_variant, back); + } + } + + #[test] + fn round_trip_db_to_api() { + use strum::IntoEnumIterator; + for variant in Db::iter() { + let api = batch_generation_entity_type_to_api(&variant); + let back = batch_generation_entity_type_to_db(&api); + assert_eq!(variant, back); + } + } +} diff --git a/crates/schema/public/enums_convert/src/by_table/batch_generations/mod.rs b/crates/schema/public/enums_convert/src/by_table/batch_generations/mod.rs new file mode 100644 index 0000000000..6feec4da5f --- /dev/null +++ b/crates/schema/public/enums_convert/src/by_table/batch_generations/mod.rs @@ -0,0 +1 @@ +pub mod batch_generation_entity_type; diff --git a/crates/schema/public/enums_convert/src/by_table/beta_keys/beta_key_product.rs b/crates/schema/public/enums_convert/src/by_table/beta_keys/beta_key_product.rs new file mode 100644 index 0000000000..ea85acce90 --- /dev/null +++ b/crates/schema/public/enums_convert/src/by_table/beta_keys/beta_key_product.rs @@ -0,0 +1,39 @@ +use enums_api::by_table::beta_keys::beta_key_product::BetaKeyProduct as Api; +use enums_db::by_table::beta_keys::beta_key_product::BetaKeyProduct as Db; + +pub fn beta_key_product_to_db(api_value: &Api) -> Db { + match api_value { + Api::Studio => Db::Studio, + } +} + +pub fn beta_key_product_to_api(db_value: &Db) -> Api { + match db_value { + Db::Studio => Api::Studio, + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn round_trip_api_to_db() { + use strum::IntoEnumIterator; + for api_variant in Api::iter() { + let db = beta_key_product_to_db(&api_variant); + let back = beta_key_product_to_api(&db); + assert_eq!(api_variant, back); + } + } + + #[test] + fn round_trip_db_to_api() { + use strum::IntoEnumIterator; + for variant in Db::iter() { + let api = beta_key_product_to_api(&variant); + let back = beta_key_product_to_db(&api); + assert_eq!(variant, back); + } + } +} diff --git a/crates/schema/public/enums_convert/src/by_table/beta_keys/mod.rs b/crates/schema/public/enums_convert/src/by_table/beta_keys/mod.rs new file mode 100644 index 0000000000..1e30a227d3 --- /dev/null +++ b/crates/schema/public/enums_convert/src/by_table/beta_keys/mod.rs @@ -0,0 +1 @@ +pub mod beta_key_product; diff --git a/crates/schema/public/enums_convert/src/by_table/comments/comment_entity_type.rs b/crates/schema/public/enums_convert/src/by_table/comments/comment_entity_type.rs new file mode 100644 index 0000000000..c75edc21c7 --- /dev/null +++ b/crates/schema/public/enums_convert/src/by_table/comments/comment_entity_type.rs @@ -0,0 +1,52 @@ +use enums_api::by_table::comments::comment_entity_type::CommentEntityType as Api; +use enums_db::by_table::comments::comment_entity_type::CommentEntityType as Db; + +pub fn comment_entity_type_to_db(api_value: &Api) -> Db { + match api_value { + Api::User => Db::User, + Api::MediaFile => Db::MediaFile, + Api::ModelWeight => Db::ModelWeight, + Api::TtsModel => Db::TtsModel, + Api::TtsResult => Db::TtsResult, + Api::W2lTemplate => Db::W2lTemplate, + Api::W2lResult => Db::W2lResult, + } +} + +pub fn comment_entity_type_to_api(db_value: &Db) -> Api { + match db_value { + Db::User => Api::User, + Db::MediaFile => Api::MediaFile, + Db::ModelWeight => Api::ModelWeight, + Db::TtsModel => Api::TtsModel, + Db::TtsResult => Api::TtsResult, + Db::W2lTemplate => Api::W2lTemplate, + Db::W2lResult => Api::W2lResult, + } +} + +#[cfg(test)] +mod tests { + use super::*; + use strum::IntoEnumIterator; + + #[test] + fn round_trip_api_to_db() { + use strum::IntoEnumIterator; + for api_variant in Api::iter() { + let db = comment_entity_type_to_db(&api_variant); + let back = comment_entity_type_to_api(&db); + assert_eq!(api_variant, back); + } + } + + #[test] + fn round_trip_db_to_api() { + use strum::IntoEnumIterator; + for api_variant in Api::iter() { + let db = comment_entity_type_to_db(&api_variant); + let back = comment_entity_type_to_api(&db); + assert_eq!(api_variant, back); + } + } +} diff --git a/crates/schema/public/enums_convert/src/by_table/comments/mod.rs b/crates/schema/public/enums_convert/src/by_table/comments/mod.rs new file mode 100644 index 0000000000..e30377b8e0 --- /dev/null +++ b/crates/schema/public/enums_convert/src/by_table/comments/mod.rs @@ -0,0 +1 @@ +pub mod comment_entity_type; diff --git a/crates/schema/public/enums_convert/src/by_table/email_sender_jobs/email_category.rs b/crates/schema/public/enums_convert/src/by_table/email_sender_jobs/email_category.rs new file mode 100644 index 0000000000..db0d3bd333 --- /dev/null +++ b/crates/schema/public/enums_convert/src/by_table/email_sender_jobs/email_category.rs @@ -0,0 +1,41 @@ +use enums_api::by_table::email_sender_jobs::email_category::EmailCategory as Api; +use enums_db::by_table::email_sender_jobs::email_category::EmailCategory as Db; + +pub fn email_category_to_db(api_value: &Api) -> Db { + match api_value { + Api::Welcome => Db::Welcome, + Api::PasswordReset => Db::PasswordReset, + } +} + +pub fn email_category_to_api(db_value: &Db) -> Api { + match db_value { + Db::Welcome => Api::Welcome, + Db::PasswordReset => Api::PasswordReset, + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn round_trip_api_to_db() { + use strum::IntoEnumIterator; + for api_variant in Api::iter() { + let db = email_category_to_db(&api_variant); + let back = email_category_to_api(&db); + assert_eq!(api_variant, back); + } + } + + #[test] + fn round_trip_db_to_api() { + use strum::IntoEnumIterator; + for variant in Db::iter() { + let api = email_category_to_api(&variant); + let back = email_category_to_db(&api); + assert_eq!(variant, back); + } + } +} diff --git a/crates/schema/public/enums_convert/src/by_table/email_sender_jobs/mod.rs b/crates/schema/public/enums_convert/src/by_table/email_sender_jobs/mod.rs new file mode 100644 index 0000000000..18d5731795 --- /dev/null +++ b/crates/schema/public/enums_convert/src/by_table/email_sender_jobs/mod.rs @@ -0,0 +1 @@ +pub mod email_category; diff --git a/crates/schema/public/enums_convert/src/by_table/entity_stats/mod.rs b/crates/schema/public/enums_convert/src/by_table/entity_stats/mod.rs new file mode 100644 index 0000000000..58a4a07b90 --- /dev/null +++ b/crates/schema/public/enums_convert/src/by_table/entity_stats/mod.rs @@ -0,0 +1 @@ +pub mod stats_entity_type; diff --git a/crates/schema/public/enums_convert/src/by_table/entity_stats/stats_entity_type.rs b/crates/schema/public/enums_convert/src/by_table/entity_stats/stats_entity_type.rs new file mode 100644 index 0000000000..440f4c536c --- /dev/null +++ b/crates/schema/public/enums_convert/src/by_table/entity_stats/stats_entity_type.rs @@ -0,0 +1,43 @@ +use enums_api::by_table::entity_stats::stats_entity_type::StatsEntityType as Api; +use enums_db::by_table::entity_stats::stats_entity_type::StatsEntityType as Db; + +pub fn stats_entity_type_to_db(api_value: &Api) -> Db { + match api_value { + Api::Comment => Db::Comment, + Api::MediaFile => Db::MediaFile, + Api::ModelWeight => Db::ModelWeight, + } +} + +pub fn stats_entity_type_to_api(db_value: &Db) -> Api { + match db_value { + Db::Comment => Api::Comment, + Db::MediaFile => Api::MediaFile, + Db::ModelWeight => Api::ModelWeight, + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn round_trip_api_to_db() { + use strum::IntoEnumIterator; + for api_variant in Api::iter() { + let db = stats_entity_type_to_db(&api_variant); + let back = stats_entity_type_to_api(&db); + assert_eq!(api_variant, back); + } + } + + #[test] + fn round_trip_db_to_api() { + use strum::IntoEnumIterator; + for variant in Db::iter() { + let api = stats_entity_type_to_api(&variant); + let back = stats_entity_type_to_db(&api); + assert_eq!(variant, back); + } + } +} diff --git a/crates/schema/public/enums_convert/src/by_table/featured_items/featured_item_entity_type.rs b/crates/schema/public/enums_convert/src/by_table/featured_items/featured_item_entity_type.rs new file mode 100644 index 0000000000..f776decd0a --- /dev/null +++ b/crates/schema/public/enums_convert/src/by_table/featured_items/featured_item_entity_type.rs @@ -0,0 +1,43 @@ +use enums_api::by_table::featured_items::featured_item_entity_type::FeaturedItemEntityType as Api; +use enums_db::by_table::featured_items::featured_item_entity_type::FeaturedItemEntityType as Db; + +pub fn featured_item_entity_type_to_db(api_value: &Api) -> Db { + match api_value { + Api::MediaFile => Db::MediaFile, + Api::ModelWeight => Db::ModelWeight, + Api::User => Db::User, + } +} + +pub fn featured_item_entity_type_to_api(db_value: &Db) -> Api { + match db_value { + Db::MediaFile => Api::MediaFile, + Db::ModelWeight => Api::ModelWeight, + Db::User => Api::User, + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn round_trip_api_to_db() { + use strum::IntoEnumIterator; + for api_variant in Api::iter() { + let db = featured_item_entity_type_to_db(&api_variant); + let back = featured_item_entity_type_to_api(&db); + assert_eq!(api_variant, back); + } + } + + #[test] + fn round_trip_db_to_api() { + use strum::IntoEnumIterator; + for variant in Db::iter() { + let api = featured_item_entity_type_to_api(&variant); + let back = featured_item_entity_type_to_db(&api); + assert_eq!(variant, back); + } + } +} diff --git a/crates/schema/public/enums_convert/src/by_table/featured_items/mod.rs b/crates/schema/public/enums_convert/src/by_table/featured_items/mod.rs new file mode 100644 index 0000000000..61e791bb90 --- /dev/null +++ b/crates/schema/public/enums_convert/src/by_table/featured_items/mod.rs @@ -0,0 +1 @@ +pub mod featured_item_entity_type; diff --git a/crates/schema/public/enums_convert/src/by_table/generic_download_jobs/generic_download_type.rs b/crates/schema/public/enums_convert/src/by_table/generic_download_jobs/generic_download_type.rs new file mode 100644 index 0000000000..9c8c03e5dc --- /dev/null +++ b/crates/schema/public/enums_convert/src/by_table/generic_download_jobs/generic_download_type.rs @@ -0,0 +1,53 @@ +use enums_api::by_table::generic_download_jobs::generic_download_type::GenericDownloadType as Api; +use enums_db::by_table::generic_download_jobs::generic_download_type::GenericDownloadType as Db; + +pub fn generic_download_type_to_db(api_value: &Api) -> Db { + match api_value { + Api::HifiGan => Db::HifiGan, + Api::HifiGanRocketVc => Db::HifiGanRocketVc, + Api::HifiGanSoVitsSvc => Db::HifiGanSoVitsSvc, + Api::RocketVc => Db::RocketVc, + Api::RvcV2 => Db::RvcV2, + Api::SoVitsSvc => Db::SoVitsSvc, + Api::Tacotron2 => Db::Tacotron2, + Api::Vits => Db::Vits, + } +} + +pub fn generic_download_type_to_api(db_value: &Db) -> Api { + match db_value { + Db::HifiGan => Api::HifiGan, + Db::HifiGanRocketVc => Api::HifiGanRocketVc, + Db::HifiGanSoVitsSvc => Api::HifiGanSoVitsSvc, + Db::RocketVc => Api::RocketVc, + Db::RvcV2 => Api::RvcV2, + Db::SoVitsSvc => Api::SoVitsSvc, + Db::Tacotron2 => Api::Tacotron2, + Db::Vits => Api::Vits, + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn round_trip_api_to_db() { + use strum::IntoEnumIterator; + for api_variant in Api::iter() { + let db = generic_download_type_to_db(&api_variant); + let back = generic_download_type_to_api(&db); + assert_eq!(api_variant, back); + } + } + + #[test] + fn round_trip_db_to_api() { + use strum::IntoEnumIterator; + for variant in Db::iter() { + let api = generic_download_type_to_api(&variant); + let back = generic_download_type_to_db(&api); + assert_eq!(variant, back); + } + } +} diff --git a/crates/schema/public/enums_convert/src/by_table/generic_download_jobs/mod.rs b/crates/schema/public/enums_convert/src/by_table/generic_download_jobs/mod.rs new file mode 100644 index 0000000000..40d1e08d44 --- /dev/null +++ b/crates/schema/public/enums_convert/src/by_table/generic_download_jobs/mod.rs @@ -0,0 +1 @@ +pub mod generic_download_type; diff --git a/crates/schema/public/enums_convert/src/by_table/generic_inference_jobs/inference_category.rs b/crates/schema/public/enums_convert/src/by_table/generic_inference_jobs/inference_category.rs new file mode 100644 index 0000000000..4824a9989e --- /dev/null +++ b/crates/schema/public/enums_convert/src/by_table/generic_inference_jobs/inference_category.rs @@ -0,0 +1,71 @@ +use enums_api::by_table::generic_inference_jobs::inference_category::InferenceCategory as Api; +use enums_db::by_table::generic_inference_jobs::inference_category::InferenceCategory as Db; + +pub fn inference_category_to_db(api_value: &Api) -> Db { + match api_value { + Api::DeprecatedField => Db::DeprecatedField, + Api::LipsyncAnimation => Db::LipsyncAnimation, + Api::TextToSpeech => Db::TextToSpeech, + Api::VoiceConversion => Db::VoiceConversion, + Api::ImageGeneration => Db::ImageGeneration, + Api::VideoGeneration => Db::VideoGeneration, + Api::ObjectGeneration => Db::ObjectGeneration, + Api::SplatGeneration => Db::SplatGeneration, + Api::BackgroundRemoval => Db::BackgroundRemoval, + Api::Mocap => Db::Mocap, + Api::Workflow => Db::Workflow, + Api::FormatConversion => Db::FormatConversion, + Api::LivePortrait => Db::LivePortrait, + Api::SeedVc => Db::SeedVc, + Api::VideoFilter => Db::VideoFilter, + Api::ConvertBvhToWorkflow => Db::ConvertBvhToWorkflow, + Api::F5TTS => Db::F5TTS, + } +} + +pub fn inference_category_to_api(db_value: &Db) -> Api { + match db_value { + Db::DeprecatedField => Api::DeprecatedField, + Db::LipsyncAnimation => Api::LipsyncAnimation, + Db::TextToSpeech => Api::TextToSpeech, + Db::VoiceConversion => Api::VoiceConversion, + Db::ImageGeneration => Api::ImageGeneration, + Db::VideoGeneration => Api::VideoGeneration, + Db::ObjectGeneration => Api::ObjectGeneration, + Db::SplatGeneration => Api::SplatGeneration, + Db::BackgroundRemoval => Api::BackgroundRemoval, + Db::Mocap => Api::Mocap, + Db::Workflow => Api::Workflow, + Db::FormatConversion => Api::FormatConversion, + Db::LivePortrait => Api::LivePortrait, + Db::SeedVc => Api::SeedVc, + Db::VideoFilter => Api::VideoFilter, + Db::ConvertBvhToWorkflow => Api::ConvertBvhToWorkflow, + Db::F5TTS => Api::F5TTS, + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn round_trip_api_to_db() { + use strum::IntoEnumIterator; + for api_variant in Api::iter() { + let db = inference_category_to_db(&api_variant); + let back = inference_category_to_api(&db); + assert_eq!(api_variant, back); + } + } + + #[test] + fn round_trip_db_to_api() { + use strum::IntoEnumIterator; + for variant in Db::iter() { + let api = inference_category_to_api(&variant); + let back = inference_category_to_db(&api); + assert_eq!(variant, back); + } + } +} diff --git a/crates/schema/public/enums_convert/src/by_table/generic_inference_jobs/inference_input_source_token_type.rs b/crates/schema/public/enums_convert/src/by_table/generic_inference_jobs/inference_input_source_token_type.rs new file mode 100644 index 0000000000..8650bf54ae --- /dev/null +++ b/crates/schema/public/enums_convert/src/by_table/generic_inference_jobs/inference_input_source_token_type.rs @@ -0,0 +1,41 @@ +use enums_api::by_table::generic_inference_jobs::inference_input_source_token_type::InferenceInputSourceTokenType as Api; +use enums_db::by_table::generic_inference_jobs::inference_input_source_token_type::InferenceInputSourceTokenType as Db; + +pub fn inference_input_source_token_type_to_db(api_value: &Api) -> Db { + match api_value { + Api::MediaFile => Db::MediaFile, + Api::MediaUpload => Db::MediaUpload, + } +} + +pub fn inference_input_source_token_type_to_api(db_value: &Db) -> Api { + match db_value { + Db::MediaFile => Api::MediaFile, + Db::MediaUpload => Api::MediaUpload, + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn round_trip_api_to_db() { + use strum::IntoEnumIterator; + for api_variant in Api::iter() { + let db = inference_input_source_token_type_to_db(&api_variant); + let back = inference_input_source_token_type_to_api(&db); + assert_eq!(api_variant, back); + } + } + + #[test] + fn round_trip_db_to_api() { + use strum::IntoEnumIterator; + for variant in Db::iter() { + let api = inference_input_source_token_type_to_api(&variant); + let back = inference_input_source_token_type_to_db(&api); + assert_eq!(variant, back); + } + } +} diff --git a/crates/schema/public/enums_convert/src/by_table/generic_inference_jobs/inference_job_external_third_party.rs b/crates/schema/public/enums_convert/src/by_table/generic_inference_jobs/inference_job_external_third_party.rs new file mode 100644 index 0000000000..717e12a0d1 --- /dev/null +++ b/crates/schema/public/enums_convert/src/by_table/generic_inference_jobs/inference_job_external_third_party.rs @@ -0,0 +1,43 @@ +use enums_api::by_table::generic_inference_jobs::inference_job_external_third_party::InferenceJobExternalThirdParty as Api; +use enums_db::by_table::generic_inference_jobs::inference_job_external_third_party::InferenceJobExternalThirdParty as Db; + +pub fn inference_job_external_third_party_to_db(api_value: &Api) -> Db { + match api_value { + Api::Fal => Db::Fal, + Api::Seedance2Pro => Db::Seedance2Pro, + Api::Worldlabs => Db::Worldlabs, + } +} + +pub fn inference_job_external_third_party_to_api(db_value: &Db) -> Api { + match db_value { + Db::Fal => Api::Fal, + Db::Seedance2Pro => Api::Seedance2Pro, + Db::Worldlabs => Api::Worldlabs, + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn round_trip_api_to_db() { + use strum::IntoEnumIterator; + for api_variant in Api::iter() { + let db = inference_job_external_third_party_to_db(&api_variant); + let back = inference_job_external_third_party_to_api(&db); + assert_eq!(api_variant, back); + } + } + + #[test] + fn round_trip_db_to_api() { + use strum::IntoEnumIterator; + for variant in Db::iter() { + let api = inference_job_external_third_party_to_api(&variant); + let back = inference_job_external_third_party_to_db(&api); + assert_eq!(variant, back); + } + } +} diff --git a/crates/schema/public/enums_convert/src/by_table/generic_inference_jobs/inference_job_product_category.rs b/crates/schema/public/enums_convert/src/by_table/generic_inference_jobs/inference_job_product_category.rs new file mode 100644 index 0000000000..d2db988be6 --- /dev/null +++ b/crates/schema/public/enums_convert/src/by_table/generic_inference_jobs/inference_job_product_category.rs @@ -0,0 +1,95 @@ +use enums_api::by_table::generic_inference_jobs::inference_job_product_category::InferenceJobProductCategory as Api; +use enums_db::by_table::generic_inference_jobs::inference_job_product_category::InferenceJobProductCategory as Db; + +pub fn inference_job_product_category_to_db(api_value: &Api) -> Db { + match api_value { + Api::DownloadGptSoVits => Db::DownloadGptSoVits, + Api::FalImage => Db::FalImage, + Api::FalVideo => Db::FalVideo, + Api::FalObject => Db::FalObject, + Api::FalBgRemoval => Db::FalBgRemoval, + Api::Seedance2ProVideo => Db::Seedance2ProVideo, + Api::WorldlabsSplat => Db::WorldlabsSplat, + Api::TtsGptSoVits => Db::TtsGptSoVits, + Api::TtsF5 => Db::TtsF5, + Api::TtsStyleTts2 => Db::TtsStyleTts2, + Api::TtsTacotron2 => Db::TtsTacotron2, + Api::VcRvc2 => Db::VcRvc2, + Api::VcSvc => Db::VcSvc, + Api::VcSeedVc => Db::VcSeedVc, + Api::VidLipsyncFaceFusion => Db::VidLipsyncFaceFusion, + Api::VidLipsyncSadTalker => Db::VidLipsyncSadTalker, + Api::VidLivePortrait => Db::VidLivePortrait, + Api::VidLivePortraitWebcam => Db::VidLivePortraitWebcam, + Api::VidStudio => Db::VidStudio, + Api::VidStudioGen2 => Db::VidStudioGen2, + Api::VidStyleTransfer => Db::VidStyleTransfer, + Api::LipsyncFaceFusion => Db::LipsyncFaceFusion, + Api::LipsyncSadTalker => Db::LipsyncSadTalker, + Api::LivePortrait => Db::LivePortrait, + Api::LivePortraitWebcam => Db::LivePortraitWebcam, + Api::StableDiffusion => Db::StableDiffusion, + Api::Studio => Db::Studio, + Api::VidFaceFusion => Db::VidFaceFusion, + Api::Vst => Db::Vst, + } +} + +pub fn inference_job_product_category_to_api(db_value: &Db) -> Api { + match db_value { + Db::DownloadGptSoVits => Api::DownloadGptSoVits, + Db::FalImage => Api::FalImage, + Db::FalVideo => Api::FalVideo, + Db::FalObject => Api::FalObject, + Db::FalBgRemoval => Api::FalBgRemoval, + Db::Seedance2ProVideo => Api::Seedance2ProVideo, + Db::WorldlabsSplat => Api::WorldlabsSplat, + Db::TtsGptSoVits => Api::TtsGptSoVits, + Db::TtsF5 => Api::TtsF5, + Db::TtsStyleTts2 => Api::TtsStyleTts2, + Db::TtsTacotron2 => Api::TtsTacotron2, + Db::VcRvc2 => Api::VcRvc2, + Db::VcSvc => Api::VcSvc, + Db::VcSeedVc => Api::VcSeedVc, + Db::VidLipsyncFaceFusion => Api::VidLipsyncFaceFusion, + Db::VidLipsyncSadTalker => Api::VidLipsyncSadTalker, + Db::VidLivePortrait => Api::VidLivePortrait, + Db::VidLivePortraitWebcam => Api::VidLivePortraitWebcam, + Db::VidStudio => Api::VidStudio, + Db::VidStudioGen2 => Api::VidStudioGen2, + Db::VidStyleTransfer => Api::VidStyleTransfer, + Db::LipsyncFaceFusion => Api::LipsyncFaceFusion, + Db::LipsyncSadTalker => Api::LipsyncSadTalker, + Db::LivePortrait => Api::LivePortrait, + Db::LivePortraitWebcam => Api::LivePortraitWebcam, + Db::StableDiffusion => Api::StableDiffusion, + Db::Studio => Api::Studio, + Db::VidFaceFusion => Api::VidFaceFusion, + Db::Vst => Api::Vst, + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn round_trip_api_to_db() { + use strum::IntoEnumIterator; + for api_variant in Api::iter() { + let db = inference_job_product_category_to_db(&api_variant); + let back = inference_job_product_category_to_api(&db); + assert_eq!(api_variant, back); + } + } + + #[test] + fn round_trip_db_to_api() { + use strum::IntoEnumIterator; + for variant in Db::iter() { + let api = inference_job_product_category_to_api(&variant); + let back = inference_job_product_category_to_db(&api); + assert_eq!(variant, back); + } + } +} diff --git a/crates/schema/public/enums_convert/src/by_table/generic_inference_jobs/inference_job_type.rs b/crates/schema/public/enums_convert/src/by_table/generic_inference_jobs/inference_job_type.rs new file mode 100644 index 0000000000..73a42172e7 --- /dev/null +++ b/crates/schema/public/enums_convert/src/by_table/generic_inference_jobs/inference_job_type.rs @@ -0,0 +1,93 @@ +use enums_api::by_table::generic_inference_jobs::inference_job_type::InferenceJobType as Api; +use enums_db::by_table::generic_inference_jobs::inference_job_type::InferenceJobType as Db; + +pub fn inference_job_type_to_db(api_value: &Api) -> Db { + match api_value { + Api::ActingFace => Db::LivePortrait, + Api::Lipsync => Db::FaceFusion, + Api::FalQueue => Db::FalQueue, + Api::VideoRender => Db::VideoRender, + Api::GptSovits => Db::GptSovits, + Api::F5TTS => Db::F5TTS, + Api::ComfyUi => Db::ComfyUi, + Api::StudioGen2 => Db::StudioGen2, + Api::ConvertFbxToGltf => Db::ConvertFbxToGltf, + Api::MocapNet => Db::MocapNet, + Api::RvcV2 => Db::RvcV2, + Api::SadTalker => Db::SadTalker, + Api::SeedVc => Db::SeedVc, + Api::SoVitsSvc => Db::SoVitsSvc, + Api::StableDiffusion => Db::StableDiffusion, + Api::ImageGenApi => Db::ImageGenApi, + Api::Seedance2ProQueue => Db::Seedance2ProQueue, + Api::WorldlabsQueue => Db::WorldlabsQueue, + Api::StyleTTS2 => Db::StyleTTS2, + Api::Tacotron2 => Db::Tacotron2, + Api::Unknown => Db::Unknown, + Api::BevyToWorkflow => Db::BevyToWorkflow, + Api::RerenderAVideo => Db::RerenderAVideo, + } +} + +pub fn inference_job_type_to_api(db_value: &Db) -> Api { + match db_value { + Db::LivePortrait => Api::ActingFace, + Db::FaceFusion => Api::Lipsync, + Db::FalQueue => Api::FalQueue, + Db::VideoRender => Api::VideoRender, + Db::GptSovits => Api::GptSovits, + Db::F5TTS => Api::F5TTS, + Db::ComfyUi => Api::ComfyUi, + Db::StudioGen2 => Api::StudioGen2, + Db::ConvertFbxToGltf => Api::ConvertFbxToGltf, + Db::MocapNet => Api::MocapNet, + Db::RvcV2 => Api::RvcV2, + Db::SadTalker => Api::SadTalker, + Db::SeedVc => Api::SeedVc, + Db::SoVitsSvc => Api::SoVitsSvc, + Db::StableDiffusion => Api::StableDiffusion, + Db::StyleTTS2 => Api::StyleTTS2, + Db::Tacotron2 => Api::Tacotron2, + Db::Unknown => Api::Unknown, + Db::BevyToWorkflow => Api::BevyToWorkflow, + Db::RerenderAVideo => Api::RerenderAVideo, + Db::ImageGenApi => Api::ImageGenApi, + Db::Seedance2ProQueue => Api::Seedance2ProQueue, + Db::WorldlabsQueue => Api::WorldlabsQueue, + } +} + +#[cfg(test)] +mod tests { + use super::*; + use strum::IntoEnumIterator; + + #[test] + fn round_trip_api_to_db() { + use strum::IntoEnumIterator; + for db_variant in Db::iter() { + let api = inference_job_type_to_api(&db_variant); + let db = inference_job_type_to_db(&api); + let back = inference_job_type_to_api(&db); + assert_eq!(api, back); + } + } + + #[test] + fn round_trip_db_to_api() { + use strum::IntoEnumIterator; + for variant in Db::iter() { + let api = inference_job_type_to_api(&variant); + let back = inference_job_type_to_db(&api); + assert_eq!(variant, back); + } + } + + #[test] + fn renamed_variants() { + assert_eq!(inference_job_type_to_db(&Api::ActingFace), Db::LivePortrait); + assert_eq!(inference_job_type_to_db(&Api::Lipsync), Db::FaceFusion); + assert_eq!(inference_job_type_to_api(&Db::LivePortrait), Api::ActingFace); + assert_eq!(inference_job_type_to_api(&Db::FaceFusion), Api::Lipsync); + } +} diff --git a/crates/schema/public/enums_convert/src/by_table/generic_inference_jobs/inference_model_type.rs b/crates/schema/public/enums_convert/src/by_table/generic_inference_jobs/inference_model_type.rs new file mode 100644 index 0000000000..b7f1ce8f98 --- /dev/null +++ b/crates/schema/public/enums_convert/src/by_table/generic_inference_jobs/inference_model_type.rs @@ -0,0 +1,67 @@ +use enums_api::by_table::generic_inference_jobs::inference_model_type::InferenceModelType as Api; +use enums_db::by_table::generic_inference_jobs::inference_model_type::InferenceModelType as Db; + +pub fn inference_model_type_to_db(api_value: &Api) -> Db { + match api_value { + Api::ComfyUi => Db::ComfyUi, + Api::RvcV2 => Db::RvcV2, + Api::SadTalker => Db::SadTalker, + Api::SoVitsSvc => Db::SoVitsSvc, + Api::SeedVc => Db::SeedVc, + Api::ImageGenApi => Db::ImageGenApi, + Api::Tacotron2 => Db::Tacotron2, + Api::Vits => Db::Vits, + Api::VallEX => Db::VallEX, + Api::RerenderAVideo => Db::RerenderAVideo, + Api::StableDiffusion => Db::StableDiffusion, + Api::MocapNet => Db::MocapNet, + Api::StyleTTS2 => Db::StyleTTS2, + Api::ConvertFbxToGltf => Db::ConvertFbxToGltf, + Api::BvhToWorkflow => Db::BvhToWorkflow, + } +} + +pub fn inference_model_type_to_api(db_value: &Db) -> Api { + match db_value { + Db::ComfyUi => Api::ComfyUi, + Db::RvcV2 => Api::RvcV2, + Db::SadTalker => Api::SadTalker, + Db::SoVitsSvc => Api::SoVitsSvc, + Db::SeedVc => Api::SeedVc, + Db::ImageGenApi => Api::ImageGenApi, + Db::Tacotron2 => Api::Tacotron2, + Db::Vits => Api::Vits, + Db::VallEX => Api::VallEX, + Db::RerenderAVideo => Api::RerenderAVideo, + Db::StableDiffusion => Api::StableDiffusion, + Db::MocapNet => Api::MocapNet, + Db::StyleTTS2 => Api::StyleTTS2, + Db::ConvertFbxToGltf => Api::ConvertFbxToGltf, + Db::BvhToWorkflow => Api::BvhToWorkflow, + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn round_trip_api_to_db() { + use strum::IntoEnumIterator; + for api_variant in Api::iter() { + let db = inference_model_type_to_db(&api_variant); + let back = inference_model_type_to_api(&db); + assert_eq!(api_variant, back); + } + } + + #[test] + fn round_trip_db_to_api() { + use strum::IntoEnumIterator; + for variant in Db::iter() { + let api = inference_model_type_to_api(&variant); + let back = inference_model_type_to_db(&api); + assert_eq!(variant, back); + } + } +} diff --git a/crates/schema/public/enums_convert/src/by_table/generic_inference_jobs/inference_result_type.rs b/crates/schema/public/enums_convert/src/by_table/generic_inference_jobs/inference_result_type.rs new file mode 100644 index 0000000000..f666b07349 --- /dev/null +++ b/crates/schema/public/enums_convert/src/by_table/generic_inference_jobs/inference_result_type.rs @@ -0,0 +1,47 @@ +use enums_api::by_table::generic_inference_jobs::inference_result_type::InferenceResultType as Api; +use enums_db::by_table::generic_inference_jobs::inference_result_type::InferenceResultType as Db; + +pub fn inference_result_type_to_db(api_value: &Api) -> Db { + match api_value { + Api::MediaFile => Db::MediaFile, + Api::TextToSpeech => Db::TextToSpeech, + Api::VoiceConversion => Db::VoiceConversion, + Api::ZeroShotVoiceEmbedding => Db::ZeroShotVoiceEmbedding, + Api::UploadModel => Db::UploadModel, + } +} + +pub fn inference_result_type_to_api(db_value: &Db) -> Api { + match db_value { + Db::MediaFile => Api::MediaFile, + Db::TextToSpeech => Api::TextToSpeech, + Db::VoiceConversion => Api::VoiceConversion, + Db::ZeroShotVoiceEmbedding => Api::ZeroShotVoiceEmbedding, + Db::UploadModel => Api::UploadModel, + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn round_trip_api_to_db() { + use strum::IntoEnumIterator; + for api_variant in Api::iter() { + let db = inference_result_type_to_db(&api_variant); + let back = inference_result_type_to_api(&db); + assert_eq!(api_variant, back); + } + } + + #[test] + fn round_trip_db_to_api() { + use strum::IntoEnumIterator; + for variant in Db::iter() { + let api = inference_result_type_to_api(&variant); + let back = inference_result_type_to_db(&api); + assert_eq!(variant, back); + } + } +} diff --git a/crates/schema/public/enums_convert/src/by_table/generic_inference_jobs/mod.rs b/crates/schema/public/enums_convert/src/by_table/generic_inference_jobs/mod.rs new file mode 100644 index 0000000000..df452ad0c6 --- /dev/null +++ b/crates/schema/public/enums_convert/src/by_table/generic_inference_jobs/mod.rs @@ -0,0 +1,7 @@ +pub mod inference_category; +pub mod inference_input_source_token_type; +pub mod inference_job_external_third_party; +pub mod inference_job_product_category; +pub mod inference_job_type; +pub mod inference_model_type; +pub mod inference_result_type; diff --git a/crates/schema/public/enums_convert/src/by_table/generic_synthetic_ids/id_category.rs b/crates/schema/public/enums_convert/src/by_table/generic_synthetic_ids/id_category.rs new file mode 100644 index 0000000000..e6522e45ba --- /dev/null +++ b/crates/schema/public/enums_convert/src/by_table/generic_synthetic_ids/id_category.rs @@ -0,0 +1,67 @@ +use enums_api::by_table::generic_synthetic_ids::id_category::IdCategory as Api; +use enums_db::by_table::generic_synthetic_ids::id_category::IdCategory as Db; + +pub fn id_category_to_db(api_value: &Api) -> Db { + match api_value { + Api::MediaFile => Db::MediaFile, + Api::LipsyncAnimationResult => Db::LipsyncAnimationResult, + Api::FaceFusionResult => Db::FaceFusionResult, + Api::VideoFilterResult => Db::VideoFilterResult, + Api::LivePortraitResult => Db::LivePortraitResult, + Api::StudioRender => Db::StudioRender, + Api::MocapResult => Db::MocapResult, + Api::WorkflowResult => Db::WorkflowResult, + Api::TtsResult => Db::TtsResult, + Api::VoiceConversionResult => Db::VoiceConversionResult, + Api::ZeroShotTtsResult => Db::ZeroShotTtsResult, + Api::ZeroShotVoiceDataset => Db::ZeroShotVoiceDataset, + Api::ZeroShotVoiceEmbedding => Db::ZeroShotVoiceEmbedding, + Api::ModelWeights => Db::ModelWeights, + Api::FileUpload => Db::FileUpload, + } +} + +pub fn id_category_to_api(db_value: &Db) -> Api { + match db_value { + Db::MediaFile => Api::MediaFile, + Db::LipsyncAnimationResult => Api::LipsyncAnimationResult, + Db::FaceFusionResult => Api::FaceFusionResult, + Db::VideoFilterResult => Api::VideoFilterResult, + Db::LivePortraitResult => Api::LivePortraitResult, + Db::StudioRender => Api::StudioRender, + Db::MocapResult => Api::MocapResult, + Db::WorkflowResult => Api::WorkflowResult, + Db::TtsResult => Api::TtsResult, + Db::VoiceConversionResult => Api::VoiceConversionResult, + Db::ZeroShotTtsResult => Api::ZeroShotTtsResult, + Db::ZeroShotVoiceDataset => Api::ZeroShotVoiceDataset, + Db::ZeroShotVoiceEmbedding => Api::ZeroShotVoiceEmbedding, + Db::ModelWeights => Api::ModelWeights, + Db::FileUpload => Api::FileUpload, + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn round_trip_api_to_db() { + use strum::IntoEnumIterator; + for api_variant in Api::iter() { + let db = id_category_to_db(&api_variant); + let back = id_category_to_api(&db); + assert_eq!(api_variant, back); + } + } + + #[test] + fn round_trip_db_to_api() { + use strum::IntoEnumIterator; + for variant in Db::iter() { + let api = id_category_to_api(&variant); + let back = id_category_to_db(&api); + assert_eq!(variant, back); + } + } +} diff --git a/crates/schema/public/enums_convert/src/by_table/generic_synthetic_ids/mod.rs b/crates/schema/public/enums_convert/src/by_table/generic_synthetic_ids/mod.rs new file mode 100644 index 0000000000..f130b83c6e --- /dev/null +++ b/crates/schema/public/enums_convert/src/by_table/generic_synthetic_ids/mod.rs @@ -0,0 +1 @@ +pub mod id_category; diff --git a/crates/schema/public/enums_convert/src/by_table/media_files/media_file_animation_type.rs b/crates/schema/public/enums_convert/src/by_table/media_files/media_file_animation_type.rs new file mode 100644 index 0000000000..7b966c34d2 --- /dev/null +++ b/crates/schema/public/enums_convert/src/by_table/media_files/media_file_animation_type.rs @@ -0,0 +1,63 @@ +use enums_api::by_table::media_files::media_file_animation_type::MediaFileAnimationType as Api; +use enums_db::by_table::media_files::media_file_animation_type::MediaFileAnimationType as Db; + +pub fn media_file_animation_type_to_db(api_value: &Api) -> Db { + match api_value { + Api::ArKit => Db::ArKit, + Api::MikuMikuDance => Db::MikuMikuDance, + Api::MikuMikuDanceArKit => Db::MikuMikuDanceArKit, + Api::Mixamo => Db::Mixamo, + Api::MixamoArKit => Db::MixamoArKit, + Api::MocapNet => Db::MocapNet, + Api::MocapNetArKit => Db::MocapNetArKit, + Api::MoveAi => Db::MoveAi, + Api::MoveAiArKit => Db::MoveAiArKit, + Api::Rigify => Db::Rigify, + Api::RigifyArKit => Db::RigifyArKit, + Api::Rokoko => Db::Rokoko, + Api::RokokoArKit => Db::RokokoArKit, + } +} + +pub fn media_file_animation_type_to_api(db_value: &Db) -> Api { + match db_value { + Db::ArKit => Api::ArKit, + Db::MikuMikuDance => Api::MikuMikuDance, + Db::MikuMikuDanceArKit => Api::MikuMikuDanceArKit, + Db::Mixamo => Api::Mixamo, + Db::MixamoArKit => Api::MixamoArKit, + Db::MocapNet => Api::MocapNet, + Db::MocapNetArKit => Api::MocapNetArKit, + Db::MoveAi => Api::MoveAi, + Db::MoveAiArKit => Api::MoveAiArKit, + Db::Rigify => Api::Rigify, + Db::RigifyArKit => Api::RigifyArKit, + Db::Rokoko => Api::Rokoko, + Db::RokokoArKit => Api::RokokoArKit, + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn round_trip_api_to_db() { + use strum::IntoEnumIterator; + for api_variant in Api::iter() { + let db = media_file_animation_type_to_db(&api_variant); + let back = media_file_animation_type_to_api(&db); + assert_eq!(api_variant, back); + } + } + + #[test] + fn round_trip_db_to_api() { + use strum::IntoEnumIterator; + for variant in Db::iter() { + let api = media_file_animation_type_to_api(&variant); + let back = media_file_animation_type_to_db(&api); + assert_eq!(variant, back); + } + } +} diff --git a/crates/schema/public/enums_convert/src/by_table/media_files/media_file_class.rs b/crates/schema/public/enums_convert/src/by_table/media_files/media_file_class.rs new file mode 100644 index 0000000000..f675d62327 --- /dev/null +++ b/crates/schema/public/enums_convert/src/by_table/media_files/media_file_class.rs @@ -0,0 +1,47 @@ +use enums_api::by_table::media_files::media_file_class::MediaFileClass as Api; +use enums_db::by_table::media_files::media_file_class::MediaFileClass as Db; + +pub fn media_file_class_to_db(api_value: &Api) -> Db { + match api_value { + Api::Unknown => Db::Unknown, + Api::Audio => Db::Audio, + Api::Image => Db::Image, + Api::Video => Db::Video, + Api::Dimensional => Db::Dimensional, + } +} + +pub fn media_file_class_to_api(db_value: &Db) -> Api { + match db_value { + Db::Unknown => Api::Unknown, + Db::Audio => Api::Audio, + Db::Image => Api::Image, + Db::Video => Api::Video, + Db::Dimensional => Api::Dimensional, + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn round_trip_api_to_db() { + use strum::IntoEnumIterator; + for api_variant in Api::iter() { + let db = media_file_class_to_db(&api_variant); + let back = media_file_class_to_api(&db); + assert_eq!(api_variant, back); + } + } + + #[test] + fn round_trip_db_to_api() { + use strum::IntoEnumIterator; + for variant in Db::iter() { + let api = media_file_class_to_api(&variant); + let back = media_file_class_to_db(&api); + assert_eq!(variant, back); + } + } +} diff --git a/crates/schema/public/enums_convert/src/by_table/media_files/media_file_engine_category.rs b/crates/schema/public/enums_convert/src/by_table/media_files/media_file_engine_category.rs new file mode 100644 index 0000000000..be3dd8cf8a --- /dev/null +++ b/crates/schema/public/enums_convert/src/by_table/media_files/media_file_engine_category.rs @@ -0,0 +1,59 @@ +use enums_api::by_table::media_files::media_file_engine_category::MediaFileEngineCategory as Api; +use enums_db::by_table::media_files::media_file_engine_category::MediaFileEngineCategory as Db; + +pub fn media_file_engine_category_to_db(api_value: &Api) -> Db { + match api_value { + Api::Scene => Db::Scene, + Api::Character => Db::Character, + Api::Creature => Db::Creature, + Api::Animation => Db::Animation, + Api::Expression => Db::Expression, + Api::Location => Db::Location, + Api::SetDressing => Db::SetDressing, + Api::Object => Db::Object, + Api::Skybox => Db::Skybox, + Api::ImagePlane => Db::ImagePlane, + Api::VideoPlane => Db::VideoPlane, + } +} + +pub fn media_file_engine_category_to_api(db_value: &Db) -> Api { + match db_value { + Db::Scene => Api::Scene, + Db::Character => Api::Character, + Db::Creature => Api::Creature, + Db::Animation => Api::Animation, + Db::Expression => Api::Expression, + Db::Location => Api::Location, + Db::SetDressing => Api::SetDressing, + Db::Object => Api::Object, + Db::Skybox => Api::Skybox, + Db::ImagePlane => Api::ImagePlane, + Db::VideoPlane => Api::VideoPlane, + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn round_trip_api_to_db() { + use strum::IntoEnumIterator; + for api_variant in Api::iter() { + let db = media_file_engine_category_to_db(&api_variant); + let back = media_file_engine_category_to_api(&db); + assert_eq!(api_variant, back); + } + } + + #[test] + fn round_trip_db_to_api() { + use strum::IntoEnumIterator; + for variant in Db::iter() { + let api = media_file_engine_category_to_api(&variant); + let back = media_file_engine_category_to_db(&api); + assert_eq!(variant, back); + } + } +} diff --git a/crates/schema/public/enums_convert/src/by_table/media_files/media_file_origin_category.rs b/crates/schema/public/enums_convert/src/by_table/media_files/media_file_origin_category.rs new file mode 100644 index 0000000000..566e79011f --- /dev/null +++ b/crates/schema/public/enums_convert/src/by_table/media_files/media_file_origin_category.rs @@ -0,0 +1,49 @@ +use enums_api::by_table::media_files::media_file_origin_category::MediaFileOriginCategory as Api; +use enums_db::by_table::media_files::media_file_origin_category::MediaFileOriginCategory as Db; + +pub fn media_file_origin_category_to_db(api_value: &Api) -> Db { + match api_value { + Api::Inference => Db::Inference, + Api::Processed => Db::Processed, + Api::Upload => Db::Upload, + Api::DeviceApi => Db::DeviceApi, + Api::StorytellerStudio => Db::StorytellerStudio, + Api::StoryEngine => Db::StoryEngine, + } +} + +pub fn media_file_origin_category_to_api(db_value: &Db) -> Api { + match db_value { + Db::Inference => Api::Inference, + Db::Processed => Api::Processed, + Db::Upload => Api::Upload, + Db::DeviceApi => Api::DeviceApi, + Db::StorytellerStudio => Api::StorytellerStudio, + Db::StoryEngine => Api::StoryEngine, + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn round_trip_api_to_db() { + use strum::IntoEnumIterator; + for api_variant in Api::iter() { + let db = media_file_origin_category_to_db(&api_variant); + let back = media_file_origin_category_to_api(&db); + assert_eq!(api_variant, back); + } + } + + #[test] + fn round_trip_db_to_api() { + use strum::IntoEnumIterator; + for variant in Db::iter() { + let api = media_file_origin_category_to_api(&variant); + let back = media_file_origin_category_to_db(&api); + assert_eq!(variant, back); + } + } +} diff --git a/crates/schema/public/enums_convert/src/by_table/media_files/media_file_origin_model_type.rs b/crates/schema/public/enums_convert/src/by_table/media_files/media_file_origin_model_type.rs new file mode 100644 index 0000000000..aa2ba4eaa0 --- /dev/null +++ b/crates/schema/public/enums_convert/src/by_table/media_files/media_file_origin_model_type.rs @@ -0,0 +1,87 @@ +use enums_api::by_table::media_files::media_file_origin_model_type::MediaFileOriginModelType as Api; +use enums_db::by_table::media_files::media_file_origin_model_type::MediaFileOriginModelType as Db; + +pub fn media_file_origin_model_type_to_db(api_value: &Api) -> Db { + match api_value { + Api::FaceMirror => Db::LivePortrait, + Api::FaceAnimator => Db::SadTalker, + Api::Lipsync => Db::FaceFusion, + Api::VoiceDesigner => Db::StyleTTS2, + Api::StorytellerStudioImageGen => Db::StorytellerStudioImageGen, + Api::RvcV2 => Db::RvcV2, + Api::SoVitsSvc => Db::SoVitsSvc, + Api::SeedVc => Db::SeedVc, + Api::Tacotron2 => Db::Tacotron2, + Api::MocapNet => Db::MocapNet, + Api::StableDiffusion15 => Db::StableDiffusion15, + Api::GptSovits => Db::GptSovits, + Api::F5TTS => Db::F5TTS, + Api::StorytellerStudio => Db::StorytellerStudio, + Api::VideoStyleTransfer => Db::VideoStyleTransfer, + Api::ComfyUi => Db::ComfyUi, + Api::VallEX => Db::VallEX, + Api::Rerender => Db::Rerender, + } +} + +pub fn media_file_origin_model_type_to_api(db_value: &Db) -> Api { + match db_value { + Db::FaceFusion => Api::Lipsync, + Db::LivePortrait => Api::FaceMirror, + Db::SadTalker => Api::FaceAnimator, + Db::StyleTTS2 => Api::VoiceDesigner, + Db::StorytellerStudioImageGen => Api::StorytellerStudioImageGen, + Db::RvcV2 => Api::RvcV2, + Db::SoVitsSvc => Api::SoVitsSvc, + Db::SeedVc => Api::SeedVc, + Db::Tacotron2 => Api::Tacotron2, + Db::MocapNet => Api::MocapNet, + Db::StableDiffusion15 => Api::StableDiffusion15, + Db::GptSovits => Api::GptSovits, + Db::F5TTS => Api::F5TTS, + Db::StorytellerStudio => Api::StorytellerStudio, + Db::VideoStyleTransfer => Api::VideoStyleTransfer, + Db::ComfyUi => Api::ComfyUi, + Db::VallEX => Api::VallEX, + Db::Rerender => Api::Rerender, + } +} + +#[cfg(test)] +mod tests { + use super::*; + use strum::IntoEnumIterator; + + #[test] + fn round_trip_api_to_db() { + use strum::IntoEnumIterator; + for db_variant in Db::iter() { + let api = media_file_origin_model_type_to_api(&db_variant); + let db = media_file_origin_model_type_to_db(&api); + let back = media_file_origin_model_type_to_api(&db); + assert_eq!(api, back); + } + } + + #[test] + fn round_trip_db_to_api() { + use strum::IntoEnumIterator; + for variant in Db::iter() { + let api = media_file_origin_model_type_to_api(&variant); + let back = media_file_origin_model_type_to_db(&api); + assert_eq!(variant, back); + } + } + + #[test] + fn renamed_variants() { + assert_eq!(media_file_origin_model_type_to_db(&Api::FaceMirror), Db::LivePortrait); + assert_eq!(media_file_origin_model_type_to_db(&Api::FaceAnimator), Db::SadTalker); + assert_eq!(media_file_origin_model_type_to_db(&Api::Lipsync), Db::FaceFusion); + assert_eq!(media_file_origin_model_type_to_db(&Api::VoiceDesigner), Db::StyleTTS2); + assert_eq!(media_file_origin_model_type_to_api(&Db::LivePortrait), Api::FaceMirror); + assert_eq!(media_file_origin_model_type_to_api(&Db::SadTalker), Api::FaceAnimator); + assert_eq!(media_file_origin_model_type_to_api(&Db::FaceFusion), Api::Lipsync); + assert_eq!(media_file_origin_model_type_to_api(&Db::StyleTTS2), Api::VoiceDesigner); + } +} diff --git a/crates/schema/public/enums_convert/src/by_table/media_files/media_file_origin_product_category.rs b/crates/schema/public/enums_convert/src/by_table/media_files/media_file_origin_product_category.rs new file mode 100644 index 0000000000..c56e3f1e2b --- /dev/null +++ b/crates/schema/public/enums_convert/src/by_table/media_files/media_file_origin_product_category.rs @@ -0,0 +1,69 @@ +use enums_api::by_table::media_files::media_file_origin_product_category::MediaFileOriginProductCategory as Api; +use enums_db::by_table::media_files::media_file_origin_product_category::MediaFileOriginProductCategory as Db; + +pub fn media_file_origin_product_category_to_db(api_value: &Api) -> Db { + match api_value { + Api::Unknown => Db::Unknown, + Api::FaceAnimator => Db::FaceAnimator, + Api::FaceFusion => Db::FaceFusion, + Api::FaceMirror => Db::FaceMirror, + Api::VideoStyleTransfer => Db::VideoStyleTransfer, + Api::ImageStudio => Db::ImageStudio, + Api::StorytellerStudio => Db::StorytellerStudio, + Api::TextToSpeech => Db::TextToSpeech, + Api::VoiceConversion => Db::VoiceConversion, + Api::ZeroShotVoice => Db::ZeroShotVoice, + Api::Mocap => Db::Mocap, + Api::ImageGeneration => Db::ImageGeneration, + Api::VideoGeneration => Db::VideoGeneration, + Api::WorldGeneration => Db::WorldGeneration, + Api::VideoFilter => Db::VideoFilter, + Api::Workflow => Db::Workflow, + } +} + +pub fn media_file_origin_product_category_to_api(db_value: &Db) -> Api { + match db_value { + Db::Unknown => Api::Unknown, + Db::FaceAnimator => Api::FaceAnimator, + Db::FaceFusion => Api::FaceFusion, + Db::FaceMirror => Api::FaceMirror, + Db::VideoStyleTransfer => Api::VideoStyleTransfer, + Db::ImageStudio => Api::ImageStudio, + Db::StorytellerStudio => Api::StorytellerStudio, + Db::TextToSpeech => Api::TextToSpeech, + Db::VoiceConversion => Api::VoiceConversion, + Db::ZeroShotVoice => Api::ZeroShotVoice, + Db::Mocap => Api::Mocap, + Db::ImageGeneration => Api::ImageGeneration, + Db::VideoGeneration => Api::VideoGeneration, + Db::WorldGeneration => Api::WorldGeneration, + Db::VideoFilter => Api::VideoFilter, + Db::Workflow => Api::Workflow, + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn round_trip_api_to_db() { + use strum::IntoEnumIterator; + for api_variant in Api::iter() { + let db = media_file_origin_product_category_to_db(&api_variant); + let back = media_file_origin_product_category_to_api(&db); + assert_eq!(api_variant, back); + } + } + + #[test] + fn round_trip_db_to_api() { + use strum::IntoEnumIterator; + for variant in Db::iter() { + let api = media_file_origin_product_category_to_api(&variant); + let back = media_file_origin_product_category_to_db(&api); + assert_eq!(variant, back); + } + } +} diff --git a/crates/schema/public/enums_convert/src/by_table/media_files/media_file_subtype.rs b/crates/schema/public/enums_convert/src/by_table/media_files/media_file_subtype.rs new file mode 100644 index 0000000000..73226d3df5 --- /dev/null +++ b/crates/schema/public/enums_convert/src/by_table/media_files/media_file_subtype.rs @@ -0,0 +1,59 @@ +use enums_api::by_table::media_files::media_file_subtype::MediaFileSubtype as Api; +use enums_db::by_table::media_files::media_file_subtype::MediaFileSubtype as Db; + +pub fn media_file_subtype_to_db(api_value: &Api) -> Db { + match api_value { + Api::Deprecated => Db::Deprecated, + Api::Mixamo => Db::Mixamo, + Api::MocapNet => Db::MocapNet, + Api::AnimationOnly => Db::AnimationOnly, + Api::SceneImport => Db::SceneImport, + Api::StorytellerScene => Db::StorytellerScene, + Api::Scene => Db::Scene, + Api::Character => Db::Character, + Api::Animation => Db::Animation, + Api::Object => Db::Object, + Api::Skybox => Db::Skybox, + } +} + +pub fn media_file_subtype_to_api(db_value: &Db) -> Api { + match db_value { + Db::Deprecated => Api::Deprecated, + Db::Mixamo => Api::Mixamo, + Db::MocapNet => Api::MocapNet, + Db::AnimationOnly => Api::AnimationOnly, + Db::SceneImport => Api::SceneImport, + Db::StorytellerScene => Api::StorytellerScene, + Db::Scene => Api::Scene, + Db::Character => Api::Character, + Db::Animation => Api::Animation, + Db::Object => Api::Object, + Db::Skybox => Api::Skybox, + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn round_trip_api_to_db() { + use strum::IntoEnumIterator; + for api_variant in Api::iter() { + let db = media_file_subtype_to_db(&api_variant); + let back = media_file_subtype_to_api(&db); + assert_eq!(api_variant, back); + } + } + + #[test] + fn round_trip_db_to_api() { + use strum::IntoEnumIterator; + for variant in Db::iter() { + let api = media_file_subtype_to_api(&variant); + let back = media_file_subtype_to_db(&api); + assert_eq!(variant, back); + } + } +} diff --git a/crates/schema/public/enums_convert/src/by_table/media_files/media_file_type.rs b/crates/schema/public/enums_convert/src/by_table/media_files/media_file_type.rs new file mode 100644 index 0000000000..deb1d1cf89 --- /dev/null +++ b/crates/schema/public/enums_convert/src/by_table/media_files/media_file_type.rs @@ -0,0 +1,77 @@ +use enums_api::by_table::media_files::media_file_type::MediaFileType as Api; +use enums_db::by_table::media_files::media_file_type::MediaFileType as Db; + +pub fn media_file_type_to_db(api_value: &Api) -> Db { + match api_value { + Api::Audio => Db::Audio, + Api::Image => Db::Image, + Api::Video => Db::Video, + Api::Bvh => Db::Bvh, + Api::Fbx => Db::Fbx, + Api::Glb => Db::Glb, + Api::Gltf => Db::Gltf, + Api::Spz => Db::Spz, + Api::SceneRon => Db::SceneRon, + Api::SceneJson => Db::SceneJson, + Api::Pmd => Db::Pmd, + Api::Vmd => Db::Vmd, + Api::Pmx => Db::Pmx, + Api::Csv => Db::Csv, + Api::Jpg => Db::Jpg, + Api::Png => Db::Png, + Api::Gif => Db::Gif, + Api::Mp4 => Db::Mp4, + Api::Wav => Db::Wav, + Api::Mp3 => Db::Mp3, + } +} + +pub fn media_file_type_to_api(db_value: &Db) -> Api { + match db_value { + Db::Audio => Api::Audio, + Db::Image => Api::Image, + Db::Video => Api::Video, + Db::Bvh => Api::Bvh, + Db::Fbx => Api::Fbx, + Db::Glb => Api::Glb, + Db::Gltf => Api::Gltf, + Db::Spz => Api::Spz, + Db::SceneRon => Api::SceneRon, + Db::SceneJson => Api::SceneJson, + Db::Pmd => Api::Pmd, + Db::Vmd => Api::Vmd, + Db::Pmx => Api::Pmx, + Db::Csv => Api::Csv, + Db::Jpg => Api::Jpg, + Db::Png => Api::Png, + Db::Gif => Api::Gif, + Db::Mp4 => Api::Mp4, + Db::Wav => Api::Wav, + Db::Mp3 => Api::Mp3, + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn round_trip_api_to_db() { + use strum::IntoEnumIterator; + for api_variant in Api::iter() { + let db = media_file_type_to_db(&api_variant); + let back = media_file_type_to_api(&db); + assert_eq!(api_variant, back); + } + } + + #[test] + fn round_trip_db_to_api() { + use strum::IntoEnumIterator; + for variant in Db::iter() { + let api = media_file_type_to_api(&variant); + let back = media_file_type_to_db(&api); + assert_eq!(variant, back); + } + } +} diff --git a/crates/schema/public/enums_convert/src/by_table/media_files/mod.rs b/crates/schema/public/enums_convert/src/by_table/media_files/mod.rs new file mode 100644 index 0000000000..173082c091 --- /dev/null +++ b/crates/schema/public/enums_convert/src/by_table/media_files/mod.rs @@ -0,0 +1,8 @@ +pub mod media_file_animation_type; +pub mod media_file_class; +pub mod media_file_engine_category; +pub mod media_file_origin_category; +pub mod media_file_origin_model_type; +pub mod media_file_origin_product_category; +pub mod media_file_subtype; +pub mod media_file_type; diff --git a/crates/schema/public/enums_convert/src/by_table/media_uploads/media_upload_source.rs b/crates/schema/public/enums_convert/src/by_table/media_uploads/media_upload_source.rs new file mode 100644 index 0000000000..2bf3aab3d2 --- /dev/null +++ b/crates/schema/public/enums_convert/src/by_table/media_uploads/media_upload_source.rs @@ -0,0 +1,44 @@ +use enums_api::by_table::media_uploads::media_upload_source::MediaUploadSource as Api; +use enums_db::by_table::media_uploads::media_upload_source::MediaUploadSource as Db; + +pub fn media_upload_source_to_db(api_value: &Api) -> Db { + match api_value { + Api::DeviceApi => Db::DeviceApi, + Api::File => Db::File, + Api::Unknown => Db::Unknown, + } +} + +pub fn media_upload_source_to_api(db_value: &Db) -> Api { + match db_value { + Db::DeviceApi => Api::DeviceApi, + Db::File => Api::File, + Db::Unknown => Api::Unknown, + } +} + +#[cfg(test)] +mod tests { + use super::*; + use strum::IntoEnumIterator; + + #[test] + fn round_trip_api_to_db() { + use strum::IntoEnumIterator; + for api_variant in Api::iter() { + let db = media_upload_source_to_db(&api_variant); + let back = media_upload_source_to_api(&db); + assert_eq!(api_variant, back); + } + } + + #[test] + fn round_trip_db_to_api() { + use strum::IntoEnumIterator; + for api_variant in Api::iter() { + let db = media_upload_source_to_db(&api_variant); + let back = media_upload_source_to_api(&db); + assert_eq!(api_variant, back); + } + } +} diff --git a/crates/schema/public/enums_convert/src/by_table/media_uploads/media_upload_type.rs b/crates/schema/public/enums_convert/src/by_table/media_uploads/media_upload_type.rs new file mode 100644 index 0000000000..d3204c127f --- /dev/null +++ b/crates/schema/public/enums_convert/src/by_table/media_uploads/media_upload_type.rs @@ -0,0 +1,46 @@ +use enums_api::by_table::media_uploads::media_upload_type::MediaUploadType as Api; +use enums_db::by_table::media_uploads::media_upload_type::MediaUploadType as Db; + +pub fn media_upload_type_to_db(api_value: &Api) -> Db { + match api_value { + Api::Audio => Db::Audio, + Api::Image => Db::Image, + Api::Video => Db::Video, + Api::Binary => Db::Binary, + } +} + +pub fn media_upload_type_to_api(db_value: &Db) -> Api { + match db_value { + Db::Audio => Api::Audio, + Db::Image => Api::Image, + Db::Video => Api::Video, + Db::Binary => Api::Binary, + } +} + +#[cfg(test)] +mod tests { + use super::*; + use strum::IntoEnumIterator; + + #[test] + fn round_trip_api_to_db() { + use strum::IntoEnumIterator; + for api_variant in Api::iter() { + let db = media_upload_type_to_db(&api_variant); + let back = media_upload_type_to_api(&db); + assert_eq!(api_variant, back); + } + } + + #[test] + fn round_trip_db_to_api() { + use strum::IntoEnumIterator; + for api_variant in Api::iter() { + let db = media_upload_type_to_db(&api_variant); + let back = media_upload_type_to_api(&db); + assert_eq!(api_variant, back); + } + } +} diff --git a/crates/schema/public/enums_convert/src/by_table/media_uploads/mod.rs b/crates/schema/public/enums_convert/src/by_table/media_uploads/mod.rs new file mode 100644 index 0000000000..38dbfbff74 --- /dev/null +++ b/crates/schema/public/enums_convert/src/by_table/media_uploads/mod.rs @@ -0,0 +1,2 @@ +pub mod media_upload_source; +pub mod media_upload_type; diff --git a/crates/schema/public/enums_convert/src/by_table/mod.rs b/crates/schema/public/enums_convert/src/by_table/mod.rs new file mode 100644 index 0000000000..f875036ef4 --- /dev/null +++ b/crates/schema/public/enums_convert/src/by_table/mod.rs @@ -0,0 +1,30 @@ +pub mod audit_logs; +pub mod batch_generations; +pub mod beta_keys; +pub mod comments; +pub mod email_sender_jobs; +pub mod entity_stats; +pub mod featured_items; +pub mod generic_download_jobs; +pub mod generic_inference_jobs; +pub mod generic_synthetic_ids; +pub mod media_files; +pub mod media_uploads; +pub mod model_categories; +pub mod model_weights; +pub mod prompt_context_items; +pub mod prompts; +pub mod tag_uses; +pub mod trending_model_analytics; +pub mod tts_models; +pub mod tts_render_tasks; +pub mod usages; +pub mod user_bookmarks; +pub mod user_ratings; +pub mod users; +pub mod voice_conversion_models; +pub mod voice_conversion_results; +pub mod wallet_ledger_entries; +pub mod web_rendition_targets; +pub mod web_scraping_targets; +pub mod zs_voices; diff --git a/crates/schema/public/enums_convert/src/by_table/model_categories/mod.rs b/crates/schema/public/enums_convert/src/by_table/model_categories/mod.rs new file mode 100644 index 0000000000..3c5df49228 --- /dev/null +++ b/crates/schema/public/enums_convert/src/by_table/model_categories/mod.rs @@ -0,0 +1 @@ +pub mod model_type; diff --git a/crates/schema/public/enums_convert/src/by_table/model_categories/model_type.rs b/crates/schema/public/enums_convert/src/by_table/model_categories/model_type.rs new file mode 100644 index 0000000000..994fd5f8be --- /dev/null +++ b/crates/schema/public/enums_convert/src/by_table/model_categories/model_type.rs @@ -0,0 +1,42 @@ +use enums_api::by_table::model_categories::model_type::ModelType as Api; +use enums_db::by_table::model_categories::model_type::ModelType as Db; + +pub fn model_type_to_db(api_value: &Api) -> Db { + match api_value { + Api::Tts => Db::Tts, + Api::W2l => Db::W2l, + } +} + +pub fn model_type_to_api(db_value: &Db) -> Api { + match db_value { + Db::Tts => Api::Tts, + Db::W2l => Api::W2l, + } +} + +#[cfg(test)] +mod tests { + use super::*; + use strum::IntoEnumIterator; + + #[test] + fn round_trip_api_to_db() { + use strum::IntoEnumIterator; + for api_variant in Api::iter() { + let db = model_type_to_db(&api_variant); + let back = model_type_to_api(&db); + assert_eq!(api_variant, back); + } + } + + #[test] + fn round_trip_db_to_api() { + use strum::IntoEnumIterator; + for api_variant in Api::iter() { + let db = model_type_to_db(&api_variant); + let back = model_type_to_api(&db); + assert_eq!(api_variant, back); + } + } +} diff --git a/crates/schema/public/enums_convert/src/by_table/model_weights/mod.rs b/crates/schema/public/enums_convert/src/by_table/model_weights/mod.rs new file mode 100644 index 0000000000..e98246b3d0 --- /dev/null +++ b/crates/schema/public/enums_convert/src/by_table/model_weights/mod.rs @@ -0,0 +1,3 @@ +pub mod weights_category; +pub mod weights_file_type; +pub mod weights_types; diff --git a/crates/schema/public/enums_convert/src/by_table/model_weights/weights_category.rs b/crates/schema/public/enums_convert/src/by_table/model_weights/weights_category.rs new file mode 100644 index 0000000000..7869a92ab7 --- /dev/null +++ b/crates/schema/public/enums_convert/src/by_table/model_weights/weights_category.rs @@ -0,0 +1,47 @@ +use enums_api::by_table::model_weights::weights_category::WeightsCategory as Api; +use enums_db::by_table::model_weights::weights_category::WeightsCategory as Db; + +pub fn weights_category_to_db(api_value: &Api) -> Db { + match api_value { + Api::ImageGeneration => Db::ImageGeneration, + Api::TextToSpeech => Db::TextToSpeech, + Api::Vocoder => Db::Vocoder, + Api::VoiceConversion => Db::VoiceConversion, + Api::WorkflowConfig => Db::WorkflowConfig, + } +} + +pub fn weights_category_to_api(db_value: &Db) -> Api { + match db_value { + Db::ImageGeneration => Api::ImageGeneration, + Db::TextToSpeech => Api::TextToSpeech, + Db::Vocoder => Api::Vocoder, + Db::VoiceConversion => Api::VoiceConversion, + Db::WorkflowConfig => Api::WorkflowConfig, + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn round_trip_api_to_db() { + use strum::IntoEnumIterator; + for api_variant in Api::iter() { + let db = weights_category_to_db(&api_variant); + let back = weights_category_to_api(&db); + assert_eq!(api_variant, back); + } + } + + #[test] + fn round_trip_db_to_api() { + use strum::IntoEnumIterator; + for variant in Db::iter() { + let api = weights_category_to_api(&variant); + let back = weights_category_to_db(&api); + assert_eq!(variant, back); + } + } +} diff --git a/crates/schema/public/enums_convert/src/by_table/model_weights/weights_file_type.rs b/crates/schema/public/enums_convert/src/by_table/model_weights/weights_file_type.rs new file mode 100644 index 0000000000..78de1428a3 --- /dev/null +++ b/crates/schema/public/enums_convert/src/by_table/model_weights/weights_file_type.rs @@ -0,0 +1,41 @@ +use enums_api::by_table::model_weights::weights_file_type::WeightsFileType as Api; +use enums_db::by_table::model_weights::weights_file_type::WeightsFileType as Db; + +pub fn weights_file_type_to_db(api_value: &Api) -> Db { + match api_value { + Api::Checkpoint => Db::Checkpoint, + Api::SafeTensors => Db::SafeTensors, + } +} + +pub fn weights_file_type_to_api(db_value: &Db) -> Api { + match db_value { + Db::Checkpoint => Api::Checkpoint, + Db::SafeTensors => Api::SafeTensors, + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn round_trip_api_to_db() { + use strum::IntoEnumIterator; + for api_variant in Api::iter() { + let db = weights_file_type_to_db(&api_variant); + let back = weights_file_type_to_api(&db); + assert_eq!(api_variant, back); + } + } + + #[test] + fn round_trip_db_to_api() { + use strum::IntoEnumIterator; + for variant in Db::iter() { + let api = weights_file_type_to_api(&variant); + let back = weights_file_type_to_db(&api); + assert_eq!(variant, back); + } + } +} diff --git a/crates/schema/public/enums_convert/src/by_table/model_weights/weights_types.rs b/crates/schema/public/enums_convert/src/by_table/model_weights/weights_types.rs new file mode 100644 index 0000000000..7e42cb973e --- /dev/null +++ b/crates/schema/public/enums_convert/src/by_table/model_weights/weights_types.rs @@ -0,0 +1,65 @@ +use enums_api::by_table::model_weights::weights_types::WeightsType as Api; +use enums_db::by_table::model_weights::weights_types::WeightsType as Db; + +pub fn weights_type_to_db(api_value: &Api) -> Db { + match api_value { + Api::Tacotron2_5 => Db::GptSoVits, + Api::HifiganTacotron2 => Db::HifiganTacotron2, + Api::RvcV2 => Db::RvcV2, + Api::StableDiffusion15 => Db::StableDiffusion15, + Api::StableDiffusionXL => Db::StableDiffusionXL, + Api::SoVitsSvc => Db::SoVitsSvc, + Api::Tacotron2 => Db::Tacotron2, + Api::LoRA => Db::LoRA, + Api::VallE => Db::VallE, + Api::ComfyUi => Db::ComfyUi, + } +} + +pub fn weights_type_to_api(db_value: &Db) -> Api { + match db_value { + Db::GptSoVits => Api::Tacotron2_5, + Db::HifiganTacotron2 => Api::HifiganTacotron2, + Db::RvcV2 => Api::RvcV2, + Db::StableDiffusion15 => Api::StableDiffusion15, + Db::StableDiffusionXL => Api::StableDiffusionXL, + Db::SoVitsSvc => Api::SoVitsSvc, + Db::Tacotron2 => Api::Tacotron2, + Db::LoRA => Api::LoRA, + Db::VallE => Api::VallE, + Db::ComfyUi => Api::ComfyUi, + } +} + +#[cfg(test)] +mod tests { + use super::*; + use strum::IntoEnumIterator; + + #[test] + fn round_trip_api_to_db() { + use strum::IntoEnumIterator; + for db_variant in Db::iter() { + let api = weights_type_to_api(&db_variant); + let db = weights_type_to_db(&api); + let back = weights_type_to_api(&db); + assert_eq!(api, back); + } + } + + #[test] + fn round_trip_db_to_api() { + use strum::IntoEnumIterator; + for variant in Db::iter() { + let api = weights_type_to_api(&variant); + let back = weights_type_to_db(&api); + assert_eq!(variant, back); + } + } + + #[test] + fn renamed_variants() { + assert_eq!(weights_type_to_db(&Api::Tacotron2_5), Db::GptSoVits); + assert_eq!(weights_type_to_api(&Db::GptSoVits), Api::Tacotron2_5); + } +} diff --git a/crates/schema/public/enums_convert/src/by_table/prompt_context_items/mod.rs b/crates/schema/public/enums_convert/src/by_table/prompt_context_items/mod.rs new file mode 100644 index 0000000000..9a47938052 --- /dev/null +++ b/crates/schema/public/enums_convert/src/by_table/prompt_context_items/mod.rs @@ -0,0 +1 @@ +pub mod prompt_context_semantic_type; diff --git a/crates/schema/public/enums_convert/src/by_table/prompt_context_items/prompt_context_semantic_type.rs b/crates/schema/public/enums_convert/src/by_table/prompt_context_items/prompt_context_semantic_type.rs new file mode 100644 index 0000000000..d1b1f0b076 --- /dev/null +++ b/crates/schema/public/enums_convert/src/by_table/prompt_context_items/prompt_context_semantic_type.rs @@ -0,0 +1,57 @@ +use enums_api::by_table::prompt_context_items::prompt_context_semantic_type::PromptContextSemanticType as Api; +use enums_db::by_table::prompt_context_items::prompt_context_semantic_type::PromptContextSemanticType as Db; + +pub fn prompt_context_semantic_type_to_db(api_value: &Api) -> Db { + match api_value { + Api::VidStartFrame => Db::VidStartFrame, + Api::VidEndFrame => Db::VidEndFrame, + Api::VidRef => Db::VidRef, + Api::Imgsrc => Db::Imgsrc, + Api::Imgmask => Db::Imgmask, + Api::Imgref => Db::Imgref, + Api::ImgrefCharacter => Db::ImgrefCharacter, + Api::ImgrefStyle => Db::ImgrefStyle, + Api::ImgrefBg => Db::ImgrefBg, + Api::Audioref => Db::Audioref, + } +} + +pub fn prompt_context_semantic_type_to_api(db_value: &Db) -> Api { + match db_value { + Db::VidStartFrame => Api::VidStartFrame, + Db::VidEndFrame => Api::VidEndFrame, + Db::VidRef => Api::VidRef, + Db::Imgsrc => Api::Imgsrc, + Db::Imgmask => Api::Imgmask, + Db::Imgref => Api::Imgref, + Db::ImgrefCharacter => Api::ImgrefCharacter, + Db::ImgrefStyle => Api::ImgrefStyle, + Db::ImgrefBg => Api::ImgrefBg, + Db::Audioref => Api::Audioref, + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn round_trip_api_to_db() { + use strum::IntoEnumIterator; + for api_variant in Api::iter() { + let db = prompt_context_semantic_type_to_db(&api_variant); + let back = prompt_context_semantic_type_to_api(&db); + assert_eq!(api_variant, back); + } + } + + #[test] + fn round_trip_db_to_api() { + use strum::IntoEnumIterator; + for variant in Db::iter() { + let api = prompt_context_semantic_type_to_api(&variant); + let back = prompt_context_semantic_type_to_db(&api); + assert_eq!(variant, back); + } + } +} diff --git a/crates/schema/public/enums_convert/src/by_table/prompts/mod.rs b/crates/schema/public/enums_convert/src/by_table/prompts/mod.rs new file mode 100644 index 0000000000..1dd09b23cd --- /dev/null +++ b/crates/schema/public/enums_convert/src/by_table/prompts/mod.rs @@ -0,0 +1 @@ +pub mod prompt_type; diff --git a/crates/schema/public/enums_convert/src/by_table/prompts/prompt_type.rs b/crates/schema/public/enums_convert/src/by_table/prompts/prompt_type.rs new file mode 100644 index 0000000000..71337ec1de --- /dev/null +++ b/crates/schema/public/enums_convert/src/by_table/prompts/prompt_type.rs @@ -0,0 +1,43 @@ +use enums_api::by_table::prompts::prompt_type::PromptType as Api; +use enums_db::by_table::prompts::prompt_type::PromptType as Db; + +pub fn prompt_type_to_db(api_value: &Api) -> Db { + match api_value { + Api::ArtcraftApp => Db::ArtcraftApp, + Api::StableDiffusion => Db::StableDiffusion, + Api::ComfyUi => Db::ComfyUi, + } +} + +pub fn prompt_type_to_api(db_value: &Db) -> Api { + match db_value { + Db::ArtcraftApp => Api::ArtcraftApp, + Db::StableDiffusion => Api::StableDiffusion, + Db::ComfyUi => Api::ComfyUi, + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn round_trip_api_to_db() { + use strum::IntoEnumIterator; + for api_variant in Api::iter() { + let db = prompt_type_to_db(&api_variant); + let back = prompt_type_to_api(&db); + assert_eq!(api_variant, back); + } + } + + #[test] + fn round_trip_db_to_api() { + use strum::IntoEnumIterator; + for variant in Db::iter() { + let api = prompt_type_to_api(&variant); + let back = prompt_type_to_db(&api); + assert_eq!(variant, back); + } + } +} diff --git a/crates/schema/public/enums_convert/src/by_table/tag_uses/mod.rs b/crates/schema/public/enums_convert/src/by_table/tag_uses/mod.rs new file mode 100644 index 0000000000..08e9530e42 --- /dev/null +++ b/crates/schema/public/enums_convert/src/by_table/tag_uses/mod.rs @@ -0,0 +1 @@ +pub mod tag_use_entity_type; diff --git a/crates/schema/public/enums_convert/src/by_table/tag_uses/tag_use_entity_type.rs b/crates/schema/public/enums_convert/src/by_table/tag_uses/tag_use_entity_type.rs new file mode 100644 index 0000000000..467f54b99b --- /dev/null +++ b/crates/schema/public/enums_convert/src/by_table/tag_uses/tag_use_entity_type.rs @@ -0,0 +1,41 @@ +use enums_api::by_table::tag_uses::tag_use_entity_type::TagUseEntityType as Api; +use enums_db::by_table::tag_uses::tag_use_entity_type::TagUseEntityType as Db; + +pub fn tag_use_entity_type_to_db(api_value: &Api) -> Db { + match api_value { + Api::MediaFile => Db::MediaFile, + Api::ModelWeight => Db::ModelWeight, + } +} + +pub fn tag_use_entity_type_to_api(db_value: &Db) -> Api { + match db_value { + Db::MediaFile => Api::MediaFile, + Db::ModelWeight => Api::ModelWeight, + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn round_trip_api_to_db() { + use strum::IntoEnumIterator; + for api_variant in Api::iter() { + let db = tag_use_entity_type_to_db(&api_variant); + let back = tag_use_entity_type_to_api(&db); + assert_eq!(api_variant, back); + } + } + + #[test] + fn round_trip_db_to_api() { + use strum::IntoEnumIterator; + for variant in Db::iter() { + let api = tag_use_entity_type_to_api(&variant); + let back = tag_use_entity_type_to_db(&api); + assert_eq!(variant, back); + } + } +} diff --git a/crates/schema/public/enums_convert/src/by_table/trending_model_analytics/mod.rs b/crates/schema/public/enums_convert/src/by_table/trending_model_analytics/mod.rs new file mode 100644 index 0000000000..b7f654af7e --- /dev/null +++ b/crates/schema/public/enums_convert/src/by_table/trending_model_analytics/mod.rs @@ -0,0 +1,2 @@ +pub mod model_type; +pub mod window_name; diff --git a/crates/schema/public/enums_convert/src/by_table/trending_model_analytics/model_type.rs b/crates/schema/public/enums_convert/src/by_table/trending_model_analytics/model_type.rs new file mode 100644 index 0000000000..6641c14af9 --- /dev/null +++ b/crates/schema/public/enums_convert/src/by_table/trending_model_analytics/model_type.rs @@ -0,0 +1,40 @@ +use enums_api::by_table::trending_model_analytics::model_type::ModelType as Api; +use enums_db::by_table::trending_model_analytics::model_type::ModelType as Db; + +pub fn model_type_to_db(api_value: &Api) -> Db { + match api_value { + Api::Tts => Db::Tts, + } +} + +pub fn model_type_to_api(db_value: &Db) -> Api { + match db_value { + Db::Tts => Api::Tts, + } +} + +#[cfg(test)] +mod tests { + use super::*; + use strum::IntoEnumIterator; + + #[test] + fn round_trip_api_to_db() { + use strum::IntoEnumIterator; + for api_variant in Api::iter() { + let db = model_type_to_db(&api_variant); + let back = model_type_to_api(&db); + assert_eq!(api_variant, back); + } + } + + #[test] + fn round_trip_db_to_api() { + use strum::IntoEnumIterator; + for api_variant in Api::iter() { + let db = model_type_to_db(&api_variant); + let back = model_type_to_api(&db); + assert_eq!(api_variant, back); + } + } +} diff --git a/crates/schema/public/enums_convert/src/by_table/trending_model_analytics/window_name.rs b/crates/schema/public/enums_convert/src/by_table/trending_model_analytics/window_name.rs new file mode 100644 index 0000000000..c1b678d43f --- /dev/null +++ b/crates/schema/public/enums_convert/src/by_table/trending_model_analytics/window_name.rs @@ -0,0 +1,44 @@ +use enums_api::by_table::trending_model_analytics::window_name::WindowName as Api; +use enums_db::by_table::trending_model_analytics::window_name::WindowName as Db; + +pub fn window_name_to_db(api_value: &Api) -> Db { + match api_value { + Api::Last3Hours => Db::Last3Hours, + Api::Last3Days => Db::Last3Days, + Api::AllTime => Db::AllTime, + } +} + +pub fn window_name_to_api(db_value: &Db) -> Api { + match db_value { + Db::Last3Hours => Api::Last3Hours, + Db::Last3Days => Api::Last3Days, + Db::AllTime => Api::AllTime, + } +} + +#[cfg(test)] +mod tests { + use super::*; + use strum::IntoEnumIterator; + + #[test] + fn round_trip_api_to_db() { + use strum::IntoEnumIterator; + for api_variant in Api::iter() { + let db = window_name_to_db(&api_variant); + let back = window_name_to_api(&db); + assert_eq!(api_variant, back); + } + } + + #[test] + fn round_trip_db_to_api() { + use strum::IntoEnumIterator; + for api_variant in Api::iter() { + let db = window_name_to_db(&api_variant); + let back = window_name_to_api(&db); + assert_eq!(api_variant, back); + } + } +} diff --git a/crates/schema/public/enums_convert/src/by_table/tts_models/mod.rs b/crates/schema/public/enums_convert/src/by_table/tts_models/mod.rs new file mode 100644 index 0000000000..f2bd5d5cae --- /dev/null +++ b/crates/schema/public/enums_convert/src/by_table/tts_models/mod.rs @@ -0,0 +1 @@ +pub mod tts_model_type; diff --git a/crates/schema/public/enums_convert/src/by_table/tts_models/tts_model_type.rs b/crates/schema/public/enums_convert/src/by_table/tts_models/tts_model_type.rs new file mode 100644 index 0000000000..c9811ff5c5 --- /dev/null +++ b/crates/schema/public/enums_convert/src/by_table/tts_models/tts_model_type.rs @@ -0,0 +1,42 @@ +use enums_api::by_table::tts_models::tts_model_type::TtsModelType as Api; +use enums_db::by_table::tts_models::tts_model_type::TtsModelType as Db; + +pub fn tts_model_type_to_db(api_value: &Api) -> Db { + match api_value { + Api::Tacotron2 => Db::Tacotron2, + Api::Vits => Db::Vits, + } +} + +pub fn tts_model_type_to_api(db_value: &Db) -> Api { + match db_value { + Db::Tacotron2 => Api::Tacotron2, + Db::Vits => Api::Vits, + } +} + +#[cfg(test)] +mod tests { + use super::*; + use strum::IntoEnumIterator; + + #[test] + fn round_trip_api_to_db() { + use strum::IntoEnumIterator; + for api_variant in Api::iter() { + let db = tts_model_type_to_db(&api_variant); + let back = tts_model_type_to_api(&db); + assert_eq!(api_variant, back); + } + } + + #[test] + fn round_trip_db_to_api() { + use strum::IntoEnumIterator; + for api_variant in Api::iter() { + let db = tts_model_type_to_db(&api_variant); + let back = tts_model_type_to_api(&db); + assert_eq!(api_variant, back); + } + } +} diff --git a/crates/schema/public/enums_convert/src/by_table/tts_render_tasks/mod.rs b/crates/schema/public/enums_convert/src/by_table/tts_render_tasks/mod.rs new file mode 100644 index 0000000000..2fd09fffe5 --- /dev/null +++ b/crates/schema/public/enums_convert/src/by_table/tts_render_tasks/mod.rs @@ -0,0 +1 @@ +pub mod tts_render_status; diff --git a/crates/schema/public/enums_convert/src/by_table/tts_render_tasks/tts_render_status.rs b/crates/schema/public/enums_convert/src/by_table/tts_render_tasks/tts_render_status.rs new file mode 100644 index 0000000000..00defd2cb2 --- /dev/null +++ b/crates/schema/public/enums_convert/src/by_table/tts_render_tasks/tts_render_status.rs @@ -0,0 +1,50 @@ +use enums_api::by_table::tts_render_tasks::tts_render_status::TtsRenderStatus as Api; +use enums_db::by_table::tts_render_tasks::tts_render_status::TtsRenderStatus as Db; + +pub fn tts_render_status_to_db(api_value: &Api) -> Db { + match api_value { + Api::New => Db::New, + Api::Processing => Db::Processing, + Api::Skipped => Db::Skipped, + Api::Failed => Db::Failed, + Api::PermanentlyFailed => Db::PermanentlyFailed, + Api::Success => Db::Success, + } +} + +pub fn tts_render_status_to_api(db_value: &Db) -> Api { + match db_value { + Db::New => Api::New, + Db::Processing => Api::Processing, + Db::Skipped => Api::Skipped, + Db::Failed => Api::Failed, + Db::PermanentlyFailed => Api::PermanentlyFailed, + Db::Success => Api::Success, + } +} + +#[cfg(test)] +mod tests { + use super::*; + use strum::IntoEnumIterator; + + #[test] + fn round_trip_api_to_db() { + use strum::IntoEnumIterator; + for api_variant in Api::iter() { + let db = tts_render_status_to_db(&api_variant); + let back = tts_render_status_to_api(&db); + assert_eq!(api_variant, back); + } + } + + #[test] + fn round_trip_db_to_api() { + use strum::IntoEnumIterator; + for api_variant in Api::iter() { + let db = tts_render_status_to_db(&api_variant); + let back = tts_render_status_to_api(&db); + assert_eq!(api_variant, back); + } + } +} diff --git a/crates/schema/public/enums_convert/src/by_table/usages/mod.rs b/crates/schema/public/enums_convert/src/by_table/usages/mod.rs new file mode 100644 index 0000000000..cd5a40cf1b --- /dev/null +++ b/crates/schema/public/enums_convert/src/by_table/usages/mod.rs @@ -0,0 +1 @@ +pub mod usages_type; diff --git a/crates/schema/public/enums_convert/src/by_table/usages/usages_type.rs b/crates/schema/public/enums_convert/src/by_table/usages/usages_type.rs new file mode 100644 index 0000000000..35eccc5fb1 --- /dev/null +++ b/crates/schema/public/enums_convert/src/by_table/usages/usages_type.rs @@ -0,0 +1,41 @@ +use enums_api::by_table::usages::usages_type::UsagesType as Api; +use enums_db::by_table::usages::usages_type::UsagesType as Db; + +pub fn usages_type_to_db(api_value: &Api) -> Db { + match api_value { + Api::ModelWeight => Db::ModelWeight, + Api::MediaFile => Db::MediaFile, + } +} + +pub fn usages_type_to_api(db_value: &Db) -> Api { + match db_value { + Db::ModelWeight => Api::ModelWeight, + Db::MediaFile => Api::MediaFile, + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn round_trip_api_to_db() { + use strum::IntoEnumIterator; + for api_variant in Api::iter() { + let db = usages_type_to_db(&api_variant); + let back = usages_type_to_api(&db); + assert_eq!(api_variant, back); + } + } + + #[test] + fn round_trip_db_to_api() { + use strum::IntoEnumIterator; + for variant in Db::iter() { + let api = usages_type_to_api(&variant); + let back = usages_type_to_db(&api); + assert_eq!(variant, back); + } + } +} diff --git a/crates/schema/public/enums_convert/src/by_table/user_bookmarks/mod.rs b/crates/schema/public/enums_convert/src/by_table/user_bookmarks/mod.rs new file mode 100644 index 0000000000..49689232da --- /dev/null +++ b/crates/schema/public/enums_convert/src/by_table/user_bookmarks/mod.rs @@ -0,0 +1 @@ +pub mod user_bookmark_entity_type; diff --git a/crates/schema/public/enums_convert/src/by_table/user_bookmarks/user_bookmark_entity_type.rs b/crates/schema/public/enums_convert/src/by_table/user_bookmarks/user_bookmark_entity_type.rs new file mode 100644 index 0000000000..ece86fc1ed --- /dev/null +++ b/crates/schema/public/enums_convert/src/by_table/user_bookmarks/user_bookmark_entity_type.rs @@ -0,0 +1,56 @@ +use enums_api::by_table::user_bookmarks::user_bookmark_entity_type::UserBookmarkEntityType as Api; +use enums_db::by_table::user_bookmarks::user_bookmark_entity_type::UserBookmarkEntityType as Db; + +pub fn user_bookmark_entity_type_to_db(api_value: &Api) -> Db { + match api_value { + Api::User => Db::User, + Api::TtsModel => Db::TtsModel, + Api::TtsResult => Db::TtsResult, + Api::W2lTemplate => Db::W2lTemplate, + Api::W2lResult => Db::W2lResult, + Api::MediaFile => Db::MediaFile, + Api::ModelWeight => Db::ModelWeight, + Api::VoiceConversionModel => Db::VoiceConversionModel, + Api::ZsVoice => Db::ZsVoice, + } +} + +pub fn user_bookmark_entity_type_to_api(db_value: &Db) -> Api { + match db_value { + Db::User => Api::User, + Db::TtsModel => Api::TtsModel, + Db::TtsResult => Api::TtsResult, + Db::W2lTemplate => Api::W2lTemplate, + Db::W2lResult => Api::W2lResult, + Db::MediaFile => Api::MediaFile, + Db::ModelWeight => Api::ModelWeight, + Db::VoiceConversionModel => Api::VoiceConversionModel, + Db::ZsVoice => Api::ZsVoice, + } +} + +#[cfg(test)] +mod tests { + use super::*; + use strum::IntoEnumIterator; + + #[test] + fn round_trip_api_to_db() { + use strum::IntoEnumIterator; + for api_variant in Api::iter() { + let db = user_bookmark_entity_type_to_db(&api_variant); + let back = user_bookmark_entity_type_to_api(&db); + assert_eq!(api_variant, back); + } + } + + #[test] + fn round_trip_db_to_api() { + use strum::IntoEnumIterator; + for api_variant in Api::iter() { + let db = user_bookmark_entity_type_to_db(&api_variant); + let back = user_bookmark_entity_type_to_api(&db); + assert_eq!(api_variant, back); + } + } +} diff --git a/crates/schema/public/enums_convert/src/by_table/user_ratings/entity_type.rs b/crates/schema/public/enums_convert/src/by_table/user_ratings/entity_type.rs new file mode 100644 index 0000000000..ef6c385846 --- /dev/null +++ b/crates/schema/public/enums_convert/src/by_table/user_ratings/entity_type.rs @@ -0,0 +1,50 @@ +use enums_api::by_table::user_ratings::entity_type::UserRatingEntityType as Api; +use enums_db::by_table::user_ratings::entity_type::UserRatingEntityType as Db; + +pub fn user_rating_entity_type_to_db(api_value: &Api) -> Db { + match api_value { + Api::MediaFile => Db::MediaFile, + Api::ModelWeight => Db::ModelWeight, + Api::TtsModel => Db::TtsModel, + Api::TtsResult => Db::TtsResult, + Api::W2lTemplate => Db::W2lTemplate, + Api::W2lResult => Db::W2lResult, + } +} + +pub fn user_rating_entity_type_to_api(db_value: &Db) -> Api { + match db_value { + Db::MediaFile => Api::MediaFile, + Db::ModelWeight => Api::ModelWeight, + Db::TtsModel => Api::TtsModel, + Db::TtsResult => Api::TtsResult, + Db::W2lTemplate => Api::W2lTemplate, + Db::W2lResult => Api::W2lResult, + } +} + +#[cfg(test)] +mod tests { + use super::*; + use strum::IntoEnumIterator; + + #[test] + fn round_trip_api_to_db() { + use strum::IntoEnumIterator; + for api_variant in Api::iter() { + let db = user_rating_entity_type_to_db(&api_variant); + let back = user_rating_entity_type_to_api(&db); + assert_eq!(api_variant, back); + } + } + + #[test] + fn round_trip_db_to_api() { + use strum::IntoEnumIterator; + for api_variant in Api::iter() { + let db = user_rating_entity_type_to_db(&api_variant); + let back = user_rating_entity_type_to_api(&db); + assert_eq!(api_variant, back); + } + } +} diff --git a/crates/schema/public/enums_convert/src/by_table/user_ratings/mod.rs b/crates/schema/public/enums_convert/src/by_table/user_ratings/mod.rs new file mode 100644 index 0000000000..cd3855acfb --- /dev/null +++ b/crates/schema/public/enums_convert/src/by_table/user_ratings/mod.rs @@ -0,0 +1,2 @@ +pub mod entity_type; +pub mod rating_value; diff --git a/crates/schema/public/enums_convert/src/by_table/user_ratings/rating_value.rs b/crates/schema/public/enums_convert/src/by_table/user_ratings/rating_value.rs new file mode 100644 index 0000000000..95702ae12d --- /dev/null +++ b/crates/schema/public/enums_convert/src/by_table/user_ratings/rating_value.rs @@ -0,0 +1,44 @@ +use enums_api::by_table::user_ratings::rating_value::UserRatingValue as Api; +use enums_db::by_table::user_ratings::rating_value::UserRatingValue as Db; + +pub fn user_rating_value_to_db(api_value: &Api) -> Db { + match api_value { + Api::Neutral => Db::Neutral, + Api::Positive => Db::Positive, + Api::Negative => Db::Negative, + } +} + +pub fn user_rating_value_to_api(db_value: &Db) -> Api { + match db_value { + Db::Neutral => Api::Neutral, + Db::Positive => Api::Positive, + Db::Negative => Api::Negative, + } +} + +#[cfg(test)] +mod tests { + use super::*; + use strum::IntoEnumIterator; + + #[test] + fn round_trip_api_to_db() { + use strum::IntoEnumIterator; + for api_variant in Api::iter() { + let db = user_rating_value_to_db(&api_variant); + let back = user_rating_value_to_api(&db); + assert_eq!(api_variant, back); + } + } + + #[test] + fn round_trip_db_to_api() { + use strum::IntoEnumIterator; + for api_variant in Api::iter() { + let db = user_rating_value_to_db(&api_variant); + let back = user_rating_value_to_api(&db); + assert_eq!(api_variant, back); + } + } +} diff --git a/crates/schema/public/enums_convert/src/by_table/users/mod.rs b/crates/schema/public/enums_convert/src/by_table/users/mod.rs new file mode 100644 index 0000000000..e4f4741f1b --- /dev/null +++ b/crates/schema/public/enums_convert/src/by_table/users/mod.rs @@ -0,0 +1,3 @@ +pub mod user_feature_flag; +pub mod user_signup_method; +pub mod user_signup_source; diff --git a/crates/schema/public/enums_convert/src/by_table/users/user_feature_flag.rs b/crates/schema/public/enums_convert/src/by_table/users/user_feature_flag.rs new file mode 100644 index 0000000000..245aecd52a --- /dev/null +++ b/crates/schema/public/enums_convert/src/by_table/users/user_feature_flag.rs @@ -0,0 +1,45 @@ +use enums_api::by_table::users::user_feature_flag::UserFeatureFlag as Api; +use enums_db::by_table::users::user_feature_flag::UserFeatureFlag as Db; + +pub fn user_feature_flag_to_db(api_value: &Api) -> Db { + match api_value { + Api::ExploreMedia => Db::ExploreMedia, + Api::Studio => Db::Studio, + Api::Upload3d => Db::Upload3d, + Api::VideoStyleTransfer => Db::VideoStyleTransfer, + } +} + +pub fn user_feature_flag_to_api(db_value: &Db) -> Api { + match db_value { + Db::ExploreMedia => Api::ExploreMedia, + Db::Studio => Api::Studio, + Db::Upload3d => Api::Upload3d, + Db::VideoStyleTransfer => Api::VideoStyleTransfer, + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn round_trip_api_to_db() { + use strum::IntoEnumIterator; + for api_variant in Api::iter() { + let db = user_feature_flag_to_db(&api_variant); + let back = user_feature_flag_to_api(&db); + assert_eq!(api_variant, back); + } + } + + #[test] + fn round_trip_db_to_api() { + use strum::IntoEnumIterator; + for variant in Db::iter() { + let api = user_feature_flag_to_api(&variant); + let back = user_feature_flag_to_db(&api); + assert_eq!(variant, back); + } + } +} diff --git a/crates/schema/public/enums_convert/src/by_table/users/user_signup_method.rs b/crates/schema/public/enums_convert/src/by_table/users/user_signup_method.rs new file mode 100644 index 0000000000..4ae1063b21 --- /dev/null +++ b/crates/schema/public/enums_convert/src/by_table/users/user_signup_method.rs @@ -0,0 +1,43 @@ +use enums_api::by_table::users::user_signup_method::UserSignupMethod as Api; +use enums_db::by_table::users::user_signup_method::UserSignupMethod as Db; + +pub fn user_signup_method_to_db(api_value: &Api) -> Db { + match api_value { + Api::EmailPassword => Db::EmailPassword, + Api::GoogleSignIn => Db::GoogleSignIn, + Api::StripeCheckout => Db::StripeCheckout, + } +} + +pub fn user_signup_method_to_api(db_value: &Db) -> Api { + match db_value { + Db::EmailPassword => Api::EmailPassword, + Db::GoogleSignIn => Api::GoogleSignIn, + Db::StripeCheckout => Api::StripeCheckout, + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn round_trip_api_to_db() { + use strum::IntoEnumIterator; + for api_variant in Api::iter() { + let db = user_signup_method_to_db(&api_variant); + let back = user_signup_method_to_api(&db); + assert_eq!(api_variant, back); + } + } + + #[test] + fn round_trip_db_to_api() { + use strum::IntoEnumIterator; + for variant in Db::iter() { + let api = user_signup_method_to_api(&variant); + let back = user_signup_method_to_db(&api); + assert_eq!(variant, back); + } + } +} diff --git a/crates/schema/public/enums_convert/src/by_table/users/user_signup_source.rs b/crates/schema/public/enums_convert/src/by_table/users/user_signup_source.rs new file mode 100644 index 0000000000..821c5725b7 --- /dev/null +++ b/crates/schema/public/enums_convert/src/by_table/users/user_signup_source.rs @@ -0,0 +1,53 @@ +use enums_api::by_table::users::user_signup_source::UserSignupSource as Api; +use enums_db::by_table::users::user_signup_source::UserSignupSource as Db; + +pub fn user_signup_source_to_db(api_value: &Api) -> Db { + match api_value { + Api::ArtCraft => Db::ArtCraft, + Api::ArtCraftApp => Db::ArtCraftApp, + Api::ArtCraftAiWeb => Db::ArtCraftAiWeb, + Api::ArtCraftAiStripe => Db::ArtCraftAiStripe, + Api::ArtCraftGetWeb => Db::ArtCraftGetWeb, + Api::ArtCraftGetStripe => Db::ArtCraftGetStripe, + Api::FakeYou => Db::FakeYou, + Api::Storyteller => Db::Storyteller, + } +} + +pub fn user_signup_source_to_api(db_value: &Db) -> Api { + match db_value { + Db::ArtCraft => Api::ArtCraft, + Db::ArtCraftApp => Api::ArtCraftApp, + Db::ArtCraftAiWeb => Api::ArtCraftAiWeb, + Db::ArtCraftAiStripe => Api::ArtCraftAiStripe, + Db::ArtCraftGetWeb => Api::ArtCraftGetWeb, + Db::ArtCraftGetStripe => Api::ArtCraftGetStripe, + Db::FakeYou => Api::FakeYou, + Db::Storyteller => Api::Storyteller, + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn round_trip_api_to_db() { + use strum::IntoEnumIterator; + for api_variant in Api::iter() { + let db = user_signup_source_to_db(&api_variant); + let back = user_signup_source_to_api(&db); + assert_eq!(api_variant, back); + } + } + + #[test] + fn round_trip_db_to_api() { + use strum::IntoEnumIterator; + for variant in Db::iter() { + let api = user_signup_source_to_api(&variant); + let back = user_signup_source_to_db(&api); + assert_eq!(variant, back); + } + } +} diff --git a/crates/schema/public/enums_convert/src/by_table/voice_conversion_models/mod.rs b/crates/schema/public/enums_convert/src/by_table/voice_conversion_models/mod.rs new file mode 100644 index 0000000000..25778ac3ec --- /dev/null +++ b/crates/schema/public/enums_convert/src/by_table/voice_conversion_models/mod.rs @@ -0,0 +1 @@ +pub mod voice_conversion_model_type; diff --git a/crates/schema/public/enums_convert/src/by_table/voice_conversion_models/voice_conversion_model_type.rs b/crates/schema/public/enums_convert/src/by_table/voice_conversion_models/voice_conversion_model_type.rs new file mode 100644 index 0000000000..bccc8d7c74 --- /dev/null +++ b/crates/schema/public/enums_convert/src/by_table/voice_conversion_models/voice_conversion_model_type.rs @@ -0,0 +1,43 @@ +use enums_api::by_table::voice_conversion_models::voice_conversion_model_type::VoiceConversionModelType as Api; +use enums_db::by_table::voice_conversion_models::voice_conversion_model_type::VoiceConversionModelType as Db; + +pub fn voice_conversion_model_type_to_db(api_value: &Api) -> Db { + match api_value { + Api::RvcV2 => Db::RvcV2, + Api::SoftVc => Db::SoftVc, + Api::SoVitsSvc => Db::SoVitsSvc, + } +} + +pub fn voice_conversion_model_type_to_api(db_value: &Db) -> Api { + match db_value { + Db::RvcV2 => Api::RvcV2, + Db::SoftVc => Api::SoftVc, + Db::SoVitsSvc => Api::SoVitsSvc, + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn round_trip_api_to_db() { + use strum::IntoEnumIterator; + for api_variant in Api::iter() { + let db = voice_conversion_model_type_to_db(&api_variant); + let back = voice_conversion_model_type_to_api(&db); + assert_eq!(api_variant, back); + } + } + + #[test] + fn round_trip_db_to_api() { + use strum::IntoEnumIterator; + for variant in Db::iter() { + let api = voice_conversion_model_type_to_api(&variant); + let back = voice_conversion_model_type_to_db(&api); + assert_eq!(variant, back); + } + } +} diff --git a/crates/schema/public/enums_convert/src/by_table/voice_conversion_results/mod.rs b/crates/schema/public/enums_convert/src/by_table/voice_conversion_results/mod.rs new file mode 100644 index 0000000000..4568dc03ed --- /dev/null +++ b/crates/schema/public/enums_convert/src/by_table/voice_conversion_results/mod.rs @@ -0,0 +1 @@ +pub mod voice_conversion_media_token_type; diff --git a/crates/schema/public/enums_convert/src/by_table/voice_conversion_results/voice_conversion_media_token_type.rs b/crates/schema/public/enums_convert/src/by_table/voice_conversion_results/voice_conversion_media_token_type.rs new file mode 100644 index 0000000000..c4facec300 --- /dev/null +++ b/crates/schema/public/enums_convert/src/by_table/voice_conversion_results/voice_conversion_media_token_type.rs @@ -0,0 +1,40 @@ +use enums_api::by_table::voice_conversion_results::voice_conversion_media_token_type::VoiceConversionMediaTokenType as Api; +use enums_db::by_table::voice_conversion_results::voice_conversion_media_token_type::VoiceConversionMediaTokenType as Db; + +pub fn voice_conversion_media_token_type_to_db(api_value: &Api) -> Db { + match api_value { + Api::MediaUpload => Db::MediaUpload, + } +} + +pub fn voice_conversion_media_token_type_to_api(db_value: &Db) -> Api { + match db_value { + Db::MediaUpload => Api::MediaUpload, + } +} + +#[cfg(test)] +mod tests { + use super::*; + use strum::IntoEnumIterator; + + #[test] + fn round_trip_api_to_db() { + use strum::IntoEnumIterator; + for api_variant in Api::iter() { + let db = voice_conversion_media_token_type_to_db(&api_variant); + let back = voice_conversion_media_token_type_to_api(&db); + assert_eq!(api_variant, back); + } + } + + #[test] + fn round_trip_db_to_api() { + use strum::IntoEnumIterator; + for api_variant in Api::iter() { + let db = voice_conversion_media_token_type_to_db(&api_variant); + let back = voice_conversion_media_token_type_to_api(&db); + assert_eq!(api_variant, back); + } + } +} diff --git a/crates/schema/public/enums_convert/src/by_table/wallet_ledger_entries/mod.rs b/crates/schema/public/enums_convert/src/by_table/wallet_ledger_entries/mod.rs new file mode 100644 index 0000000000..385570f7f1 --- /dev/null +++ b/crates/schema/public/enums_convert/src/by_table/wallet_ledger_entries/mod.rs @@ -0,0 +1 @@ +pub mod wallet_ledger_entry_type; diff --git a/crates/schema/public/enums_convert/src/by_table/wallet_ledger_entries/wallet_ledger_entry_type.rs b/crates/schema/public/enums_convert/src/by_table/wallet_ledger_entries/wallet_ledger_entry_type.rs new file mode 100644 index 0000000000..ae53e80ad6 --- /dev/null +++ b/crates/schema/public/enums_convert/src/by_table/wallet_ledger_entries/wallet_ledger_entry_type.rs @@ -0,0 +1,53 @@ +use enums_api::by_table::wallet_ledger_entries::wallet_ledger_entry_type::WalletLedgerEntryType as Api; +use enums_db::by_table::wallet_ledger_entries::wallet_ledger_entry_type::WalletLedgerEntryType as Db; + +pub fn wallet_ledger_entry_type_to_db(api_value: &Api) -> Db { + match api_value { + Api::Create => Db::Create, + Api::CreditBanked => Db::CreditBanked, + Api::CreditMonthly => Db::CreditMonthly, + Api::DeductMixed => Db::DeductMixed, + Api::DeductBanked => Db::DeductBanked, + Api::DeductMonthly => Db::DeductMonthly, + Api::RefundBanked => Db::RefundBanked, + Api::StaffAddBanked => Db::StaffAddBanked, + } +} + +pub fn wallet_ledger_entry_type_to_api(db_value: &Db) -> Api { + match db_value { + Db::Create => Api::Create, + Db::CreditBanked => Api::CreditBanked, + Db::CreditMonthly => Api::CreditMonthly, + Db::DeductMixed => Api::DeductMixed, + Db::DeductBanked => Api::DeductBanked, + Db::DeductMonthly => Api::DeductMonthly, + Db::RefundBanked => Api::RefundBanked, + Db::StaffAddBanked => Api::StaffAddBanked, + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn round_trip_api_to_db() { + use strum::IntoEnumIterator; + for api_variant in Api::iter() { + let db = wallet_ledger_entry_type_to_db(&api_variant); + let back = wallet_ledger_entry_type_to_api(&db); + assert_eq!(api_variant, back); + } + } + + #[test] + fn round_trip_db_to_api() { + use strum::IntoEnumIterator; + for variant in Db::iter() { + let api = wallet_ledger_entry_type_to_api(&variant); + let back = wallet_ledger_entry_type_to_db(&api); + assert_eq!(variant, back); + } + } +} diff --git a/crates/schema/public/enums_convert/src/by_table/web_rendition_targets/mod.rs b/crates/schema/public/enums_convert/src/by_table/web_rendition_targets/mod.rs new file mode 100644 index 0000000000..371fe4d32f --- /dev/null +++ b/crates/schema/public/enums_convert/src/by_table/web_rendition_targets/mod.rs @@ -0,0 +1 @@ +pub mod rendition_status; diff --git a/crates/schema/public/enums_convert/src/by_table/web_rendition_targets/rendition_status.rs b/crates/schema/public/enums_convert/src/by_table/web_rendition_targets/rendition_status.rs new file mode 100644 index 0000000000..ad577676c4 --- /dev/null +++ b/crates/schema/public/enums_convert/src/by_table/web_rendition_targets/rendition_status.rs @@ -0,0 +1,48 @@ +use enums_api::by_table::web_rendition_targets::rendition_status::RenditionStatus as Api; +use enums_db::by_table::web_rendition_targets::rendition_status::RenditionStatus as Db; + +pub fn rendition_status_to_db(api_value: &Api) -> Db { + match api_value { + Api::New => Db::New, + Api::Skipped => Db::Skipped, + Api::Failed => Db::Failed, + Api::PermanentlyFailed => Db::PermanentlyFailed, + Api::Success => Db::Success, + } +} + +pub fn rendition_status_to_api(db_value: &Db) -> Api { + match db_value { + Db::New => Api::New, + Db::Skipped => Api::Skipped, + Db::Failed => Api::Failed, + Db::PermanentlyFailed => Api::PermanentlyFailed, + Db::Success => Api::Success, + } +} + +#[cfg(test)] +mod tests { + use super::*; + use strum::IntoEnumIterator; + + #[test] + fn round_trip_api_to_db() { + use strum::IntoEnumIterator; + for api_variant in Api::iter() { + let db = rendition_status_to_db(&api_variant); + let back = rendition_status_to_api(&db); + assert_eq!(api_variant, back); + } + } + + #[test] + fn round_trip_db_to_api() { + use strum::IntoEnumIterator; + for api_variant in Api::iter() { + let db = rendition_status_to_db(&api_variant); + let back = rendition_status_to_api(&db); + assert_eq!(api_variant, back); + } + } +} diff --git a/crates/schema/public/enums_convert/src/by_table/web_scraping_targets/mod.rs b/crates/schema/public/enums_convert/src/by_table/web_scraping_targets/mod.rs new file mode 100644 index 0000000000..2dea4d4509 --- /dev/null +++ b/crates/schema/public/enums_convert/src/by_table/web_scraping_targets/mod.rs @@ -0,0 +1 @@ +pub mod scraping_status; diff --git a/crates/schema/public/enums_convert/src/by_table/web_scraping_targets/scraping_status.rs b/crates/schema/public/enums_convert/src/by_table/web_scraping_targets/scraping_status.rs new file mode 100644 index 0000000000..857c3e89b6 --- /dev/null +++ b/crates/schema/public/enums_convert/src/by_table/web_scraping_targets/scraping_status.rs @@ -0,0 +1,48 @@ +use enums_api::by_table::web_scraping_targets::scraping_status::ScrapingStatus as Api; +use enums_db::by_table::web_scraping_targets::scraping_status::ScrapingStatus as Db; + +pub fn scraping_status_to_db(api_value: &Api) -> Db { + match api_value { + Api::New => Db::New, + Api::Skipped => Db::Skipped, + Api::Failed => Db::Failed, + Api::PermanentlyFailed => Db::PermanentlyFailed, + Api::Success => Db::Success, + } +} + +pub fn scraping_status_to_api(db_value: &Db) -> Api { + match db_value { + Db::New => Api::New, + Db::Skipped => Api::Skipped, + Db::Failed => Api::Failed, + Db::PermanentlyFailed => Api::PermanentlyFailed, + Db::Success => Api::Success, + } +} + +#[cfg(test)] +mod tests { + use super::*; + use strum::IntoEnumIterator; + + #[test] + fn round_trip_api_to_db() { + use strum::IntoEnumIterator; + for api_variant in Api::iter() { + let db = scraping_status_to_db(&api_variant); + let back = scraping_status_to_api(&db); + assert_eq!(api_variant, back); + } + } + + #[test] + fn round_trip_db_to_api() { + use strum::IntoEnumIterator; + for api_variant in Api::iter() { + let db = scraping_status_to_db(&api_variant); + let back = scraping_status_to_api(&db); + assert_eq!(api_variant, back); + } + } +} diff --git a/crates/schema/public/enums_convert/src/by_table/zs_voices/encoding_type.rs b/crates/schema/public/enums_convert/src/by_table/zs_voices/encoding_type.rs new file mode 100644 index 0000000000..33feeb81bf --- /dev/null +++ b/crates/schema/public/enums_convert/src/by_table/zs_voices/encoding_type.rs @@ -0,0 +1,39 @@ +use enums_api::by_table::zs_voices::encoding_type::ZsVoiceEncodingType as Api; +use enums_db::by_table::zs_voices::encoding_type::ZsVoiceEncodingType as Db; + +pub fn zs_voice_encoding_type_to_db(api_value: &Api) -> Db { + match api_value { + Api::Encodec => Db::Encodec, + } +} + +pub fn zs_voice_encoding_type_to_api(db_value: &Db) -> Api { + match db_value { + Db::Encodec => Api::Encodec, + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn round_trip_api_to_db() { + use strum::IntoEnumIterator; + for api_variant in Api::iter() { + let db = zs_voice_encoding_type_to_db(&api_variant); + let back = zs_voice_encoding_type_to_api(&db); + assert_eq!(api_variant, back); + } + } + + #[test] + fn round_trip_db_to_api() { + use strum::IntoEnumIterator; + for variant in Db::iter() { + let api = zs_voice_encoding_type_to_api(&variant); + let back = zs_voice_encoding_type_to_db(&api); + assert_eq!(variant, back); + } + } +} diff --git a/crates/schema/public/enums_convert/src/by_table/zs_voices/mod.rs b/crates/schema/public/enums_convert/src/by_table/zs_voices/mod.rs new file mode 100644 index 0000000000..45e42bce9c --- /dev/null +++ b/crates/schema/public/enums_convert/src/by_table/zs_voices/mod.rs @@ -0,0 +1,3 @@ +pub mod encoding_type; +pub mod model_category; +pub mod model_type; diff --git a/crates/schema/public/enums_convert/src/by_table/zs_voices/model_category.rs b/crates/schema/public/enums_convert/src/by_table/zs_voices/model_category.rs new file mode 100644 index 0000000000..8bc17cad2d --- /dev/null +++ b/crates/schema/public/enums_convert/src/by_table/zs_voices/model_category.rs @@ -0,0 +1,39 @@ +use enums_api::by_table::zs_voices::model_category::ZsVoiceModelCategory as Api; +use enums_db::by_table::zs_voices::model_category::ZsVoiceModelCategory as Db; + +pub fn zs_voice_model_category_to_db(api_value: &Api) -> Db { + match api_value { + Api::Tts => Db::Tts, + } +} + +pub fn zs_voice_model_category_to_api(db_value: &Db) -> Api { + match db_value { + Db::Tts => Api::Tts, + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn round_trip_api_to_db() { + use strum::IntoEnumIterator; + for api_variant in Api::iter() { + let db = zs_voice_model_category_to_db(&api_variant); + let back = zs_voice_model_category_to_api(&db); + assert_eq!(api_variant, back); + } + } + + #[test] + fn round_trip_db_to_api() { + use strum::IntoEnumIterator; + for variant in Db::iter() { + let api = zs_voice_model_category_to_api(&variant); + let back = zs_voice_model_category_to_db(&api); + assert_eq!(variant, back); + } + } +} diff --git a/crates/schema/public/enums_convert/src/by_table/zs_voices/model_type.rs b/crates/schema/public/enums_convert/src/by_table/zs_voices/model_type.rs new file mode 100644 index 0000000000..3bcf807881 --- /dev/null +++ b/crates/schema/public/enums_convert/src/by_table/zs_voices/model_type.rs @@ -0,0 +1,41 @@ +use enums_api::by_table::zs_voices::model_type::ZsVoiceModelType as Api; +use enums_db::by_table::zs_voices::model_type::ZsVoiceModelType as Db; + +pub fn zs_voice_model_type_to_db(api_value: &Api) -> Db { + match api_value { + Api::VallEX => Db::VallEX, + Api::StyleTTS2 => Db::StyleTTS2, + } +} + +pub fn zs_voice_model_type_to_api(db_value: &Db) -> Api { + match db_value { + Db::VallEX => Api::VallEX, + Db::StyleTTS2 => Api::StyleTTS2, + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn round_trip_api_to_db() { + use strum::IntoEnumIterator; + for api_variant in Api::iter() { + let db = zs_voice_model_type_to_db(&api_variant); + let back = zs_voice_model_type_to_api(&db); + assert_eq!(api_variant, back); + } + } + + #[test] + fn round_trip_db_to_api() { + use strum::IntoEnumIterator; + for variant in Db::iter() { + let api = zs_voice_model_type_to_api(&variant); + let back = zs_voice_model_type_to_db(&api); + assert_eq!(variant, back); + } + } +} diff --git a/crates/schema/public/enums_convert/src/common/artcraft_credits_pack_slug.rs b/crates/schema/public/enums_convert/src/common/artcraft_credits_pack_slug.rs new file mode 100644 index 0000000000..944c919413 --- /dev/null +++ b/crates/schema/public/enums_convert/src/common/artcraft_credits_pack_slug.rs @@ -0,0 +1,50 @@ +use enums_api::common::artcraft_credits_pack_slug::ArtcraftCreditsPackSlug as Api; +use enums_db::common::artcraft_credits_pack_slug::ArtcraftCreditsPackSlug as Db; + +pub fn artcraft_credits_pack_slug_to_db(api_value: &Api) -> Db { + match api_value { + Api::Artcraft1000 => Db::Artcraft1000, + Api::Artcraft2500 => Db::Artcraft2500, + Api::Artcraft5000 => Db::Artcraft5000, + Api::Artcraft10000 => Db::Artcraft10000, + Api::Artcraft25000 => Db::Artcraft25000, + Api::Artcraft50000 => Db::Artcraft50000, + } +} + +pub fn artcraft_credits_pack_slug_to_api(db_value: &Db) -> Api { + match db_value { + Db::Artcraft1000 => Api::Artcraft1000, + Db::Artcraft2500 => Api::Artcraft2500, + Db::Artcraft5000 => Api::Artcraft5000, + Db::Artcraft10000 => Api::Artcraft10000, + Db::Artcraft25000 => Api::Artcraft25000, + Db::Artcraft50000 => Api::Artcraft50000, + } +} + +#[cfg(test)] +mod tests { + use super::*; + use strum::IntoEnumIterator; + + #[test] + fn round_trip_db_to_api() { + use strum::IntoEnumIterator; + for variant in Db::iter() { + let api = artcraft_credits_pack_slug_to_api(&variant); + let back = artcraft_credits_pack_slug_to_db(&api); + assert_eq!(variant, back); + } + } + + #[test] + fn round_trip_api_to_db() { + use strum::IntoEnumIterator; + for variant in Api::iter() { + let db = artcraft_credits_pack_slug_to_db(&variant); + let back = artcraft_credits_pack_slug_to_api(&db); + assert_eq!(variant, back); + } + } +} diff --git a/crates/schema/public/enums_convert/src/common/artcraft_subscription_slug.rs b/crates/schema/public/enums_convert/src/common/artcraft_subscription_slug.rs new file mode 100644 index 0000000000..dc87ef78c8 --- /dev/null +++ b/crates/schema/public/enums_convert/src/common/artcraft_subscription_slug.rs @@ -0,0 +1,44 @@ +use enums_api::common::artcraft_subscription_slug::ArtcraftSubscriptionSlug as Api; +use enums_db::common::artcraft_subscription_slug::ArtcraftSubscriptionSlug as Db; + +pub fn artcraft_subscription_slug_to_db(api_value: &Api) -> Db { + match api_value { + Api::ArtcraftBasic => Db::ArtcraftBasic, + Api::ArtcraftPro => Db::ArtcraftPro, + Api::ArtcraftMax => Db::ArtcraftMax, + } +} + +pub fn artcraft_subscription_slug_to_api(db_value: &Db) -> Api { + match db_value { + Db::ArtcraftBasic => Api::ArtcraftBasic, + Db::ArtcraftPro => Api::ArtcraftPro, + Db::ArtcraftMax => Api::ArtcraftMax, + } +} + +#[cfg(test)] +mod tests { + use super::*; + use strum::IntoEnumIterator; + + #[test] + fn round_trip_db_to_api() { + use strum::IntoEnumIterator; + for variant in Db::iter() { + let api = artcraft_subscription_slug_to_api(&variant); + let back = artcraft_subscription_slug_to_db(&api); + assert_eq!(variant, back); + } + } + + #[test] + fn round_trip_api_to_db() { + use strum::IntoEnumIterator; + for variant in Api::iter() { + let db = artcraft_subscription_slug_to_db(&variant); + let back = artcraft_subscription_slug_to_api(&db); + assert_eq!(variant, back); + } + } +} diff --git a/crates/schema/public/enums_convert/src/common/generation/generation_provider.rs b/crates/schema/public/enums_convert/src/common/generation/generation_provider.rs new file mode 100644 index 0000000000..fd758d939f --- /dev/null +++ b/crates/schema/public/enums_convert/src/common/generation/generation_provider.rs @@ -0,0 +1,50 @@ +use enums_api::common::generation::generation_provider::GenerationProvider as Api; +use enums_db::common::generation::generation_provider::GenerationProvider as Db; + +pub fn generation_provider_to_db(api_value: &Api) -> Db { + match api_value { + Api::Artcraft => Db::Artcraft, + Api::Fal => Db::Fal, + Api::Grok => Db::Grok, + Api::Midjourney => Db::Midjourney, + Api::Sora => Db::Sora, + Api::WorldLabs => Db::WorldLabs, + } +} + +pub fn generation_provider_to_api(db_value: &Db) -> Api { + match db_value { + Db::Artcraft => Api::Artcraft, + Db::Fal => Api::Fal, + Db::Grok => Api::Grok, + Db::Midjourney => Api::Midjourney, + Db::Sora => Api::Sora, + Db::WorldLabs => Api::WorldLabs, + } +} + +#[cfg(test)] +mod tests { + use super::*; + use strum::IntoEnumIterator; + + #[test] + fn round_trip_api_to_db() { + use strum::IntoEnumIterator; + for variant in Api::iter() { + let db = generation_provider_to_db(&variant); + let back = generation_provider_to_api(&db); + assert_eq!(variant, back); + } + } + + #[test] + fn round_trip_db_to_api() { + use strum::IntoEnumIterator; + for api_variant in Api::iter() { + let db = generation_provider_to_db(&api_variant); + let back = generation_provider_to_api(&db); + assert_eq!(api_variant, back); + } +} +} diff --git a/crates/schema/public/enums_convert/src/common/generation/mod.rs b/crates/schema/public/enums_convert/src/common/generation/mod.rs new file mode 100644 index 0000000000..37014dbd57 --- /dev/null +++ b/crates/schema/public/enums_convert/src/common/generation/mod.rs @@ -0,0 +1 @@ +pub mod generation_provider; diff --git a/crates/schema/public/enums_convert/src/common/job_status.rs b/crates/schema/public/enums_convert/src/common/job_status.rs new file mode 100644 index 0000000000..7e45ed8c44 --- /dev/null +++ b/crates/schema/public/enums_convert/src/common/job_status.rs @@ -0,0 +1,50 @@ +use enums_api::common::job_status::JobStatus as Api; +use enums_db::common::job_status::JobStatus as Db; + +pub fn job_status_to_db(api_value: &Api) -> Db { + match api_value { + Api::Pending => Db::Pending, + Api::Started => Db::Started, + Api::CompleteSuccess => Db::CompleteSuccess, + Api::CompleteFailure => Db::CompleteFailure, + Api::AttemptFailed => Db::AttemptFailed, + Api::Dead => Db::Dead, + } +} + +pub fn job_status_to_api(db_value: &Db) -> Api { + match db_value { + Db::Pending => Api::Pending, + Db::Started => Api::Started, + Db::CompleteSuccess => Api::CompleteSuccess, + Db::CompleteFailure => Api::CompleteFailure, + Db::AttemptFailed => Api::AttemptFailed, + Db::Dead => Api::Dead, + } +} + +#[cfg(test)] +mod tests { + use super::*; + use strum::IntoEnumIterator; + + #[test] + fn round_trip_db_to_api() { + use strum::IntoEnumIterator; + for variant in Db::iter() { + let api = job_status_to_api(&variant); + let back = job_status_to_db(&api); + assert_eq!(variant, back); + } + } + + #[test] + fn round_trip_api_to_db() { + use strum::IntoEnumIterator; + for variant in Api::iter() { + let db = job_status_to_db(&variant); + let back = job_status_to_api(&db); + assert_eq!(variant, back); + } + } +} diff --git a/crates/schema/public/enums_convert/src/common/job_status_plus.rs b/crates/schema/public/enums_convert/src/common/job_status_plus.rs new file mode 100644 index 0000000000..891592213d --- /dev/null +++ b/crates/schema/public/enums_convert/src/common/job_status_plus.rs @@ -0,0 +1,54 @@ +use enums_api::common::job_status_plus::JobStatusPlus as Api; +use enums_db::common::job_status_plus::JobStatusPlus as Db; + +pub fn job_status_plus_to_db(api_value: &Api) -> Db { + match api_value { + Api::Pending => Db::Pending, + Api::Started => Db::Started, + Api::CompleteSuccess => Db::CompleteSuccess, + Api::CompleteFailure => Db::CompleteFailure, + Api::AttemptFailed => Db::AttemptFailed, + Api::Dead => Db::Dead, + Api::CancelledByUser => Db::CancelledByUser, + Api::CancelledBySystem => Db::CancelledBySystem, + } +} + +pub fn job_status_plus_to_api(db_value: &Db) -> Api { + match db_value { + Db::Pending => Api::Pending, + Db::Started => Api::Started, + Db::CompleteSuccess => Api::CompleteSuccess, + Db::CompleteFailure => Api::CompleteFailure, + Db::AttemptFailed => Api::AttemptFailed, + Db::Dead => Api::Dead, + Db::CancelledByUser => Api::CancelledByUser, + Db::CancelledBySystem => Api::CancelledBySystem, + } +} + +#[cfg(test)] +mod tests { + use super::*; + use strum::IntoEnumIterator; + + #[test] + fn round_trip_db_to_api() { + use strum::IntoEnumIterator; + for variant in Db::iter() { + let api = job_status_plus_to_api(&variant); + let back = job_status_plus_to_db(&api); + assert_eq!(variant, back); + } + } + + #[test] + fn round_trip_api_to_db() { + use strum::IntoEnumIterator; + for variant in Api::iter() { + let db = job_status_plus_to_db(&variant); + let back = job_status_plus_to_api(&db); + assert_eq!(variant, back); + } + } +} diff --git a/crates/schema/public/enums_convert/src/common/mod.rs b/crates/schema/public/enums_convert/src/common/mod.rs new file mode 100644 index 0000000000..972e0c2ae4 --- /dev/null +++ b/crates/schema/public/enums_convert/src/common/mod.rs @@ -0,0 +1,12 @@ +pub mod artcraft_credits_pack_slug; +pub mod artcraft_subscription_slug; +pub mod generation; +pub mod job_status; +pub mod job_status_plus; +pub mod model_type; +pub mod payments_namespace; +pub mod sqlite; +pub mod stripe_subscription_status; +pub mod view_as; +pub mod visibility; +pub mod vocoder_type; diff --git a/crates/schema/public/enums_convert/src/common/model_type.rs b/crates/schema/public/enums_convert/src/common/model_type.rs new file mode 100644 index 0000000000..0b6a5eb511 --- /dev/null +++ b/crates/schema/public/enums_convert/src/common/model_type.rs @@ -0,0 +1,146 @@ +use enums_api::common::model_type::ModelType as Api; +use enums_db::common::model_type::ModelType as Db; + +pub fn model_type_to_db(api_value: &Api) -> Db { + match api_value { + Api::Flux1Dev => Db::Flux1Dev, + Api::Flux1Schnell => Db::Flux1Schnell, + Api::FluxDevJuggernaut => Db::FluxDevJuggernaut, + Api::FluxPro1 => Db::FluxPro1, + Api::FluxPro11 => Db::FluxPro11, + Api::FluxPro11Ultra => Db::FluxPro11Ultra, + Api::FluxProKontextMax => Db::FluxProKontextMax, + Api::Flux2LoraAngles => Db::Flux2LoraAngles, + Api::GptImage1 => Db::GptImage1, + Api::GptImage1p5 => Db::GptImage1p5, + Api::GrokImage => Db::GrokImage, + Api::Recraft3 => Db::Recraft3, + Api::SeedEdit3 => Db::SeedEdit3, + Api::Qwen => Db::Qwen, + Api::QwenEdit2511Angles => Db::QwenEdit2511Angles, + Api::Gemini25Flash => Db::Gemini25Flash, + Api::NanoBanana => Db::NanoBanana, + Api::NanoBanana2 => Db::NanoBanana2, + Api::NanoBananaPro => Db::NanoBananaPro, + Api::Seedream4 => Db::Seedream4, + Api::Seedream4p5 => Db::Seedream4p5, + Api::Seedream5Lite => Db::Seedream5Lite, + Api::Midjourney => Db::Midjourney, + Api::MidjourneyV6 => Db::MidjourneyV6, + Api::MidjourneyV6p1 => Db::MidjourneyV6p1, + Api::MidjourneyV6p1Raw => Db::MidjourneyV6p1Raw, + Api::MidjourneyV7 => Db::MidjourneyV7, + Api::MidjourneyV7Draft => Db::MidjourneyV7Draft, + Api::MidjourneyV7DraftRaw => Db::MidjourneyV7DraftRaw, + Api::MidjourneyV7Raw => Db::MidjourneyV7Raw, + Api::GrokVideo => Db::GrokVideo, + Api::Kling16Pro => Db::Kling16Pro, + Api::Kling21Pro => Db::Kling21Pro, + Api::Kling21Master => Db::Kling21Master, + Api::Kling2p5TurboPro => Db::Kling2p5TurboPro, + Api::Kling2p6Pro => Db::Kling2p6Pro, + Api::Kling3p0Standard => Db::Kling3p0Standard, + Api::Kling3p0Pro => Db::Kling3p0Pro, + Api::Seedance10Lite => Db::Seedance10Lite, + Api::Seedance10Pro => Db::Seedance10Pro, + Api::Seedance1p5Pro => Db::Seedance1p5Pro, + Api::Seedance2p0 => Db::Seedance2p0, + Api::Sora2 => Db::Sora2, + Api::Sora2Pro => Db::Sora2Pro, + Api::Veo2 => Db::Veo2, + Api::Veo3 => Db::Veo3, + Api::Veo3Fast => Db::Veo3Fast, + Api::Veo3p1 => Db::Veo3p1, + Api::Veo3p1Fast => Db::Veo3p1Fast, + Api::Hunyuan3d2_0 => Db::Hunyuan3d2_0, + Api::Hunyuan3d2_1 => Db::Hunyuan3d2_1, + Api::Hunyuan3d3 => Db::Hunyuan3d3, + Api::Marble0p1Mini => Db::Marble0p1Mini, + Api::Marble0p1Plus => Db::Marble0p1Plus, + } +} + +pub fn model_type_to_api(db_value: &Db) -> Api { + match db_value { + Db::Flux1Dev => Api::Flux1Dev, + Db::Flux1Schnell => Api::Flux1Schnell, + Db::FluxDevJuggernaut => Api::FluxDevJuggernaut, + Db::FluxPro1 => Api::FluxPro1, + Db::FluxPro11 => Api::FluxPro11, + Db::FluxPro11Ultra => Api::FluxPro11Ultra, + Db::FluxProKontextMax => Api::FluxProKontextMax, + Db::Flux2LoraAngles => Api::Flux2LoraAngles, + Db::GptImage1 => Api::GptImage1, + Db::GptImage1p5 => Api::GptImage1p5, + Db::GrokImage => Api::GrokImage, + Db::Recraft3 => Api::Recraft3, + Db::SeedEdit3 => Api::SeedEdit3, + Db::Qwen => Api::Qwen, + Db::QwenEdit2511Angles => Api::QwenEdit2511Angles, + Db::Gemini25Flash => Api::Gemini25Flash, + Db::NanoBanana => Api::NanoBanana, + Db::NanoBanana2 => Api::NanoBanana2, + Db::NanoBananaPro => Api::NanoBananaPro, + Db::Seedream4 => Api::Seedream4, + Db::Seedream4p5 => Api::Seedream4p5, + Db::Seedream5Lite => Api::Seedream5Lite, + Db::Midjourney => Api::Midjourney, + Db::MidjourneyV6 => Api::MidjourneyV6, + Db::MidjourneyV6p1 => Api::MidjourneyV6p1, + Db::MidjourneyV6p1Raw => Api::MidjourneyV6p1Raw, + Db::MidjourneyV7 => Api::MidjourneyV7, + Db::MidjourneyV7Draft => Api::MidjourneyV7Draft, + Db::MidjourneyV7DraftRaw => Api::MidjourneyV7DraftRaw, + Db::MidjourneyV7Raw => Api::MidjourneyV7Raw, + Db::GrokVideo => Api::GrokVideo, + Db::Kling16Pro => Api::Kling16Pro, + Db::Kling21Pro => Api::Kling21Pro, + Db::Kling21Master => Api::Kling21Master, + Db::Kling2p5TurboPro => Api::Kling2p5TurboPro, + Db::Kling2p6Pro => Api::Kling2p6Pro, + Db::Kling3p0Standard => Api::Kling3p0Standard, + Db::Kling3p0Pro => Api::Kling3p0Pro, + Db::Seedance10Lite => Api::Seedance10Lite, + Db::Seedance10Pro => Api::Seedance10Pro, + Db::Seedance1p5Pro => Api::Seedance1p5Pro, + Db::Seedance2p0 => Api::Seedance2p0, + Db::Sora2 => Api::Sora2, + Db::Sora2Pro => Api::Sora2Pro, + Db::Veo2 => Api::Veo2, + Db::Veo3 => Api::Veo3, + Db::Veo3Fast => Api::Veo3Fast, + Db::Veo3p1 => Api::Veo3p1, + Db::Veo3p1Fast => Api::Veo3p1Fast, + Db::Hunyuan3d2_0 => Api::Hunyuan3d2_0, + Db::Hunyuan3d2_1 => Api::Hunyuan3d2_1, + Db::Hunyuan3d3 => Api::Hunyuan3d3, + Db::Marble0p1Mini => Api::Marble0p1Mini, + Db::Marble0p1Plus => Api::Marble0p1Plus, + } +} + +#[cfg(test)] +mod tests { + use super::*; + use strum::IntoEnumIterator; + + #[test] + fn round_trip_db_to_api() { + use strum::IntoEnumIterator; + for variant in Db::iter() { + let api = model_type_to_api(&variant); + let back = model_type_to_db(&api); + assert_eq!(variant, back); + } + } + + #[test] + fn round_trip_api_to_db() { + use strum::IntoEnumIterator; + for variant in Api::iter() { + let db = model_type_to_db(&variant); + let back = model_type_to_api(&db); + assert_eq!(variant, back); + } + } +} diff --git a/crates/schema/public/enums_convert/src/common/payments_namespace.rs b/crates/schema/public/enums_convert/src/common/payments_namespace.rs new file mode 100644 index 0000000000..09d8ab23e3 --- /dev/null +++ b/crates/schema/public/enums_convert/src/common/payments_namespace.rs @@ -0,0 +1,42 @@ +use enums_api::common::payments_namespace::PaymentsNamespace as Api; +use enums_db::common::payments_namespace::PaymentsNamespace as Db; + +pub fn payments_namespace_to_db(api_value: &Api) -> Db { + match api_value { + Api::Artcraft => Db::Artcraft, + Api::FakeYou => Db::FakeYou, + } +} + +pub fn payments_namespace_to_api(db_value: &Db) -> Api { + match db_value { + Db::Artcraft => Api::Artcraft, + Db::FakeYou => Api::FakeYou, + } +} + +#[cfg(test)] +mod tests { + use super::*; + use strum::IntoEnumIterator; + + #[test] + fn round_trip_db_to_api() { + use strum::IntoEnumIterator; + for variant in Db::iter() { + let api = payments_namespace_to_api(&variant); + let back = payments_namespace_to_db(&api); + assert_eq!(variant, back); + } + } + + #[test] + fn round_trip_api_to_db() { + use strum::IntoEnumIterator; + for variant in Api::iter() { + let db = payments_namespace_to_db(&variant); + let back = payments_namespace_to_api(&db); + assert_eq!(variant, back); + } + } +} diff --git a/crates/schema/public/enums_convert/src/common/sqlite/awaitable_job_status.rs b/crates/schema/public/enums_convert/src/common/sqlite/awaitable_job_status.rs new file mode 100644 index 0000000000..1deea00f8f --- /dev/null +++ b/crates/schema/public/enums_convert/src/common/sqlite/awaitable_job_status.rs @@ -0,0 +1,42 @@ +use enums_api::common::sqlite::awaitable_job_status::AwaitableJobStatus as Api; +use enums_db::common::sqlite::awaitable_job_status::AwaitableJobStatus as Db; + +pub fn awaitable_job_status_to_db(api_value: &Api) -> Db { + match api_value { + Api::NotReady => Db::NotReady, + Api::ReadyWaiting => Db::ReadyWaiting, + Api::Processing => Db::Processing, + Api::RetryablyFailed => Db::RetryablyFailed, + Api::PermanentlyFailed => Db::PermanentlyFailed, + Api::Skipped => Db::Skipped, + Api::Done => Db::Done, + } +} + +pub fn awaitable_job_status_to_api(db_value: &Db) -> Api { + match db_value { + Db::NotReady => Api::NotReady, + Db::ReadyWaiting => Api::ReadyWaiting, + Db::Processing => Api::Processing, + Db::RetryablyFailed => Api::RetryablyFailed, + Db::PermanentlyFailed => Api::PermanentlyFailed, + Db::Skipped => Api::Skipped, + Db::Done => Api::Done, + } +} + +#[cfg(test)] +mod tests { + use super::*; + use strum::IntoEnumIterator; + + #[test] + fn round_trip_db_to_api() { + use strum::IntoEnumIterator; + for api_variant in Api::iter() { + let db = awaitable_job_status_to_db(&api_variant); + let back = awaitable_job_status_to_api(&db); + assert_eq!(api_variant, back); + } + } +} diff --git a/crates/schema/public/enums_convert/src/common/sqlite/chatbot_job_status.rs b/crates/schema/public/enums_convert/src/common/sqlite/chatbot_job_status.rs new file mode 100644 index 0000000000..c758020dd1 --- /dev/null +++ b/crates/schema/public/enums_convert/src/common/sqlite/chatbot_job_status.rs @@ -0,0 +1,38 @@ +use enums_api::common::sqlite::chatbot_job_status::ChatbotJobStatus as Api; +use enums_db::common::sqlite::chatbot_job_status::ChatbotJobStatus as Db; + +pub fn chatbot_job_status_to_db(api_value: &Api) -> Db { + match api_value { + Api::New => Db::New, + Api::Skipped => Db::Skipped, + Api::Failed => Db::Failed, + Api::PermanentlyFailed => Db::PermanentlyFailed, + Api::Success => Db::Success, + } +} + +pub fn chatbot_job_status_to_api(db_value: &Db) -> Api { + match db_value { + Db::New => Api::New, + Db::Skipped => Api::Skipped, + Db::Failed => Api::Failed, + Db::PermanentlyFailed => Api::PermanentlyFailed, + Db::Success => Api::Success, + } +} + +#[cfg(test)] +mod tests { + use super::*; + use strum::IntoEnumIterator; + + #[test] + fn round_trip_db_to_api() { + use strum::IntoEnumIterator; + for api_variant in Api::iter() { + let db = chatbot_job_status_to_db(&api_variant); + let back = chatbot_job_status_to_api(&db); + assert_eq!(api_variant, back); + } +} +} diff --git a/crates/schema/public/enums_convert/src/common/sqlite/mod.rs b/crates/schema/public/enums_convert/src/common/sqlite/mod.rs new file mode 100644 index 0000000000..7659a1e044 --- /dev/null +++ b/crates/schema/public/enums_convert/src/common/sqlite/mod.rs @@ -0,0 +1,4 @@ +pub mod awaitable_job_status; +pub mod chatbot_job_status; +pub mod skip_reason; +pub mod web_content_type; diff --git a/crates/schema/public/enums_convert/src/common/sqlite/skip_reason.rs b/crates/schema/public/enums_convert/src/common/sqlite/skip_reason.rs new file mode 100644 index 0000000000..3b5f1c9011 --- /dev/null +++ b/crates/schema/public/enums_convert/src/common/sqlite/skip_reason.rs @@ -0,0 +1,40 @@ +use enums_api::common::sqlite::skip_reason::SkipReason as Api; +use enums_db::common::sqlite::skip_reason::SkipReason as Db; + +pub fn skip_reason_to_db(api_value: &Api) -> Db { + match api_value { + Api::EmptyContent => Db::EmptyContent, + Api::Advertisement => Db::Advertisement, + Api::VideoContent => Db::VideoContent, + Api::FilteredTopic => Db::FilteredTopic, + Api::FilteredTopicPolitics => Db::FilteredTopicPolitics, + Api::NobodyCares => Db::NobodyCares, + } +} + +pub fn skip_reason_to_api(db_value: &Db) -> Api { + match db_value { + Db::EmptyContent => Api::EmptyContent, + Db::Advertisement => Api::Advertisement, + Db::VideoContent => Api::VideoContent, + Db::FilteredTopic => Api::FilteredTopic, + Db::FilteredTopicPolitics => Api::FilteredTopicPolitics, + Db::NobodyCares => Api::NobodyCares, + } +} + +#[cfg(test)] +mod tests { + use super::*; + use strum::IntoEnumIterator; + + #[test] + fn round_trip_db_to_api() { + use strum::IntoEnumIterator; + for api_variant in Api::iter() { + let db = skip_reason_to_db(&api_variant); + let back = skip_reason_to_api(&db); + assert_eq!(api_variant, back); + } +} +} diff --git a/crates/schema/public/enums_convert/src/common/sqlite/web_content_type.rs b/crates/schema/public/enums_convert/src/common/sqlite/web_content_type.rs new file mode 100644 index 0000000000..ff0a200522 --- /dev/null +++ b/crates/schema/public/enums_convert/src/common/sqlite/web_content_type.rs @@ -0,0 +1,48 @@ +use enums_api::common::sqlite::web_content_type::WebContentType as Api; +use enums_db::common::sqlite::web_content_type::WebContentType as Db; + +pub fn web_content_type_to_db(api_value: &Api) -> Db { + match api_value { + Api::CbsNewsArticle => Db::CbsNewsArticle, + Api::CnnArticle => Db::CnnArticle, + Api::GizmodoArticle => Db::GizmodoArticle, + Api::HackerNewsThread => Db::HackerNewsThread, + Api::KotakuArticle => Db::KotakuArticle, + Api::RedditThread => Db::RedditThread, + Api::SlashdotArticle => Db::SlashdotArticle, + Api::SubstackPost => Db::SubstackPost, + Api::TechCrunchArticle => Db::TechCrunchArticle, + Api::TheGuardianArticle => Db::TheGuardianArticle, + } +} + +pub fn web_content_type_to_api(db_value: &Db) -> Api { + match db_value { + Db::CbsNewsArticle => Api::CbsNewsArticle, + Db::CnnArticle => Api::CnnArticle, + Db::GizmodoArticle => Api::GizmodoArticle, + Db::HackerNewsThread => Api::HackerNewsThread, + Db::KotakuArticle => Api::KotakuArticle, + Db::RedditThread => Api::RedditThread, + Db::SlashdotArticle => Api::SlashdotArticle, + Db::SubstackPost => Api::SubstackPost, + Db::TechCrunchArticle => Api::TechCrunchArticle, + Db::TheGuardianArticle => Api::TheGuardianArticle, + } +} + +#[cfg(test)] +mod tests { + use super::*; + use strum::IntoEnumIterator; + + #[test] + fn round_trip_db_to_api() { + use strum::IntoEnumIterator; + for api_variant in Api::iter() { + let db = web_content_type_to_db(&api_variant); + let back = web_content_type_to_api(&db); + assert_eq!(api_variant, back); + } +} +} diff --git a/crates/schema/public/enums_convert/src/common/stripe_subscription_status.rs b/crates/schema/public/enums_convert/src/common/stripe_subscription_status.rs new file mode 100644 index 0000000000..710d8b72d5 --- /dev/null +++ b/crates/schema/public/enums_convert/src/common/stripe_subscription_status.rs @@ -0,0 +1,44 @@ +use enums_api::common::stripe_subscription_status::StripeSubscriptionStatus as Api; +use enums_db::common::stripe_subscription_status::StripeSubscriptionStatus as Db; + +pub fn stripe_subscription_status_to_db(api_value: &Api) -> Db { + match api_value { + Api::Active => Db::Active, + Api::Canceled => Db::Canceled, + Api::Incomplete => Db::Incomplete, + Api::IncompleteExpired => Db::IncompleteExpired, + Api::PastDue => Db::PastDue, + Api::Trialing => Db::Trialing, + Api::Unpaid => Db::Unpaid, + Api::Paused => Db::Paused, + } +} + +pub fn stripe_subscription_status_to_api(db_value: &Db) -> Api { + match db_value { + Db::Active => Api::Active, + Db::Canceled => Api::Canceled, + Db::Incomplete => Api::Incomplete, + Db::IncompleteExpired => Api::IncompleteExpired, + Db::PastDue => Api::PastDue, + Db::Trialing => Api::Trialing, + Db::Unpaid => Api::Unpaid, + Db::Paused => Api::Paused, + } +} + +#[cfg(test)] +mod tests { + use super::*; + use strum::IntoEnumIterator; + + #[test] + fn round_trip_db_to_api() { + use strum::IntoEnumIterator; + for variant in Db::iter() { + let api = stripe_subscription_status_to_api(&variant); + let back = stripe_subscription_status_to_db(&api); + assert_eq!(variant, back); + } +} +} diff --git a/crates/schema/public/enums_convert/src/common/view_as.rs b/crates/schema/public/enums_convert/src/common/view_as.rs new file mode 100644 index 0000000000..24ea10e8b4 --- /dev/null +++ b/crates/schema/public/enums_convert/src/common/view_as.rs @@ -0,0 +1,44 @@ +use enums_api::common::view_as::ViewAs as Api; +use enums_db::common::view_as::ViewAs as Db; + +pub fn view_as_to_db(api_value: &Api) -> Db { + match api_value { + Api::Author => Db::Author, + Api::Moderator => Db::Moderator, + Api::AnotherUser => Db::AnotherUser, + } +} + +pub fn view_as_to_api(db_value: &Db) -> Api { + match db_value { + Db::Author => Api::Author, + Db::Moderator => Api::Moderator, + Db::AnotherUser => Api::AnotherUser, + } +} + +#[cfg(test)] +mod tests { + use super::*; + use strum::IntoEnumIterator; + + #[test] + fn round_trip_db_to_api() { + use strum::IntoEnumIterator; + for api_variant in Api::iter() { + let db = view_as_to_db(&api_variant); + let back = view_as_to_api(&db); + assert_eq!(api_variant, back); + } + } + + #[test] + fn round_trip_api_to_db() { + use strum::IntoEnumIterator; + for variant in Api::iter() { + let db = view_as_to_db(&variant); + let back = view_as_to_api(&db); + assert_eq!(variant, back); + } + } +} diff --git a/crates/schema/public/enums_convert/src/common/visibility.rs b/crates/schema/public/enums_convert/src/common/visibility.rs new file mode 100644 index 0000000000..88afc27750 --- /dev/null +++ b/crates/schema/public/enums_convert/src/common/visibility.rs @@ -0,0 +1,44 @@ +use enums_api::common::visibility::Visibility as Api; +use enums_db::common::visibility::Visibility as Db; + +pub fn visibility_to_db(api_value: &Api) -> Db { + match api_value { + Api::Public => Db::Public, + Api::Hidden => Db::Hidden, + Api::Private => Db::Private, + } +} + +pub fn visibility_to_api(db_value: &Db) -> Api { + match db_value { + Db::Public => Api::Public, + Db::Hidden => Api::Hidden, + Db::Private => Api::Private, + } +} + +#[cfg(test)] +mod tests { + use super::*; + use strum::IntoEnumIterator; + + #[test] + fn round_trip_db_to_api() { + use strum::IntoEnumIterator; + for api_variant in Api::iter() { + let db = visibility_to_db(&api_variant); + let back = visibility_to_api(&db); + assert_eq!(api_variant, back); + } + } + + #[test] + fn round_trip_api_to_db() { + use strum::IntoEnumIterator; + for variant in Api::iter() { + let db = visibility_to_db(&variant); + let back = visibility_to_api(&db); + assert_eq!(variant, back); + } + } +} diff --git a/crates/schema/public/enums_convert/src/common/vocoder_type.rs b/crates/schema/public/enums_convert/src/common/vocoder_type.rs new file mode 100644 index 0000000000..3ee2a22dd9 --- /dev/null +++ b/crates/schema/public/enums_convert/src/common/vocoder_type.rs @@ -0,0 +1,34 @@ +use enums_api::common::vocoder_type::VocoderType as Api; +use enums_db::common::vocoder_type::VocoderType as Db; + +pub fn vocoder_type_to_db(api_value: &Api) -> Db { + match api_value { + Api::HifiGan => Db::HifiGan, + Api::HifiGanSuperResolution => Db::HifiGanSuperResolution, + Api::HifiGanRocketVc => Db::HifiGanRocketVc, + } +} + +pub fn vocoder_type_to_api(db_value: &Db) -> Api { + match db_value { + Db::HifiGan => Api::HifiGan, + Db::HifiGanSuperResolution => Api::HifiGanSuperResolution, + Db::HifiGanRocketVc => Api::HifiGanRocketVc, + } +} + +#[cfg(test)] +mod tests { + use super::*; + use strum::IntoEnumIterator; + + #[test] + fn round_trip_db_to_api() { + use strum::IntoEnumIterator; + for api_variant in Api::iter() { + let db = vocoder_type_to_db(&api_variant); + let back = vocoder_type_to_api(&db); + assert_eq!(api_variant, back); + } +} +} diff --git a/crates/schema/public/enums_convert/src/lib.rs b/crates/schema/public/enums_convert/src/lib.rs new file mode 100644 index 0000000000..b7b0a4e59f --- /dev/null +++ b/crates/schema/public/enums_convert/src/lib.rs @@ -0,0 +1,5 @@ +pub mod api_safe; +pub mod by_table; +pub mod common; +pub mod no_table; +pub mod tauri; diff --git a/crates/schema/public/enums_convert/src/no_table/mod.rs b/crates/schema/public/enums_convert/src/no_table/mod.rs new file mode 100644 index 0000000000..df89af707b --- /dev/null +++ b/crates/schema/public/enums_convert/src/no_table/mod.rs @@ -0,0 +1,2 @@ +pub mod premium_product; +pub mod style_transfer; diff --git a/crates/schema/public/enums_convert/src/no_table/premium_product/mod.rs b/crates/schema/public/enums_convert/src/no_table/premium_product/mod.rs new file mode 100644 index 0000000000..09a42c40ff --- /dev/null +++ b/crates/schema/public/enums_convert/src/no_table/premium_product/mod.rs @@ -0,0 +1 @@ +pub mod premium_product_name; diff --git a/crates/schema/public/enums_convert/src/no_table/premium_product/premium_product_name.rs b/crates/schema/public/enums_convert/src/no_table/premium_product/premium_product_name.rs new file mode 100644 index 0000000000..4cce22f6ee --- /dev/null +++ b/crates/schema/public/enums_convert/src/no_table/premium_product/premium_product_name.rs @@ -0,0 +1,36 @@ +use enums_api::no_table::premium_product::premium_product_name::PremiumProductName as Api; +use enums_db::no_table::premium_product::premium_product_name::PremiumProductName as Db; + +pub fn premium_product_name_to_db(api_value: &Api) -> Db { + match api_value { + Api::FaceAnimator => Db::FaceAnimator, + Api::FaceMirror => Db::FaceMirror, + Api::Lipsync => Db::Lipsync, + Api::VideoStyleTransfer => Db::VideoStyleTransfer, + } +} + +pub fn premium_product_name_to_api(db_value: &Db) -> Api { + match db_value { + Db::FaceAnimator => Api::FaceAnimator, + Db::FaceMirror => Api::FaceMirror, + Db::Lipsync => Api::Lipsync, + Db::VideoStyleTransfer => Api::VideoStyleTransfer, + } +} + +#[cfg(test)] +mod tests { + use super::*; + use strum::IntoEnumIterator; + + #[test] + fn round_trip_db_to_api() { + use strum::IntoEnumIterator; + for variant in Db::iter() { + let api = premium_product_name_to_api(&variant); + let back = premium_product_name_to_db(&api); + assert_eq!(variant, back); + } + } +} diff --git a/crates/schema/public/enums_convert/src/no_table/style_transfer/mod.rs b/crates/schema/public/enums_convert/src/no_table/style_transfer/mod.rs new file mode 100644 index 0000000000..f7f0351a17 --- /dev/null +++ b/crates/schema/public/enums_convert/src/no_table/style_transfer/mod.rs @@ -0,0 +1 @@ +pub mod style_transfer_name; diff --git a/crates/schema/public/enums_convert/src/no_table/style_transfer/style_transfer_name.rs b/crates/schema/public/enums_convert/src/no_table/style_transfer/style_transfer_name.rs new file mode 100644 index 0000000000..7216723cb2 --- /dev/null +++ b/crates/schema/public/enums_convert/src/no_table/style_transfer/style_transfer_name.rs @@ -0,0 +1,107 @@ +use enums_api::no_table::style_transfer::style_transfer_name::StyleTransferName as Api; +use enums_db::no_table::style_transfer::style_transfer_name::StyleTransferName as Db; + +pub fn style_transfer_name_to_db(api_value: &Api) -> Db { + match api_value { + Api::Anime2_5D => Db::Anime2_5D, + Api::Anime2DFlat => Db::Anime2DFlat, + Api::Cartoon3D => Db::Cartoon3D, + Api::ComicBook => Db::ComicBook, + Api::AnimeGhibli => Db::AnimeGhibli, + Api::InkPunk => Db::InkPunk, + Api::InkSplash => Db::InkSplash, + Api::InkBWStyle => Db::InkBWStyle, + Api::JojoStyle => Db::JojoStyle, + Api::PaperOrigami => Db::PaperOrigami, + Api::PixelArt => Db::PixelArt, + Api::PopArt => Db::PopArt, + Api::Realistic1 => Db::Realistic1, + Api::Realistic2 => Db::Realistic2, + Api::AnimeRetroNeon => Db::AnimeRetroNeon, + Api::AnimeStandard => Db::AnimeStandard, + Api::HrGiger => Db::HrGiger, + Api::Simpsons => Db::Simpsons, + Api::Carnage => Db::Carnage, + Api::AnimePastelCute => Db::AnimePastelCute, + Api::BloomLighting => Db::BloomLighting, + Api::Horror2_5D => Db::Horror2_5D, + Api::Creepy => Db::Creepy, + Api::CreepyVhs => Db::CreepyVhs, + Api::TrailCamFootage => Db::TrailCamFootage, + Api::OldBlackWhiteMovie => Db::OldBlackWhiteMovie, + Api::HorrorNoirBlackWhite => Db::HorrorNoirBlackWhite, + Api::TechnoNoirBlackWhite => Db::TechnoNoirBlackWhite, + Api::BlackWhite20s => Db::BlackWhite20s, + Api::CyberpunkAnime => Db::CyberpunkAnime, + Api::Dragonball => Db::Dragonball, + Api::RealisticMatrix => Db::RealisticMatrix, + Api::RealisticCyberpunk => Db::RealisticCyberpunk, + Api::Dreamer => Db::Dreamer, + } +} + +pub fn style_transfer_name_to_api(db_value: &Db) -> Api { + match db_value { + Db::Anime2_5D => Api::Anime2_5D, + Db::Anime2DFlat => Api::Anime2DFlat, + Db::Cartoon3D => Api::Cartoon3D, + Db::ComicBook => Api::ComicBook, + Db::AnimeGhibli => Api::AnimeGhibli, + Db::InkPunk => Api::InkPunk, + Db::InkSplash => Api::InkSplash, + Db::InkBWStyle => Api::InkBWStyle, + Db::JojoStyle => Api::JojoStyle, + Db::PaperOrigami => Api::PaperOrigami, + Db::PixelArt => Api::PixelArt, + Db::PopArt => Api::PopArt, + Db::Realistic1 => Api::Realistic1, + Db::Realistic2 => Api::Realistic2, + Db::AnimeRetroNeon => Api::AnimeRetroNeon, + Db::AnimeStandard => Api::AnimeStandard, + Db::HrGiger => Api::HrGiger, + Db::Simpsons => Api::Simpsons, + Db::Carnage => Api::Carnage, + Db::AnimePastelCute => Api::AnimePastelCute, + Db::BloomLighting => Api::BloomLighting, + Db::Horror2_5D => Api::Horror2_5D, + Db::Creepy => Api::Creepy, + Db::CreepyVhs => Api::CreepyVhs, + Db::TrailCamFootage => Api::TrailCamFootage, + Db::OldBlackWhiteMovie => Api::OldBlackWhiteMovie, + Db::HorrorNoirBlackWhite => Api::HorrorNoirBlackWhite, + Db::TechnoNoirBlackWhite => Api::TechnoNoirBlackWhite, + Db::BlackWhite20s => Api::BlackWhite20s, + Db::CyberpunkAnime => Api::CyberpunkAnime, + Db::Dragonball => Api::Dragonball, + Db::RealisticMatrix => Api::RealisticMatrix, + Db::RealisticCyberpunk => Api::RealisticCyberpunk, + Db::Dreamer => Api::Dreamer, + } +} + +#[cfg(test)] +mod tests { + use super::*; + use strum::IntoEnumIterator; + + #[test] + fn round_trip_api_to_db() { + use strum::IntoEnumIterator; + for db_variant in Db::iter() { + let api = style_transfer_name_to_api(&db_variant); + let db = style_transfer_name_to_db(&api); + let back = style_transfer_name_to_api(&db); + assert_eq!(api, back); + } + } + + #[test] + fn round_trip_db_to_api() { + use strum::IntoEnumIterator; + for variant in Db::iter() { + let api = style_transfer_name_to_api(&variant); + let back = style_transfer_name_to_db(&api); + assert_eq!(variant, back); + } + } +} diff --git a/crates/schema/public/enums_convert/src/tauri/mod.rs b/crates/schema/public/enums_convert/src/tauri/mod.rs new file mode 100644 index 0000000000..c687f0ee1b --- /dev/null +++ b/crates/schema/public/enums_convert/src/tauri/mod.rs @@ -0,0 +1,2 @@ +pub mod tasks; +pub mod ux; diff --git a/crates/schema/public/enums_convert/src/tauri/tasks/mod.rs b/crates/schema/public/enums_convert/src/tauri/tasks/mod.rs new file mode 100644 index 0000000000..ef469ecb21 --- /dev/null +++ b/crates/schema/public/enums_convert/src/tauri/tasks/mod.rs @@ -0,0 +1,5 @@ +pub mod task_failure_type; +pub mod task_media_file_class; +pub mod task_model_type; +pub mod task_status; +pub mod task_type; diff --git a/crates/schema/public/enums_convert/src/tauri/tasks/task_failure_type.rs b/crates/schema/public/enums_convert/src/tauri/tasks/task_failure_type.rs new file mode 100644 index 0000000000..4c06ff75cf --- /dev/null +++ b/crates/schema/public/enums_convert/src/tauri/tasks/task_failure_type.rs @@ -0,0 +1,56 @@ +use enums_api::tauri::tasks::task_failure_type::TaskFailureType as Api; +use enums_db::tauri::tasks::task_failure_type::TaskFailureType as Db; + +pub fn task_failure_type_to_db(api_value: &Api) -> Db { + match api_value { + Api::Unknown => Db::Unknown, + Api::RuleBansUserImage => Db::RuleBansUserImage, + Api::RuleBansUserImageWithFaces => Db::RuleBansUserImageWithFaces, + Api::RuleBansUserTextPrompt => Db::RuleBansUserTextPrompt, + Api::RuleBansUserContent => Db::RuleBansUserContent, + Api::RuleBansGeneratedVideo => Db::RuleBansGeneratedVideo, + Api::RuleBansGeneratedAudio => Db::RuleBansGeneratedAudio, + Api::RuleBansGeneratedContent => Db::RuleBansGeneratedContent, + Api::GenerationFailed => Db::GenerationFailed, + } +} + +pub fn task_failure_type_to_api(db_value: &Db) -> Api { + match db_value { + Db::Unknown => Api::Unknown, + Db::RuleBansUserImage => Api::RuleBansUserImage, + Db::RuleBansUserImageWithFaces => Api::RuleBansUserImageWithFaces, + Db::RuleBansUserTextPrompt => Api::RuleBansUserTextPrompt, + Db::RuleBansUserContent => Api::RuleBansUserContent, + Db::RuleBansGeneratedVideo => Api::RuleBansGeneratedVideo, + Db::RuleBansGeneratedAudio => Api::RuleBansGeneratedAudio, + Db::RuleBansGeneratedContent => Api::RuleBansGeneratedContent, + Db::GenerationFailed => Api::GenerationFailed, + } +} + +#[cfg(test)] +mod tests { + use super::*; + use strum::IntoEnumIterator; + + #[test] + fn round_trip_db_to_api() { + use strum::IntoEnumIterator; + for variant in Db::iter() { + let api = task_failure_type_to_api(&variant); + let back = task_failure_type_to_db(&api); + assert_eq!(variant, back); + } + } + + #[test] + fn round_trip_api_to_db() { + use strum::IntoEnumIterator; + for variant in Api::iter() { + let db = task_failure_type_to_db(&variant); + let back = task_failure_type_to_api(&db); + assert_eq!(variant, back); + } + } +} diff --git a/crates/schema/public/enums_convert/src/tauri/tasks/task_media_file_class.rs b/crates/schema/public/enums_convert/src/tauri/tasks/task_media_file_class.rs new file mode 100644 index 0000000000..d124d5b1a7 --- /dev/null +++ b/crates/schema/public/enums_convert/src/tauri/tasks/task_media_file_class.rs @@ -0,0 +1,46 @@ +use enums_api::tauri::tasks::task_media_file_class::TaskMediaFileClass as Api; +use enums_db::tauri::tasks::task_media_file_class::TaskMediaFileClass as Db; + +pub fn task_media_file_class_to_db(api_value: &Api) -> Db { + match api_value { + Api::Audio => Db::Audio, + Api::Image => Db::Image, + Api::Video => Db::Video, + Api::Dimensional => Db::Dimensional, + } +} + +pub fn task_media_file_class_to_api(db_value: &Db) -> Api { + match db_value { + Db::Audio => Api::Audio, + Db::Image => Api::Image, + Db::Video => Api::Video, + Db::Dimensional => Api::Dimensional, + } +} + +#[cfg(test)] +mod tests { + use super::*; + use strum::IntoEnumIterator; + + #[test] + fn round_trip_db_to_api() { + use strum::IntoEnumIterator; + for variant in Db::iter() { + let api = task_media_file_class_to_api(&variant); + let back = task_media_file_class_to_db(&api); + assert_eq!(variant, back); + } + } + + #[test] + fn round_trip_api_to_db() { + use strum::IntoEnumIterator; + for variant in Api::iter() { + let db = task_media_file_class_to_db(&variant); + let back = task_media_file_class_to_api(&db); + assert_eq!(variant, back); + } + } +} diff --git a/crates/schema/public/enums_convert/src/tauri/tasks/task_model_type.rs b/crates/schema/public/enums_convert/src/tauri/tasks/task_model_type.rs new file mode 100644 index 0000000000..9802307f0d --- /dev/null +++ b/crates/schema/public/enums_convert/src/tauri/tasks/task_model_type.rs @@ -0,0 +1,128 @@ +use enums_api::tauri::tasks::task_model_type::TaskModelType as Api; +use enums_db::tauri::tasks::task_model_type::TaskModelType as Db; + +pub fn task_model_type_to_db(api_value: &Api) -> Db { + match api_value { + Api::Flux1Dev => Db::Flux1Dev, + Api::Flux1Schnell => Db::Flux1Schnell, + Api::FluxDevJuggernaut => Db::FluxDevJuggernaut, + Api::FluxPro1 => Db::FluxPro1, + Api::FluxPro11 => Db::FluxPro11, + Api::FluxPro11Ultra => Db::FluxPro11Ultra, + Api::FluxProKontextMax => Db::FluxProKontextMax, + Api::Gemini25Flash => Db::Gemini25Flash, + Api::NanoBanana => Db::NanoBanana, + Api::NanoBanana2 => Db::NanoBanana2, + Api::NanoBananaPro => Db::NanoBananaPro, + Api::GptImage1 => Db::GptImage1, + Api::GptImage1p5 => Db::GptImage1p5, + Api::Seedream4 => Db::Seedream4, + Api::Seedream4p5 => Db::Seedream4p5, + Api::Seedream5Lite => Db::Seedream5Lite, + Api::QwenEdit2511Angles => Db::QwenEdit2511Angles, + Api::Flux2LoraAngles => Db::Flux2LoraAngles, + Api::GrokImage => Db::GrokImage, + Api::Recraft3 => Db::Recraft3, + Api::Midjourney => Db::Midjourney, + Api::GrokVideo => Db::GrokVideo, + Api::Kling16Pro => Db::Kling16Pro, + Api::Kling21Pro => Db::Kling21Pro, + Api::Kling21Master => Db::Kling21Master, + Api::Kling2p5TurboPro => Db::Kling2p5TurboPro, + Api::Kling2p6Pro => Db::Kling2p6Pro, + Api::Kling3p0Standard => Db::Kling3p0Standard, + Api::Kling3p0Pro => Db::Kling3p0Pro, + Api::Seedance10Lite => Db::Seedance10Lite, + Api::Seedance1p5Pro => Db::Seedance1p5Pro, + Api::Seedance2p0 => Db::Seedance2p0, + Api::Sora2 => Db::Sora2, + Api::Sora2Pro => Db::Sora2Pro, + Api::Veo2 => Db::Veo2, + Api::Veo3 => Db::Veo3, + Api::Veo3Fast => Db::Veo3Fast, + Api::Veo3p1 => Db::Veo3p1, + Api::Veo3p1Fast => Db::Veo3p1Fast, + Api::Hunyuan3d2_0 => Db::Hunyuan3d2_0, + Api::Hunyuan3d2_1 => Db::Hunyuan3d2_1, + Api::Hunyuan3d3 => Db::Hunyuan3d3, + Api::WorldlabsMarble => Db::WorldlabsMarble, + Api::WorldlabsMarble0p1Mini => Db::WorldlabsMarble0p1Mini, + Api::WorldlabsMarble0p1Plus => Db::WorldlabsMarble0p1Plus, + } +} + +pub fn task_model_type_to_api(db_value: &Db) -> Api { + match db_value { + Db::Flux1Dev => Api::Flux1Dev, + Db::Flux1Schnell => Api::Flux1Schnell, + Db::FluxDevJuggernaut => Api::FluxDevJuggernaut, + Db::FluxPro1 => Api::FluxPro1, + Db::FluxPro11 => Api::FluxPro11, + Db::FluxPro11Ultra => Api::FluxPro11Ultra, + Db::FluxProKontextMax => Api::FluxProKontextMax, + Db::Gemini25Flash => Api::Gemini25Flash, + Db::NanoBanana => Api::NanoBanana, + Db::NanoBanana2 => Api::NanoBanana2, + Db::NanoBananaPro => Api::NanoBananaPro, + Db::GptImage1 => Api::GptImage1, + Db::GptImage1p5 => Api::GptImage1p5, + Db::Seedream4 => Api::Seedream4, + Db::Seedream4p5 => Api::Seedream4p5, + Db::Seedream5Lite => Api::Seedream5Lite, + Db::QwenEdit2511Angles => Api::QwenEdit2511Angles, + Db::Flux2LoraAngles => Api::Flux2LoraAngles, + Db::GrokImage => Api::GrokImage, + Db::Recraft3 => Api::Recraft3, + Db::Midjourney => Api::Midjourney, + Db::GrokVideo => Api::GrokVideo, + Db::Kling16Pro => Api::Kling16Pro, + Db::Kling21Pro => Api::Kling21Pro, + Db::Kling21Master => Api::Kling21Master, + Db::Kling2p5TurboPro => Api::Kling2p5TurboPro, + Db::Kling2p6Pro => Api::Kling2p6Pro, + Db::Kling3p0Standard => Api::Kling3p0Standard, + Db::Kling3p0Pro => Api::Kling3p0Pro, + Db::Seedance10Lite => Api::Seedance10Lite, + Db::Seedance1p5Pro => Api::Seedance1p5Pro, + Db::Seedance2p0 => Api::Seedance2p0, + Db::Sora2 => Api::Sora2, + Db::Sora2Pro => Api::Sora2Pro, + Db::Veo2 => Api::Veo2, + Db::Veo3 => Api::Veo3, + Db::Veo3Fast => Api::Veo3Fast, + Db::Veo3p1 => Api::Veo3p1, + Db::Veo3p1Fast => Api::Veo3p1Fast, + Db::Hunyuan3d2_0 => Api::Hunyuan3d2_0, + Db::Hunyuan3d2_1 => Api::Hunyuan3d2_1, + Db::Hunyuan3d3 => Api::Hunyuan3d3, + Db::WorldlabsMarble => Api::WorldlabsMarble, + Db::WorldlabsMarble0p1Mini => Api::WorldlabsMarble0p1Mini, + Db::WorldlabsMarble0p1Plus => Api::WorldlabsMarble0p1Plus, + } +} + +#[cfg(test)] +mod tests { + use super::*; + use strum::IntoEnumIterator; + + #[test] + fn round_trip_db_to_api() { + use strum::IntoEnumIterator; + for variant in Db::iter() { + let api = task_model_type_to_api(&variant); + let back = task_model_type_to_db(&api); + assert_eq!(variant, back); + } + } + + #[test] + fn round_trip_api_to_db() { + use strum::IntoEnumIterator; + for variant in Api::iter() { + let db = task_model_type_to_db(&variant); + let back = task_model_type_to_api(&db); + assert_eq!(variant, back); + } + } +} diff --git a/crates/schema/public/enums_convert/src/tauri/tasks/task_status.rs b/crates/schema/public/enums_convert/src/tauri/tasks/task_status.rs new file mode 100644 index 0000000000..923aaad491 --- /dev/null +++ b/crates/schema/public/enums_convert/src/tauri/tasks/task_status.rs @@ -0,0 +1,56 @@ +use enums_api::tauri::tasks::task_status::TaskStatus as Api; +use enums_db::tauri::tasks::task_status::TaskStatus as Db; + +pub fn task_status_to_db(api_value: &Api) -> Db { + match api_value { + Api::Pending => Db::Pending, + Api::Started => Db::Started, + Api::CompleteSuccess => Db::CompleteSuccess, + Api::CompleteFailure => Db::CompleteFailure, + Api::AttemptFailed => Db::AttemptFailed, + Api::Dead => Db::Dead, + Api::CancelledByUser => Db::CancelledByUser, + Api::CancelledByProvider => Db::CancelledByProvider, + Api::CancelledByUs => Db::CancelledByUs, + } +} + +pub fn task_status_to_api(db_value: &Db) -> Api { + match db_value { + Db::Pending => Api::Pending, + Db::Started => Api::Started, + Db::CompleteSuccess => Api::CompleteSuccess, + Db::CompleteFailure => Api::CompleteFailure, + Db::AttemptFailed => Api::AttemptFailed, + Db::Dead => Api::Dead, + Db::CancelledByUser => Api::CancelledByUser, + Db::CancelledByProvider => Api::CancelledByProvider, + Db::CancelledByUs => Api::CancelledByUs, + } +} + +#[cfg(test)] +mod tests { + use super::*; + use strum::IntoEnumIterator; + + #[test] + fn round_trip_db_to_api() { + use strum::IntoEnumIterator; + for variant in Db::iter() { + let api = task_status_to_api(&variant); + let back = task_status_to_db(&api); + assert_eq!(variant, back); + } + } + + #[test] + fn round_trip_api_to_db() { + use strum::IntoEnumIterator; + for variant in Api::iter() { + let db = task_status_to_db(&variant); + let back = task_status_to_api(&db); + assert_eq!(variant, back); + } + } +} diff --git a/crates/schema/public/enums_convert/src/tauri/tasks/task_type.rs b/crates/schema/public/enums_convert/src/tauri/tasks/task_type.rs new file mode 100644 index 0000000000..84b0437ab5 --- /dev/null +++ b/crates/schema/public/enums_convert/src/tauri/tasks/task_type.rs @@ -0,0 +1,50 @@ +use enums_api::tauri::tasks::task_type::TaskType as Api; +use enums_db::tauri::tasks::task_type::TaskType as Db; + +pub fn task_type_to_db(api_value: &Api) -> Db { + match api_value { + Api::ImageGeneration => Db::ImageGeneration, + Api::ImageInpaintEdit => Db::ImageInpaintEdit, + Api::VideoGeneration => Db::VideoGeneration, + Api::ObjectGeneration => Db::ObjectGeneration, + Api::GaussianGeneration => Db::GaussianGeneration, + Api::BackgroundRemoval => Db::BackgroundRemoval, + } +} + +pub fn task_type_to_api(db_value: &Db) -> Api { + match db_value { + Db::ImageGeneration => Api::ImageGeneration, + Db::ImageInpaintEdit => Api::ImageInpaintEdit, + Db::VideoGeneration => Api::VideoGeneration, + Db::ObjectGeneration => Api::ObjectGeneration, + Db::GaussianGeneration => Api::GaussianGeneration, + Db::BackgroundRemoval => Api::BackgroundRemoval, + } +} + +#[cfg(test)] +mod tests { + use super::*; + use strum::IntoEnumIterator; + + #[test] + fn round_trip_db_to_api() { + use strum::IntoEnumIterator; + for variant in Db::iter() { + let api = task_type_to_api(&variant); + let back = task_type_to_db(&api); + assert_eq!(variant, back); + } + } + + #[test] + fn round_trip_api_to_db() { + use strum::IntoEnumIterator; + for variant in Api::iter() { + let db = task_type_to_db(&variant); + let back = task_type_to_api(&db); + assert_eq!(variant, back); + } + } +} diff --git a/crates/schema/public/enums_convert/src/tauri/ux/mod.rs b/crates/schema/public/enums_convert/src/tauri/ux/mod.rs new file mode 100644 index 0000000000..40215426d6 --- /dev/null +++ b/crates/schema/public/enums_convert/src/tauri/ux/mod.rs @@ -0,0 +1,2 @@ +pub mod tauri_command_caller; +pub mod tauri_event_name; diff --git a/crates/schema/public/enums_convert/src/tauri/ux/tauri_command_caller.rs b/crates/schema/public/enums_convert/src/tauri/ux/tauri_command_caller.rs new file mode 100644 index 0000000000..a9a1a9a073 --- /dev/null +++ b/crates/schema/public/enums_convert/src/tauri/ux/tauri_command_caller.rs @@ -0,0 +1,48 @@ +use enums_api::tauri::ux::tauri_command_caller::TauriCommandCaller as Api; +use enums_db::tauri::ux::tauri_command_caller::TauriCommandCaller as Db; + +pub fn tauri_command_caller_to_db(api_value: &Api) -> Db { + match api_value { + Api::Canvas => Db::Canvas, + Api::ImageEditor => Db::ImageEditor, + Api::TextToImage => Db::TextToImage, + Api::ImageToVideo => Db::ImageToVideo, + Api::MiniApp => Db::MiniApp, + } +} + +pub fn tauri_command_caller_to_api(db_value: &Db) -> Api { + match db_value { + Db::Canvas => Api::Canvas, + Db::ImageEditor => Api::ImageEditor, + Db::TextToImage => Api::TextToImage, + Db::ImageToVideo => Api::ImageToVideo, + Db::MiniApp => Api::MiniApp, + } +} + +#[cfg(test)] +mod tests { + use super::*; + use strum::IntoEnumIterator; + + #[test] + fn round_trip_db_to_api() { + use strum::IntoEnumIterator; + for variant in Db::iter() { + let api = tauri_command_caller_to_api(&variant); + let back = tauri_command_caller_to_db(&api); + assert_eq!(variant, back); + } + } + + #[test] + fn round_trip_api_to_db() { + use strum::IntoEnumIterator; + for variant in Api::iter() { + let db = tauri_command_caller_to_db(&variant); + let back = tauri_command_caller_to_api(&db); + assert_eq!(variant, back); + } + } +} diff --git a/crates/schema/public/enums_convert/src/tauri/ux/tauri_event_name.rs b/crates/schema/public/enums_convert/src/tauri/ux/tauri_event_name.rs new file mode 100644 index 0000000000..7ad7791b7f --- /dev/null +++ b/crates/schema/public/enums_convert/src/tauri/ux/tauri_event_name.rs @@ -0,0 +1,74 @@ +use enums_api::tauri::ux::tauri_event_name::TauriEventName as Api; +use enums_db::tauri::ux::tauri_event_name::TauriEventName as Db; + +pub fn tauri_event_name_to_db(api_value: &Api) -> Db { + match api_value { + Api::GenerationEnqueueSuccessEvent => Db::GenerationEnqueueSuccessEvent, + Api::GenerationEnqueueFailureEvent => Db::GenerationEnqueueFailureEvent, + Api::GenerationCompleteEvent => Db::GenerationCompleteEvent, + Api::GenerationFailedEvent => Db::GenerationFailedEvent, + Api::CreditsBalanceChangedEvent => Db::CreditsBalanceChangedEvent, + Api::SubscriptionPlanChangedEvent => Db::SubscriptionPlanChangedEvent, + Api::MediaFileDeletedEvent => Db::MediaFileDeletedEvent, + Api::CanvasBgRemovedEvent => Db::CanvasBgRemovedEvent, + Api::TextToImageGenerationCompleteEvent => Db::TextToImageGenerationCompleteEvent, + Api::ImageEditCompleteEvent => Db::ImageEditCompleteEvent, + Api::ObjectGenerationCompleteEvent => Db::ObjectGenerationCompleteEvent, + Api::GaussianGenerationCompleteEvent => Db::GaussianGenerationCompleteEvent, + Api::VideoGenerationCompleteEvent => Db::VideoGenerationCompleteEvent, + Api::RefreshAccountStateEvent => Db::RefreshAccountStateEvent, + Api::ShowProviderBillingModalEvent => Db::ShowProviderBillingModalEvent, + Api::ShowProviderLoginModalEvent => Db::ShowProviderLoginModalEvent, + Api::FlashUserInputErrorEvent => Db::FlashUserInputErrorEvent, + Api::FlashFileDownloadErrorEvent => Db::FlashFileDownloadErrorEvent, + } +} + +pub fn tauri_event_name_to_api(db_value: &Db) -> Api { + match db_value { + Db::GenerationEnqueueSuccessEvent => Api::GenerationEnqueueSuccessEvent, + Db::GenerationEnqueueFailureEvent => Api::GenerationEnqueueFailureEvent, + Db::GenerationCompleteEvent => Api::GenerationCompleteEvent, + Db::GenerationFailedEvent => Api::GenerationFailedEvent, + Db::CreditsBalanceChangedEvent => Api::CreditsBalanceChangedEvent, + Db::SubscriptionPlanChangedEvent => Api::SubscriptionPlanChangedEvent, + Db::MediaFileDeletedEvent => Api::MediaFileDeletedEvent, + Db::CanvasBgRemovedEvent => Api::CanvasBgRemovedEvent, + Db::TextToImageGenerationCompleteEvent => Api::TextToImageGenerationCompleteEvent, + Db::ImageEditCompleteEvent => Api::ImageEditCompleteEvent, + Db::ObjectGenerationCompleteEvent => Api::ObjectGenerationCompleteEvent, + Db::GaussianGenerationCompleteEvent => Api::GaussianGenerationCompleteEvent, + Db::VideoGenerationCompleteEvent => Api::VideoGenerationCompleteEvent, + Db::RefreshAccountStateEvent => Api::RefreshAccountStateEvent, + Db::ShowProviderBillingModalEvent => Api::ShowProviderBillingModalEvent, + Db::ShowProviderLoginModalEvent => Api::ShowProviderLoginModalEvent, + Db::FlashUserInputErrorEvent => Api::FlashUserInputErrorEvent, + Db::FlashFileDownloadErrorEvent => Api::FlashFileDownloadErrorEvent, + } +} + +#[cfg(test)] +mod tests { + use super::*; + use strum::IntoEnumIterator; + + #[test] + fn round_trip_db_to_api() { + use strum::IntoEnumIterator; + for variant in Db::iter() { + let api = tauri_event_name_to_api(&variant); + let back = tauri_event_name_to_db(&api); + assert_eq!(variant, back); + } + } + + #[test] + fn round_trip_api_to_db() { + use strum::IntoEnumIterator; + for variant in Api::iter() { + let db = tauri_event_name_to_db(&variant); + let back = tauri_event_name_to_api(&db); + assert_eq!(variant, back); + } + } +} diff --git a/crates/schema/public/enums_db/Cargo.toml b/crates/schema/public/enums_db/Cargo.toml new file mode 100644 index 0000000000..40e9acb153 --- /dev/null +++ b/crates/schema/public/enums_db/Cargo.toml @@ -0,0 +1,50 @@ +[package] +name = "enums_db" +edition = "2021" +version = "0.0.1" +authors = [ + "Brandon Thomas ", + "Brandon Thomas ", +] +publish = false + +[package.metadata.cargo-udeps.ignore] +normal = ["workspace-build-acceleration"] + +[lib] +name = "enums_db" +path = "src/lib.rs" + +[features] +default = [] +utoipa = ["dep:utoipa"] + +[dependencies] +# Workspace hack (faster compile times) +workspace-build-acceleration.workspace = true + +# Internal +enums_shared.workspace = true + +# Serialization +serde.workspace = true +serde_derive.workspace = true + +# Database +sqlx = { version = "0.7.4", features = [ "mysql", "runtime-tokio-rustls", "chrono" ] } +sqlx-core = { version = "0.7.4" } +sqlx-mysql = { version = "0.7.4" } + +# API Documentation (optional — enabled by crates that need ToSchema on DB enums) +utoipa = { workspace = true, optional = true } + +# Enum utilities (EnumIter, EnumCount) +strum.workspace = true + +log.workspace = true + +[dev-dependencies] + +# Test serialization +serde_json.workspace = true +toml.workspace = true diff --git a/crates/schema/public/enums_db/src/by_table/audit_logs/audit_log_entity_action.rs b/crates/schema/public/enums_db/src/by_table/audit_logs/audit_log_entity_action.rs new file mode 100644 index 0000000000..7c40a9469d --- /dev/null +++ b/crates/schema/public/enums_db/src/by_table/audit_logs/audit_log_entity_action.rs @@ -0,0 +1,131 @@ +use strum::EnumCount; +use strum::EnumIter; + +/// Used in the `audit_logs` table in a `VARCHAR(32)` field named `entity_action`. +#[derive(Clone, Copy, Eq, PartialEq, Hash, Deserialize, Serialize, EnumIter, EnumCount)] +pub enum AuditLogEntityAction { + /// Create action + #[serde(rename = "create")] + Create, + + /// Edit action + #[serde(rename = "edit")] + Edit, + + /// Edit features (eg. user feature flags) + #[serde(rename = "edit_features")] + EditFeatures, + + /// Delete action + #[serde(rename = "delete")] + Delete, + + /// Create featured item + #[serde(rename = "featured_item_create")] + FeaturedItemCreate, + + /// Delete featured item + #[serde(rename = "featured_item_delete")] + FeaturedItemDelete, +} + +// TODO(bt, 2023-01-17): This desperately needs MySQL integration tests! +impl_enum_display_and_debug_using_to_str!(AuditLogEntityAction); +impl_mysql_enum_coders!(AuditLogEntityAction); +impl_mysql_from_row!(AuditLogEntityAction); + +/// NB: Legacy API for older code. +impl AuditLogEntityAction { + pub fn to_str(&self) -> &'static str { + match self { + Self::Create => "create", + Self::Edit => "edit", + Self::EditFeatures => "edit_features", + Self::Delete => "delete", + Self::FeaturedItemCreate => "featured_item_create", + Self::FeaturedItemDelete => "featured_item_delete", + } + } + + pub fn from_str(value: &str) -> Result { + match value { + "create" => Ok(Self::Create), + "edit" => Ok(Self::Edit), + "edit_features" => Ok(Self::EditFeatures), + "delete" => Ok(Self::Delete), + "featured_item_create" => Ok(Self::FeaturedItemCreate), + "featured_item_delete" => Ok(Self::FeaturedItemDelete), + _ => Err(format!("invalid value: {:?}", value)), + } + } +} + +#[cfg(test)] +mod tests { + use super::super::audit_log_entity_action::AuditLogEntityAction; + use enums_shared::test_helpers::assert_serialization; + + mod serde { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(AuditLogEntityAction::Create, "create"); + assert_serialization(AuditLogEntityAction::Edit, "edit"); + assert_serialization(AuditLogEntityAction::EditFeatures, "edit_features"); + assert_serialization(AuditLogEntityAction::Delete, "delete"); + assert_serialization(AuditLogEntityAction::FeaturedItemCreate, "featured_item_create"); + assert_serialization(AuditLogEntityAction::FeaturedItemDelete, "featured_item_delete"); + } + } + + mod impl_methods { + use super::*; + + #[test] + fn test_to_str() { + assert_eq!(AuditLogEntityAction::Create.to_str(), "create"); + assert_eq!(AuditLogEntityAction::Edit.to_str(), "edit"); + assert_eq!(AuditLogEntityAction::EditFeatures.to_str(), "edit_features"); + assert_eq!(AuditLogEntityAction::Delete.to_str(), "delete"); + assert_eq!(AuditLogEntityAction::FeaturedItemCreate.to_str(), "featured_item_create"); + assert_eq!(AuditLogEntityAction::FeaturedItemDelete.to_str(), "featured_item_delete"); + } + + #[test] + fn test_from_str() { + assert_eq!(AuditLogEntityAction::from_str("create").unwrap(), AuditLogEntityAction::Create); + assert_eq!(AuditLogEntityAction::from_str("edit").unwrap(), AuditLogEntityAction::Edit); + assert_eq!(AuditLogEntityAction::from_str("edit_features").unwrap(), AuditLogEntityAction::EditFeatures); + assert_eq!(AuditLogEntityAction::from_str("delete").unwrap(), AuditLogEntityAction::Delete); + assert_eq!(AuditLogEntityAction::from_str("featured_item_create").unwrap(), AuditLogEntityAction::FeaturedItemCreate); + assert_eq!(AuditLogEntityAction::from_str("featured_item_delete").unwrap(), AuditLogEntityAction::FeaturedItemDelete); + assert!(AuditLogEntityAction::from_str("foo").is_err()); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip() { + use strum::IntoEnumIterator; + for variant in AuditLogEntityAction::iter() { + assert_eq!(variant, AuditLogEntityAction::from_str(variant.to_str()).unwrap()); + assert_eq!(variant, AuditLogEntityAction::from_str(&format!("{}", variant)).unwrap()); + assert_eq!(variant, AuditLogEntityAction::from_str(&format!("{:?}", variant)).unwrap()); + } + } + + #[test] + fn serialized_length_ok_for_database() { + const MAX_LENGTH: usize = 32; // TODO(bt): Confirm database column width, then remove this comment. + use strum::IntoEnumIterator; + for variant in AuditLogEntityAction::iter() { + let serialized = variant.to_str(); + assert!(!serialized.is_empty(), "variant {:?} is too short", variant); + assert!(serialized.len() <= MAX_LENGTH, "variant {:?} is too long", variant); + } + } + } +} diff --git a/crates/schema/public/enums_db/src/by_table/audit_logs/audit_log_entity_type.rs b/crates/schema/public/enums_db/src/by_table/audit_logs/audit_log_entity_type.rs new file mode 100644 index 0000000000..21bf3b714d --- /dev/null +++ b/crates/schema/public/enums_db/src/by_table/audit_logs/audit_log_entity_type.rs @@ -0,0 +1,113 @@ +use strum::EnumCount; +use strum::EnumIter; + +/// Used in the `audit_logs` table in a `VARCHAR(32)` field named `entity_type`. +#[derive(Clone, Copy, Eq, PartialEq, Hash, Deserialize, Serialize, EnumIter, EnumCount)] +pub enum AuditLogEntityType { + /// Comment system + #[serde(rename = "comment")] + Comment, + + /// Media file + #[serde(rename = "media_file")] + MediaFile, + + /// Model weight + #[serde(rename = "model_weight")] + ModelWeight, + + /// User + #[serde(rename = "user")] + User, +} + +// TODO(bt, 2023-01-17): This desperately needs MySQL integration tests! +impl_enum_display_and_debug_using_to_str!(AuditLogEntityType); +impl_mysql_enum_coders!(AuditLogEntityType); +impl_mysql_from_row!(AuditLogEntityType); + +/// NB: Legacy API for older code. +impl AuditLogEntityType { + pub fn to_str(&self) -> &'static str { + match self { + Self::Comment => "comment", + Self::MediaFile => "media_file", + Self::ModelWeight => "model_weight", + Self::User => "user", + } + } + + pub fn from_str(value: &str) -> Result { + match value { + "comment" => Ok(Self::Comment), + "media_file" => Ok(Self::MediaFile), + "model_weight" => Ok(Self::ModelWeight), + "user" => Ok(Self::User), + _ => Err(format!("invalid value: {:?}", value)), + } + } +} + +#[cfg(test)] +mod tests { + use super::super::audit_log_entity_type::AuditLogEntityType; + use enums_shared::test_helpers::assert_serialization; + + mod serde { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(AuditLogEntityType::Comment, "comment"); + assert_serialization(AuditLogEntityType::MediaFile, "media_file"); + assert_serialization(AuditLogEntityType::ModelWeight, "model_weight"); + assert_serialization(AuditLogEntityType::User, "user"); + } + } + + mod impl_methods { + use super::*; + + #[test] + fn test_to_str() { + assert_eq!(AuditLogEntityType::Comment.to_str(), "comment"); + assert_eq!(AuditLogEntityType::MediaFile.to_str(), "media_file"); + assert_eq!(AuditLogEntityType::ModelWeight.to_str(), "model_weight"); + assert_eq!(AuditLogEntityType::User.to_str(), "user"); + } + + #[test] + fn test_from_str() { + assert_eq!(AuditLogEntityType::from_str("comment").unwrap(), AuditLogEntityType::Comment); + assert_eq!(AuditLogEntityType::from_str("media_file").unwrap(), AuditLogEntityType::MediaFile); + assert_eq!(AuditLogEntityType::from_str("model_weight").unwrap(), AuditLogEntityType::ModelWeight); + assert_eq!(AuditLogEntityType::from_str("user").unwrap(), AuditLogEntityType::User); + assert!(AuditLogEntityType::from_str("foo").is_err()); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip() { + use strum::IntoEnumIterator; + for variant in AuditLogEntityType::iter() { + assert_eq!(variant, AuditLogEntityType::from_str(variant.to_str()).unwrap()); + assert_eq!(variant, AuditLogEntityType::from_str(&format!("{}", variant)).unwrap()); + assert_eq!(variant, AuditLogEntityType::from_str(&format!("{:?}", variant)).unwrap()); + } + } + + #[test] + fn serialized_length_ok_for_database() { + const MAX_LENGTH: usize = 32; // TODO(bt): Confirm database column width, then remove this comment. + use strum::IntoEnumIterator; + for variant in AuditLogEntityType::iter() { + let serialized = variant.to_str(); + assert!(!serialized.is_empty(), "variant {:?} is too short", variant); + assert!(serialized.len() <= MAX_LENGTH, "variant {:?} is too long", variant); + } + } + } +} diff --git a/crates/schema/public/enums_db/src/by_table/audit_logs/mod.rs b/crates/schema/public/enums_db/src/by_table/audit_logs/mod.rs new file mode 100644 index 0000000000..9de3fca75c --- /dev/null +++ b/crates/schema/public/enums_db/src/by_table/audit_logs/mod.rs @@ -0,0 +1,2 @@ +pub mod audit_log_entity_action; +pub mod audit_log_entity_type; diff --git a/crates/schema/public/enums_db/src/by_table/batch_generations/batch_generation_entity_type.rs b/crates/schema/public/enums_db/src/by_table/batch_generations/batch_generation_entity_type.rs new file mode 100644 index 0000000000..e3fbd1c9a7 --- /dev/null +++ b/crates/schema/public/enums_db/src/by_table/batch_generations/batch_generation_entity_type.rs @@ -0,0 +1,88 @@ +use strum::EnumCount; +use strum::EnumIter; + +/// Used in the `batch_generations` table in a `VARCHAR(32)` field named `entity_type`. +#[derive(Clone, Copy, Eq, PartialEq, Hash, Deserialize, Serialize, Ord, PartialOrd, EnumIter, EnumCount)] +pub enum BatchGenerationEntityType { + /// Media files + /// This will probably be the only type supported, but we'll leave the possibility of future types. + #[serde(rename = "media_file")] + MediaFile, +} + +// TODO(bt, 2023-01-17): This desperately needs MySQL integration tests! +impl_enum_display_and_debug_using_to_str!(BatchGenerationEntityType); +impl_mysql_enum_coders!(BatchGenerationEntityType); +impl_mysql_from_row!(BatchGenerationEntityType); + +/// NB: Legacy API for older code. +impl BatchGenerationEntityType { + pub fn to_str(&self) -> &'static str { + match self { + Self::MediaFile => "media_file", + } + } + + pub fn from_str(value: &str) -> Result { + match value { + "media_file" => Ok(Self::MediaFile), + _ => Err(format!("invalid value: {:?}", value)), + } + } + +} + +#[cfg(test)] +mod tests { + use super::super::batch_generation_entity_type::BatchGenerationEntityType; + use enums_shared::test_helpers::assert_serialization; + + mod serde { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(BatchGenerationEntityType::MediaFile, "media_file"); + } + } + + mod impl_methods { + use super::*; + + #[test] + fn to_str() { + assert_eq!(BatchGenerationEntityType::MediaFile.to_str(), "media_file"); + } + + #[test] + fn from_str() { + assert_eq!(BatchGenerationEntityType::from_str("media_file").unwrap(), BatchGenerationEntityType::MediaFile); + assert!(BatchGenerationEntityType::from_str("foo").is_err()); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip() { + use strum::IntoEnumIterator; + for variant in BatchGenerationEntityType::iter() { + assert_eq!(variant, BatchGenerationEntityType::from_str(variant.to_str()).unwrap()); + assert_eq!(variant, BatchGenerationEntityType::from_str(&format!("{}", variant)).unwrap()); + assert_eq!(variant, BatchGenerationEntityType::from_str(&format!("{:?}", variant)).unwrap()); + } + } + + #[test] + fn serialized_length_ok_for_database() { + const MAX_LENGTH: usize = 32; // TODO(bt): Confirm database column width, then remove this comment. + use strum::IntoEnumIterator; + for variant in BatchGenerationEntityType::iter() { + let serialized = variant.to_str(); + assert!(!serialized.is_empty(), "variant {:?} is too short", variant); + assert!(serialized.len() <= MAX_LENGTH, "variant {:?} is too long", variant); + } + } + } +} diff --git a/crates/schema/public/enums_db/src/by_table/batch_generations/mod.rs b/crates/schema/public/enums_db/src/by_table/batch_generations/mod.rs new file mode 100644 index 0000000000..6feec4da5f --- /dev/null +++ b/crates/schema/public/enums_db/src/by_table/batch_generations/mod.rs @@ -0,0 +1 @@ +pub mod batch_generation_entity_type; diff --git a/crates/schema/public/enums_db/src/by_table/beta_keys/beta_key_product.rs b/crates/schema/public/enums_db/src/by_table/beta_keys/beta_key_product.rs new file mode 100644 index 0000000000..ef945796f3 --- /dev/null +++ b/crates/schema/public/enums_db/src/by_table/beta_keys/beta_key_product.rs @@ -0,0 +1,88 @@ +use strum::EnumCount; +use strum::EnumIter; + +/// Used in the `batch_generations` table in a `VARCHAR(32)` field named `entity_type`. +#[derive(Clone, Copy, Eq, PartialEq, Hash, Deserialize, Serialize, Ord, PartialOrd, EnumIter, EnumCount)] +pub enum BetaKeyProduct { + /// Media files + /// This will probably be the only type supported, but we'll leave the possibility of future types. + #[serde(rename = "studio")] + Studio, +} + +// TODO(bt, 2023-01-17): This desperately needs MySQL integration tests! +impl_enum_display_and_debug_using_to_str!(BetaKeyProduct); +impl_mysql_enum_coders!(BetaKeyProduct); +impl_mysql_from_row!(BetaKeyProduct); + +/// NB: Legacy API for older code. +impl BetaKeyProduct { + pub fn to_str(&self) -> &'static str { + match self { + Self::Studio => "studio", + } + } + + pub fn from_str(value: &str) -> Result { + match value { + "studio" => Ok(Self::Studio), + _ => Err(format!("invalid value: {:?}", value)), + } + } + +} + +#[cfg(test)] +mod tests { + use super::super::beta_key_product::BetaKeyProduct; + use enums_shared::test_helpers::assert_serialization; + + mod serde { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(BetaKeyProduct::Studio, "studio"); + } + } + + mod impl_methods { + use super::*; + + #[test] + fn to_str() { + assert_eq!(BetaKeyProduct::Studio.to_str(), "studio"); + } + + #[test] + fn from_str() { + assert_eq!(BetaKeyProduct::from_str("studio").unwrap(), BetaKeyProduct::Studio); + assert!(BetaKeyProduct::from_str("foo").is_err()); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip() { + use strum::IntoEnumIterator; + for variant in BetaKeyProduct::iter() { + assert_eq!(variant, BetaKeyProduct::from_str(variant.to_str()).unwrap()); + assert_eq!(variant, BetaKeyProduct::from_str(&format!("{}", variant)).unwrap()); + assert_eq!(variant, BetaKeyProduct::from_str(&format!("{:?}", variant)).unwrap()); + } + } + + #[test] + fn serialized_length_ok_for_database() { + const MAX_LENGTH: usize = 32; // TODO(bt): Confirm database column width, then remove this comment. + use strum::IntoEnumIterator; + for variant in BetaKeyProduct::iter() { + let serialized = variant.to_str(); + assert!(!serialized.is_empty(), "variant {:?} is too short", variant); + assert!(serialized.len() <= MAX_LENGTH, "variant {:?} is too long", variant); + } + } + } +} diff --git a/crates/schema/public/enums_db/src/by_table/beta_keys/mod.rs b/crates/schema/public/enums_db/src/by_table/beta_keys/mod.rs new file mode 100644 index 0000000000..1e30a227d3 --- /dev/null +++ b/crates/schema/public/enums_db/src/by_table/beta_keys/mod.rs @@ -0,0 +1 @@ +pub mod beta_key_product; diff --git a/crates/schema/public/enums_db/src/by_table/comments/comment_entity_type.rs b/crates/schema/public/enums_db/src/by_table/comments/comment_entity_type.rs new file mode 100644 index 0000000000..e313219739 --- /dev/null +++ b/crates/schema/public/enums_db/src/by_table/comments/comment_entity_type.rs @@ -0,0 +1,140 @@ +use strum::EnumCount; +use strum::EnumIter; + +/// Used in the `comments` table in a `VARCHAR(32)` field named `entity_type`. +#[derive(Clone, Copy, Eq, PartialEq, Hash, Deserialize, Serialize, EnumIter, EnumCount)] +pub enum CommentEntityType { + /// User + #[serde(rename = "user")] + User, + + /// Media files + #[serde(rename = "media_file")] + MediaFile, + + /// Model weights + #[serde(rename = "model_weight")] + ModelWeight, + + /// TTS model (architecture does not matter) + #[serde(rename = "tts_model")] + TtsModel, + + /// TTS result (architecture does not matter) + #[serde(rename = "tts_result")] + TtsResult, + + /// W2L template + #[serde(rename = "w2l_template")] + W2lTemplate, + + /// W2L result + #[serde(rename = "w2l_result")] + W2lResult, +} + +// TODO(bt, 2023-01-17): This desperately needs MySQL integration tests! +impl_enum_display_and_debug_using_to_str!(CommentEntityType); +impl_mysql_enum_coders!(CommentEntityType); +impl_mysql_from_row!(CommentEntityType); + +/// NB: Legacy API for older code. +impl CommentEntityType { + pub fn to_str(&self) -> &'static str { + match self { + Self::User => "user", + Self::MediaFile => "media_file", + Self::ModelWeight => "model_weight", + Self::TtsModel => "tts_model", + Self::TtsResult => "tts_result", + Self::W2lTemplate => "w2l_template", + Self::W2lResult => "w2l_result", + } + } + + pub fn from_str(value: &str) -> Result { + match value { + "user" => Ok(Self::User), + "media_file" => Ok(Self::MediaFile), + "model_weight" => Ok(Self::ModelWeight), + "tts_model" => Ok(Self::TtsModel), + "tts_result" => Ok(Self::TtsResult), + "w2l_template" => Ok(Self::W2lTemplate), + "w2l_result" => Ok(Self::W2lResult), + _ => Err(format!("invalid value: {:?}", value)), + } + } +} + +#[cfg(test)] +mod tests { + use super::super::comment_entity_type::CommentEntityType; + use enums_shared::test_helpers::assert_serialization; + + mod serde { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(CommentEntityType::User, "user"); + assert_serialization(CommentEntityType::MediaFile, "media_file"); + assert_serialization(CommentEntityType::ModelWeight, "model_weight"); + assert_serialization(CommentEntityType::TtsModel, "tts_model"); + assert_serialization(CommentEntityType::TtsResult, "tts_result"); + assert_serialization(CommentEntityType::W2lTemplate, "w2l_template"); + assert_serialization(CommentEntityType::W2lResult, "w2l_result"); + } + } + + mod impl_methods { + use super::*; + + #[test] + fn test_to_str() { + assert_eq!(CommentEntityType::User.to_str(), "user"); + assert_eq!(CommentEntityType::MediaFile.to_str(), "media_file"); + assert_eq!(CommentEntityType::ModelWeight.to_str(), "model_weight"); + assert_eq!(CommentEntityType::TtsModel.to_str(), "tts_model"); + assert_eq!(CommentEntityType::TtsResult.to_str(), "tts_result"); + assert_eq!(CommentEntityType::W2lTemplate.to_str(), "w2l_template"); + assert_eq!(CommentEntityType::W2lResult.to_str(), "w2l_result"); + } + + #[test] + fn test_from_str() { + assert_eq!(CommentEntityType::from_str("user").unwrap(), CommentEntityType::User); + assert_eq!(CommentEntityType::from_str("media_file").unwrap(), CommentEntityType::MediaFile); + assert_eq!(CommentEntityType::from_str("model_weight").unwrap(), CommentEntityType::ModelWeight); + assert_eq!(CommentEntityType::from_str("tts_model").unwrap(), CommentEntityType::TtsModel); + assert_eq!(CommentEntityType::from_str("tts_result").unwrap(), CommentEntityType::TtsResult); + assert_eq!(CommentEntityType::from_str("w2l_template").unwrap(), CommentEntityType::W2lTemplate); + assert_eq!(CommentEntityType::from_str("w2l_result").unwrap(), CommentEntityType::W2lResult); + assert!(CommentEntityType::from_str("foo").is_err()); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip() { + use strum::IntoEnumIterator; + for variant in CommentEntityType::iter() { + assert_eq!(variant, CommentEntityType::from_str(variant.to_str()).unwrap()); + assert_eq!(variant, CommentEntityType::from_str(&format!("{}", variant)).unwrap()); + assert_eq!(variant, CommentEntityType::from_str(&format!("{:?}", variant)).unwrap()); + } + } + + #[test] + fn serialized_length_ok_for_database() { + const MAX_LENGTH: usize = 32; // TODO(bt): Confirm database column width, then remove this comment. + use strum::IntoEnumIterator; + for variant in CommentEntityType::iter() { + let serialized = variant.to_str(); + assert!(!serialized.is_empty(), "variant {:?} is too short", variant); + assert!(serialized.len() <= MAX_LENGTH, "variant {:?} is too long", variant); + } + } + } +} diff --git a/crates/schema/public/enums_db/src/by_table/comments/mod.rs b/crates/schema/public/enums_db/src/by_table/comments/mod.rs new file mode 100644 index 0000000000..e30377b8e0 --- /dev/null +++ b/crates/schema/public/enums_db/src/by_table/comments/mod.rs @@ -0,0 +1 @@ +pub mod comment_entity_type; diff --git a/crates/schema/public/enums_db/src/by_table/email_sender_jobs/email_category.rs b/crates/schema/public/enums_db/src/by_table/email_sender_jobs/email_category.rs new file mode 100644 index 0000000000..245b4942a0 --- /dev/null +++ b/crates/schema/public/enums_db/src/by_table/email_sender_jobs/email_category.rs @@ -0,0 +1,96 @@ +use strum::EnumCount; +use strum::EnumIter; + +/// Used in the `email_sender_jobs` table in `VARCHAR(32)` field `id_category`. +/// +/// This denotes the type of email being sent. +/// +/// DO NOT CHANGE VALUES WITHOUT A MIGRATION STRATEGY. +#[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, Deserialize, Serialize, EnumIter, EnumCount)] +pub enum EmailCategory { + /// User is recently registered + #[serde(rename = "welcome")] + Welcome, + + /// User is resetting their password + #[serde(rename = "password_reset")] + PasswordReset, +} + +// TODO(bt, 2022-12-21): This desperately needs MySQL integration tests! +impl_enum_display_and_debug_using_to_str!(EmailCategory); +impl_mysql_enum_coders!(EmailCategory); +impl_mysql_from_row!(EmailCategory); + +/// NB: Legacy API for older code. +impl EmailCategory { + pub fn to_str(&self) -> &'static str { + match self { + Self::Welcome => "welcome", + Self::PasswordReset => "password_reset", + } + } + + pub fn from_str(value: &str) -> Result { + match value { + "welcome" => Ok(Self::Welcome), + "password_reset" => Ok(Self::PasswordReset), + _ => Err(format!("invalid value: {:?}", value)), + } + } + +} + +#[cfg(test)] +mod tests { + use super::super::email_category::EmailCategory; + use enums_shared::test_helpers::assert_serialization; + + mod explicit_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(EmailCategory::Welcome, "welcome"); + assert_serialization(EmailCategory::PasswordReset, "password_reset"); + } + + #[test] + fn to_str() { + assert_eq!(EmailCategory::Welcome.to_str(), "welcome"); + assert_eq!(EmailCategory::PasswordReset.to_str(), "password_reset"); + } + + #[test] + fn from_str() { + assert_eq!(EmailCategory::from_str("welcome").unwrap(), EmailCategory::Welcome); + assert_eq!(EmailCategory::from_str("password_reset").unwrap(), EmailCategory::PasswordReset); + } + + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip() { + use strum::IntoEnumIterator; + for variant in EmailCategory::iter() { + assert_eq!(variant, EmailCategory::from_str(variant.to_str()).unwrap()); + assert_eq!(variant, EmailCategory::from_str(&format!("{}", variant)).unwrap()); + assert_eq!(variant, EmailCategory::from_str(&format!("{:?}", variant)).unwrap()); + } + } + + #[test] + fn serialized_length_ok_for_database() { + const MAX_LENGTH: usize = 32; // TODO(bt): Confirm database column width, then remove this comment. + use strum::IntoEnumIterator; + for variant in EmailCategory::iter() { + let serialized = variant.to_str(); + assert!(!serialized.is_empty(), "variant {:?} is too short", variant); + assert!(serialized.len() <= MAX_LENGTH, "variant {:?} is too long", variant); + } + } + } +} diff --git a/crates/schema/public/enums_db/src/by_table/email_sender_jobs/mod.rs b/crates/schema/public/enums_db/src/by_table/email_sender_jobs/mod.rs new file mode 100644 index 0000000000..18d5731795 --- /dev/null +++ b/crates/schema/public/enums_db/src/by_table/email_sender_jobs/mod.rs @@ -0,0 +1 @@ +pub mod email_category; diff --git a/crates/schema/public/enums_db/src/by_table/entity_stats/mod.rs b/crates/schema/public/enums_db/src/by_table/entity_stats/mod.rs new file mode 100644 index 0000000000..58a4a07b90 --- /dev/null +++ b/crates/schema/public/enums_db/src/by_table/entity_stats/mod.rs @@ -0,0 +1 @@ +pub mod stats_entity_type; diff --git a/crates/schema/public/enums_db/src/by_table/entity_stats/stats_entity_type.rs b/crates/schema/public/enums_db/src/by_table/entity_stats/stats_entity_type.rs new file mode 100644 index 0000000000..054f9c7f86 --- /dev/null +++ b/crates/schema/public/enums_db/src/by_table/entity_stats/stats_entity_type.rs @@ -0,0 +1,102 @@ +use strum::EnumCount; +use strum::EnumIter; + +/// Used in the `user_stats` table in a `VARCHAR(32)` field named `entity_type`. +#[derive(Clone, Copy, Eq, PartialEq, Hash, Deserialize, Serialize, Ord, PartialOrd, EnumIter, EnumCount)] +pub enum StatsEntityType { + /// Comment + #[serde(rename = "comment")] + Comment, + + /// MediaFile + #[serde(rename = "media_file")] + MediaFile, + + /// ModelWeight (the new way to store models) + #[serde(rename = "model_weight")] + ModelWeight, +} + +// TODO(bt, 2023-01-17): This desperately needs MySQL integration tests! +impl_enum_display_and_debug_using_to_str!(StatsEntityType); +impl_mysql_enum_coders!(StatsEntityType); +impl_mysql_from_row!(StatsEntityType); + +/// NB: Legacy API for older code. +impl StatsEntityType { + pub fn to_str(&self) -> &'static str { + match self { + Self::Comment => "comment", + Self::MediaFile => "media_file", + Self::ModelWeight => "model_weight", + } + } + + pub fn from_str(value: &str) -> Result { + match value { + "comment" => Ok(Self::Comment), + "media_file" => Ok(Self::MediaFile), + "model_weight" => Ok(Self::ModelWeight), + _ => Err(format!("invalid value: {:?}", value)), + } + } + +} + +#[cfg(test)] +mod tests { + use super::super::stats_entity_type::StatsEntityType; + use enums_shared::test_helpers::assert_serialization; + + mod explicit_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(StatsEntityType::Comment, "comment"); + assert_serialization(StatsEntityType::MediaFile, "media_file"); + assert_serialization(StatsEntityType::ModelWeight, "model_weight"); + } + + #[test] + fn test_to_str() { + assert_eq!(StatsEntityType::Comment.to_str(), "comment"); + assert_eq!(StatsEntityType::MediaFile.to_str(), "media_file"); + assert_eq!(StatsEntityType::ModelWeight.to_str(), "model_weight"); + } + + #[test] + fn test_from_str() { + assert_eq!(StatsEntityType::from_str("comment").unwrap(), StatsEntityType::Comment); + assert_eq!(StatsEntityType::from_str("media_file").unwrap(), StatsEntityType::MediaFile); + assert_eq!(StatsEntityType::from_str("model_weight").unwrap(), StatsEntityType::ModelWeight); + assert!(StatsEntityType::from_str("foo").is_err()); + } + + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip() { + use strum::IntoEnumIterator; + for variant in StatsEntityType::iter() { + assert_eq!(variant, StatsEntityType::from_str(variant.to_str()).unwrap()); + assert_eq!(variant, StatsEntityType::from_str(&format!("{}", variant)).unwrap()); + assert_eq!(variant, StatsEntityType::from_str(&format!("{:?}", variant)).unwrap()); + } + } + + #[test] + fn serialized_length_ok_for_database() { + const MAX_LENGTH: usize = 32; // TODO(bt): Confirm database column width, then remove this comment. + use strum::IntoEnumIterator; + for variant in StatsEntityType::iter() { + let serialized = variant.to_str(); + assert!(!serialized.is_empty(), "variant {:?} is too short", variant); + assert!(serialized.len() <= MAX_LENGTH, "variant {:?} is too long", variant); + } + } + } +} diff --git a/crates/schema/public/enums_db/src/by_table/featured_items/featured_item_entity_type.rs b/crates/schema/public/enums_db/src/by_table/featured_items/featured_item_entity_type.rs new file mode 100644 index 0000000000..82d6144fcd --- /dev/null +++ b/crates/schema/public/enums_db/src/by_table/featured_items/featured_item_entity_type.rs @@ -0,0 +1,105 @@ +use strum::EnumCount; +use strum::EnumIter; + +/// Used in the `user_bookmarks` table in a `VARCHAR(32)` field named `entity_type`. +#[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, Deserialize, Serialize, EnumIter, EnumCount)] +pub enum FeaturedItemEntityType { + /// MediaFile + #[serde(rename = "media_file")] + MediaFile, + + /// ModelWeight (the new way to store models) + #[serde(rename = "model_weight")] + ModelWeight, + + /// User + #[serde(rename = "user")] + User, +} + +// TODO(bt, 2023-01-17): This desperately needs MySQL integration tests! +impl_enum_display_and_debug_using_to_str!(FeaturedItemEntityType); +impl_mysql_enum_coders!(FeaturedItemEntityType); +impl_mysql_from_row!(FeaturedItemEntityType); + +/// NB: Legacy API for older code. +impl FeaturedItemEntityType { + pub fn to_str(&self) -> &'static str { + match self { + Self::MediaFile => "media_file", + Self::ModelWeight => "model_weight", + Self::User => "user", + } + } + + pub fn from_str(value: &str) -> Result { + match value { + "media_file" => Ok(Self::MediaFile), + "model_weight" => Ok(Self::ModelWeight), + "user" => Ok(Self::User), + _ => Err(format!("invalid value: {:?}", value)), + } + } + +} + +#[cfg(test)] +mod tests { + use super::super::featured_item_entity_type::FeaturedItemEntityType; + use enums_shared::test_helpers::assert_serialization; + + mod serde { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(FeaturedItemEntityType::MediaFile, "media_file"); + assert_serialization(FeaturedItemEntityType::ModelWeight, "model_weight"); + assert_serialization(FeaturedItemEntityType::User, "user"); + } + } + + mod impl_methods { + use super::*; + + #[test] + fn test_to_str() { + assert_eq!(FeaturedItemEntityType::MediaFile.to_str(), "media_file"); + assert_eq!(FeaturedItemEntityType::ModelWeight.to_str(), "model_weight"); + assert_eq!(FeaturedItemEntityType::User.to_str(), "user"); + } + + #[test] + fn test_from_str() { + assert_eq!(FeaturedItemEntityType::from_str("media_file").unwrap(), FeaturedItemEntityType::MediaFile); + assert_eq!(FeaturedItemEntityType::from_str("model_weight").unwrap(), FeaturedItemEntityType::ModelWeight); + assert_eq!(FeaturedItemEntityType::from_str("user").unwrap(), FeaturedItemEntityType::User); + assert!(FeaturedItemEntityType::from_str("foo").is_err()); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip() { + use strum::IntoEnumIterator; + for variant in FeaturedItemEntityType::iter() { + assert_eq!(variant, FeaturedItemEntityType::from_str(variant.to_str()).unwrap()); + assert_eq!(variant, FeaturedItemEntityType::from_str(&format!("{}", variant)).unwrap()); + assert_eq!(variant, FeaturedItemEntityType::from_str(&format!("{:?}", variant)).unwrap()); + } + } + + #[test] + fn serialized_length_ok_for_database() { + use strum::IntoEnumIterator; + const MAX_LENGTH : usize = 32; + for variant in FeaturedItemEntityType::iter() { + let serialized = variant.to_str(); + assert!(serialized.len() > 0, "variant {:?} is too short", variant); + assert!(serialized.len() <= MAX_LENGTH, "variant {:?} is too long", variant); + } + } + } +} diff --git a/crates/schema/public/enums_db/src/by_table/featured_items/mod.rs b/crates/schema/public/enums_db/src/by_table/featured_items/mod.rs new file mode 100644 index 0000000000..61e791bb90 --- /dev/null +++ b/crates/schema/public/enums_db/src/by_table/featured_items/mod.rs @@ -0,0 +1 @@ +pub mod featured_item_entity_type; diff --git a/crates/schema/public/enums_db/src/by_table/generic_download_jobs/generic_download_type.rs b/crates/schema/public/enums_db/src/by_table/generic_download_jobs/generic_download_type.rs new file mode 100644 index 0000000000..7ff344ee06 --- /dev/null +++ b/crates/schema/public/enums_db/src/by_table/generic_download_jobs/generic_download_type.rs @@ -0,0 +1,158 @@ +use strum::EnumCount; +use strum::EnumIter; + +// TODO: Use macro-derived impls + +/// Our "generic downloads" pipeline supports a wide variety of ML models and other media. +/// They are serialized in the database table `generic_download_jobs` as a VARCHAR(32). +/// +/// Each type of download is identified by the following enum variants. +/// These types are present in the HTTP API and database columns as serialized here. +/// +/// DO NOT CHANGE VALUES WITHOUT A MIGRATION STRATEGY. +#[derive(Clone, Copy, Eq, PartialEq, Debug, Deserialize, Serialize, Hash, Ord, PartialOrd, EnumIter, EnumCount)] +#[cfg_attr(feature = "database", derive(sqlx::Type))] +pub enum GenericDownloadType { + /// NB: Note - this is hifigan for Tacotron2. + /// Some work will be needed to unify this with other hifigan types. + #[serde(rename = "hifigan")] + #[cfg_attr(feature = "database", sqlx(rename = "hifigan"))] + HifiGan, + + /// NB: Note - this is hifigan for SoftVC (our internal codename is "rocketvc"). + /// Some work will need to be done to unify this with other hifigan types. + #[serde(rename = "hifigan_rocket_vc")] + #[cfg_attr(feature = "database", sqlx(rename = "hifigan_rocket_vc"))] + HifiGanRocketVc, + + /// NB: Note - this is hifigan for SoVitsSvc + /// Some work will need to be done to unify this with other hifigan types. + #[serde(rename = "hifigan_so_vits_svc")] + #[cfg_attr(feature = "database", sqlx(rename = "hifigan_so_vits_svc"))] + HifiGanSoVitsSvc, + + //#[serde(rename = "melgan_vocodes")] + //#[sqlx(rename = "melgan_vocodes")] + //MelGanVocodes, + + /// NB: Our external-facing name for "softvc" is rocketvc. + /// I wish we could stop being stupid about this. + #[serde(rename = "rocket_vc")] + #[cfg_attr(feature = "database", sqlx(rename = "rocket_vc"))] + RocketVc, + + /// RVC (v2) voice conversion models + #[serde(rename = "rvc_v2")] + #[cfg_attr(feature = "database", sqlx(rename = "rvc_v2"))] + RvcV2, + + /// so-vits-svc voice conversion models + #[serde(rename = "so_vits_svc")] + #[cfg_attr(feature = "database", sqlx(rename = "so_vits_svc"))] + SoVitsSvc, + + /// Tacotron TTS models. + #[serde(rename = "tacotron2")] + #[cfg_attr(feature = "database", sqlx(rename = "tacotron2"))] + Tacotron2, + + /// VITS TTS models. + #[serde(rename = "vits")] + #[cfg_attr(feature = "database", sqlx(rename = "vits"))] + Vits, +} + +/// NB: Legacy API for older code. +impl GenericDownloadType { + pub fn to_str(&self) -> &'static str { + match self { + Self::HifiGan => "hifigan", + Self::HifiGanRocketVc => "hifigan_rocket_vc", + Self::HifiGanSoVitsSvc => "hifigan_so_vits_svc", + Self::RocketVc => "rocket_vc", + Self::RvcV2 => "rvc_v2", + Self::SoVitsSvc => "so_vits_svc", + Self::Tacotron2 => "tacotron2", + Self::Vits => "vits", + } + } + + pub fn from_str(value: &str) -> Result { + match value { + "hifigan" => Ok(Self::HifiGan), + "hifigan_rocket_vc" => Ok(Self::HifiGanRocketVc), + "hifigan_so_vits_svc" => Ok(Self::HifiGanSoVitsSvc), + "rocket_vc" => Ok(Self::RocketVc), + "rvc_v2" => Ok(Self::RvcV2), + "so_vits_svc" => Ok(Self::SoVitsSvc), + "tacotron2" => Ok(Self::Tacotron2), + "vits" => Ok(Self::Vits), + _ => Err(format!("invalid value: {:?}", value)), + } + } +} + +#[cfg(test)] +mod tests { + use super::super::generic_download_type::GenericDownloadType; + use enums_shared::test_helpers::assert_serialization; + + #[test] + fn test_serialization() { + assert_serialization(GenericDownloadType::HifiGan, "hifigan"); + assert_serialization(GenericDownloadType::HifiGanRocketVc, "hifigan_rocket_vc"); + assert_serialization(GenericDownloadType::HifiGanSoVitsSvc, "hifigan_so_vits_svc"); + assert_serialization(GenericDownloadType::RocketVc, "rocket_vc"); + assert_serialization(GenericDownloadType::RvcV2, "rvc_v2"); + assert_serialization(GenericDownloadType::SoVitsSvc, "so_vits_svc"); + assert_serialization(GenericDownloadType::Tacotron2, "tacotron2"); + assert_serialization(GenericDownloadType::Vits, "vits"); + } + + #[test] + fn to_str() { + assert_eq!(GenericDownloadType::HifiGan.to_str(), "hifigan"); + assert_eq!(GenericDownloadType::HifiGanRocketVc.to_str(), "hifigan_rocket_vc"); + assert_eq!(GenericDownloadType::HifiGanSoVitsSvc.to_str(), "hifigan_so_vits_svc"); + assert_eq!(GenericDownloadType::RocketVc.to_str(), "rocket_vc"); + assert_eq!(GenericDownloadType::RvcV2.to_str(), "rvc_v2"); + assert_eq!(GenericDownloadType::SoVitsSvc.to_str(), "so_vits_svc"); + assert_eq!(GenericDownloadType::Tacotron2.to_str(), "tacotron2"); + assert_eq!(GenericDownloadType::Vits.to_str(), "vits"); + } + + #[test] + fn from_str() { + assert_eq!(GenericDownloadType::from_str("hifigan").unwrap(), GenericDownloadType::HifiGan); + assert_eq!(GenericDownloadType::from_str("hifigan_rocket_vc").unwrap(), GenericDownloadType::HifiGanRocketVc); + assert_eq!(GenericDownloadType::from_str("hifigan_so_vits_svc").unwrap(), GenericDownloadType::HifiGanSoVitsSvc); + assert_eq!(GenericDownloadType::from_str("rocket_vc").unwrap(), GenericDownloadType::RocketVc); + assert_eq!(GenericDownloadType::from_str("rvc_v2").unwrap(), GenericDownloadType::RvcV2); + assert_eq!(GenericDownloadType::from_str("so_vits_svc").unwrap(), GenericDownloadType::SoVitsSvc); + assert_eq!(GenericDownloadType::from_str("tacotron2").unwrap(), GenericDownloadType::Tacotron2); + assert_eq!(GenericDownloadType::from_str("vits").unwrap(), GenericDownloadType::Vits); + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip() { + use strum::IntoEnumIterator; + for variant in GenericDownloadType::iter() { + assert_eq!(variant, GenericDownloadType::from_str(variant.to_str()).unwrap()); + } + } + + #[test] + fn serialized_length_ok_for_database() { + const MAX_LENGTH: usize = 32; // TODO(bt): Confirm database column width, then remove this comment. + use strum::IntoEnumIterator; + for variant in GenericDownloadType::iter() { + let serialized = variant.to_str(); + assert!(!serialized.is_empty(), "variant {:?} is too short", variant); + assert!(serialized.len() <= MAX_LENGTH, "variant {:?} is too long", variant); + } + } + } +} diff --git a/crates/schema/public/enums_db/src/by_table/generic_download_jobs/mod.rs b/crates/schema/public/enums_db/src/by_table/generic_download_jobs/mod.rs new file mode 100644 index 0000000000..40d1e08d44 --- /dev/null +++ b/crates/schema/public/enums_db/src/by_table/generic_download_jobs/mod.rs @@ -0,0 +1 @@ +pub mod generic_download_type; diff --git a/crates/schema/public/enums_db/src/by_table/generic_inference_jobs/frontend_failure_category.rs b/crates/schema/public/enums_db/src/by_table/generic_inference_jobs/frontend_failure_category.rs new file mode 100644 index 0000000000..8bb440971e --- /dev/null +++ b/crates/schema/public/enums_db/src/by_table/generic_inference_jobs/frontend_failure_category.rs @@ -0,0 +1,228 @@ +use strum::EnumCount; +use strum::EnumIter; + +/// Used in the `generic_inference_jobs` table in `VARCHAR(32)` field `frontend_failure_category`. +/// +/// When jobs fail (permanently or transiently), we need to inform the frontend of the reason, +/// because perhaps there's something the user can do to change their input. +/// +/// The previous "VARCHAR(32) failure_reason" column was a text-based message that could not be +/// localized or made user friendly. This `frontend_failure_category` exists to provide well-defined +/// failure categories to the frontend that can easily be localized and indicated consistently in +/// the UI. +/// +/// Another benefit is that we'll surface all of the various types of failure and perhaps eventually +/// come to handle some in a cross-cutting way. +/// +/// YOU CAN ADD NEW VALUES, BUT DO NOT CHANGE EXISTING VALUES WITHOUT A MIGRATION STRATEGY. +#[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, Deserialize, Serialize, EnumIter, EnumCount)] +pub enum FrontendFailureCategory { + /// When a face is not detected in the image used for animation. + /// For SadTalker (and possibly Wav2Lip) + #[serde(rename = "face_not_detected")] + FaceNotDetected, + + /// The user stepped away from their device and expected the workload to finish. + /// Some workloads require that the user keep their browser open. + #[serde(rename = "keep_alive_elapsed")] + KeepAliveElapsed, + + /// This is mostly for developers -- a feature isn't complete somewhere in the code. + /// Big oops if errors of this class make it to production. + #[serde(rename = "not_yet_implemented")] + NotYetImplemented, + + /// Tell the user that some kind of transient error happened. They don't need to know + /// exactly what happened. We'll retry their workload in any case. + #[serde(rename = "retryable_worker_error")] + RetryableWorkerError, + + /// Model content rules were violated + /// Eg. Seedance 2 will report: "your input text violates platform rules. please modify and try again" + #[serde(rename = "model_rules_violation")] + ModelRulesViolation, + + /// Model content violation + /// e.g. "Your uploaded image violates platform rules. Please modify and try again." (seedance2pro) + /// Model content rules prohibit the uploaded image. + #[serde(rename = "rule_bans_user_image")] + RuleBansUserImage, + + /// Model content violation + /// Model content rules prohibit user uploaded images containing faces (Seedance 2.0) + /// e.g. "The generated video did not pass review. Credits will not be deducted." (seedance2pro) + #[serde(rename = "rule_bans_user_image_with_faces")] + RuleBansUserImageWithFaces, + + /// Model content violation + /// Model content rules prohibit the user's given text prompt (this fails early). + /// e.g. "The generated video did not pass review. Credits will not be deducted." (seedance2pro) + #[serde(rename = "rule_bans_user_text_prompt")] + RuleBansUserTextPrompt, + + /// Model content violation + /// Model content rules prohibit user content. (I think this check happens early.) + /// e.g. "Content violates platform rules. Please modify and try again." (seedance2pro) + #[serde(rename = "rule_bans_user_content")] + RuleBansUserContent, + + /// Model content violation + /// The video didn't pass checks after it finished generation (this fails at the very end of the generation). + /// e.g. "The generated video did not pass review. Credits will not be deducted." (seedance2pro) + #[serde(rename = "rule_bans_generated_video")] + RuleBansGeneratedVideo, + + /// Model content violation + /// The audio (even in video!) didn't pass checks after it finished generation (this fails at the very end of the generation). + /// e.g. "The generated audio violates platform rules. Please adjust your prompt or images and try again." (seedance2pro) + #[serde(rename = "rule_bans_generated_audio")] + RuleBansGeneratedAudio, + + /// Model content violation + /// The content didn't pass checks after it finished generation (this fails at the very end of the generation). + /// e.g. "The generated content violates platform rules. Please adjust your prompt or images and try again." (seedance2pro) + #[serde(rename = "rule_bans_generated_content")] + RuleBansGeneratedContent, + + /// Generation failed (no reason) + /// Unspecified failure reason + /// Various example failures: + /// - "The generated video did not pass review. Credits will not be deducted." (seedance2pro) + /// - "Server error. Please try again later." (seedance2pro) + #[serde(rename = "generation_failed")] + GenerationFailed, +} + +// TODO(bt, 2022-12-21): This desperately needs MySQL integration tests! +impl_enum_display_and_debug_using_to_str!(FrontendFailureCategory); +impl_mysql_enum_coders!(FrontendFailureCategory); +impl_mysql_from_row!(FrontendFailureCategory); + +/// NB: Legacy API for older code. +impl FrontendFailureCategory { + pub fn to_str(&self) -> &'static str { + match self { + Self::FaceNotDetected => "face_not_detected", + Self::KeepAliveElapsed => "keep_alive_elapsed", + Self::NotYetImplemented => "not_yet_implemented", + Self::RetryableWorkerError => "retryable_worker_error", + Self::ModelRulesViolation => "model_rules_violation", + Self::RuleBansUserImage => "rule_bans_user_image", + Self::RuleBansUserImageWithFaces => "rule_bans_user_image_with_faces", + Self::RuleBansUserTextPrompt => "rule_bans_user_text_prompt", + Self::RuleBansUserContent => "rule_bans_user_content", + Self::RuleBansGeneratedVideo => "rule_bans_generated_video", + Self::RuleBansGeneratedAudio => "rule_bans_generated_audio", + Self::RuleBansGeneratedContent => "rule_bans_generated_content", + Self::GenerationFailed => "generation_failed", + } + } + + pub fn from_str(value: &str) -> Result { + match value { + "face_not_detected" => Ok(Self::FaceNotDetected), + "keep_alive_elapsed" => Ok(Self::KeepAliveElapsed), + "not_yet_implemented" => Ok(Self::NotYetImplemented), + "retryable_worker_error" => Ok(Self::RetryableWorkerError), + "model_rules_violation" => Ok(Self::ModelRulesViolation), + "rule_bans_user_image" => Ok(Self::RuleBansUserImage), + "rule_bans_user_image_with_faces" => Ok(Self::RuleBansUserImageWithFaces), + "rule_bans_user_text_prompt" => Ok(Self::RuleBansUserTextPrompt), + "rule_bans_user_content" => Ok(Self::RuleBansUserContent), + "rule_bans_generated_video" => Ok(Self::RuleBansGeneratedVideo), + "rule_bans_generated_audio" => Ok(Self::RuleBansGeneratedAudio), + "rule_bans_generated_content" => Ok(Self::RuleBansGeneratedContent), + "generation_failed" => Ok(Self::GenerationFailed), + _ => Err(format!("invalid value: {:?}", value)), + } + } + +} + +#[cfg(test)] +mod tests { + use super::super::frontend_failure_category::FrontendFailureCategory; + use enums_shared::test_helpers::assert_serialization; + + mod explicit_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(FrontendFailureCategory::FaceNotDetected, "face_not_detected"); + assert_serialization(FrontendFailureCategory::KeepAliveElapsed, "keep_alive_elapsed"); + assert_serialization(FrontendFailureCategory::NotYetImplemented, "not_yet_implemented"); + assert_serialization(FrontendFailureCategory::RetryableWorkerError, "retryable_worker_error"); + assert_serialization(FrontendFailureCategory::ModelRulesViolation, "model_rules_violation"); + assert_serialization(FrontendFailureCategory::RuleBansUserImage, "rule_bans_user_image"); + assert_serialization(FrontendFailureCategory::RuleBansUserImageWithFaces, "rule_bans_user_image_with_faces"); + assert_serialization(FrontendFailureCategory::RuleBansUserTextPrompt, "rule_bans_user_text_prompt"); + assert_serialization(FrontendFailureCategory::RuleBansUserContent, "rule_bans_user_content"); + assert_serialization(FrontendFailureCategory::RuleBansGeneratedVideo, "rule_bans_generated_video"); + assert_serialization(FrontendFailureCategory::RuleBansGeneratedAudio, "rule_bans_generated_audio"); + assert_serialization(FrontendFailureCategory::RuleBansGeneratedContent, "rule_bans_generated_content"); + assert_serialization(FrontendFailureCategory::GenerationFailed, "generation_failed"); + } + + #[test] + fn to_str() { + assert_eq!(FrontendFailureCategory::FaceNotDetected.to_str(), "face_not_detected"); + assert_eq!(FrontendFailureCategory::KeepAliveElapsed.to_str(), "keep_alive_elapsed"); + assert_eq!(FrontendFailureCategory::NotYetImplemented.to_str(), "not_yet_implemented"); + assert_eq!(FrontendFailureCategory::RetryableWorkerError.to_str(), "retryable_worker_error"); + assert_eq!(FrontendFailureCategory::ModelRulesViolation.to_str(), "model_rules_violation"); + assert_eq!(FrontendFailureCategory::RuleBansUserImage.to_str(), "rule_bans_user_image"); + assert_eq!(FrontendFailureCategory::RuleBansUserImageWithFaces.to_str(), "rule_bans_user_image_with_faces"); + assert_eq!(FrontendFailureCategory::RuleBansUserTextPrompt.to_str(), "rule_bans_user_text_prompt"); + assert_eq!(FrontendFailureCategory::RuleBansUserContent.to_str(), "rule_bans_user_content"); + assert_eq!(FrontendFailureCategory::RuleBansGeneratedVideo.to_str(), "rule_bans_generated_video"); + assert_eq!(FrontendFailureCategory::RuleBansGeneratedAudio.to_str(), "rule_bans_generated_audio"); + assert_eq!(FrontendFailureCategory::RuleBansGeneratedContent.to_str(), "rule_bans_generated_content"); + assert_eq!(FrontendFailureCategory::GenerationFailed.to_str(), "generation_failed"); + } + + #[test] + fn from_str() { + assert_eq!(FrontendFailureCategory::from_str("face_not_detected").unwrap(), FrontendFailureCategory::FaceNotDetected); + assert_eq!(FrontendFailureCategory::from_str("keep_alive_elapsed").unwrap(), FrontendFailureCategory::KeepAliveElapsed); + assert_eq!(FrontendFailureCategory::from_str("not_yet_implemented").unwrap(), FrontendFailureCategory::NotYetImplemented); + assert_eq!(FrontendFailureCategory::from_str("retryable_worker_error").unwrap(), FrontendFailureCategory::RetryableWorkerError); + assert_eq!(FrontendFailureCategory::from_str("model_rules_violation").unwrap(), FrontendFailureCategory::ModelRulesViolation); + assert_eq!(FrontendFailureCategory::from_str("rule_bans_user_image").unwrap(), FrontendFailureCategory::RuleBansUserImage); + assert_eq!(FrontendFailureCategory::from_str("rule_bans_user_image_with_faces").unwrap(), FrontendFailureCategory::RuleBansUserImageWithFaces); + assert_eq!(FrontendFailureCategory::from_str("rule_bans_user_text_prompt").unwrap(), FrontendFailureCategory::RuleBansUserTextPrompt); + assert_eq!(FrontendFailureCategory::from_str("rule_bans_user_content").unwrap(), FrontendFailureCategory::RuleBansUserContent); + assert_eq!(FrontendFailureCategory::from_str("rule_bans_generated_video").unwrap(), FrontendFailureCategory::RuleBansGeneratedVideo); + assert_eq!(FrontendFailureCategory::from_str("rule_bans_generated_audio").unwrap(), FrontendFailureCategory::RuleBansGeneratedAudio); + assert_eq!(FrontendFailureCategory::from_str("rule_bans_generated_content").unwrap(), FrontendFailureCategory::RuleBansGeneratedContent); + assert_eq!(FrontendFailureCategory::from_str("generation_failed").unwrap(), FrontendFailureCategory::GenerationFailed); + assert_eq!(FrontendFailureCategory::from_str("invalid_value").is_err(), true); + } + + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip() { + use strum::IntoEnumIterator; + for variant in FrontendFailureCategory::iter() { + assert_eq!(variant, FrontendFailureCategory::from_str(variant.to_str()).unwrap()); + assert_eq!(variant, FrontendFailureCategory::from_str(&format!("{}", variant)).unwrap()); + assert_eq!(variant, FrontendFailureCategory::from_str(&format!("{:?}", variant)).unwrap()); + } + } + + #[test] + fn serialized_length_ok_for_database() { + const MAX_LENGTH: usize = 32; // TODO(bt): Confirm database column width, then remove this comment. + use strum::IntoEnumIterator; + for variant in FrontendFailureCategory::iter() { + let serialized = variant.to_str(); + assert!(!serialized.is_empty(), "variant {:?} is too short", variant); + assert!(serialized.len() <= MAX_LENGTH, "variant {:?} is too long", variant); + } + } + } +} diff --git a/crates/schema/public/enums_db/src/by_table/generic_inference_jobs/inference_category.rs b/crates/schema/public/enums_db/src/by_table/generic_inference_jobs/inference_category.rs new file mode 100644 index 0000000000..5b63ed2fa2 --- /dev/null +++ b/crates/schema/public/enums_db/src/by_table/generic_inference_jobs/inference_category.rs @@ -0,0 +1,240 @@ +use strum::EnumCount; +use strum::EnumIter; + +/// Used in the `generic_inference_jobs` table in `VARCHAR(32)` field `inference_category`. +/// +/// Our "generic inference" pipeline supports a wide variety of ML models and other media. +/// Each "category" of inference is identified by the following enum variants. +/// These types are present in the HTTP API and database columns as serialized here. +/// +/// YOU CAN ADD NEW VALUES, BUT DO NOT CHANGE EXISTING VALUES WITHOUT A MIGRATION STRATEGY. +#[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, Deserialize, Serialize, Default, EnumIter, EnumCount)] +pub enum InferenceCategory { + /// Deprecate this field !!! + /// We should drain all jobs from using this database field, then remove it. + #[deprecated(note = "NB(bt,2024-09-05): The frontend still needs this")] + #[serde(rename = "deprecated_field")] + DeprecatedField, + + /// Facial lipsync animation (eg. SadTalker, Wav2Lip, FaceFusion) + #[serde(rename = "lipsync_animation")] + #[default] + LipsyncAnimation, + + /// FakeYou's text to speech (eg. Tacotron2) + #[serde(rename = "text_to_speech")] + TextToSpeech, + + /// FakeYou's voice conversion (eg. svc, rvc) + #[serde(rename = "voice_conversion")] + VoiceConversion, + + /// Image generation (eg. Stable Diffusion 1.5), FAL-powered image generation, etc. + #[serde(rename = "image_generation")] + ImageGeneration, + + /// FAL-powered video generation + /// (Also Seedance2-Pro.com) + #[serde(rename = "video_generation")] + VideoGeneration, + + /// FAL-powered 3D object generation + #[serde(rename = "object_generation")] + ObjectGeneration, + + /// Gaussian Splat generation (eg. World Labs Marble) + #[serde(rename = "splat_generation")] + SplatGeneration, + + /// FAL-powered image background removal + #[serde(rename = "background_removal")] + BackgroundRemoval, + + /// Turn video into animation data with mocap processing (eg. Mocapnet). + #[serde(rename = "mocap")] + Mocap, + + /// ComfyUI workflows + /// This is what powers Storyteller Studio! + #[serde(rename = "workflow")] + Workflow, + + /// FBX to GLTF/GLB. + /// Still supported, but few people will use it. + #[serde(rename = "format_conversion")] + FormatConversion, + + /// Live portrait + #[serde(rename = "live_portrait")] + LivePortrait, + + #[serde(rename="seed_vc")] + SeedVc, + + /// DEPRECATED. Do not use. + /// This was for ReRenderAVideo, which we never productionized. + #[deprecated(note = "This was for ReRenderAVideo, which we never productionized.")] + #[serde(rename = "video_filter")] + VideoFilter, + + /// DEPRECATED. Bevy engine serverside rendering. + #[deprecated(note = "This was for Bevy engine's server side rendering.")] + #[serde(rename = "convert_bvh_to_workflow")] + ConvertBvhToWorkflow, + + #[serde(rename = "f5_tts")] + F5TTS, +} + +// TODO(bt, 2022-12-21): This desperately needs MySQL integration tests! +impl_enum_display_and_debug_using_to_str!(InferenceCategory); +impl_mysql_enum_coders!(InferenceCategory); +impl_mysql_from_row!(InferenceCategory); + +/// NB: Legacy API for older code. +impl InferenceCategory { + pub fn to_str(&self) -> &'static str { + match self { + Self::DeprecatedField => "deprecated_field", + Self::LipsyncAnimation => "lipsync_animation", + Self::TextToSpeech => "text_to_speech", + Self::VoiceConversion => "voice_conversion", + Self::ImageGeneration => "image_generation", + Self::VideoGeneration => "video_generation", + Self::ObjectGeneration => "object_generation", + Self::SplatGeneration => "splat_generation", + Self::BackgroundRemoval => "background_removal", + Self::Mocap => "mocap", + Self::Workflow => "workflow", + Self::F5TTS => "f5_tts", + Self::FormatConversion => "format_conversion", + Self::LivePortrait => "live_portrait", + Self::SeedVc => "seed_vc", + Self::VideoFilter => "video_filter", + Self::ConvertBvhToWorkflow => "convert_bvh_to_workflow", + } + } + + pub fn from_str(value: &str) -> Result { + match value { + "deprecated_field" => Ok(Self::DeprecatedField), + "lipsync_animation" => Ok(Self::LipsyncAnimation), + "text_to_speech" => Ok(Self::TextToSpeech), + "voice_conversion" => Ok(Self::VoiceConversion), + "image_generation" => Ok(Self::ImageGeneration), + "video_generation" => Ok(Self::VideoGeneration), + "object_generation" => Ok(Self::ObjectGeneration), + "splat_generation" => Ok(Self::SplatGeneration), + "background_removal" => Ok(Self::BackgroundRemoval), + "f5_tts" => Ok(Self::F5TTS), + "mocap" => Ok(Self::Mocap), + "workflow" => Ok(Self::Workflow), + "format_conversion" => Ok(Self::FormatConversion), + "live_portrait" => Ok(Self::LivePortrait), + "seed_vc" => Ok(Self::SeedVc), + "video_filter" => Ok(Self::VideoFilter), + "convert_bvh_to_workflow" => Ok(Self::ConvertBvhToWorkflow), + _ => Err(format!("invalid value: {:?}", value)), + } + } + +} + +#[cfg(test)] +mod tests { + use super::super::inference_category::InferenceCategory; + use enums_shared::test_helpers::assert_serialization; + + mod explicit_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(InferenceCategory::DeprecatedField, "deprecated_field"); + assert_serialization(InferenceCategory::LipsyncAnimation, "lipsync_animation"); + assert_serialization(InferenceCategory::TextToSpeech, "text_to_speech"); + assert_serialization(InferenceCategory::VoiceConversion, "voice_conversion"); + assert_serialization(InferenceCategory::ImageGeneration, "image_generation"); + assert_serialization(InferenceCategory::VideoGeneration, "video_generation"); + assert_serialization(InferenceCategory::ObjectGeneration, "object_generation"); + assert_serialization(InferenceCategory::SplatGeneration, "splat_generation"); + assert_serialization(InferenceCategory::BackgroundRemoval, "background_removal"); + assert_serialization(InferenceCategory::Mocap, "mocap"); + assert_serialization(InferenceCategory::F5TTS, "f5_tts"); + assert_serialization(InferenceCategory::SeedVc, "seed_vc"); + assert_serialization(InferenceCategory::Workflow, "workflow"); + assert_serialization(InferenceCategory::FormatConversion, "format_conversion"); + assert_serialization(InferenceCategory::LivePortrait, "live_portrait"); + assert_serialization(InferenceCategory::VideoFilter, "video_filter"); + assert_serialization(InferenceCategory::ConvertBvhToWorkflow, "convert_bvh_to_workflow"); + } + + #[test] + fn to_str() { + assert_eq!(InferenceCategory::DeprecatedField.to_str(), "deprecated_field"); + assert_eq!(InferenceCategory::LipsyncAnimation.to_str(), "lipsync_animation"); + assert_eq!(InferenceCategory::TextToSpeech.to_str(), "text_to_speech"); + assert_eq!(InferenceCategory::VoiceConversion.to_str(), "voice_conversion"); + assert_eq!(InferenceCategory::ImageGeneration.to_str(), "image_generation"); + assert_eq!(InferenceCategory::VideoGeneration.to_str(), "video_generation"); + assert_eq!(InferenceCategory::ObjectGeneration.to_str(), "object_generation"); + assert_eq!(InferenceCategory::SplatGeneration.to_str(), "splat_generation"); + assert_eq!(InferenceCategory::BackgroundRemoval.to_str(), "background_removal"); + assert_eq!(InferenceCategory::F5TTS.to_str(), "f5_tts"); + assert_eq!(InferenceCategory::SeedVc.to_str(), "seed_vc"); + assert_eq!(InferenceCategory::Mocap.to_str(), "mocap"); + assert_eq!(InferenceCategory::Workflow.to_str(), "workflow"); + assert_eq!(InferenceCategory::FormatConversion.to_str(), "format_conversion"); + assert_eq!(InferenceCategory::LivePortrait.to_str(), "live_portrait"); + assert_eq!(InferenceCategory::VideoFilter.to_str(), "video_filter"); + assert_eq!(InferenceCategory::ConvertBvhToWorkflow.to_str(), "convert_bvh_to_workflow"); + } + + #[test] + fn from_str() { + assert_eq!(InferenceCategory::from_str("deprecated_field").unwrap(), InferenceCategory::DeprecatedField); + assert_eq!(InferenceCategory::from_str("lipsync_animation").unwrap(), InferenceCategory::LipsyncAnimation); + assert_eq!(InferenceCategory::from_str("text_to_speech").unwrap(), InferenceCategory::TextToSpeech); + assert_eq!(InferenceCategory::from_str("voice_conversion").unwrap(), InferenceCategory::VoiceConversion); + assert_eq!(InferenceCategory::from_str("image_generation").unwrap(), InferenceCategory::ImageGeneration); + assert_eq!(InferenceCategory::from_str("video_generation").unwrap(), InferenceCategory::VideoGeneration); + assert_eq!(InferenceCategory::from_str("object_generation").unwrap(), InferenceCategory::ObjectGeneration); + assert_eq!(InferenceCategory::from_str("splat_generation").unwrap(), InferenceCategory::SplatGeneration); + assert_eq!(InferenceCategory::from_str("background_removal").unwrap(), InferenceCategory::BackgroundRemoval); + assert_eq!(InferenceCategory::from_str("f5_tts").unwrap(), InferenceCategory::F5TTS); + assert_eq!(InferenceCategory::from_str("seed_vc").unwrap(), InferenceCategory::SeedVc); + assert_eq!(InferenceCategory::from_str("mocap").unwrap(), InferenceCategory::Mocap); + assert_eq!(InferenceCategory::from_str("workflow").unwrap(), InferenceCategory::Workflow); + assert_eq!(InferenceCategory::from_str("format_conversion").unwrap(), InferenceCategory::FormatConversion); + assert_eq!(InferenceCategory::from_str("live_portrait").unwrap(), InferenceCategory::LivePortrait); + assert_eq!(InferenceCategory::from_str("video_filter").unwrap(), InferenceCategory::VideoFilter); + assert_eq!(InferenceCategory::from_str("convert_bvh_to_workflow").unwrap(), InferenceCategory::ConvertBvhToWorkflow); + } + + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip() { + use strum::IntoEnumIterator; + for variant in InferenceCategory::iter() { + assert_eq!(variant, InferenceCategory::from_str(variant.to_str()).unwrap()); + assert_eq!(variant, InferenceCategory::from_str(&format!("{}", variant)).unwrap()); + assert_eq!(variant, InferenceCategory::from_str(&format!("{:?}", variant)).unwrap()); + } + } + + #[test] + fn serialized_length_ok_for_database() { + use strum::IntoEnumIterator; + const MAX_LENGTH : usize = 32; + for variant in InferenceCategory::iter() { + let serialized = variant.to_str(); + assert!(serialized.len() > 0, "variant {:?} is too short", variant); + assert!(serialized.len() <= MAX_LENGTH, "variant {:?} is too long", variant); + } + } + } +} diff --git a/crates/schema/public/enums_db/src/by_table/generic_inference_jobs/inference_input_source_token_type.rs b/crates/schema/public/enums_db/src/by_table/generic_inference_jobs/inference_input_source_token_type.rs new file mode 100644 index 0000000000..a3ef7d4232 --- /dev/null +++ b/crates/schema/public/enums_db/src/by_table/generic_inference_jobs/inference_input_source_token_type.rs @@ -0,0 +1,86 @@ +use strum::EnumCount; +use strum::EnumIter; + +/// Used in the `generic_inference_jobs` table in `VARCHAR(32)` field `maybe_input_source_token`. +/// +/// YOU CAN ADD NEW VALUES, BUT DO NOT CHANGE EXISTING VALUES WITHOUT A MIGRATION STRATEGY. +#[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, Deserialize, Serialize, EnumIter, EnumCount)] +pub enum InferenceInputSourceTokenType { + #[serde(rename = "media_file")] + MediaFile, + #[serde(rename = "media_upload")] + MediaUpload, +} + +// TODO(bt, 2022-12-21): This desperately needs MySQL integration tests! +impl_enum_display_and_debug_using_to_str!(InferenceInputSourceTokenType); +impl_mysql_enum_coders!(InferenceInputSourceTokenType); +impl_mysql_from_row!(InferenceInputSourceTokenType); + +/// NB: Legacy API for older code. +impl InferenceInputSourceTokenType { + pub fn to_str(&self) -> &'static str { + match self { + Self::MediaFile => "media_file", + Self::MediaUpload => "media_upload", + } + } + + pub fn from_str(value: &str) -> Result { + match value { + "media_file" => Ok(Self::MediaFile), + "media_upload" => Ok(Self::MediaUpload), + _ => Err(format!("invalid value: {:?}", value)), + } + } + +} + +#[cfg(test)] +mod tests { + use super::super::inference_input_source_token_type::InferenceInputSourceTokenType; + use enums_shared::test_helpers::assert_serialization; + + #[test] + fn test_serialization() { + assert_serialization(InferenceInputSourceTokenType::MediaFile, "media_file"); + assert_serialization(InferenceInputSourceTokenType::MediaUpload, "media_upload"); + } + + #[test] + fn to_str() { + assert_eq!(InferenceInputSourceTokenType::MediaFile.to_str(), "media_file"); + assert_eq!(InferenceInputSourceTokenType::MediaUpload.to_str(), "media_upload"); + } + + #[test] + fn from_str() { + assert_eq!(InferenceInputSourceTokenType::from_str("media_file").unwrap(), InferenceInputSourceTokenType::MediaFile); + assert_eq!(InferenceInputSourceTokenType::from_str("media_upload").unwrap(), InferenceInputSourceTokenType::MediaUpload); + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip() { + use strum::IntoEnumIterator; + for variant in InferenceInputSourceTokenType::iter() { + assert_eq!(variant, InferenceInputSourceTokenType::from_str(variant.to_str()).unwrap()); + assert_eq!(variant, InferenceInputSourceTokenType::from_str(&format!("{}", variant)).unwrap()); + assert_eq!(variant, InferenceInputSourceTokenType::from_str(&format!("{:?}", variant)).unwrap()); + } + } + + #[test] + fn serialized_length_ok_for_database() { + const MAX_LENGTH: usize = 32; // TODO(bt): Confirm database column width, then remove this comment. + use strum::IntoEnumIterator; + for variant in InferenceInputSourceTokenType::iter() { + let serialized = variant.to_str(); + assert!(!serialized.is_empty(), "variant {:?} is too short", variant); + assert!(serialized.len() <= MAX_LENGTH, "variant {:?} is too long", variant); + } + } + } +} diff --git a/crates/schema/public/enums_db/src/by_table/generic_inference_jobs/inference_job_external_third_party.rs b/crates/schema/public/enums_db/src/by_table/generic_inference_jobs/inference_job_external_third_party.rs new file mode 100644 index 0000000000..57fd6e2a21 --- /dev/null +++ b/crates/schema/public/enums_db/src/by_table/generic_inference_jobs/inference_job_external_third_party.rs @@ -0,0 +1,105 @@ +use strum::EnumCount; +use strum::EnumIter; + +/// Used in the `generic_inference_jobs` table in `VARCHAR(16)` field `maybe_external_third_party`. +/// +/// YOU CAN ADD NEW VALUES, BUT DO NOT CHANGE EXISTING VALUES WITHOUT A MIGRATION STRATEGY. +#[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, Deserialize, Serialize, Default, EnumIter, EnumCount)] +#[serde(rename_all = "snake_case")] +pub enum InferenceJobExternalThirdParty { + /// Fal jobs + #[serde(rename = "fal")] + #[default] + Fal, + + /// Seedance 2 Pro jobs + #[serde(rename = "seedance2pro")] + Seedance2Pro, + + /// World Labs jobs + #[serde(rename = "worldlabs")] + Worldlabs, +} + +// TODO(bt, 2022-12-21): This desperately needs MySQL integration tests! +impl_enum_display_and_debug_using_to_str!(InferenceJobExternalThirdParty); +impl_mysql_enum_coders!(InferenceJobExternalThirdParty); +impl_mysql_from_row!(InferenceJobExternalThirdParty); + +/// NB: Legacy API for older code. +impl InferenceJobExternalThirdParty { + pub fn to_str(&self) -> &'static str { + match self { + Self::Fal => "fal", + Self::Seedance2Pro => "seedance2pro", + Self::Worldlabs => "worldlabs", + } + } + + pub fn from_str(value: &str) -> Result { + match value { + "fal" => Ok(Self::Fal), + "seedance2pro" => Ok(Self::Seedance2Pro), + "worldlabs" => Ok(Self::Worldlabs), + _ => Err(format!("invalid value: {:?}", value)), + } + } + +} + +#[cfg(test)] +mod tests { + use super::super::inference_job_external_third_party::InferenceJobExternalThirdParty; + use enums_shared::test_helpers::assert_serialization; + + mod explicit_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(InferenceJobExternalThirdParty::Fal, "fal"); + assert_serialization(InferenceJobExternalThirdParty::Seedance2Pro, "seedance2pro"); + assert_serialization(InferenceJobExternalThirdParty::Worldlabs, "worldlabs"); + } + + #[test] + fn to_str() { + assert_eq!(InferenceJobExternalThirdParty::Fal.to_str(), "fal"); + assert_eq!(InferenceJobExternalThirdParty::Seedance2Pro.to_str(), "seedance2pro"); + assert_eq!(InferenceJobExternalThirdParty::Worldlabs.to_str(), "worldlabs"); + } + + #[test] + fn from_str() { + assert_eq!(InferenceJobExternalThirdParty::from_str("fal").unwrap(), InferenceJobExternalThirdParty::Fal); + assert_eq!(InferenceJobExternalThirdParty::from_str("seedance2pro").unwrap(), InferenceJobExternalThirdParty::Seedance2Pro); + assert_eq!(InferenceJobExternalThirdParty::from_str("worldlabs").unwrap(), InferenceJobExternalThirdParty::Worldlabs); + } + + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip() { + use strum::IntoEnumIterator; + for variant in InferenceJobExternalThirdParty::iter() { + assert_eq!(variant, InferenceJobExternalThirdParty::from_str(variant.to_str()).unwrap()); + assert_eq!(variant, InferenceJobExternalThirdParty::from_str(&format!("{}", variant)).unwrap()); + assert_eq!(variant, InferenceJobExternalThirdParty::from_str(&format!("{:?}", variant)).unwrap()); + } + } + + #[test] + fn serialized_length_ok_for_database() { + use strum::IntoEnumIterator; + const MAX_LENGTH : usize = 16; + for variant in InferenceJobExternalThirdParty::iter() { + let serialized = variant.to_str(); + assert!(serialized.len() > 0, "variant {:?} is too short", variant); + assert!(serialized.len() <= MAX_LENGTH, "variant {:?} is too long", variant); + } + } + } +} diff --git a/crates/schema/public/enums_db/src/by_table/generic_inference_jobs/inference_job_product_category.rs b/crates/schema/public/enums_db/src/by_table/generic_inference_jobs/inference_job_product_category.rs new file mode 100644 index 0000000000..2272f863e1 --- /dev/null +++ b/crates/schema/public/enums_db/src/by_table/generic_inference_jobs/inference_job_product_category.rs @@ -0,0 +1,330 @@ +use strum::EnumCount; +use strum::EnumIter; + +/// Used in the `generic_inference_jobs` table in `VARCHAR(32)` field `product_category`. +/// +/// This is a user-facing and analytics-facing column that describes what product area the job +/// is attributed to. For example, this will help us separate "video style transfer" from +/// "storyteller studio" and also separate "live portrait" from "webcam live portrait". +/// +/// YOU CAN ADD NEW VALUES, BUT DO NOT CHANGE EXISTING VALUES WITHOUT A MIGRATION STRATEGY. +#[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, Deserialize, Serialize, Default, EnumIter, EnumCount)] +#[serde(rename_all = "snake_case")] +pub enum InferenceJobProductCategory { + // =============== DOWNLOAD =============== + + /// Download: GptSoVits + #[default] + DownloadGptSoVits, + + // =============== FAL =============== + + FalImage, + FalVideo, + /// Fal: 3D Object Generation + FalObject, + FalBgRemoval, + + // =============== SEEDANCE 2 PRO =============== + + #[serde(rename = "seedance2pro_video")] + Seedance2ProVideo, + + // =============== WORLD LABS =============== + + /// World Labs: Gaussian Splat Generation + #[serde(rename = "worldlabs_splat")] + WorldlabsSplat, + + // =============== TEXT TO SPEECH =============== + + /// TTS: GptSoVits + TtsGptSoVits, + + /// TTS: F5Tts (Zero Shot) + TtsF5, + + /// TTS: StyleTts2 (Zero Shot) + TtsStyleTts2, + + /// TTS: Tacotron2 + TtsTacotron2, + + // =============== VOICE CONVERSION =============== + + /// Voice Conversion: RVC v2 + VcRvc2, + + /// Voice Conversion: SoVitsSvc + VcSvc, + + VcSeedVc, // Ugh + + // =============== VIDEO =============== + + /// Video: Face Fusion (Lipsync) + VidLipsyncFaceFusion, + + /// Video: Sad Talker (Lipsync) + VidLipsyncSadTalker, + + /// Live Portrait (normal interface) + VidLivePortrait, + + /// Live Portrait (webcam interface) + VidLivePortraitWebcam, + + /// Video: Studio + VidStudio, + + /// Video: Studio Gen 2 + VidStudioGen2, + + /// Video: Style Transfer + VidStyleTransfer, + + // =============== DEPRECATED =============== + + /// Lipsync: Face Fusion + #[deprecated(note = "Use `VidLipsyncFaceFusion` instead")] + LipsyncFaceFusion, + + /// Lipsync: SadTalker + #[deprecated(note = "Use `VidLipsyncSadTalker` instead")] + LipsyncSadTalker, + + /// Live Portrait (normal interface) + #[deprecated(note = "Use `VidLivePortrait` instead")] + LivePortrait, + + /// Live Portrait (webcam interface) + #[deprecated(note = "Use `VidLivePortraitWebcam` instead")] + LivePortraitWebcam, + + /// Stable Diffusion (deprecated) + #[deprecated(note = "unused")] + StableDiffusion, + + /// Storyteller Studio + #[deprecated(note = "Use `VidStudio` instead")] + Studio, + + /// Lipsync: Face Fusion + #[deprecated(note = "Use `VidLipsyncFaceFusion` instead")] + VidFaceFusion, + + /// Video Style Transfer + #[deprecated(note = "Use `VidStyleTransfer` instead")] + Vst, +} + +// TODO(bt, 2022-12-21): This desperately needs MySQL integration tests! +impl_enum_display_and_debug_using_to_str!(InferenceJobProductCategory); +impl_mysql_enum_coders!(InferenceJobProductCategory); +impl_mysql_from_row!(InferenceJobProductCategory); + +/// NB: Legacy API for older code. +impl InferenceJobProductCategory { + pub fn to_str(&self) -> &'static str { + match self { + Self::DownloadGptSoVits => "download_gpt_so_vits", + Self::FalImage => "fal_image", + Self::FalVideo => "fal_video", + Self::FalObject => "fal_object", + Self::FalBgRemoval => "fal_bg_removal", + Self::Seedance2ProVideo => "seedance2pro_video", + Self::WorldlabsSplat => "worldlabs_splat", + Self::TtsGptSoVits => "tts_gpt_so_vits", + Self::TtsStyleTts2 => "tts_style_tts2", + Self::TtsTacotron2 => "tts_tacotron2", + Self::TtsF5 => "tts_f5", + Self::VcSvc => "vc_svc", + Self::VcRvc2 => "vc_rvc2", + Self::VcSeedVc => "vc_seed_vc", + Self::VidLipsyncFaceFusion => "vid_lipsync_face_fusion", + Self::VidLipsyncSadTalker => "vid_lipsync_sad_talker", + Self::VidLivePortrait => "vid_live_portrait", + Self::VidLivePortraitWebcam => "vid_live_portrait_webcam", + Self::VidStudio => "vid_studio", + Self::VidStudioGen2 => "vid_studio_gen2", + Self::VidStyleTransfer => "vid_style_transfer", + Self::LipsyncFaceFusion => "lipsync_face_fusion", + Self::LipsyncSadTalker => "lipsync_sad_talker", + Self::LivePortrait => "live_portrait", + Self::LivePortraitWebcam => "live_portrait_webcam", + Self::StableDiffusion => "stable_diffusion", + Self::Studio => "studio", + Self::VidFaceFusion => "vid_face_fusion", + Self::Vst => "vst", + } + } + + pub fn from_str(value: &str) -> Result { + match value { + "download_gpt_so_vits" => Ok(Self::DownloadGptSoVits), + "fal_image" => Ok(Self::FalImage), + "fal_video" => Ok(Self::FalVideo), + "fal_object" => Ok(Self::FalObject), + "fal_bg_removal" => Ok(Self::FalBgRemoval), + "seedance2pro_video" => Ok(Self::Seedance2ProVideo), + "worldlabs_splat" => Ok(Self::WorldlabsSplat), + "tts_gpt_so_vits" => Ok(Self::TtsGptSoVits), + "tts_style_tts2" => Ok(Self::TtsStyleTts2), + "tts_tacotron2" => Ok(Self::TtsTacotron2), + "tts_f5" => Ok(Self::TtsF5), + "vc_svc" => Ok(Self::VcSvc), + "vc_rvc2" => Ok(Self::VcRvc2), + "vc_seed_vc" => Ok(Self::VcSeedVc), + "vid_lipsync_face_fusion" => Ok(Self::VidLipsyncFaceFusion), + "vid_lipsync_sad_talker" => Ok(Self::VidLipsyncSadTalker), + "vid_live_portrait" => Ok(Self::VidLivePortrait), + "vid_live_portrait_webcam" => Ok(Self::VidLivePortraitWebcam), + "vid_studio" => Ok(Self::VidStudio), + "vid_studio_gen2" => Ok(Self::VidStudioGen2), + "vid_style_transfer" => Ok(Self::VidStyleTransfer), + "lipsync_face_fusion" => Ok(Self::LipsyncFaceFusion), + "lipsync_sad_talker" => Ok(Self::LipsyncSadTalker), + "live_portrait" => Ok(Self::LivePortrait), + "live_portrait_webcam" => Ok(Self::LivePortraitWebcam), + "stable_diffusion" => Ok(Self::StableDiffusion), + "studio" => Ok(Self::Studio), + "vid_face_fusion" => Ok(Self::VidFaceFusion), + "vst" => Ok(Self::Vst), + _ => Err(format!("invalid value: {:?}", value)), + } + } + +} + +#[cfg(test)] +mod tests { + use super::super::inference_job_product_category::InferenceJobProductCategory; + use enums_shared::test_helpers::assert_serialization; + + mod explicit_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(InferenceJobProductCategory::DownloadGptSoVits, "download_gpt_so_vits"); + assert_serialization(InferenceJobProductCategory::FalImage, "fal_image"); + assert_serialization(InferenceJobProductCategory::FalVideo, "fal_video"); + assert_serialization(InferenceJobProductCategory::FalObject, "fal_object"); + assert_serialization(InferenceJobProductCategory::FalBgRemoval, "fal_bg_removal"); + assert_serialization(InferenceJobProductCategory::Seedance2ProVideo, "seedance2pro_video"); + assert_serialization(InferenceJobProductCategory::WorldlabsSplat, "worldlabs_splat"); + assert_serialization(InferenceJobProductCategory::TtsGptSoVits, "tts_gpt_so_vits"); + assert_serialization(InferenceJobProductCategory::TtsStyleTts2, "tts_style_tts2"); + assert_serialization(InferenceJobProductCategory::TtsTacotron2, "tts_tacotron2"); + assert_serialization(InferenceJobProductCategory::TtsF5, "tts_f5"); + assert_serialization(InferenceJobProductCategory::VcRvc2, "vc_rvc2"); + assert_serialization(InferenceJobProductCategory::VcSvc, "vc_svc"); + assert_serialization(InferenceJobProductCategory::VcSvc, "vc_svc"); + assert_serialization(InferenceJobProductCategory::VidLipsyncFaceFusion, "vid_lipsync_face_fusion"); + assert_serialization(InferenceJobProductCategory::VidLipsyncSadTalker, "vid_lipsync_sad_talker"); + assert_serialization(InferenceJobProductCategory::VidLivePortrait, "vid_live_portrait"); + assert_serialization(InferenceJobProductCategory::VidLivePortraitWebcam, "vid_live_portrait_webcam"); + assert_serialization(InferenceJobProductCategory::VidStudio, "vid_studio"); + assert_serialization(InferenceJobProductCategory::VidStudioGen2, "vid_studio_gen2"); + assert_serialization(InferenceJobProductCategory::VidStyleTransfer, "vid_style_transfer"); + assert_serialization(InferenceJobProductCategory::LipsyncFaceFusion, "lipsync_face_fusion"); + assert_serialization(InferenceJobProductCategory::LipsyncSadTalker, "lipsync_sad_talker"); + assert_serialization(InferenceJobProductCategory::LivePortrait, "live_portrait"); + assert_serialization(InferenceJobProductCategory::LivePortraitWebcam, "live_portrait_webcam"); + assert_serialization(InferenceJobProductCategory::StableDiffusion, "stable_diffusion"); + assert_serialization(InferenceJobProductCategory::Studio, "studio"); + assert_serialization(InferenceJobProductCategory::VidFaceFusion, "vid_face_fusion"); + assert_serialization(InferenceJobProductCategory::Vst, "vst"); + } + + #[test] + fn to_str() { + assert_eq!(InferenceJobProductCategory::DownloadGptSoVits.to_str(), "download_gpt_so_vits"); + assert_eq!(InferenceJobProductCategory::FalImage.to_str(), "fal_image"); + assert_eq!(InferenceJobProductCategory::FalVideo.to_str(), "fal_video"); + assert_eq!(InferenceJobProductCategory::FalObject.to_str(), "fal_object"); + assert_eq!(InferenceJobProductCategory::FalBgRemoval.to_str(), "fal_bg_removal"); + assert_eq!(InferenceJobProductCategory::Seedance2ProVideo.to_str(), "seedance2pro_video"); + assert_eq!(InferenceJobProductCategory::WorldlabsSplat.to_str(), "worldlabs_splat"); + assert_eq!(InferenceJobProductCategory::TtsGptSoVits.to_str(), "tts_gpt_so_vits"); + assert_eq!(InferenceJobProductCategory::TtsStyleTts2.to_str(), "tts_style_tts2"); + assert_eq!(InferenceJobProductCategory::TtsTacotron2.to_str(), "tts_tacotron2"); + assert_eq!(InferenceJobProductCategory::VcRvc2.to_str(), "vc_rvc2"); + assert_eq!(InferenceJobProductCategory::VcSvc.to_str(), "vc_svc"); + assert_eq!(InferenceJobProductCategory::VcSvc.to_str(), "vc_svc"); + assert_eq!(InferenceJobProductCategory::VidLipsyncFaceFusion.to_str(), "vid_lipsync_face_fusion"); + assert_eq!(InferenceJobProductCategory::VidLipsyncSadTalker.to_str(), "vid_lipsync_sad_talker"); + assert_eq!(InferenceJobProductCategory::VidLivePortrait.to_str(), "vid_live_portrait"); + assert_eq!(InferenceJobProductCategory::VidLivePortraitWebcam.to_str(), "vid_live_portrait_webcam"); + assert_eq!(InferenceJobProductCategory::VidStudio.to_str(), "vid_studio"); + assert_eq!(InferenceJobProductCategory::VidStudioGen2.to_str(), "vid_studio_gen2"); + assert_eq!(InferenceJobProductCategory::VidStyleTransfer.to_str(), "vid_style_transfer"); + assert_eq!(InferenceJobProductCategory::LipsyncFaceFusion.to_str(), "lipsync_face_fusion"); + assert_eq!(InferenceJobProductCategory::LipsyncSadTalker.to_str(), "lipsync_sad_talker"); + assert_eq!(InferenceJobProductCategory::LivePortrait.to_str(), "live_portrait"); + assert_eq!(InferenceJobProductCategory::LivePortraitWebcam.to_str(), "live_portrait_webcam"); + assert_eq!(InferenceJobProductCategory::StableDiffusion.to_str(), "stable_diffusion"); + assert_eq!(InferenceJobProductCategory::Studio.to_str(), "studio"); + assert_eq!(InferenceJobProductCategory::VidFaceFusion.to_str(), "vid_face_fusion"); + assert_eq!(InferenceJobProductCategory::Vst.to_str(), "vst"); + } + + #[test] + fn from_str() { + assert_eq!(InferenceJobProductCategory::from_str("download_gpt_so_vits").unwrap(), InferenceJobProductCategory::DownloadGptSoVits); + assert_eq!(InferenceJobProductCategory::from_str("fal_image").unwrap(), InferenceJobProductCategory::FalImage); + assert_eq!(InferenceJobProductCategory::from_str("fal_video").unwrap(), InferenceJobProductCategory::FalVideo); + assert_eq!(InferenceJobProductCategory::from_str("fal_object").unwrap(), InferenceJobProductCategory::FalObject); + assert_eq!(InferenceJobProductCategory::from_str("fal_bg_removal").unwrap(), InferenceJobProductCategory::FalBgRemoval); + assert_eq!(InferenceJobProductCategory::from_str("seedance2pro_video").unwrap(), InferenceJobProductCategory::Seedance2ProVideo); + assert_eq!(InferenceJobProductCategory::from_str("worldlabs_splat").unwrap(), InferenceJobProductCategory::WorldlabsSplat); + assert_eq!(InferenceJobProductCategory::from_str("tts_gpt_so_vits").unwrap(), InferenceJobProductCategory::TtsGptSoVits); + assert_eq!(InferenceJobProductCategory::from_str("tts_style_tts2").unwrap(), InferenceJobProductCategory::TtsStyleTts2); + assert_eq!(InferenceJobProductCategory::from_str("tts_tacotron2").unwrap(), InferenceJobProductCategory::TtsTacotron2); + assert_eq!(InferenceJobProductCategory::from_str("vc_rvc2").unwrap(), InferenceJobProductCategory::VcRvc2); + assert_eq!(InferenceJobProductCategory::from_str("vc_svc").unwrap(), InferenceJobProductCategory::VcSvc); + assert_eq!(InferenceJobProductCategory::from_str("vc_svc").unwrap(), InferenceJobProductCategory::VcSvc); + assert_eq!(InferenceJobProductCategory::from_str("vid_lipsync_face_fusion").unwrap(), InferenceJobProductCategory::VidLipsyncFaceFusion); + assert_eq!(InferenceJobProductCategory::from_str("vid_lipsync_sad_talker").unwrap(), InferenceJobProductCategory::VidLipsyncSadTalker); + assert_eq!(InferenceJobProductCategory::from_str("vid_live_portrait").unwrap(), InferenceJobProductCategory::VidLivePortrait); + assert_eq!(InferenceJobProductCategory::from_str("vid_live_portrait_webcam").unwrap(), InferenceJobProductCategory::VidLivePortraitWebcam); + assert_eq!(InferenceJobProductCategory::from_str("vid_studio").unwrap(), InferenceJobProductCategory::VidStudio); + assert_eq!(InferenceJobProductCategory::from_str("vid_studio_gen2").unwrap(), InferenceJobProductCategory::VidStudioGen2); + assert_eq!(InferenceJobProductCategory::from_str("vid_style_transfer").unwrap(), InferenceJobProductCategory::VidStyleTransfer); + assert_eq!(InferenceJobProductCategory::from_str("lipsync_face_fusion").unwrap(), InferenceJobProductCategory::LipsyncFaceFusion); + assert_eq!(InferenceJobProductCategory::from_str("lipsync_sad_talker").unwrap(), InferenceJobProductCategory::LipsyncSadTalker); + assert_eq!(InferenceJobProductCategory::from_str("live_portrait").unwrap(), InferenceJobProductCategory::LivePortrait); + assert_eq!(InferenceJobProductCategory::from_str("live_portrait_webcam").unwrap(), InferenceJobProductCategory::LivePortraitWebcam); + assert_eq!(InferenceJobProductCategory::from_str("stable_diffusion").unwrap(), InferenceJobProductCategory::StableDiffusion); + assert_eq!(InferenceJobProductCategory::from_str("studio").unwrap(), InferenceJobProductCategory::Studio); + assert_eq!(InferenceJobProductCategory::from_str("vid_face_fusion").unwrap(), InferenceJobProductCategory::VidFaceFusion); + assert_eq!(InferenceJobProductCategory::from_str("vst").unwrap(), InferenceJobProductCategory::Vst); + } + + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip() { + use strum::IntoEnumIterator; + for variant in InferenceJobProductCategory::iter() { + assert_eq!(variant, InferenceJobProductCategory::from_str(variant.to_str()).unwrap()); + assert_eq!(variant, InferenceJobProductCategory::from_str(&format!("{}", variant)).unwrap()); + assert_eq!(variant, InferenceJobProductCategory::from_str(&format!("{:?}", variant)).unwrap()); + } + } + + #[test] + fn serialized_length_ok_for_database() { + use strum::IntoEnumIterator; + const MAX_LENGTH : usize = 32; + for variant in InferenceJobProductCategory::iter() { + let serialized = variant.to_str(); + assert!(serialized.len() > 0, "variant {:?} is too short", variant); + assert!(serialized.len() <= MAX_LENGTH, "variant {:?} is too long", variant); + } + } + } +} diff --git a/crates/schema/public/enums_db/src/by_table/generic_inference_jobs/inference_job_type.rs b/crates/schema/public/enums_db/src/by_table/generic_inference_jobs/inference_job_type.rs new file mode 100644 index 0000000000..b84362c5d8 --- /dev/null +++ b/crates/schema/public/enums_db/src/by_table/generic_inference_jobs/inference_job_type.rs @@ -0,0 +1,233 @@ +use strum::EnumCount; +use strum::EnumIter; + +/// Used in the `generic_inference_jobs` table in `VARCHAR(32)` field `job_type`. +/// +/// YOU CAN ADD NEW VALUES, BUT DO NOT CHANGE EXISTING VALUES WITHOUT A MIGRATION STRATEGY. +#[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, Deserialize, Serialize, Default, EnumIter, EnumCount)] +#[serde(rename_all = "snake_case")] +pub enum InferenceJobType { + FalQueue, + #[serde(rename = "seedance2pro_queue")] + Seedance2ProQueue, + #[serde(rename = "worldlabs_queue")] + WorldlabsQueue, + VideoRender, + LivePortrait, + FaceFusion, + GptSovits, + #[deprecated(note = "Use VideoRender instead.")] + ComfyUi, + #[serde(rename = "studio_gen2")] + StudioGen2, + #[serde(rename = "image_gen_api")] + ImageGenApi, + #[serde(rename = "convert_fbx_gltf")] + ConvertFbxToGltf, + MocapNet, + #[serde(rename = "f5_tts")] + F5TTS, + #[serde(rename = "rvc_v2")] + RvcV2, + SadTalker, + SoVitsSvc, + #[serde(rename = "seed_vc")] + SeedVc, + StableDiffusion, + #[serde(rename = "styletts2")] + StyleTTS2, + Tacotron2, + #[default] + Unknown, + #[deprecated(note = "This was for Bevy engine's server side rendering.")] + #[serde(rename = "bevy_to_workflow")] + BevyToWorkflow, + #[deprecated(note = "This was for ReRenderAVideo, which we never productionized.")] + RerenderAVideo, +} + +impl_enum_display_and_debug_using_to_str!(InferenceJobType); +impl_mysql_enum_coders!(InferenceJobType); +impl_mysql_from_row!(InferenceJobType); + +impl InferenceJobType { + pub fn to_str(&self) -> &'static str { + match self { + Self::FalQueue => "fal_queue", + Self::Seedance2ProQueue => "seedance2pro_queue", + Self::WorldlabsQueue => "worldlabs_queue", + Self::VideoRender => "video_render", + Self::LivePortrait => "live_portrait", + Self::FaceFusion => "face_fusion", + Self::F5TTS => "f5_tts", + Self::GptSovits => "gpt_sovits", + Self::ComfyUi => "comfy_ui", + Self::StudioGen2 => "studio_gen2", + Self::ImageGenApi => "image_gen_api", + Self::ConvertFbxToGltf => "convert_fbx_gltf", + Self::MocapNet => "mocap_net", + Self::RvcV2 => "rvc_v2", + Self::SadTalker => "sad_talker", + Self::SeedVc => "seed_vc", + Self::SoVitsSvc => "so_vits_svc", + Self::StableDiffusion => "stable_diffusion", + Self::StyleTTS2 => "styletts2", + Self::Tacotron2 => "tacotron2", + Self::Unknown => "unknown", + Self::BevyToWorkflow => "bevy_to_workflow", + Self::RerenderAVideo => "rerender_a_video", + } + } + + pub fn from_str(value: &str) -> Result { + match value { + "fal_queue" => Ok(Self::FalQueue), + "seedance2pro_queue" => Ok(Self::Seedance2ProQueue), + "worldlabs_queue" => Ok(Self::WorldlabsQueue), + "video_render" => Ok(Self::VideoRender), + "live_portrait" => Ok(Self::LivePortrait), + "face_fusion" => Ok(Self::FaceFusion), + "f5_tts" => Ok(Self::F5TTS), + "gpt_sovits" => Ok(Self::GptSovits), + "comfy_ui" => Ok(Self::ComfyUi), + "studio_gen2" => Ok(Self::StudioGen2), + "image_gen_api" => Ok(Self::ImageGenApi), + "convert_fbx_gltf" => Ok(Self::ConvertFbxToGltf), + "mocap_net" => Ok(Self::MocapNet), + "rvc_v2" => Ok(Self::RvcV2), + "sad_talker" => Ok(Self::SadTalker), + "seed_vc" => Ok(Self::SeedVc), + "so_vits_svc" => Ok(Self::SoVitsSvc), + "stable_diffusion" => Ok(Self::StableDiffusion), + "styletts2" => Ok(Self::StyleTTS2), + "tacotron2" => Ok(Self::Tacotron2), + "unknown" => Ok(Self::Unknown), + "bevy_to_workflow" => Ok(Self::BevyToWorkflow), + "rerender_a_video" => Ok(Self::RerenderAVideo), + _ => Err(format!("invalid value: {:?}", value)), + } + } + +} + +#[cfg(test)] +mod tests { + use super::InferenceJobType; + use enums_shared::test_helpers::assert_serialization; + + mod explicit_checks { + use super::*; + + #[test] + fn default() { + assert_eq!(InferenceJobType::default(), InferenceJobType::Unknown); + } + + #[test] + fn test_serialization() { + assert_serialization(InferenceJobType::FalQueue, "fal_queue"); + assert_serialization(InferenceJobType::Seedance2ProQueue, "seedance2pro_queue"); + assert_serialization(InferenceJobType::WorldlabsQueue, "worldlabs_queue"); + assert_serialization(InferenceJobType::VideoRender, "video_render"); + assert_serialization(InferenceJobType::LivePortrait, "live_portrait"); + assert_serialization(InferenceJobType::FaceFusion, "face_fusion"); + assert_serialization(InferenceJobType::F5TTS, "f5_tts"); + assert_serialization(InferenceJobType::GptSovits, "gpt_sovits"); + assert_serialization(InferenceJobType::ComfyUi, "comfy_ui"); + assert_serialization(InferenceJobType::StudioGen2, "studio_gen2"); + assert_serialization(InferenceJobType::ImageGenApi, "image_gen_api"); + assert_serialization(InferenceJobType::ConvertFbxToGltf, "convert_fbx_gltf"); + assert_serialization(InferenceJobType::MocapNet, "mocap_net"); + assert_serialization(InferenceJobType::RvcV2, "rvc_v2"); + assert_serialization(InferenceJobType::SadTalker, "sad_talker"); + assert_serialization(InferenceJobType::SeedVc, "seed_vc"); + assert_serialization(InferenceJobType::SoVitsSvc, "so_vits_svc"); + assert_serialization(InferenceJobType::StableDiffusion, "stable_diffusion"); + assert_serialization(InferenceJobType::StyleTTS2, "styletts2"); + assert_serialization(InferenceJobType::Tacotron2, "tacotron2"); + assert_serialization(InferenceJobType::Unknown, "unknown"); + assert_serialization(InferenceJobType::BevyToWorkflow, "bevy_to_workflow"); + assert_serialization(InferenceJobType::RerenderAVideo, "rerender_a_video"); + } + + #[test] + fn to_str() { + assert_eq!(InferenceJobType::FalQueue.to_str(), "fal_queue"); + assert_eq!(InferenceJobType::Seedance2ProQueue.to_str(), "seedance2pro_queue"); + assert_eq!(InferenceJobType::WorldlabsQueue.to_str(), "worldlabs_queue"); + assert_eq!(InferenceJobType::VideoRender.to_str(), "video_render"); + assert_eq!(InferenceJobType::LivePortrait.to_str(), "live_portrait"); + assert_eq!(InferenceJobType::FaceFusion.to_str(), "face_fusion"); + assert_eq!(InferenceJobType::F5TTS.to_str(), "f5_tts"); + assert_eq!(InferenceJobType::GptSovits.to_str(), "gpt_sovits"); + assert_eq!(InferenceJobType::ComfyUi.to_str(), "comfy_ui"); + assert_eq!(InferenceJobType::StudioGen2.to_str(), "studio_gen2"); + assert_eq!(InferenceJobType::ImageGenApi.to_str(), "image_gen_api"); + assert_eq!(InferenceJobType::ConvertFbxToGltf.to_str(), "convert_fbx_gltf"); + assert_eq!(InferenceJobType::MocapNet.to_str(), "mocap_net"); + assert_eq!(InferenceJobType::RvcV2.to_str(), "rvc_v2"); + assert_eq!(InferenceJobType::SadTalker.to_str(), "sad_talker"); + assert_eq!(InferenceJobType::SeedVc.to_str(), "seed_vc"); + assert_eq!(InferenceJobType::SoVitsSvc.to_str(), "so_vits_svc"); + assert_eq!(InferenceJobType::StableDiffusion.to_str(), "stable_diffusion"); + assert_eq!(InferenceJobType::StyleTTS2.to_str(), "styletts2"); + assert_eq!(InferenceJobType::Tacotron2.to_str(), "tacotron2"); + assert_eq!(InferenceJobType::Unknown.to_str(), "unknown"); + assert_eq!(InferenceJobType::BevyToWorkflow.to_str(), "bevy_to_workflow"); + assert_eq!(InferenceJobType::RerenderAVideo.to_str(), "rerender_a_video"); + } + + #[test] + fn from_str() { + assert_eq!(InferenceJobType::from_str("fal_queue").unwrap(), InferenceJobType::FalQueue); + assert_eq!(InferenceJobType::from_str("seedance2pro_queue").unwrap(), InferenceJobType::Seedance2ProQueue); + assert_eq!(InferenceJobType::from_str("worldlabs_queue").unwrap(), InferenceJobType::WorldlabsQueue); + assert_eq!(InferenceJobType::from_str("video_render").unwrap(), InferenceJobType::VideoRender); + assert_eq!(InferenceJobType::from_str("live_portrait").unwrap(), InferenceJobType::LivePortrait); + assert_eq!(InferenceJobType::from_str("face_fusion").unwrap(), InferenceJobType::FaceFusion); + assert_eq!(InferenceJobType::from_str("f5_tts").unwrap(), InferenceJobType::F5TTS); + assert_eq!(InferenceJobType::from_str("gpt_sovits").unwrap(), InferenceJobType::GptSovits); + assert_eq!(InferenceJobType::from_str("comfy_ui").unwrap(), InferenceJobType::ComfyUi); + assert_eq!(InferenceJobType::from_str("studio_gen2").unwrap(), InferenceJobType::StudioGen2); + assert_eq!(InferenceJobType::from_str("image_gen_api").unwrap(), InferenceJobType::ImageGenApi); + assert_eq!(InferenceJobType::from_str("convert_fbx_gltf").unwrap(), InferenceJobType::ConvertFbxToGltf); + assert_eq!(InferenceJobType::from_str("mocap_net").unwrap(), InferenceJobType::MocapNet); + assert_eq!(InferenceJobType::from_str("rvc_v2").unwrap(), InferenceJobType::RvcV2); + assert_eq!(InferenceJobType::from_str("sad_talker").unwrap(), InferenceJobType::SadTalker); + assert_eq!(InferenceJobType::from_str("seed_vc").unwrap(), InferenceJobType::SeedVc); + assert_eq!(InferenceJobType::from_str("so_vits_svc").unwrap(), InferenceJobType::SoVitsSvc); + assert_eq!(InferenceJobType::from_str("stable_diffusion").unwrap(), InferenceJobType::StableDiffusion); + assert_eq!(InferenceJobType::from_str("styletts2").unwrap(), InferenceJobType::StyleTTS2); + assert_eq!(InferenceJobType::from_str("tacotron2").unwrap(), InferenceJobType::Tacotron2); + assert_eq!(InferenceJobType::from_str("unknown").unwrap(), InferenceJobType::Unknown); + assert_eq!(InferenceJobType::from_str("bevy_to_workflow").unwrap(), InferenceJobType::BevyToWorkflow); + assert_eq!(InferenceJobType::from_str("rerender_a_video").unwrap(), InferenceJobType::RerenderAVideo); + } + + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip() { + use strum::IntoEnumIterator; + for variant in InferenceJobType::iter() { + assert_eq!(variant, InferenceJobType::from_str(variant.to_str()).unwrap()); + assert_eq!(variant, InferenceJobType::from_str(&format!("{}", variant)).unwrap()); + assert_eq!(variant, InferenceJobType::from_str(&format!("{:?}", variant)).unwrap()); + } + } + + #[test] + fn serialized_length_ok_for_database() { + use strum::IntoEnumIterator; + const MAX_LENGTH: usize = 32; // TODO(bt): Confirm database column width, then remove this comment. + for variant in InferenceJobType::iter() { + let serialized = variant.to_str(); + assert!(!serialized.is_empty(), "variant {:?} is too short", variant); + assert!(serialized.len() <= MAX_LENGTH, "variant {:?} is too long", variant); + } + } + } +} diff --git a/crates/schema/public/enums_db/src/by_table/generic_inference_jobs/inference_model_type.rs b/crates/schema/public/enums_db/src/by_table/generic_inference_jobs/inference_model_type.rs new file mode 100644 index 0000000000..eb281f84c5 --- /dev/null +++ b/crates/schema/public/enums_db/src/by_table/generic_inference_jobs/inference_model_type.rs @@ -0,0 +1,197 @@ +use strum::EnumCount; +use strum::EnumIter; + +/// Used in the `generic_inference_jobs` table in `VARCHAR(32)` field `maybe_model_type`. +/// +/// Our "generic inference" pipeline supports a wide variety of ML models and other media. +/// Each inference "model type" identified by the following enum variants, though some pipelines +/// may use multiple models or no model (and may report NULL). +/// +/// These types are present in the HTTP API and database columns as serialized here. +/// +/// YOU CAN ADD NEW VALUES, BUT DO NOT CHANGE EXISTING VALUES WITHOUT A MIGRATION STRATEGY. +#[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, Deserialize, Serialize, EnumIter, EnumCount)] +pub enum InferenceModelType { + // TODO(bt,2024-07-15): This is too generic. We probably need "StorytellerStudio", "LivePortrait", etc. + #[serde(rename = "comfy_ui")] + ComfyUi, + + #[serde(rename = "rvc_v2")] + RvcV2, + // NB: sad_talker does use user-supplied models, so there is no "model token" + #[serde(rename = "sad_talker")] + SadTalker, + #[serde(rename = "so_vits_svc")] + SoVitsSvc, + // TODO: Does this need to be "legacy_tacotron2" ? + + #[serde(rename = "seed_vc")] + SeedVc, + + /// NB: This is for Sora GPT 4o image gen + #[serde(rename = "image_gen_api")] + ImageGenApi, + + #[serde(rename = "tacotron2")] + Tacotron2, + #[serde(rename = "vits")] + Vits, + #[serde(rename = "vall_e_x")] + VallEX, + #[serde(rename = "rerender_a_video")] + RerenderAVideo, + #[serde(rename = "stable_diffusion")] + StableDiffusion, + #[serde(rename = "mocap_net")] + MocapNet, + #[serde(rename = "styletts2")] + StyleTTS2, + /// A job that turns "FBX" game engine files into "GLTF" files (Bevy-compatible). + #[serde(rename = "convert_fbx_gltf")] + ConvertFbxToGltf, + #[serde(rename = "bvh_to_workflow")] + BvhToWorkflow +} + +// TODO(bt, 2022-12-21): This desperately needs MySQL integration tests! +impl_enum_display_and_debug_using_to_str!(InferenceModelType); +impl_mysql_enum_coders!(InferenceModelType); +impl_mysql_from_row!(InferenceModelType); + +/// NB: Legacy API for older code. +impl InferenceModelType { + pub fn to_str(&self) -> &'static str { + match self { + Self::RvcV2 => "rvc_v2", + Self::SadTalker => "sad_talker", + Self::SoVitsSvc => "so_vits_svc", + Self::Tacotron2 => "tacotron2", + Self::Vits => "vits", + Self::VallEX => "vall_e_x", + Self::RerenderAVideo => "rerender_a_video", + Self::StableDiffusion => "stable_diffusion", + Self::ImageGenApi => "image_gen_api", + Self::SeedVc => "seed_vc", + Self::MocapNet => "mocap_net", + Self::StyleTTS2 => "styletts2", + Self::ComfyUi => "comfy_ui", + Self::ConvertFbxToGltf => "convert_fbx_gltf", + Self::BvhToWorkflow => "bvh_to_workflow", + } + } + + pub fn from_str(value: &str) -> Result { + match value { + "rvc_v2" => Ok(Self::RvcV2), + "sad_talker" => Ok(Self::SadTalker), + "so_vits_svc" => Ok(Self::SoVitsSvc), + "seed_vc" => Ok(Self::SeedVc), + "tacotron2" => Ok(Self::Tacotron2), + "vits" => Ok(Self::Vits), + "vall_e_x" => Ok(Self::VallEX), + "rerender_a_video" => Ok(Self::RerenderAVideo), + "stable_diffusion" => Ok(Self::StableDiffusion), + "image_gen_api" => Ok(Self::ImageGenApi), + "mocap_net" => Ok(Self::MocapNet), + "styletts2" => Ok(Self::StyleTTS2), + "comfy_ui" => Ok(Self::ComfyUi), + "convert_fbx_gltf" => Ok(Self::ConvertFbxToGltf), + "bvh_to_workflow" => Ok(Self::BvhToWorkflow), + _ => Err(format!("invalid value: {:?}", value)), + } + } + +} + +#[cfg(test)] +mod tests { + use super::super::inference_model_type::InferenceModelType; + use enums_shared::test_helpers::assert_serialization; + + mod explicit_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(InferenceModelType::RvcV2, "rvc_v2"); + assert_serialization(InferenceModelType::SadTalker, "sad_talker"); + assert_serialization(InferenceModelType::SeedVc, "seed_vc"); + assert_serialization(InferenceModelType::SoVitsSvc, "so_vits_svc"); + assert_serialization(InferenceModelType::Tacotron2, "tacotron2"); + assert_serialization(InferenceModelType::Vits, "vits"); + assert_serialization(InferenceModelType::VallEX, "vall_e_x"); + assert_serialization(InferenceModelType::RerenderAVideo, "rerender_a_video"); + assert_serialization(InferenceModelType::StableDiffusion, "stable_diffusion"); + assert_serialization(InferenceModelType::ImageGenApi, "image_gen_api"); + assert_serialization(InferenceModelType::MocapNet, "mocap_net"); + assert_serialization(InferenceModelType::ComfyUi, "comfy_ui"); + assert_serialization(InferenceModelType::StyleTTS2, "styletts2"); + assert_serialization(InferenceModelType::ConvertFbxToGltf, "convert_fbx_gltf"); + assert_serialization(InferenceModelType::BvhToWorkflow, "bvh_to_workflow"); + } + + #[test] + fn to_str() { + assert_eq!(InferenceModelType::ComfyUi.to_str(), "comfy_ui"); + assert_eq!(InferenceModelType::RvcV2.to_str(), "rvc_v2"); + assert_eq!(InferenceModelType::SadTalker.to_str(), "sad_talker"); + assert_eq!(InferenceModelType::SoVitsSvc.to_str(), "so_vits_svc"); + assert_eq!(InferenceModelType::SoVitsSvc.to_str(), "so_vits_svc"); + assert_eq!(InferenceModelType::Tacotron2.to_str(), "tacotron2"); + assert_eq!(InferenceModelType::Vits.to_str(), "vits"); + assert_eq!(InferenceModelType::VallEX.to_str(), "vall_e_x"); + assert_eq!(InferenceModelType::RerenderAVideo.to_str(), "rerender_a_video"); + assert_eq!(InferenceModelType::StableDiffusion.to_str(), "stable_diffusion"); + assert_eq!(InferenceModelType::ImageGenApi.to_str(), "image_gen_api"); + assert_eq!(InferenceModelType::MocapNet.to_str(), "mocap_net"); + assert_eq!(InferenceModelType::StyleTTS2.to_str(), "styletts2"); + assert_eq!(InferenceModelType::ConvertFbxToGltf.to_str(), "convert_fbx_gltf"); + assert_eq!(InferenceModelType::BvhToWorkflow.to_str(), "bvh_to_workflow"); + } + + #[test] + fn from_str() { + assert_eq!(InferenceModelType::from_str("rvc_v2").unwrap(), InferenceModelType::RvcV2); + assert_eq!(InferenceModelType::from_str("sad_talker").unwrap(), InferenceModelType::SadTalker); + assert_eq!(InferenceModelType::from_str("seed_vc").unwrap(), InferenceModelType::SeedVc); + assert_eq!(InferenceModelType::from_str("so_vits_svc").unwrap(), InferenceModelType::SoVitsSvc); + assert_eq!(InferenceModelType::from_str("tacotron2").unwrap(), InferenceModelType::Tacotron2); + assert_eq!(InferenceModelType::from_str("vits").unwrap(), InferenceModelType::Vits); + assert_eq!(InferenceModelType::from_str("vall_e_x").unwrap(), InferenceModelType::VallEX); + assert_eq!(InferenceModelType::from_str("rerender_a_video").unwrap(), InferenceModelType::RerenderAVideo); + assert_eq!(InferenceModelType::from_str("stable_diffusion").unwrap(), InferenceModelType::StableDiffusion); + assert_eq!(InferenceModelType::from_str("image_gen_api").unwrap(), InferenceModelType::ImageGenApi); + assert_eq!(InferenceModelType::from_str("mocap_net").unwrap(), InferenceModelType::MocapNet); + assert_eq!(InferenceModelType::from_str("styletts2").unwrap(), InferenceModelType::StyleTTS2); + assert_eq!(InferenceModelType::from_str("comfy_ui").unwrap(), InferenceModelType::ComfyUi); + assert_eq!(InferenceModelType::from_str("convert_fbx_gltf").unwrap(), InferenceModelType::ConvertFbxToGltf); + assert_eq!(InferenceModelType::from_str("bvh_to_workflow").unwrap(), InferenceModelType::BvhToWorkflow); + } + + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip() { + use strum::IntoEnumIterator; + for variant in InferenceModelType::iter() { + assert_eq!(variant, InferenceModelType::from_str(variant.to_str()).unwrap()); + assert_eq!(variant, InferenceModelType::from_str(&format!("{}", variant)).unwrap()); + assert_eq!(variant, InferenceModelType::from_str(&format!("{:?}", variant)).unwrap()); + } + } + + #[test] + fn serialized_length_ok_for_database() { + use strum::IntoEnumIterator; + const MAX_LENGTH : usize = 32; + for variant in InferenceModelType::iter() { + let serialized = variant.to_str(); + assert!(serialized.len() > 0, "variant {:?} is too short", variant); + assert!(serialized.len() <= MAX_LENGTH, "variant {:?} is too long", variant); + } + } + } +} diff --git a/crates/schema/public/enums_db/src/by_table/generic_inference_jobs/inference_result_type.rs b/crates/schema/public/enums_db/src/by_table/generic_inference_jobs/inference_result_type.rs new file mode 100644 index 0000000000..fa334a403d --- /dev/null +++ b/crates/schema/public/enums_db/src/by_table/generic_inference_jobs/inference_result_type.rs @@ -0,0 +1,118 @@ +use strum::EnumCount; +use strum::EnumIter; + +/// Used in the `generic_inference_jobs` table in `VARCHAR(32)` field `on_success_result_entity_type`. +/// +/// Our "generic inference" pipeline supports a wide variety of output types. +/// Each "result type" is identified by the following enum variants. +/// +/// These types are present in the HTTP API and database columns as serialized here. +/// +/// YOU CAN ADD NEW VALUES, BUT DO NOT CHANGE EXISTING VALUES WITHOUT A MIGRATION STRATEGY. +#[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, Deserialize, Serialize, EnumIter, EnumCount)] +pub enum InferenceResultType { + /// Result is stored in the "media_files" table. + /// (The upstream model could have produced any type of media - image, video, audio. That is irrelevant.) + #[serde(rename = "media_file")] + MediaFile, + + #[serde(rename = "text_to_speech")] + TextToSpeech, + + #[serde(rename = "voice_conversion")] + VoiceConversion, + + #[serde(rename = "zs_voice_embedding")] + ZeroShotVoiceEmbedding, + + #[serde(rename = "upload_model")] + UploadModel +} + +// TODO(bt, 2022-12-21): This desperately needs MySQL integration tests! +impl_enum_display_and_debug_using_to_str!(InferenceResultType); +impl_mysql_enum_coders!(InferenceResultType); +impl_mysql_from_row!(InferenceResultType); + +/// NB: Legacy API for older code. +impl InferenceResultType { + pub fn to_str(&self) -> &'static str { + match self { + Self::MediaFile => "media_file", + Self::TextToSpeech => "text_to_speech", + Self::VoiceConversion => "voice_conversion", + Self::ZeroShotVoiceEmbedding => "zs_voice_embedding", + Self::UploadModel => "upload_model", + } + } + + pub fn from_str(value: &str) -> Result { + match value { + "media_file" => Ok(Self::MediaFile), + "text_to_speech" => Ok(Self::TextToSpeech), + "voice_conversion" => Ok(Self::VoiceConversion), + "zs_voice_embedding" => Ok(Self::ZeroShotVoiceEmbedding), + "upload_model" => Ok(Self::UploadModel), + _ => Err(format!("invalid value: {:?}", value)), + } + } + +} + +#[cfg(test)] +mod tests { + use super::super::inference_result_type::InferenceResultType; + use enums_shared::test_helpers::assert_serialization; + + #[test] + fn test_serialization() { + assert_serialization(InferenceResultType::MediaFile, "media_file"); + assert_serialization(InferenceResultType::TextToSpeech, "text_to_speech"); + assert_serialization(InferenceResultType::VoiceConversion, "voice_conversion"); + assert_serialization(InferenceResultType::ZeroShotVoiceEmbedding, "zs_voice_embedding"); + assert_serialization(InferenceResultType::UploadModel, "upload_model"); + } + + #[test] + fn to_str() { + assert_eq!(InferenceResultType::MediaFile.to_str(), "media_file"); + assert_eq!(InferenceResultType::TextToSpeech.to_str(), "text_to_speech"); + assert_eq!(InferenceResultType::VoiceConversion.to_str(), "voice_conversion"); + assert_eq!(InferenceResultType::ZeroShotVoiceEmbedding.to_str(), "zs_voice_embedding"); + assert_eq!(InferenceResultType::UploadModel.to_str(), "upload_model"); + } + + #[test] + fn from_str() { + assert_eq!(InferenceResultType::from_str("media_file").unwrap(), InferenceResultType::MediaFile); + assert_eq!(InferenceResultType::from_str("text_to_speech").unwrap(), InferenceResultType::TextToSpeech); + assert_eq!(InferenceResultType::from_str("voice_conversion").unwrap(), InferenceResultType::VoiceConversion); + assert_eq!(InferenceResultType::from_str("zs_voice_embedding").unwrap(), InferenceResultType::ZeroShotVoiceEmbedding); + assert_eq!(InferenceResultType::from_str("upload_model").unwrap(), InferenceResultType::UploadModel); + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip() { + use strum::IntoEnumIterator; + for variant in InferenceResultType::iter() { + assert_eq!(variant, InferenceResultType::from_str(variant.to_str()).unwrap()); + assert_eq!(variant, InferenceResultType::from_str(&format!("{}", variant)).unwrap()); + assert_eq!(variant, InferenceResultType::from_str(&format!("{:?}", variant)).unwrap()); + } + } + + #[test] + fn serialized_length_ok_for_database() { + const MAX_LENGTH: usize = 32; // TODO(bt): Confirm database column width, then remove this comment. + use strum::IntoEnumIterator; + for variant in InferenceResultType::iter() { + let serialized = variant.to_str(); + assert!(!serialized.is_empty(), "variant {:?} is too short", variant); + assert!(serialized.len() <= MAX_LENGTH, "variant {:?} is too long", variant); + } + } + } +} diff --git a/crates/schema/public/enums_db/src/by_table/generic_inference_jobs/mod.rs b/crates/schema/public/enums_db/src/by_table/generic_inference_jobs/mod.rs new file mode 100644 index 0000000000..ab12b4e367 --- /dev/null +++ b/crates/schema/public/enums_db/src/by_table/generic_inference_jobs/mod.rs @@ -0,0 +1,8 @@ +pub mod frontend_failure_category; +pub mod inference_category; +pub mod inference_input_source_token_type; +pub mod inference_job_external_third_party; +pub mod inference_job_product_category; +pub mod inference_job_type; +pub mod inference_model_type; +pub mod inference_result_type; diff --git a/crates/schema/public/enums_db/src/by_table/generic_synthetic_ids/id_category.rs b/crates/schema/public/enums_db/src/by_table/generic_synthetic_ids/id_category.rs new file mode 100644 index 0000000000..3cebfd28e4 --- /dev/null +++ b/crates/schema/public/enums_db/src/by_table/generic_synthetic_ids/id_category.rs @@ -0,0 +1,214 @@ +use strum::EnumCount; +use strum::EnumIter; + +/// Used in the `generic_synthetic_ids` table in `VARCHAR(32)` field `id_category`. +/// +/// This lets us create synthetic increment IDs on a per-user, per-category basis. +/// +/// DO NOT CHANGE VALUES WITHOUT A MIGRATION STRATEGY. +#[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, Deserialize, Serialize, EnumIter, EnumCount)] +pub enum IdCategory { + /// media_files table + #[serde(rename = "media_file")] + MediaFile, + + /// Results from lipsync animations (which may live in the media_files table) + #[serde(rename = "lipsync_animation")] + LipsyncAnimationResult, + + /// Results from face fusion + #[serde(rename = "face_fusion")] + FaceFusionResult, + + /// Results from video filters + #[serde(rename = "video_filter")] + VideoFilterResult, + + /// Results from Live Portrait + #[serde(rename = "live_portrait")] + LivePortraitResult, + + /// Studio Renders + #[serde(rename = "studio_render")] + StudioRender, + + /// Results from mocap + #[serde(rename = "mocap")] + MocapResult, + + /// Results from workflows + #[serde(rename = "workflow")] + WorkflowResult, + + /// Results from tacotron2 + /// Applies for RVC and SVC + #[serde(rename = "tts_result")] + TtsResult, + + /// Results from voice conversion (which may live in the media_files table) + /// Applies for RVC and SVC + #[serde(rename = "voice_conversion")] + VoiceConversionResult, + + /// Results from the zero shot tts (which may live in the media_files table) + #[serde(rename = "zs_tts_result")] + ZeroShotTtsResult, + + /// Zs dataset which lives in the zs_voice_datasets table + #[serde(rename = "zs_dataset")] + ZeroShotVoiceDataset, + + /// Zs voice which lives in the zs_voices table + #[serde(rename = "zs_voice")] + ZeroShotVoiceEmbedding, + + #[serde(rename = "model_weights")] + ModelWeights, + + /// Files that are uploaded with no general product area they belong to. (Eg. local dev testing) + #[serde(rename = "file_upload")] + FileUpload, +} + +// TODO(bt, 2022-12-21): This desperately needs MySQL integration tests! +impl_enum_display_and_debug_using_to_str!(IdCategory); +impl_mysql_enum_coders!(IdCategory); +impl_mysql_from_row!(IdCategory); + +/// NB: Legacy API for older code. +impl IdCategory { + pub fn to_str(&self) -> &'static str { + match self { + Self::MediaFile => "media_file", + Self::LipsyncAnimationResult => "lipsync_animation", + Self::FaceFusionResult => "face_fusion", + Self::TtsResult => "tts_result", + Self::VoiceConversionResult => "voice_conversion", + Self::ZeroShotVoiceDataset => "zs_dataset", + Self::ZeroShotVoiceEmbedding => "zs_voice", + Self::ZeroShotTtsResult => "zs_tts_result", + Self::VideoFilterResult => "video_filter", + Self::LivePortraitResult => "live_portrait", + Self::StudioRender => "studio_render", + Self::ModelWeights => "model_weights", + Self::FileUpload => "file_upload", + Self::MocapResult => "mocap", + Self::WorkflowResult => "workflow", + } + } + + pub fn from_str(value: &str) -> Result { + match value { + "media_file" => Ok(Self::MediaFile), + "lipsync_animation" => Ok(Self::LipsyncAnimationResult), + "face_fusion" => Ok(Self::FaceFusionResult), + "tts_result" => Ok(Self::TtsResult), + "voice_conversion" => Ok(Self::VoiceConversionResult), + "zs_dataset" => Ok(Self::ZeroShotVoiceDataset), + "zs_voice" => Ok(Self::ZeroShotVoiceEmbedding), + "zs_tts_result" => Ok(Self::ZeroShotTtsResult), + "video_filter" => Ok(Self::VideoFilterResult), + "live_portrait" => Ok(Self::LivePortraitResult), + "studio_render" => Ok(Self::StudioRender), + "model_weights" => Ok(Self::ModelWeights), + "file_upload" => Ok(Self::FileUpload), + "mocap" => Ok(Self::MocapResult), + "workflow" => Ok(Self::WorkflowResult), + _ => Err(format!("invalid value: {:?}", value)), + } + } + +} + +#[cfg(test)] +mod tests { + use super::super::id_category::IdCategory; + use enums_shared::test_helpers::assert_serialization; + + mod explicit_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(IdCategory::MediaFile, "media_file"); + assert_serialization(IdCategory::LipsyncAnimationResult, "lipsync_animation"); + assert_serialization(IdCategory::FaceFusionResult, "face_fusion"); + assert_serialization(IdCategory::VideoFilterResult, "video_filter"); + assert_serialization(IdCategory::LivePortraitResult, "live_portrait"); + assert_serialization(IdCategory::StudioRender, "studio_render"); + assert_serialization(IdCategory::TtsResult, "tts_result"); + assert_serialization(IdCategory::VoiceConversionResult, "voice_conversion"); + assert_serialization(IdCategory::ZeroShotVoiceDataset, "zs_dataset"); + assert_serialization(IdCategory::ZeroShotVoiceEmbedding, "zs_voice"); + assert_serialization(IdCategory::ZeroShotTtsResult, "zs_tts_result"); + assert_serialization(IdCategory::ModelWeights, "model_weights"); + assert_serialization(IdCategory::FileUpload, "file_upload"); + assert_serialization(IdCategory::MocapResult, "mocap"); + assert_serialization(IdCategory::WorkflowResult, "workflow"); + } + + #[test] + fn to_str() { + assert_eq!(IdCategory::MediaFile.to_str(), "media_file"); + assert_eq!(IdCategory::LipsyncAnimationResult.to_str(), "lipsync_animation"); + assert_eq!(IdCategory::FaceFusionResult.to_str(), "face_fusion"); + assert_eq!(IdCategory::VideoFilterResult.to_str(), "video_filter"); + assert_eq!(IdCategory::LivePortraitResult.to_str(), "live_portrait"); + assert_eq!(IdCategory::StudioRender.to_str(), "studio_render"); + assert_eq!(IdCategory::TtsResult.to_str(), "tts_result"); + assert_eq!(IdCategory::VoiceConversionResult.to_str(), "voice_conversion"); + assert_eq!(IdCategory::ZeroShotVoiceDataset.to_str(), "zs_dataset"); + assert_eq!(IdCategory::ZeroShotVoiceEmbedding.to_str(), "zs_voice"); + assert_eq!(IdCategory::ZeroShotTtsResult.to_str(), "zs_tts_result"); + assert_eq!(IdCategory::ModelWeights.to_str(), "model_weights"); + assert_eq!(IdCategory::FileUpload.to_str(), "file_upload"); + assert_eq!(IdCategory::MocapResult.to_str(), "mocap"); + assert_eq!(IdCategory::WorkflowResult.to_str(), "workflow"); + } + + #[test] + fn from_str() { + assert_eq!(IdCategory::from_str("media_file").unwrap(), IdCategory::MediaFile); + assert_eq!(IdCategory::from_str("lipsync_animation").unwrap(), IdCategory::LipsyncAnimationResult); + assert_eq!(IdCategory::from_str("face_fusion").unwrap(), IdCategory::FaceFusionResult); + assert_eq!(IdCategory::from_str("video_filter").unwrap(), IdCategory::VideoFilterResult); + assert_eq!(IdCategory::from_str("live_portrait").unwrap(), IdCategory::LivePortraitResult); + assert_eq!(IdCategory::from_str("studio_render").unwrap(), IdCategory::StudioRender); + assert_eq!(IdCategory::from_str("tts_result").unwrap(), IdCategory::TtsResult); + assert_eq!(IdCategory::from_str("voice_conversion").unwrap(), IdCategory::VoiceConversionResult); + assert_eq!(IdCategory::from_str("zs_dataset").unwrap(), IdCategory::ZeroShotVoiceDataset); + assert_eq!(IdCategory::from_str("zs_voice").unwrap(), IdCategory::ZeroShotVoiceEmbedding); + assert_eq!(IdCategory::from_str("zs_tts_result").unwrap(), IdCategory::ZeroShotTtsResult); + assert_eq!(IdCategory::from_str("model_weights").unwrap(), IdCategory::ModelWeights); + assert_eq!(IdCategory::from_str("file_upload").unwrap(), IdCategory::FileUpload); + assert_eq!(IdCategory::from_str("mocap").unwrap(), IdCategory::MocapResult); + assert_eq!(IdCategory::from_str("workflow").unwrap(), IdCategory::WorkflowResult); + } + + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip() { + use strum::IntoEnumIterator; + for variant in IdCategory::iter() { + assert_eq!(variant, IdCategory::from_str(variant.to_str()).unwrap()); + assert_eq!(variant, IdCategory::from_str(&format!("{}", variant)).unwrap()); + assert_eq!(variant, IdCategory::from_str(&format!("{:?}", variant)).unwrap()); + } + } + + #[test] + fn serialized_length_ok_for_database() { + const MAX_LENGTH: usize = 32; // TODO(bt): Confirm database column width, then remove this comment. + use strum::IntoEnumIterator; + for variant in IdCategory::iter() { + let serialized = variant.to_str(); + assert!(!serialized.is_empty(), "variant {:?} is too short", variant); + assert!(serialized.len() <= MAX_LENGTH, "variant {:?} is too long", variant); + } + } + } +} diff --git a/crates/schema/public/enums_db/src/by_table/generic_synthetic_ids/mod.rs b/crates/schema/public/enums_db/src/by_table/generic_synthetic_ids/mod.rs new file mode 100644 index 0000000000..f130b83c6e --- /dev/null +++ b/crates/schema/public/enums_db/src/by_table/generic_synthetic_ids/mod.rs @@ -0,0 +1 @@ +pub mod id_category; diff --git a/crates/schema/public/enums_db/src/by_table/media_files/media_file_animation_type.rs b/crates/schema/public/enums_db/src/by_table/media_files/media_file_animation_type.rs new file mode 100644 index 0000000000..da939798c3 --- /dev/null +++ b/crates/schema/public/enums_db/src/by_table/media_files/media_file_animation_type.rs @@ -0,0 +1,195 @@ +use strum::EnumCount; +use strum::EnumIter; + +/// Used in the `media_files` table in a `VARCHAR` field. +/// +/// DO NOT CHANGE VALUES WITHOUT A MIGRATION STRATEGY. +#[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, Deserialize, Serialize, EnumIter, EnumCount)] +#[serde(rename_all = "snake_case")] +pub enum MediaFileAnimationType { + /// Body: No body animation or rig. + /// Face: Rig supporting ARKit face blendshapes, or ARKit data + ArKit, + + /// Body: Animation or rig for MikuMikuDance (MMD). + /// Face: No face animation. + MikuMikuDance, + + /// Body: Animation or rig for MikuMikuDance (MMD). + /// Face: Animation blendshapes for ARKit. + MikuMikuDanceArKit, + + /// Body: Animation or rig for Mixamo + /// Face: No face animation. + Mixamo, + + /// Body: Animation or rig for Mixamo + /// Face: Animation blendshapes for ARKit. + MixamoArKit, + + /// Body: Animation or rig by MocapNet + /// Face: No face animation. + MocapNet, + + /// Body: Animation or rig for MocapNet + /// Face: Animation blendshapes for ARKit. + MocapNetArKit, + + /// Body: Animation or rig by Move.ai + /// Face: No face animation. + MoveAi, + + /// Body: Animation or rig for Move.ai + /// Face: Animation blendshapes for ARKit. + MoveAiArKit, + + /// Body: Animation or rig for Rigify. + /// Face: No face animation. + Rigify, + + /// Body: Animation or rig for Rigify. + /// Face: Animation blendshapes for ARKit. + RigifyArKit, + + /// Body: Animation or rig for Rokoko. + /// Face: No face animation. + Rokoko, + + /// Body: Animation or rig for Rokoko. + /// Face: Animation blendshapes for ARKit. + RokokoArKit, +} + +// TODO(bt, 2022-12-21): This desperately needs MySQL integration tests! +impl_enum_display_and_debug_using_to_str!(MediaFileAnimationType); +impl_mysql_enum_coders!(MediaFileAnimationType); +impl_mysql_from_row!(MediaFileAnimationType); + +/// NB: Legacy API for older code. +impl MediaFileAnimationType { + pub fn to_str(&self) -> &'static str { + match self { + Self::ArKit => "ar_kit", + Self::MikuMikuDance => "miku_miku_dance", + Self::MikuMikuDanceArKit => "miku_miku_dance_ar_kit", + Self::Mixamo => "mixamo", + Self::MixamoArKit => "mixamo_ar_kit", + Self::MocapNet => "mocap_net", + Self::MocapNetArKit => "mocap_net_ar_kit", + Self::MoveAi => "move_ai", + Self::MoveAiArKit => "move_ai_ar_kit", + Self::Rigify => "rigify", + Self::RigifyArKit => "rigify_ar_kit", + Self::Rokoko => "rokoko", + Self::RokokoArKit => "rokoko_ar_kit", + } + } + + pub fn from_str(value: &str) -> Result { + match value { + "ar_kit" => Ok(Self::ArKit), + "miku_miku_dance" => Ok(Self::MikuMikuDance), + "miku_miku_dance_ar_kit" => Ok(Self::MikuMikuDanceArKit), + "mixamo" => Ok(Self::Mixamo), + "mixamo_ar_kit" => Ok(Self::MixamoArKit), + "mocap_net" => Ok(Self::MocapNet), + "mocap_net_ar_kit" => Ok(Self::MocapNetArKit), + "move_ai" => Ok(Self::MoveAi), + "move_ai_ar_kit" => Ok(Self::MoveAiArKit), + "rigify" => Ok(Self::Rigify), + "rigify_ar_kit" => Ok(Self::RigifyArKit), + "rokoko" => Ok(Self::Rokoko), + "rokoko_ar_kit" => Ok(Self::RokokoArKit), + _ => Err(format!("invalid value: {:?}", value)), + } + } + +} + +#[cfg(test)] +mod tests { + use super::super::media_file_animation_type::MediaFileAnimationType; + use enums_shared::test_helpers::assert_serialization; + + mod explicit_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(MediaFileAnimationType::ArKit, "ar_kit"); + assert_serialization(MediaFileAnimationType::MikuMikuDance, "miku_miku_dance"); + assert_serialization(MediaFileAnimationType::MikuMikuDanceArKit, "miku_miku_dance_ar_kit"); + assert_serialization(MediaFileAnimationType::Mixamo, "mixamo"); + assert_serialization(MediaFileAnimationType::MixamoArKit, "mixamo_ar_kit"); + assert_serialization(MediaFileAnimationType::MocapNet, "mocap_net"); + assert_serialization(MediaFileAnimationType::MocapNetArKit, "mocap_net_ar_kit"); + assert_serialization(MediaFileAnimationType::MoveAi, "move_ai"); + assert_serialization(MediaFileAnimationType::MoveAiArKit, "move_ai_ar_kit"); + assert_serialization(MediaFileAnimationType::Rigify, "rigify"); + assert_serialization(MediaFileAnimationType::RigifyArKit, "rigify_ar_kit"); + assert_serialization(MediaFileAnimationType::Rokoko, "rokoko"); + assert_serialization(MediaFileAnimationType::RokokoArKit, "rokoko_ar_kit"); + } + + #[test] + fn test_to_str() { + assert_eq!(MediaFileAnimationType::ArKit.to_str(), "ar_kit"); + assert_eq!(MediaFileAnimationType::MikuMikuDance.to_str(), "miku_miku_dance"); + assert_eq!(MediaFileAnimationType::MikuMikuDanceArKit.to_str(), "miku_miku_dance_ar_kit"); + assert_eq!(MediaFileAnimationType::Mixamo.to_str(), "mixamo"); + assert_eq!(MediaFileAnimationType::MixamoArKit.to_str(), "mixamo_ar_kit"); + assert_eq!(MediaFileAnimationType::MocapNet.to_str(), "mocap_net"); + assert_eq!(MediaFileAnimationType::MocapNetArKit.to_str(), "mocap_net_ar_kit"); + assert_eq!(MediaFileAnimationType::MoveAi.to_str(), "move_ai"); + assert_eq!(MediaFileAnimationType::MoveAiArKit.to_str(), "move_ai_ar_kit"); + assert_eq!(MediaFileAnimationType::Rigify.to_str(), "rigify"); + assert_eq!(MediaFileAnimationType::RigifyArKit.to_str(), "rigify_ar_kit"); + assert_eq!(MediaFileAnimationType::Rokoko.to_str(), "rokoko"); + assert_eq!(MediaFileAnimationType::RokokoArKit.to_str(), "rokoko_ar_kit"); + } + + #[test] + fn test_from_str() { + assert_eq!(MediaFileAnimationType::from_str("ar_kit").unwrap(), MediaFileAnimationType::ArKit); + assert_eq!(MediaFileAnimationType::from_str("miku_miku_dance").unwrap(), MediaFileAnimationType::MikuMikuDance); + assert_eq!(MediaFileAnimationType::from_str("miku_miku_dance_ar_kit").unwrap(), MediaFileAnimationType::MikuMikuDanceArKit); + assert_eq!(MediaFileAnimationType::from_str("mixamo").unwrap(), MediaFileAnimationType::Mixamo); + assert_eq!(MediaFileAnimationType::from_str("mixamo_ar_kit").unwrap(), MediaFileAnimationType::MixamoArKit); + assert_eq!(MediaFileAnimationType::from_str("mocap_net").unwrap(), MediaFileAnimationType::MocapNet); + assert_eq!(MediaFileAnimationType::from_str("mocap_net_ar_kit").unwrap(), MediaFileAnimationType::MocapNetArKit); + assert_eq!(MediaFileAnimationType::from_str("move_ai").unwrap(), MediaFileAnimationType::MoveAi); + assert_eq!(MediaFileAnimationType::from_str("move_ai_ar_kit").unwrap(), MediaFileAnimationType::MoveAiArKit); + assert_eq!(MediaFileAnimationType::from_str("rigify").unwrap(), MediaFileAnimationType::Rigify); + assert_eq!(MediaFileAnimationType::from_str("rigify_ar_kit").unwrap(), MediaFileAnimationType::RigifyArKit); + assert_eq!(MediaFileAnimationType::from_str("rokoko").unwrap(), MediaFileAnimationType::Rokoko); + assert_eq!(MediaFileAnimationType::from_str("rokoko_ar_kit").unwrap(), MediaFileAnimationType::RokokoArKit); + assert!(MediaFileAnimationType::from_str("foo").is_err()); + } + + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip() { + use strum::IntoEnumIterator; + for variant in MediaFileAnimationType::iter() { + assert_eq!(variant, MediaFileAnimationType::from_str(variant.to_str()).unwrap()); + assert_eq!(variant, MediaFileAnimationType::from_str(&format!("{}", variant)).unwrap()); + assert_eq!(variant, MediaFileAnimationType::from_str(&format!("{:?}", variant)).unwrap()); + } + } + + #[test] + fn serialized_length_ok_for_database() { + use strum::IntoEnumIterator; + const MAX_LENGTH : usize = 32; + for variant in MediaFileAnimationType::iter() { + let serialized = variant.to_str(); + assert!(serialized.len() > 0, "variant {:?} is too short", variant); + assert!(serialized.len() <= MAX_LENGTH, "variant {:?} is too long", variant); + } + } + } +} diff --git a/crates/schema/public/enums_db/src/by_table/media_files/media_file_class.rs b/crates/schema/public/enums_db/src/by_table/media_files/media_file_class.rs new file mode 100644 index 0000000000..af3470ba86 --- /dev/null +++ b/crates/schema/public/enums_db/src/by_table/media_files/media_file_class.rs @@ -0,0 +1,122 @@ +use strum::EnumCount; +use strum::EnumIter; + +/// Used in the `media_files` table in a `VARCHAR(16)` field. +/// +/// DO NOT CHANGE VALUES WITHOUT A MIGRATION STRATEGY. +#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash, Deserialize, Serialize, EnumIter, EnumCount)] +#[serde(rename_all = "snake_case")] +pub enum MediaFileClass { + /// Unknown (default value) + /// This will be present until we migrate all old files. + Unknown, + + /// Audio files: wav, mp3, etc. + Audio, + + /// Image files: png, jpeg, etc. + Image, + + /// Video files: mp4, etc. + Video, + + /// 3D engine data: glb, gltf, etc. + Dimensional, +} + +// TODO(bt, 2022-12-21): This desperately needs MySQL integration tests! +impl_enum_display_and_debug_using_to_str!(MediaFileClass); +impl_mysql_enum_coders!(MediaFileClass); +impl_mysql_from_row!(MediaFileClass); + +/// NB: Legacy API for older code. +impl MediaFileClass { + pub const fn to_str(&self) -> &'static str { + match self { + Self::Unknown => "unknown", + Self::Audio => "audio", + Self::Image => "image", + Self::Video => "video", + Self::Dimensional => "dimensional", + } + } + + pub fn from_str(value: &str) -> Result { + match value { + "unknown" => Ok(Self::Unknown), + "audio" => Ok(Self::Audio), + "image" => Ok(Self::Image), + "video" => Ok(Self::Video), + "dimensional" => Ok(Self::Dimensional), + _ => Err(format!("invalid value: {:?}", value)), + } + } + +} + +#[cfg(test)] +mod tests { + use super::super::media_file_class::MediaFileClass; + use enums_shared::test_helpers::assert_serialization; + + mod serde { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(MediaFileClass::Unknown, "unknown"); + assert_serialization(MediaFileClass::Audio, "audio"); + assert_serialization(MediaFileClass::Image, "image"); + assert_serialization(MediaFileClass::Video, "video"); + assert_serialization(MediaFileClass::Dimensional, "dimensional"); + } + } + + mod impl_methods { + use super::*; + + #[test] + fn to_str() { + assert_eq!(MediaFileClass::Unknown.to_str(), "unknown"); + assert_eq!(MediaFileClass::Audio.to_str(), "audio"); + assert_eq!(MediaFileClass::Image.to_str(), "image"); + assert_eq!(MediaFileClass::Video.to_str(), "video"); + assert_eq!(MediaFileClass::Dimensional.to_str(), "dimensional"); + } + + #[test] + fn from_str() { + assert_eq!(MediaFileClass::from_str("unknown").unwrap(), MediaFileClass::Unknown); + assert_eq!(MediaFileClass::from_str("audio").unwrap(), MediaFileClass::Audio); + assert_eq!(MediaFileClass::from_str("image").unwrap(), MediaFileClass::Image); + assert_eq!(MediaFileClass::from_str("video").unwrap(), MediaFileClass::Video); + assert_eq!(MediaFileClass::from_str("dimensional").unwrap(), MediaFileClass::Dimensional); + assert!(MediaFileClass::from_str("foo").is_err()); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip() { + use strum::IntoEnumIterator; + for variant in MediaFileClass::iter() { + assert_eq!(variant, MediaFileClass::from_str(variant.to_str()).unwrap()); + assert_eq!(variant, MediaFileClass::from_str(&format!("{}", variant)).unwrap()); + assert_eq!(variant, MediaFileClass::from_str(&format!("{:?}", variant)).unwrap()); + } + } + + #[test] + fn serialized_length_ok_for_database() { + use strum::IntoEnumIterator; + const MAX_LENGTH : usize = 16; + for variant in MediaFileClass::iter() { + let serialized = variant.to_str(); + assert!(serialized.len() > 0, "variant {:?} is too short", variant); + assert!(serialized.len() <= MAX_LENGTH, "variant {:?} is too long", variant); + } + } + } +} diff --git a/crates/schema/public/enums_db/src/by_table/media_files/media_file_engine_category.rs b/crates/schema/public/enums_db/src/by_table/media_files/media_file_engine_category.rs new file mode 100644 index 0000000000..07ec9d0676 --- /dev/null +++ b/crates/schema/public/enums_db/src/by_table/media_files/media_file_engine_category.rs @@ -0,0 +1,173 @@ +use strum::EnumCount; +use strum::EnumIter; + +/// Used in the `media_files` table in a `VARCHAR` field. +/// +/// DO NOT CHANGE VALUES WITHOUT A MIGRATION STRATEGY. +#[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, Deserialize, Serialize, EnumIter, EnumCount)] +#[serde(rename_all = "snake_case")] +pub enum MediaFileEngineCategory { + /// A 3D scene full of objects, characters, animations, etc. + Scene, + + /// A 3D character model. + Character, + + /// A 3D non-humanoid model, e.g. dragon, wolf, slime creature, etc. + /// These may or may not have a skeleton that can be animated with IK/FK. + Creature, + + /// A 3D skeletal animation sequence that can be applied to a character, + /// creature, etc. Typically, these use Mixamo or Move.ai. + Animation, + + /// A facial blend shape / shape key animation. Currently, these + /// are 100% ARKit. + Expression, + + /// A large 3D object that can be used as a backdrop for a scene, + /// a.k.a. "set", "stage", etc. These are typically self-contained + /// locations, buildings, or environments. + Location, + + /// All items used to add atmosphere to a scene, e.g. furniture, plants, + /// vehicles, radios, and certain props. (We'll reserve the word props for + /// "hand props" later.) + SetDressing, + + /// A 3D object that doesn't fit with the other types. + Object, + + /// A 3D skybox. + Skybox, + + /// An Image Plane (texture that spawns as an object) + ImagePlane, + + /// A Video Plane (texture that spawns as an object) + VideoPlane, +} + +// TODO(bt, 2022-12-21): This desperately needs MySQL integration tests! +impl_enum_display_and_debug_using_to_str!(MediaFileEngineCategory); +impl_mysql_enum_coders!(MediaFileEngineCategory); +impl_mysql_from_row!(MediaFileEngineCategory); + +/// NB: Legacy API for older code. +impl MediaFileEngineCategory { + pub fn to_str(&self) -> &'static str { + match self { + Self::Scene => "scene", + Self::Character => "character", + Self::Creature => "creature", + Self::Animation => "animation", + Self::Expression => "expression", + Self::Location => "location", + Self::SetDressing => "set_dressing", + Self::Object => "object", + Self::Skybox => "skybox", + Self::ImagePlane => "image_plane", + Self::VideoPlane => "video_plane", + } + } + + pub fn from_str(value: &str) -> Result { + match value { + "scene" => Ok(Self::Scene), + "character" => Ok(Self::Character), + "creature" => Ok(Self::Creature), + "animation" => Ok(Self::Animation), + "expression" => Ok(Self::Expression), + "location" => Ok(Self::Location), + "set_dressing" => Ok(Self::SetDressing), + "object" => Ok(Self::Object), + "skybox" => Ok(Self::Skybox), + "image_plane" => Ok(Self::ImagePlane), + "video_plane" => Ok(Self::VideoPlane), + _ => Err(format!("invalid value: {:?}", value)), + } + } + +} + +#[cfg(test)] +mod tests { + use super::super::media_file_engine_category::MediaFileEngineCategory; + use enums_shared::test_helpers::assert_serialization; + + mod explicit_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(MediaFileEngineCategory::Scene, "scene"); + assert_serialization(MediaFileEngineCategory::Character, "character"); + assert_serialization(MediaFileEngineCategory::Creature, "creature"); + assert_serialization(MediaFileEngineCategory::Animation, "animation"); + assert_serialization(MediaFileEngineCategory::Expression, "expression"); + assert_serialization(MediaFileEngineCategory::Location, "location"); + assert_serialization(MediaFileEngineCategory::SetDressing, "set_dressing"); + assert_serialization(MediaFileEngineCategory::Object, "object"); + assert_serialization(MediaFileEngineCategory::Skybox, "skybox"); + assert_serialization(MediaFileEngineCategory::ImagePlane, "image_plane"); + assert_serialization(MediaFileEngineCategory::VideoPlane, "video_plane"); + } + + #[test] + fn test_to_str() { + assert_eq!(MediaFileEngineCategory::Scene.to_str(), "scene"); + assert_eq!(MediaFileEngineCategory::Character.to_str(), "character"); + assert_eq!(MediaFileEngineCategory::Creature.to_str(), "creature"); + assert_eq!(MediaFileEngineCategory::Animation.to_str(), "animation"); + assert_eq!(MediaFileEngineCategory::Expression.to_str(), "expression"); + assert_eq!(MediaFileEngineCategory::Location.to_str(), "location"); + assert_eq!(MediaFileEngineCategory::SetDressing.to_str(), "set_dressing"); + assert_eq!(MediaFileEngineCategory::Object.to_str(), "object"); + assert_eq!(MediaFileEngineCategory::Skybox.to_str(), "skybox"); + assert_eq!(MediaFileEngineCategory::ImagePlane.to_str(), "image_plane"); + assert_eq!(MediaFileEngineCategory::VideoPlane.to_str(), "video_plane"); + } + + #[test] + fn test_from_str() { + assert_eq!(MediaFileEngineCategory::from_str("scene").unwrap(), MediaFileEngineCategory::Scene); + assert_eq!(MediaFileEngineCategory::from_str("character").unwrap(), MediaFileEngineCategory::Character); + assert_eq!(MediaFileEngineCategory::from_str("creature").unwrap(), MediaFileEngineCategory::Creature); + assert_eq!(MediaFileEngineCategory::from_str("animation").unwrap(), MediaFileEngineCategory::Animation); + assert_eq!(MediaFileEngineCategory::from_str("expression").unwrap(), MediaFileEngineCategory::Expression); + assert_eq!(MediaFileEngineCategory::from_str("location").unwrap(), MediaFileEngineCategory::Location); + assert_eq!(MediaFileEngineCategory::from_str("set_dressing").unwrap(), MediaFileEngineCategory::SetDressing); + assert_eq!(MediaFileEngineCategory::from_str("object").unwrap(), MediaFileEngineCategory::Object); + assert_eq!(MediaFileEngineCategory::from_str("skybox").unwrap(), MediaFileEngineCategory::Skybox); + assert_eq!(MediaFileEngineCategory::from_str("image_plane").unwrap(), MediaFileEngineCategory::ImagePlane); + assert_eq!(MediaFileEngineCategory::from_str("video_plane").unwrap(), MediaFileEngineCategory::VideoPlane); + assert!(MediaFileEngineCategory::from_str("foo").is_err()); + } + + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip() { + use strum::IntoEnumIterator; + for variant in MediaFileEngineCategory::iter() { + assert_eq!(variant, MediaFileEngineCategory::from_str(variant.to_str()).unwrap()); + assert_eq!(variant, MediaFileEngineCategory::from_str(&format!("{}", variant)).unwrap()); + assert_eq!(variant, MediaFileEngineCategory::from_str(&format!("{:?}", variant)).unwrap()); + } + } + + #[test] + fn serialized_length_ok_for_database() { + use strum::IntoEnumIterator; + const MAX_LENGTH : usize = 16; + for variant in MediaFileEngineCategory::iter() { + let serialized = variant.to_str(); + assert!(serialized.len() > 0, "variant {:?} is too short", variant); + assert!(serialized.len() <= MAX_LENGTH, "variant {:?} is too long", variant); + } + } + } +} diff --git a/crates/schema/public/enums_db/src/by_table/media_files/media_file_origin_category.rs b/crates/schema/public/enums_db/src/by_table/media_files/media_file_origin_category.rs new file mode 100644 index 0000000000..330d3638c0 --- /dev/null +++ b/crates/schema/public/enums_db/src/by_table/media_files/media_file_origin_category.rs @@ -0,0 +1,129 @@ +use strum::EnumCount; +use strum::EnumIter; + +/// Used in the `media_files` table in a `VARCHAR` field. +/// +/// DO NOT CHANGE VALUES WITHOUT A MIGRATION STRATEGY. +#[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, Deserialize, Serialize, EnumIter, EnumCount)] +#[serde(rename_all = "snake_case")] +pub enum MediaFileOriginCategory { + /// ML model inference output - uploaded models or zero shot. + Inference, + + /// Processed results - (we don't have these systems yet, but eg. trim, transcode, etc). + Processed, + + /// User uploaded files (from their filesystem) + Upload, + + /// User uploaded files recorded directly from their device (browser, mobile), typically using device APIs. + DeviceApi, + + /// From Storyteller Studio Engine + #[deprecated(note="This db field should only denote file provenance, not the product.")] + #[serde(rename = "studio")] + StorytellerStudio, + + /// From Storyteller Studio Engine + #[deprecated(note = "DO NOT USE. Originally deprecated in favor of `StorytellerStudio`.")] + StoryEngine, +} + +// TODO(bt, 2022-12-21): This desperately needs MySQL integration tests! +impl_enum_display_and_debug_using_to_str!(MediaFileOriginCategory); +impl_mysql_enum_coders!(MediaFileOriginCategory); +impl_mysql_from_row!(MediaFileOriginCategory); + +/// NB: Legacy API for older code. +impl MediaFileOriginCategory { + pub fn to_str(&self) -> &'static str { + match self { + Self::Inference => "inference", + Self::Processed => "processed", + Self::Upload => "upload", + Self::DeviceApi => "device_api", + Self::StorytellerStudio => "studio", + Self::StoryEngine => "story_engine", + } + } + + pub fn from_str(value: &str) -> Result { + match value { + "inference" => Ok(Self::Inference), + "processed" => Ok(Self::Processed), + "upload" => Ok(Self::Upload), + "device_api" => Ok(Self::DeviceApi), + "studio" => Ok(Self::StorytellerStudio), + "story_engine" => Ok(Self::StoryEngine), + _ => Err(format!("invalid value: {:?}", value)), + } + } + +} + +#[cfg(test)] +mod tests { + use super::super::media_file_origin_category::MediaFileOriginCategory; + use enums_shared::test_helpers::assert_serialization; + + mod explicit_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(MediaFileOriginCategory::Inference, "inference"); + assert_serialization(MediaFileOriginCategory::Processed, "processed"); + assert_serialization(MediaFileOriginCategory::Upload, "upload"); + assert_serialization(MediaFileOriginCategory::DeviceApi, "device_api"); + assert_serialization(MediaFileOriginCategory::StorytellerStudio, "studio"); + assert_serialization(MediaFileOriginCategory::StoryEngine, "story_engine"); + } + + #[test] + fn test_to_str() { + assert_eq!(MediaFileOriginCategory::Inference.to_str(), "inference"); + assert_eq!(MediaFileOriginCategory::Processed.to_str(), "processed"); + assert_eq!(MediaFileOriginCategory::Upload.to_str(), "upload"); + assert_eq!(MediaFileOriginCategory::DeviceApi.to_str(), "device_api"); + assert_eq!(MediaFileOriginCategory::StorytellerStudio.to_str(), "studio"); + assert_eq!(MediaFileOriginCategory::StoryEngine.to_str(), "story_engine"); + } + + #[test] + fn test_from_str() { + assert_eq!(MediaFileOriginCategory::from_str("inference").unwrap(), MediaFileOriginCategory::Inference); + assert_eq!(MediaFileOriginCategory::from_str("processed").unwrap(), MediaFileOriginCategory::Processed); + assert_eq!(MediaFileOriginCategory::from_str("upload").unwrap(), MediaFileOriginCategory::Upload); + assert_eq!(MediaFileOriginCategory::from_str("device_api").unwrap(), MediaFileOriginCategory::DeviceApi); + assert_eq!(MediaFileOriginCategory::from_str("studio").unwrap(), MediaFileOriginCategory::StorytellerStudio); + assert_eq!(MediaFileOriginCategory::from_str("story_engine").unwrap(), MediaFileOriginCategory::StoryEngine); + assert!(MediaFileOriginCategory::from_str("foo").is_err()); + } + + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip() { + use strum::IntoEnumIterator; + for variant in MediaFileOriginCategory::iter() { + assert_eq!(variant, MediaFileOriginCategory::from_str(variant.to_str()).unwrap()); + assert_eq!(variant, MediaFileOriginCategory::from_str(&format!("{}", variant)).unwrap()); + assert_eq!(variant, MediaFileOriginCategory::from_str(&format!("{:?}", variant)).unwrap()); + } + } + + #[test] + fn serialized_length_ok_for_database() { + use strum::IntoEnumIterator; + const MAX_LENGTH : usize = 16; + for variant in MediaFileOriginCategory::iter() { + let serialized = variant.to_str(); + assert!(serialized.len() > 0, "variant {:?} is too short", variant); + assert!(serialized.len() <= MAX_LENGTH, "variant {:?} is too long", variant); + } + } + } +} diff --git a/crates/schema/public/enums_db/src/by_table/media_files/media_file_origin_model_type.rs b/crates/schema/public/enums_db/src/by_table/media_files/media_file_origin_model_type.rs new file mode 100644 index 0000000000..d2d789c9a9 --- /dev/null +++ b/crates/schema/public/enums_db/src/by_table/media_files/media_file_origin_model_type.rs @@ -0,0 +1,210 @@ +use serde::Deserialize; +use serde::Serialize; +use strum::EnumCount; +use strum::EnumIter; + +/// Used in the `media_files` table in a `VARCHAR` field. +/// +/// DO NOT CHANGE VALUES WITHOUT A MIGRATION STRATEGY. +#[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, Deserialize, Serialize, EnumIter, EnumCount)] +#[serde(rename_all = "snake_case")] +pub enum MediaFileOriginModelType { + #[serde(rename = "face_fusion")] + FaceFusion, + + #[serde(rename = "f5_tts")] + F5TTS, + + #[serde(rename = "live_portrait")] + LivePortrait, + + /// RVC (v2) voice conversion models + #[serde(rename = "rvc_v2")] + RvcV2, + + /// SadTalker -- v1, we may add another enum value for future versions + #[serde(rename = "sad_talker")] + SadTalker, + + /// so-vits-svc voice conversion models + #[serde(rename = "so_vits_svc")] + SoVitsSvc, + + #[serde(rename = "tacotron2")] + Tacotron2, + + #[serde(rename = "mocap_net")] + MocapNet, + + #[serde(rename = "seed_vc")] + SeedVc, + + #[serde(rename = "styletts2")] + StyleTTS2, + + #[serde(rename = "stable_diffusion_1_5")] + StableDiffusion15, + + #[serde(rename = "gpt_sovits")] + GptSovits, + + #[serde(rename = "studio")] + StorytellerStudio, + + #[serde(rename = "studio_ig")] + StorytellerStudioImageGen, + + #[serde(rename = "vst")] + VideoStyleTransfer, + + #[deprecated(note = "This is not a model type!")] + #[serde(rename = "comfy_ui")] + ComfyUi, + + #[deprecated(note = "We don't use this anymore")] + #[serde(rename = "vall_e_x")] + VallEX, + + #[deprecated(note = "We don't use this anymore")] + #[serde(rename = "rerender")] + Rerender, +} + +impl_enum_display_and_debug_using_to_str!(MediaFileOriginModelType); +impl_mysql_enum_coders!(MediaFileOriginModelType); +impl_mysql_from_row!(MediaFileOriginModelType); + +impl MediaFileOriginModelType { + pub fn to_str(&self) -> &'static str { + match self { + Self::FaceFusion => "face_fusion", + Self::F5TTS => "f5_tts", + Self::LivePortrait => "live_portrait", + Self::RvcV2 => "rvc_v2", + Self::SadTalker => "sad_talker", + Self::SeedVc => "seed_vc", + Self::SoVitsSvc => "so_vits_svc", + Self::Tacotron2 => "tacotron2", + Self::MocapNet => "mocap_net", + Self::StyleTTS2 => "styletts2", + Self::StableDiffusion15 => "stable_diffusion_1_5", + Self::StorytellerStudioImageGen => "studio_ig", + Self::GptSovits => "gpt_sovits", + Self::StorytellerStudio => "studio", + Self::VideoStyleTransfer => "vst", + Self::ComfyUi => "comfy_ui", + Self::VallEX => "vall_e_x", + Self::Rerender => "rerender", + } + } + + pub fn from_str(value: &str) -> Result { + match value { + "face_fusion" => Ok(Self::FaceFusion), + "f5_tts" => Ok(Self::F5TTS), + "live_portrait" => Ok(Self::LivePortrait), + "rvc_v2" => Ok(Self::RvcV2), + "sad_talker" => Ok(Self::SadTalker), + "seed_vc" => Ok(Self::SeedVc), + "so_vits_svc" => Ok(Self::SoVitsSvc), + "tacotron2" => Ok(Self::Tacotron2), + "mocap_net" => Ok(Self::MocapNet), + "styletts2" => Ok(Self::StyleTTS2), + "stable_diffusion_1_5" => Ok(Self::StableDiffusion15), + "studio_ig" => Ok(Self::StorytellerStudioImageGen), + "gpt_sovits" => Ok(Self::GptSovits), + "studio" => Ok(Self::StorytellerStudio), + "vst" => Ok(Self::VideoStyleTransfer), + "comfy_ui" => Ok(Self::ComfyUi), + "vall_e_x" => Ok(Self::VallEX), + "rerender" => Ok(Self::Rerender), + _ => Err(format!("invalid value: {:?}", value)), + } + } + +} + +#[cfg(test)] +mod tests { + use super::MediaFileOriginModelType; + use enums_shared::test_helpers::assert_serialization; + + mod explicit_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(MediaFileOriginModelType::FaceFusion, "face_fusion"); + assert_serialization(MediaFileOriginModelType::SadTalker, "sad_talker"); + } + + #[test] + fn test_to_str() { + assert_eq!(MediaFileOriginModelType::FaceFusion.to_str(), "face_fusion"); + assert_eq!(MediaFileOriginModelType::F5TTS.to_str(), "f5_tts"); + assert_eq!(MediaFileOriginModelType::LivePortrait.to_str(), "live_portrait"); + assert_eq!(MediaFileOriginModelType::RvcV2.to_str(), "rvc_v2"); + assert_eq!(MediaFileOriginModelType::SadTalker.to_str(), "sad_talker"); + assert_eq!(MediaFileOriginModelType::SeedVc.to_str(), "seed_vc"); + assert_eq!(MediaFileOriginModelType::SoVitsSvc.to_str(), "so_vits_svc"); + assert_eq!(MediaFileOriginModelType::Tacotron2.to_str(), "tacotron2"); + assert_eq!(MediaFileOriginModelType::MocapNet.to_str(), "mocap_net"); + assert_eq!(MediaFileOriginModelType::StyleTTS2.to_str(), "styletts2"); + assert_eq!(MediaFileOriginModelType::StableDiffusion15.to_str(), "stable_diffusion_1_5"); + assert_eq!(MediaFileOriginModelType::GptSovits.to_str(), "gpt_sovits"); + assert_eq!(MediaFileOriginModelType::StorytellerStudio.to_str(), "studio"); + assert_eq!(MediaFileOriginModelType::VideoStyleTransfer.to_str(), "vst"); + assert_eq!(MediaFileOriginModelType::ComfyUi.to_str(), "comfy_ui"); + assert_eq!(MediaFileOriginModelType::VallEX.to_str(), "vall_e_x"); + assert_eq!(MediaFileOriginModelType::Rerender.to_str(), "rerender"); + } + + #[test] + fn test_from_str() { + assert_eq!(MediaFileOriginModelType::from_str("face_fusion").unwrap(), MediaFileOriginModelType::FaceFusion); + assert_eq!(MediaFileOriginModelType::from_str("f5_tts").unwrap(), MediaFileOriginModelType::F5TTS); + assert_eq!(MediaFileOriginModelType::from_str("live_portrait").unwrap(), MediaFileOriginModelType::LivePortrait); + assert_eq!(MediaFileOriginModelType::from_str("rvc_v2").unwrap(), MediaFileOriginModelType::RvcV2); + assert_eq!(MediaFileOriginModelType::from_str("sad_talker").unwrap(), MediaFileOriginModelType::SadTalker); + assert_eq!(MediaFileOriginModelType::from_str("seed_vc").unwrap(), MediaFileOriginModelType::SeedVc); + assert_eq!(MediaFileOriginModelType::from_str("so_vits_svc").unwrap(), MediaFileOriginModelType::SoVitsSvc); + assert_eq!(MediaFileOriginModelType::from_str("tacotron2").unwrap(), MediaFileOriginModelType::Tacotron2); + assert_eq!(MediaFileOriginModelType::from_str("mocap_net").unwrap(), MediaFileOriginModelType::MocapNet); + assert_eq!(MediaFileOriginModelType::from_str("styletts2").unwrap(), MediaFileOriginModelType::StyleTTS2); + assert_eq!(MediaFileOriginModelType::from_str("stable_diffusion_1_5").unwrap(), MediaFileOriginModelType::StableDiffusion15); + assert_eq!(MediaFileOriginModelType::from_str("gpt_sovits").unwrap(), MediaFileOriginModelType::GptSovits); + assert_eq!(MediaFileOriginModelType::from_str("studio").unwrap(), MediaFileOriginModelType::StorytellerStudio); + assert_eq!(MediaFileOriginModelType::from_str("vst").unwrap(), MediaFileOriginModelType::VideoStyleTransfer); + assert_eq!(MediaFileOriginModelType::from_str("comfy_ui").unwrap(), MediaFileOriginModelType::ComfyUi); + assert_eq!(MediaFileOriginModelType::from_str("vall_e_x").unwrap(), MediaFileOriginModelType::VallEX); + assert_eq!(MediaFileOriginModelType::from_str("rerender").unwrap(), MediaFileOriginModelType::Rerender); + assert!(MediaFileOriginModelType::from_str("foo").is_err()); + } + + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip() { + use strum::IntoEnumIterator; + for variant in MediaFileOriginModelType::iter() { + assert_eq!(variant, MediaFileOriginModelType::from_str(variant.to_str()).unwrap()); + assert_eq!(variant, MediaFileOriginModelType::from_str(&format!("{}", variant)).unwrap()); + assert_eq!(variant, MediaFileOriginModelType::from_str(&format!("{:?}", variant)).unwrap()); + } + } + + #[test] + fn serialized_length_ok_for_database() { + use strum::IntoEnumIterator; + const MAX_LENGTH: usize = 24; // TODO(bt): Confirm database column width, then remove this comment. + for variant in MediaFileOriginModelType::iter() { + let serialized = variant.to_str(); + assert!(!serialized.is_empty(), "variant {:?} is too short", variant); + assert!(serialized.len() <= MAX_LENGTH, "variant {:?} is too long", variant); + } + } + } +} diff --git a/crates/schema/public/enums_db/src/by_table/media_files/media_file_origin_product_category.rs b/crates/schema/public/enums_db/src/by_table/media_files/media_file_origin_product_category.rs new file mode 100644 index 0000000000..5e42105e32 --- /dev/null +++ b/crates/schema/public/enums_db/src/by_table/media_files/media_file_origin_product_category.rs @@ -0,0 +1,226 @@ +use strum::EnumCount; +use strum::EnumIter; + +/// Used in the `media_files` table in `VARCHAR(16)` field `origin_product_category`. +/// +/// This value indicates what product originally created the media file. (Not the ML model or +/// user upload process.) This will let us scope media files to the product that generated them +/// and filter them out of unrelated products if necessary (eg. a user probably doesn't want +/// "Voice Designer" dataset samples in a video generation flow.) +/// +/// DO NOT CHANGE VALUES WITHOUT A MIGRATION STRATEGY. +#[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, Deserialize, Serialize, EnumIter, EnumCount)] +pub enum MediaFileOriginProductCategory { + /// Unknown which product is attached to the file (generated the file, the file was + /// uploaded on behalf of, etc.) + #[serde(rename = "unknown")] + Unknown, + + /// Media files created by (or uploaded for) the Face Animator product. + /// The underlying model could be SadTalker, Wav2Lip, or some future model + #[serde(rename = "face_animator")] + FaceAnimator, + + /// Media files created by Face Fusion (lipsync) + #[serde(rename = "face_fusion")] + FaceFusion, + + /// Media files created by Face Mirror (currently powered by Live Portrait) + #[serde(rename = "face_mirror")] + FaceMirror, + + /// Video style transfer + #[serde(rename = "vst")] + VideoStyleTransfer, + + /// Image Studio + #[serde(rename = "image_studio")] + ImageStudio, + + /// Storyteller Studio + #[serde(rename = "studio")] + StorytellerStudio, + + /// Text to speech (Tacotron2, not voice designer / VallE-X) + #[serde(rename = "tts")] + TextToSpeech, + + /// Voice conversion (either RVC or SVC) + #[serde(rename = "voice_conversion")] + VoiceConversion, + + /// Media files created by (or uploaded for) the Zero Shot voice product. + #[serde(rename = "zs_voice")] + ZeroShotVoice, + + // Mocap + #[serde(rename = "mocap")] + Mocap, + + #[serde(rename = "image_gen")] + ImageGeneration, + + #[serde(rename = "video_gen")] + VideoGeneration, + + #[serde(rename = "world_gen")] + WorldGeneration, + + // Media files for video filters + #[deprecated(note = "This isn't relevant product surface area anymore")] + #[serde(rename = "video_filter")] + VideoFilter, + + // Workflow + #[deprecated(note = "Use studio and VST instead.")] + #[serde(rename = "workflow")] + Workflow, +} + +// TODO(bt, 2022-12-21): This desperately needs MySQL integration tests! +impl_enum_display_and_debug_using_to_str!(MediaFileOriginProductCategory); +impl_mysql_enum_coders!(MediaFileOriginProductCategory); +impl_mysql_from_row!(MediaFileOriginProductCategory); + +/// NB: Legacy API for older code. +impl MediaFileOriginProductCategory { + pub fn to_str(&self) -> &'static str { + match self { + Self::Unknown => "unknown", + Self::FaceAnimator => "face_animator", + Self::FaceFusion => "face_fusion", + Self::FaceMirror => "face_mirror", + Self::VideoStyleTransfer => "vst", + Self::ImageStudio => "image_studio", + Self::StorytellerStudio => "studio", + Self::TextToSpeech => "tts", + Self::VoiceConversion => "voice_conversion", + Self::ZeroShotVoice => "zs_voice", + Self::Mocap => "mocap", + Self::ImageGeneration => "image_gen", + Self::VideoGeneration => "video_gen", + Self::WorldGeneration => "world_gen", + Self::VideoFilter => "video_filter", + Self::Workflow => "workflow", + } + } + + pub fn from_str(value: &str) -> Result { + match value { + "unknown" => Ok(Self::Unknown), + "face_animator" => Ok(Self::FaceAnimator), + "face_fusion" => Ok(Self::FaceFusion), + "face_mirror" => Ok(Self::FaceMirror), + "vst" => Ok(Self::VideoStyleTransfer), + "image_studio" => Ok(Self::ImageStudio), + "studio" => Ok(Self::StorytellerStudio), + "tts" => Ok(Self::TextToSpeech), + "voice_conversion" => Ok(Self::VoiceConversion), + "zs_voice" => Ok(Self::ZeroShotVoice), + "mocap" => Ok(Self::Mocap), + "image_gen" => Ok(Self::ImageGeneration), + "video_gen" => Ok(Self::VideoGeneration), + "world_gen" => Ok(Self::WorldGeneration), + "video_filter" => Ok(Self::VideoFilter), + "workflow" => Ok(Self::Workflow), + _ => Err(format!("invalid value: {:?}", value)), + } + } + +} + +#[cfg(test)] +mod tests { + use super::super::media_file_origin_product_category::MediaFileOriginProductCategory; + use enums_shared::test_helpers::assert_serialization; + + mod explicit_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(MediaFileOriginProductCategory::Unknown, "unknown"); + assert_serialization(MediaFileOriginProductCategory::FaceAnimator, "face_animator"); + assert_serialization(MediaFileOriginProductCategory::FaceFusion, "face_fusion"); + assert_serialization(MediaFileOriginProductCategory::FaceMirror, "face_mirror"); + assert_serialization(MediaFileOriginProductCategory::VideoStyleTransfer, "vst"); + assert_serialization(MediaFileOriginProductCategory::ImageStudio, "image_studio"); + assert_serialization(MediaFileOriginProductCategory::StorytellerStudio, "studio"); + assert_serialization(MediaFileOriginProductCategory::TextToSpeech, "tts"); + assert_serialization(MediaFileOriginProductCategory::VoiceConversion, "voice_conversion"); + assert_serialization(MediaFileOriginProductCategory::ZeroShotVoice, "zs_voice"); + assert_serialization(MediaFileOriginProductCategory::Mocap, "mocap"); + assert_serialization(MediaFileOriginProductCategory::ImageGeneration, "image_gen"); + assert_serialization(MediaFileOriginProductCategory::VideoGeneration, "video_gen"); + assert_serialization(MediaFileOriginProductCategory::WorldGeneration, "world_gen"); + assert_serialization(MediaFileOriginProductCategory::VideoFilter, "video_filter"); + assert_serialization(MediaFileOriginProductCategory::Workflow, "workflow"); + } + + #[test] + fn to_str() { + assert_eq!(MediaFileOriginProductCategory::Unknown.to_str(), "unknown"); + assert_eq!(MediaFileOriginProductCategory::FaceAnimator.to_str(), "face_animator"); + assert_eq!(MediaFileOriginProductCategory::FaceFusion.to_str(), "face_fusion"); + assert_eq!(MediaFileOriginProductCategory::FaceMirror.to_str(), "face_mirror"); + assert_eq!(MediaFileOriginProductCategory::VideoStyleTransfer.to_str(), "vst"); + assert_eq!(MediaFileOriginProductCategory::ImageStudio.to_str(), "image_studio"); + assert_eq!(MediaFileOriginProductCategory::StorytellerStudio.to_str(), "studio"); + assert_eq!(MediaFileOriginProductCategory::TextToSpeech.to_str(), "tts"); + assert_eq!(MediaFileOriginProductCategory::VoiceConversion.to_str(), "voice_conversion"); + assert_eq!(MediaFileOriginProductCategory::ZeroShotVoice.to_str(), "zs_voice"); + assert_eq!(MediaFileOriginProductCategory::Mocap.to_str(), "mocap"); + assert_eq!(MediaFileOriginProductCategory::ImageGeneration.to_str(), "image_gen"); + assert_eq!(MediaFileOriginProductCategory::VideoGeneration.to_str(), "video_gen"); + assert_eq!(MediaFileOriginProductCategory::WorldGeneration.to_str(), "world_gen"); + assert_eq!(MediaFileOriginProductCategory::VideoFilter.to_str(), "video_filter"); + assert_eq!(MediaFileOriginProductCategory::Workflow.to_str(), "workflow"); + } + + #[test] + fn from_str() { + assert_eq!(MediaFileOriginProductCategory::from_str("unknown").unwrap(), MediaFileOriginProductCategory::Unknown); + assert_eq!(MediaFileOriginProductCategory::from_str("face_animator").unwrap(), MediaFileOriginProductCategory::FaceAnimator); + assert_eq!(MediaFileOriginProductCategory::from_str("face_fusion").unwrap(), MediaFileOriginProductCategory::FaceFusion); + assert_eq!(MediaFileOriginProductCategory::from_str("face_mirror").unwrap(), MediaFileOriginProductCategory::FaceMirror); + assert_eq!(MediaFileOriginProductCategory::from_str("vst").unwrap(), MediaFileOriginProductCategory::VideoStyleTransfer); + assert_eq!(MediaFileOriginProductCategory::from_str("image_studio").unwrap(), MediaFileOriginProductCategory::ImageStudio); + assert_eq!(MediaFileOriginProductCategory::from_str("studio").unwrap(), MediaFileOriginProductCategory::StorytellerStudio); + assert_eq!(MediaFileOriginProductCategory::from_str("tts").unwrap(), MediaFileOriginProductCategory::TextToSpeech); + assert_eq!(MediaFileOriginProductCategory::from_str("voice_conversion").unwrap(), MediaFileOriginProductCategory::VoiceConversion); + assert_eq!(MediaFileOriginProductCategory::from_str("zs_voice").unwrap(), MediaFileOriginProductCategory::ZeroShotVoice); + assert_eq!(MediaFileOriginProductCategory::from_str("mocap").unwrap(), MediaFileOriginProductCategory::Mocap); + assert_eq!(MediaFileOriginProductCategory::from_str("image_gen").unwrap(),MediaFileOriginProductCategory::ImageGeneration); + assert_eq!(MediaFileOriginProductCategory::from_str("video_gen").unwrap(), MediaFileOriginProductCategory::VideoGeneration); + assert_eq!(MediaFileOriginProductCategory::from_str("world_gen").unwrap(), MediaFileOriginProductCategory::WorldGeneration); + assert_eq!(MediaFileOriginProductCategory::from_str("video_filter").unwrap(), MediaFileOriginProductCategory::VideoFilter); + assert_eq!(MediaFileOriginProductCategory::from_str("workflow").unwrap(), MediaFileOriginProductCategory::Workflow); + } + + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip() { + use strum::IntoEnumIterator; + for variant in MediaFileOriginProductCategory::iter() { + assert_eq!(variant, MediaFileOriginProductCategory::from_str(variant.to_str()).unwrap()); + assert_eq!(variant, MediaFileOriginProductCategory::from_str(&format!("{}", variant)).unwrap()); + assert_eq!(variant, MediaFileOriginProductCategory::from_str(&format!("{:?}", variant)).unwrap()); + } + } + + #[test] + fn serialized_length_ok_for_database() { + use strum::IntoEnumIterator; + const MAX_LENGTH : usize = 16; + for variant in MediaFileOriginProductCategory::iter() { + let serialized = variant.to_str(); + assert!(serialized.len() > 0, "variant {:?} is too short", variant); + assert!(serialized.len() <= MAX_LENGTH, "variant {:?} is too long", variant); + } + } + } +} diff --git a/crates/schema/public/enums_db/src/by_table/media_files/media_file_subtype.rs b/crates/schema/public/enums_db/src/by_table/media_files/media_file_subtype.rs new file mode 100644 index 0000000000..b801560ba3 --- /dev/null +++ b/crates/schema/public/enums_db/src/by_table/media_files/media_file_subtype.rs @@ -0,0 +1,178 @@ +use strum::EnumCount; +use strum::EnumIter; + +/// Used in the `media_files` table in a `VARCHAR` field. +/// +/// DO NOT CHANGE VALUES WITHOUT A MIGRATION STRATEGY. +#[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, Deserialize, Serialize, EnumIter, EnumCount)] +#[serde(rename_all = "snake_case")] +#[deprecated(note = "This was primarily for Bevy")] +pub enum MediaFileSubtype { + /// NB: MediaFileSubtype is deprecated. + /// This should signal that the field / enum is fully deprecated. + Deprecated, + + // TODO(bt,2024-04-22): Deprecated (migrate) + /// Animation file from Mixamo + /// Primarily used for FBX and GLB. + Mixamo, + + // TODO(bt,2024-04-22): Deprecated (migrate) + /// Animation file from MocapNet + /// Primarily used for BVH. + MocapNet, + + // TODO(bt,2024-04-22): Deprecated + /// Generic animation case + /// Used for BVH files, but can also pertain to animation-only files of other types. + AnimationOnly, + + // TODO(bt,2024-04-22): Deprecated + /// Generic 3D scene file. + /// Can pertain to glTF, glB, FBX, etc. + SceneImport, + + // TODO(bt,2024-04-22): Deprecated + /// Native Storyteller scene format. + /// Typically stored in a `.scn.ron` file. + StorytellerScene, + + /// A 3D scene full of objects, characters, animations, etc. + Scene, + + /// A 3D character model. + Character, + + /// A 3D animation. + Animation, + + /// A 3D object that doesn't fit with the other types. + Object, + + /// A 3D skybox. + Skybox, +} + +// TODO(bt, 2022-12-21): This desperately needs MySQL integration tests! +impl_enum_display_and_debug_using_to_str!(MediaFileSubtype); +impl_mysql_enum_coders!(MediaFileSubtype); +impl_mysql_from_row!(MediaFileSubtype); + +/// NB: Legacy API for older code. +impl MediaFileSubtype { + pub fn to_str(&self) -> &'static str { + match self { + Self::Deprecated => "deprecated", + Self::Mixamo => "mixamo", + Self::MocapNet => "mocap_net", + Self::AnimationOnly => "animation_only", + Self::SceneImport => "scene_import", + Self::StorytellerScene => "storyteller_scene", + Self::Scene => "scene", + Self::Character => "character", + Self::Animation => "animation", + Self::Object => "object", + Self::Skybox => "skybox", + } + } + + pub fn from_str(value: &str) -> Result { + match value { + "deprecated" => Ok(Self::Deprecated), + "mixamo" => Ok(Self::Mixamo), + "mocap_net" => Ok(Self::MocapNet), + "animation_only" => Ok(Self::AnimationOnly), + "scene_import" => Ok(Self::SceneImport), + "storyteller_scene" => Ok(Self::StorytellerScene), + "scene" => Ok(Self::Scene), + "character" => Ok(Self::Character), + "animation" => Ok(Self::Animation), + "object" => Ok(Self::Object), + "skybox" => Ok(Self::Skybox), + _ => Err(format!("invalid value: {:?}", value)), + } + } + +} + +#[cfg(test)] +mod tests { + use super::super::media_file_subtype::MediaFileSubtype; + use enums_shared::test_helpers::assert_serialization; + + mod explicit_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(MediaFileSubtype::Deprecated, "deprecated"); + assert_serialization(MediaFileSubtype::Mixamo, "mixamo"); + assert_serialization(MediaFileSubtype::MocapNet, "mocap_net"); + assert_serialization(MediaFileSubtype::AnimationOnly, "animation_only"); + assert_serialization(MediaFileSubtype::SceneImport, "scene_import"); + assert_serialization(MediaFileSubtype::StorytellerScene, "storyteller_scene"); + assert_serialization(MediaFileSubtype::Scene, "scene"); + assert_serialization(MediaFileSubtype::Character, "character"); + assert_serialization(MediaFileSubtype::Animation, "animation"); + assert_serialization(MediaFileSubtype::Object, "object"); + assert_serialization(MediaFileSubtype::Skybox, "skybox"); + } + + #[test] + fn test_to_str() { + assert_eq!(MediaFileSubtype::Deprecated.to_str(), "deprecated"); + assert_eq!(MediaFileSubtype::Mixamo.to_str(), "mixamo"); + assert_eq!(MediaFileSubtype::MocapNet.to_str(), "mocap_net"); + assert_eq!(MediaFileSubtype::AnimationOnly.to_str(), "animation_only"); + assert_eq!(MediaFileSubtype::SceneImport.to_str(), "scene_import"); + assert_eq!(MediaFileSubtype::StorytellerScene.to_str(), "storyteller_scene"); + assert_eq!(MediaFileSubtype::Scene.to_str(), "scene"); + assert_eq!(MediaFileSubtype::Character.to_str(), "character"); + assert_eq!(MediaFileSubtype::Animation.to_str(), "animation"); + assert_eq!(MediaFileSubtype::Object.to_str(), "object"); + assert_eq!(MediaFileSubtype::Skybox.to_str(), "skybox"); + } + + #[test] + fn test_from_str() { + assert_eq!(MediaFileSubtype::from_str("deprecated").unwrap(), MediaFileSubtype::Deprecated); + assert_eq!(MediaFileSubtype::from_str("mixamo").unwrap(), MediaFileSubtype::Mixamo); + assert_eq!(MediaFileSubtype::from_str("mocap_net").unwrap(), MediaFileSubtype::MocapNet); + assert_eq!(MediaFileSubtype::from_str("animation_only").unwrap(), MediaFileSubtype::AnimationOnly); + assert_eq!(MediaFileSubtype::from_str("scene_import").unwrap(), MediaFileSubtype::SceneImport); + assert_eq!(MediaFileSubtype::from_str("storyteller_scene").unwrap(), MediaFileSubtype::StorytellerScene); + assert_eq!(MediaFileSubtype::from_str("scene").unwrap(), MediaFileSubtype::Scene); + assert_eq!(MediaFileSubtype::from_str("character").unwrap(), MediaFileSubtype::Character); + assert_eq!(MediaFileSubtype::from_str("animation").unwrap(), MediaFileSubtype::Animation); + assert_eq!(MediaFileSubtype::from_str("object").unwrap(), MediaFileSubtype::Object); + assert_eq!(MediaFileSubtype::from_str("skybox").unwrap(), MediaFileSubtype::Skybox); + assert!(MediaFileSubtype::from_str("foo").is_err()); + } + + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip() { + use strum::IntoEnumIterator; + for variant in MediaFileSubtype::iter() { + assert_eq!(variant, MediaFileSubtype::from_str(variant.to_str()).unwrap()); + assert_eq!(variant, MediaFileSubtype::from_str(&format!("{}", variant)).unwrap()); + assert_eq!(variant, MediaFileSubtype::from_str(&format!("{:?}", variant)).unwrap()); + } + } + + #[test] + fn serialized_length_ok_for_database() { + use strum::IntoEnumIterator; + const MAX_LENGTH : usize = 32; + for variant in MediaFileSubtype::iter() { + let serialized = variant.to_str(); + assert!(serialized.len() > 0, "variant {:?} is too short", variant); + assert!(serialized.len() <= MAX_LENGTH, "variant {:?} is too long", variant); + } + } + } +} diff --git a/crates/schema/public/enums_db/src/by_table/media_files/media_file_type.rs b/crates/schema/public/enums_db/src/by_table/media_files/media_file_type.rs new file mode 100644 index 0000000000..03ef90139d --- /dev/null +++ b/crates/schema/public/enums_db/src/by_table/media_files/media_file_type.rs @@ -0,0 +1,352 @@ +use strum::EnumCount; +use strum::EnumIter; + +/// Used in the `media_files` table in a `VARCHAR(16)` field. +/// +/// DO NOT CHANGE VALUES WITHOUT A MIGRATION STRATEGY. +#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash, Deserialize, Serialize, EnumIter, EnumCount)] +#[serde(rename_all = "snake_case")] +pub enum MediaFileType { + // TODO(bt): Deprecate and split into audio mime types; use media_class to represent broadly + /// Audio files: wav, mp3, etc. + #[deprecated] + Audio, + + // TODO(bt): Deprecate and split into image mime types; use media_class to represent broadly + /// Image files: png, jpeg, etc. + #[deprecated] + Image, + + // TODO(bt): Deprecate and split into video mime types; use media_class to represent broadly + /// Video files: mp4, etc. + #[deprecated] + Video, + + /// BVH files (for Bevy) + /// NB: This is the new type to migrate to. + Bvh, + + /// FBX files (for Bevy) + Fbx, + + /// glTF binary files (for Bevy) + Glb, + + /// glTF files (for Bevy) + Gltf, + + /// Spz Gaussian splats + /// This is a standard file format for Gaussian Splats, used by World Labs. + /// The mime type is application/gzip. + Spz, + + /// Bevy's scene files (in RON; Rusty Object Notation) + /// This will be replaced with another format in future versions of Bevy + SceneRon, + + /// Alternate scene files. + SceneJson, + + /// "Polygon Model Data", character data for MikuMikuDance + /// See: https://mikumikudance.fandom.com/wiki/MMD:Polygon_Model_Data + Pmd, + + /// "Vocaloid Motion Data", animation data for MikuMikuDance + /// See: https://mikumikudance.fandom.com/wiki/VMD_file_format + Vmd, + + /// "Polygon Model eXtend", character data from MikuMikuDance + /// NB: this is often associated with external files for textures, which + /// we'll store in the same bucket path. + /// See: https://mikumikudance.fandom.com/wiki/MMD:Polygon_Model_eXtend + Pmx, + + /// CSV format. (We use these for ArKit) + Csv, + + /// Jpeg images + Jpg, + + /// Png images + Png, + + /// Gif images + Gif, + + /// Mp4 videos + Mp4, + + /// Wav audio + Wav, + + /// Mp3 audio + Mp3, +} + +// TODO(bt, 2022-12-21): This desperately needs MySQL integration tests! +impl_enum_display_and_debug_using_to_str!(MediaFileType); +impl_mysql_enum_coders!(MediaFileType); +impl_mysql_from_row!(MediaFileType); + +/// NB: Legacy API for older code. +impl MediaFileType { + + /// Jpeg and Png are the most widely supported static image formats for AI inference. + /// Webp, Webm, and Gif aren't as widely supported, so we don't include them here. + pub fn is_jpg_or_png(&self) -> bool { + matches!(self, Self::Jpg | Self::Png) + } + + /// A little bit less strict than `is_jpg_or_png`, this includes the legacy `Image` type. + pub fn is_jpg_or_png_or_legacy_image(&self) -> bool { + matches!(self, Self::Jpg | Self::Png | Self::Image) + } + + /// Returns the `MediaFileType` if the mime type matches one of the known types. + /// This is not exhaustive. + /// (NB: In general we shouldn't keep much application logic in the `enums` crate, + /// but this is a good case for it.) + pub fn try_from_mime_type(mime_type: &str) -> Option { + match mime_type { + "image/jpeg" => Some(Self::Jpg), + "image/png" => Some(Self::Png), + "video/mp4" => Some(Self::Mp4), + "model/gltf-binary" => Some(Self::Glb), + //"audio/wav" => Some(Self::Wav), // NB: Not sure if this is correct + //"audio/mpeg" => Some(Self::Mp3), // NB: Not sure if this is correct + //"image/gif" => Some(Self::Gif), // NB: Not sure if this is correct + //"model/gltf+json" => Some(Self::Gltf), // NB: Not sure if this is correct + _ => None, + } + } + + pub fn to_str(&self) -> &'static str { + match self { + Self::Audio => "audio", + Self::Image => "image", + Self::Video => "video", + Self::Bvh => "bvh", + Self::Fbx => "fbx", + Self::Glb => "glb", + Self::Gltf => "gltf", + Self::Spz => "spz", + Self::SceneRon => "scene_ron", + Self::SceneJson => "scene_json", + Self::Pmd => "pmd", + Self::Vmd => "vmd", + Self::Pmx => "pmx", + Self::Csv => "csv", + Self::Jpg => "jpg", + Self::Png => "png", + Self::Gif => "gif", + Self::Mp4 => "mp4", + Self::Wav => "wav", + Self::Mp3 => "mp3", + } + } + + pub fn from_str(value: &str) -> Result { + match value { + "audio" => Ok(Self::Audio), + "image" => Ok(Self::Image), + "video" => Ok(Self::Video), + "bvh" => Ok(Self::Bvh), + "fbx" => Ok(Self::Fbx), + "glb" => Ok(Self::Glb), + "gltf" => Ok(Self::Gltf), + "spz" => Ok(Self::Spz), + "scene_ron" => Ok(Self::SceneRon), + "scene_json" => Ok(Self::SceneJson), + "pmd" => Ok(Self::Pmd), + "vmd" => Ok(Self::Vmd), + "pmx" => Ok(Self::Pmx), + "csv" => Ok(Self::Csv), + "jpg" => Ok(Self::Jpg), + "png" => Ok(Self::Png), + "gif" => Ok(Self::Gif), + "mp4" => Ok(Self::Mp4), + "wav" => Ok(Self::Wav), + "mp3" => Ok(Self::Mp3), + _ => Err(format!("invalid value: {:?}", value)), + } + } + +} + +#[cfg(test)] +mod tests { + use super::super::media_file_type::MediaFileType; + use enums_shared::test_helpers::assert_serialization; + + mod utility { + use super::*; + + #[test] + fn test_jpg_or_png() { + use strum::IntoEnumIterator; + // True + assert!(MediaFileType::Jpg.is_jpg_or_png()); + assert!(MediaFileType::Png.is_jpg_or_png()); + + // Assert these image types are false + assert!(!MediaFileType::Gif.is_jpg_or_png()); + assert!(!MediaFileType::Image.is_jpg_or_png()); + + // Everything else is false + for variant in MediaFileType::iter() { + if matches!(variant, MediaFileType::Jpg | MediaFileType::Png) { + continue; + } + assert!(!variant.is_jpg_or_png(), "Expected {:?} to not be jpg or png", variant); + } + } + } + + mod test_is_jpg_or_png_or_legacy_image { + use super::*; + use strum::IntoEnumIterator; + + #[test] + fn true_for_jpg_png_image() { + assert!(MediaFileType::Jpg.is_jpg_or_png_or_legacy_image()); + assert!(MediaFileType::Png.is_jpg_or_png_or_legacy_image()); + assert!(MediaFileType::Image.is_jpg_or_png_or_legacy_image()); + } + + #[test] + fn false_for_everything_else() { + for variant in MediaFileType::iter() { + if matches!(variant, MediaFileType::Jpg | MediaFileType::Png | MediaFileType::Image) { + continue; + } + assert!(!variant.is_jpg_or_png_or_legacy_image(), "Expected {:?} to be false", variant); + } + } + } + + mod test_try_from_mime_type { + use super::*; + + #[test] + fn known_mime_types() { + assert_eq!(MediaFileType::try_from_mime_type("image/jpeg"), Some(MediaFileType::Jpg)); + assert_eq!(MediaFileType::try_from_mime_type("image/png"), Some(MediaFileType::Png)); + assert_eq!(MediaFileType::try_from_mime_type("video/mp4"), Some(MediaFileType::Mp4)); + assert_eq!(MediaFileType::try_from_mime_type("model/gltf-binary"), Some(MediaFileType::Glb)); + } + + #[test] + fn unknown_mime_types_return_none() { + assert_eq!(MediaFileType::try_from_mime_type("audio/wav"), None); + assert_eq!(MediaFileType::try_from_mime_type("image/gif"), None); + assert_eq!(MediaFileType::try_from_mime_type("text/plain"), None); + assert_eq!(MediaFileType::try_from_mime_type(""), None); + } + } + + mod serde { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(MediaFileType::Audio, "audio"); + assert_serialization(MediaFileType::Image, "image"); + assert_serialization(MediaFileType::Video, "video"); + assert_serialization(MediaFileType::Bvh, "bvh"); + assert_serialization(MediaFileType::Fbx, "fbx"); + assert_serialization(MediaFileType::Glb, "glb"); + assert_serialization(MediaFileType::Gltf, "gltf"); + assert_serialization(MediaFileType::Spz, "spz"); + assert_serialization(MediaFileType::SceneRon, "scene_ron"); + assert_serialization(MediaFileType::SceneJson, "scene_json"); + assert_serialization(MediaFileType::Pmd, "pmd"); + assert_serialization(MediaFileType::Vmd, "vmd"); + assert_serialization(MediaFileType::Pmx, "pmx"); + assert_serialization(MediaFileType::Csv, "csv"); + assert_serialization(MediaFileType::Jpg, "jpg"); + assert_serialization(MediaFileType::Png, "png"); + assert_serialization(MediaFileType::Gif, "gif"); + assert_serialization(MediaFileType::Mp4, "mp4"); + assert_serialization(MediaFileType::Wav, "wav"); + assert_serialization(MediaFileType::Mp3, "mp3"); + } + } + + mod impl_methods { + use super::*; + + #[test] + fn to_str() { + assert_eq!(MediaFileType::Audio.to_str(), "audio"); + assert_eq!(MediaFileType::Image.to_str(), "image"); + assert_eq!(MediaFileType::Video.to_str(), "video"); + assert_eq!(MediaFileType::Bvh.to_str(), "bvh"); + assert_eq!(MediaFileType::Fbx.to_str(), "fbx"); + assert_eq!(MediaFileType::Glb.to_str(), "glb"); + assert_eq!(MediaFileType::Gltf.to_str(), "gltf"); + assert_eq!(MediaFileType::Spz.to_str(), "spz"); + assert_eq!(MediaFileType::SceneRon.to_str(), "scene_ron"); + assert_eq!(MediaFileType::SceneJson.to_str(), "scene_json"); + assert_eq!(MediaFileType::Pmd.to_str(), "pmd"); + assert_eq!(MediaFileType::Vmd.to_str(), "vmd"); + assert_eq!(MediaFileType::Pmx.to_str(), "pmx"); + assert_eq!(MediaFileType::Csv.to_str(), "csv"); + assert_eq!(MediaFileType::Jpg.to_str(), "jpg"); + assert_eq!(MediaFileType::Png.to_str(), "png"); + assert_eq!(MediaFileType::Gif.to_str(), "gif"); + assert_eq!(MediaFileType::Mp4.to_str(), "mp4"); + assert_eq!(MediaFileType::Wav.to_str(), "wav"); + assert_eq!(MediaFileType::Mp3.to_str(), "mp3"); + } + + #[test] + fn from_str() { + assert_eq!(MediaFileType::from_str("audio").unwrap(), MediaFileType::Audio); + assert_eq!(MediaFileType::from_str("image").unwrap(), MediaFileType::Image); + assert_eq!(MediaFileType::from_str("video").unwrap(), MediaFileType::Video); + assert_eq!(MediaFileType::from_str("bvh").unwrap(), MediaFileType::Bvh); + assert_eq!(MediaFileType::from_str("fbx").unwrap(), MediaFileType::Fbx); + assert_eq!(MediaFileType::from_str("glb").unwrap(), MediaFileType::Glb); + assert_eq!(MediaFileType::from_str("gltf").unwrap(), MediaFileType::Gltf); + assert_eq!(MediaFileType::from_str("spz").unwrap(), MediaFileType::Spz); + assert_eq!(MediaFileType::from_str("scene_ron").unwrap(), MediaFileType::SceneRon); + assert_eq!(MediaFileType::from_str("scene_json").unwrap(), MediaFileType::SceneJson); + assert_eq!(MediaFileType::from_str("pmd").unwrap(), MediaFileType::Pmd); + assert_eq!(MediaFileType::from_str("vmd").unwrap(), MediaFileType::Vmd); + assert_eq!(MediaFileType::from_str("pmx").unwrap(), MediaFileType::Pmx); + assert_eq!(MediaFileType::from_str("csv").unwrap(), MediaFileType::Csv); + assert_eq!(MediaFileType::from_str("jpg").unwrap(), MediaFileType::Jpg); + assert_eq!(MediaFileType::from_str("png").unwrap(), MediaFileType::Png); + assert_eq!(MediaFileType::from_str("gif").unwrap(), MediaFileType::Gif); + assert_eq!(MediaFileType::from_str("mp4").unwrap(), MediaFileType::Mp4); + assert_eq!(MediaFileType::from_str("wav").unwrap(), MediaFileType::Wav); + assert_eq!(MediaFileType::from_str("mp3").unwrap(), MediaFileType::Mp3); + assert!(MediaFileType::from_str("foo").is_err()); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip() { + use strum::IntoEnumIterator; + for variant in MediaFileType::iter() { + assert_eq!(variant, MediaFileType::from_str(variant.to_str()).unwrap()); + assert_eq!(variant, MediaFileType::from_str(&format!("{}", variant)).unwrap()); + assert_eq!(variant, MediaFileType::from_str(&format!("{:?}", variant)).unwrap()); + } + } + + #[test] + fn serialized_length_ok_for_database() { + use strum::IntoEnumIterator; + const MAX_LENGTH : usize = 16; + for variant in MediaFileType::iter() { + let serialized = variant.to_str(); + assert!(serialized.len() > 0, "variant {:?} is too short", variant); + assert!(serialized.len() <= MAX_LENGTH, "variant {:?} is too long", variant); + } + } + } +} diff --git a/crates/schema/public/enums_db/src/by_table/media_files/mod.rs b/crates/schema/public/enums_db/src/by_table/media_files/mod.rs new file mode 100644 index 0000000000..173082c091 --- /dev/null +++ b/crates/schema/public/enums_db/src/by_table/media_files/mod.rs @@ -0,0 +1,8 @@ +pub mod media_file_animation_type; +pub mod media_file_class; +pub mod media_file_engine_category; +pub mod media_file_origin_category; +pub mod media_file_origin_model_type; +pub mod media_file_origin_product_category; +pub mod media_file_subtype; +pub mod media_file_type; diff --git a/crates/schema/public/enums_db/src/by_table/media_uploads/media_upload_source.rs b/crates/schema/public/enums_db/src/by_table/media_uploads/media_upload_source.rs new file mode 100644 index 0000000000..6c526daaf2 --- /dev/null +++ b/crates/schema/public/enums_db/src/by_table/media_uploads/media_upload_source.rs @@ -0,0 +1,98 @@ +use strum::EnumCount; +use strum::EnumIter; + +/// Used in the `media_uploads` table in a `VARCHAR` field `media_source`. +/// +/// DO NOT CHANGE VALUES WITHOUT A MIGRATION STRATEGY. +#[derive(Clone, Copy, Eq, PartialEq, Deserialize, Serialize, EnumIter, EnumCount)] +pub enum MediaUploadSource { + /// Eg. browser javascript APIs to access the microphone, webcam, etc. + #[serde(rename = "device_api")] + DeviceApi, + + /// Uploaded files from the filesystem + #[serde(rename = "file")] + File, + + /// Unknown sources + #[serde(rename = "unknown")] + Unknown, +} + +// TODO(bt, 2022-12-21): This desperately needs MySQL integration tests! +impl_enum_display_and_debug_using_to_str!(MediaUploadSource); +impl_mysql_enum_coders!(MediaUploadSource); +impl_mysql_from_row!(MediaUploadSource); + +/// NB: Legacy API for older code. +impl MediaUploadSource { + pub fn to_str(&self) -> &'static str { + match self { + Self::DeviceApi => "device_api", + Self::File => "file", + Self::Unknown => "unknown", + } + } + + pub fn from_str(value: &str) -> Result { + match value { + "device_api" => Ok(Self::DeviceApi), + "file" => Ok(Self::File), + "unknown" => Ok(Self::Unknown), + _ => Err(format!("invalid value: {:?}", value)), + } + } +} + +#[cfg(test)] +mod tests { + use super::super::media_upload_source::MediaUploadSource; + use enums_shared::test_helpers::assert_serialization; + + #[test] + fn test_serialization() { + assert_serialization(MediaUploadSource::DeviceApi, "device_api"); + assert_serialization(MediaUploadSource::File, "file"); + assert_serialization(MediaUploadSource::Unknown, "unknown"); + } + + #[test] + fn test_to_str() { + assert_eq!(MediaUploadSource::DeviceApi.to_str(), "device_api"); + assert_eq!(MediaUploadSource::File.to_str(), "file"); + assert_eq!(MediaUploadSource::Unknown.to_str(), "unknown"); + } + + #[test] + fn test_from_str() { + assert_eq!(MediaUploadSource::from_str("device_api").unwrap(), MediaUploadSource::DeviceApi); + assert_eq!(MediaUploadSource::from_str("file").unwrap(), MediaUploadSource::File); + assert_eq!(MediaUploadSource::from_str("unknown").unwrap(), MediaUploadSource::Unknown); + assert!(MediaUploadSource::from_str("foo").is_err()); + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip() { + use strum::IntoEnumIterator; + for variant in MediaUploadSource::iter() { + assert_eq!(variant, MediaUploadSource::from_str(variant.to_str()).unwrap()); + assert_eq!(variant, MediaUploadSource::from_str(&format!("{}", variant)).unwrap()); + assert_eq!(variant, MediaUploadSource::from_str(&format!("{:?}", variant)).unwrap()); + } + } + + #[test] + fn serialized_length_ok_for_database() { + const MAX_LENGTH: usize = 16; // TODO(bt): Confirm database column width, then remove this comment. + use strum::IntoEnumIterator; + for variant in MediaUploadSource::iter() { + let serialized = variant.to_str(); + assert!(!serialized.is_empty(), "variant {:?} is too short", variant); + assert!(serialized.len() <= MAX_LENGTH, "variant {:?} is too long", variant); + } + } + } +} diff --git a/crates/schema/public/enums_db/src/by_table/media_uploads/media_upload_type.rs b/crates/schema/public/enums_db/src/by_table/media_uploads/media_upload_type.rs new file mode 100644 index 0000000000..22806714c9 --- /dev/null +++ b/crates/schema/public/enums_db/src/by_table/media_uploads/media_upload_type.rs @@ -0,0 +1,104 @@ +use strum::EnumCount; +use strum::EnumIter; + +/// Used in the `media_uploads` table in a `VARCHAR` field. +/// +/// DO NOT CHANGE VALUES WITHOUT A MIGRATION STRATEGY. +#[derive(Clone, Copy, Eq, PartialEq, Deserialize, Serialize, EnumIter, EnumCount)] +#[serde(rename_all = "lowercase")] +pub enum MediaUploadType { + /// Audio files: wav, mp3, etc. + Audio, + + /// Image files: png, jpeg, etc. + Image, + + /// Video files: mp4, etc. + Video, + + // Binary files: safetensors ... weights, etc. + Binary, +} + +// TODO(bt, 2022-12-21): This desperately needs MySQL integration tests! +impl_enum_display_and_debug_using_to_str!(MediaUploadType); +impl_mysql_enum_coders!(MediaUploadType); +impl_mysql_from_row!(MediaUploadType); + +/// NB: Legacy API for older code. +impl MediaUploadType { + pub fn to_str(&self) -> &'static str { + match self { + Self::Audio => "audio", + Self::Image => "image", + Self::Video => "video", + Self::Binary => "binary", + } + } + + pub fn from_str(value: &str) -> Result { + match value { + "audio" => Ok(Self::Audio), + "image" => Ok(Self::Image), + "video" => Ok(Self::Video), + "binary" => Ok(Self::Binary), + _ => Err(format!("invalid value: {:?}", value)), + } + } +} + +#[cfg(test)] +mod tests { + use super::super::media_upload_type::MediaUploadType; + use enums_shared::test_helpers::assert_serialization; + + #[test] + fn test_serialization() { + assert_serialization(MediaUploadType::Audio, "audio"); + assert_serialization(MediaUploadType::Image, "image"); + assert_serialization(MediaUploadType::Video, "video"); + assert_serialization(MediaUploadType::Binary, "binary"); + } + + #[test] + fn test_to_str() { + assert_eq!(MediaUploadType::Audio.to_str(), "audio"); + assert_eq!(MediaUploadType::Image.to_str(), "image"); + assert_eq!(MediaUploadType::Video.to_str(), "video"); + assert_eq!(MediaUploadType::Binary.to_str(), "binary"); + } + + #[test] + fn test_from_str() { + assert_eq!(MediaUploadType::from_str("audio").unwrap(), MediaUploadType::Audio); + assert_eq!(MediaUploadType::from_str("image").unwrap(), MediaUploadType::Image); + assert_eq!(MediaUploadType::from_str("video").unwrap(), MediaUploadType::Video); + assert_eq!(MediaUploadType::from_str("binary").unwrap(), MediaUploadType::Binary); + assert!(MediaUploadType::from_str("foo").is_err()); + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip() { + use strum::IntoEnumIterator; + for variant in MediaUploadType::iter() { + assert_eq!(variant, MediaUploadType::from_str(variant.to_str()).unwrap()); + assert_eq!(variant, MediaUploadType::from_str(&format!("{}", variant)).unwrap()); + assert_eq!(variant, MediaUploadType::from_str(&format!("{:?}", variant)).unwrap()); + } + } + + #[test] + fn serialized_length_ok_for_database() { + const MAX_LENGTH: usize = 16; // TODO(bt): Confirm database column width, then remove this comment. + use strum::IntoEnumIterator; + for variant in MediaUploadType::iter() { + let serialized = variant.to_str(); + assert!(!serialized.is_empty(), "variant {:?} is too short", variant); + assert!(serialized.len() <= MAX_LENGTH, "variant {:?} is too long", variant); + } + } + } +} diff --git a/crates/schema/public/enums_db/src/by_table/media_uploads/mod.rs b/crates/schema/public/enums_db/src/by_table/media_uploads/mod.rs new file mode 100644 index 0000000000..38dbfbff74 --- /dev/null +++ b/crates/schema/public/enums_db/src/by_table/media_uploads/mod.rs @@ -0,0 +1,2 @@ +pub mod media_upload_source; +pub mod media_upload_type; diff --git a/crates/schema/public/enums_db/src/by_table/mod.rs b/crates/schema/public/enums_db/src/by_table/mod.rs new file mode 100644 index 0000000000..f875036ef4 --- /dev/null +++ b/crates/schema/public/enums_db/src/by_table/mod.rs @@ -0,0 +1,30 @@ +pub mod audit_logs; +pub mod batch_generations; +pub mod beta_keys; +pub mod comments; +pub mod email_sender_jobs; +pub mod entity_stats; +pub mod featured_items; +pub mod generic_download_jobs; +pub mod generic_inference_jobs; +pub mod generic_synthetic_ids; +pub mod media_files; +pub mod media_uploads; +pub mod model_categories; +pub mod model_weights; +pub mod prompt_context_items; +pub mod prompts; +pub mod tag_uses; +pub mod trending_model_analytics; +pub mod tts_models; +pub mod tts_render_tasks; +pub mod usages; +pub mod user_bookmarks; +pub mod user_ratings; +pub mod users; +pub mod voice_conversion_models; +pub mod voice_conversion_results; +pub mod wallet_ledger_entries; +pub mod web_rendition_targets; +pub mod web_scraping_targets; +pub mod zs_voices; diff --git a/crates/schema/public/enums_db/src/by_table/model_categories/mod.rs b/crates/schema/public/enums_db/src/by_table/model_categories/mod.rs new file mode 100644 index 0000000000..3c5df49228 --- /dev/null +++ b/crates/schema/public/enums_db/src/by_table/model_categories/mod.rs @@ -0,0 +1 @@ +pub mod model_type; diff --git a/crates/schema/public/enums_db/src/by_table/model_categories/model_type.rs b/crates/schema/public/enums_db/src/by_table/model_categories/model_type.rs new file mode 100644 index 0000000000..8d714c0a32 --- /dev/null +++ b/crates/schema/public/enums_db/src/by_table/model_categories/model_type.rs @@ -0,0 +1,86 @@ +use strum::EnumCount; +use strum::EnumIter; + +/// Used in the `model_categories` table in an `ENUM` field. +/// (*WE WANT TO STOP USING ENUM FIELDS DUE TO MIGRATION ISSUES*) +/// +/// DO NOT CHANGE VALUES WITHOUT A MIGRATION STRATEGY. +#[derive(Clone, Copy, Eq, PartialEq, Hash, Deserialize, Serialize, EnumIter, EnumCount)] +#[serde(rename_all = "lowercase")] +pub enum ModelType { + Tts, + W2l, +} + +// TODO(bt, 2023-01-16): This desperately needs MySQL integration tests! +impl_enum_display_and_debug_using_to_str!(ModelType); +impl_mysql_enum_coders!(ModelType); +impl_mysql_from_row!(ModelType); + +/// NB: Legacy API for older code. +impl ModelType { + pub fn to_str(&self) -> &'static str { + match self { + Self::Tts => "tts", + Self::W2l => "w2l", + } + } + + pub fn from_str(value: &str) -> Result { + match value { + "tts" => Ok(Self::Tts), + "w2l" => Ok(Self::W2l), + _ => Err(format!("invalid value: {:?}", value)), + } + } +} + +#[cfg(test)] +mod tests { + use super::super::model_type::ModelType; + use enums_shared::test_helpers::assert_serialization; + + #[test] + fn test_serialization() { + assert_serialization(ModelType::Tts, "tts"); + assert_serialization(ModelType::W2l, "w2l"); + } + + #[test] + fn test_to_str() { + assert_eq!(ModelType::Tts.to_str(), "tts"); + assert_eq!(ModelType::W2l.to_str(), "w2l"); + } + + #[test] + fn test_from_str() { + assert_eq!(ModelType::from_str("tts").unwrap(), ModelType::Tts); + assert_eq!(ModelType::from_str("w2l").unwrap(), ModelType::W2l); + assert!(ModelType::from_str("foo").is_err()); + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip() { + use strum::IntoEnumIterator; + for variant in ModelType::iter() { + assert_eq!(variant, ModelType::from_str(variant.to_str()).unwrap()); + assert_eq!(variant, ModelType::from_str(&format!("{}", variant)).unwrap()); + assert_eq!(variant, ModelType::from_str(&format!("{:?}", variant)).unwrap()); + } + } + + #[test] + fn serialized_length_ok_for_database() { + const MAX_LENGTH: usize = 32; // TODO(bt): Confirm database column width, then remove this comment. + use strum::IntoEnumIterator; + for variant in ModelType::iter() { + let serialized = variant.to_str(); + assert!(!serialized.is_empty(), "variant {:?} is too short", variant); + assert!(serialized.len() <= MAX_LENGTH, "variant {:?} is too long", variant); + } + } + } +} diff --git a/crates/schema/public/enums_db/src/by_table/model_weights/mod.rs b/crates/schema/public/enums_db/src/by_table/model_weights/mod.rs new file mode 100644 index 0000000000..e98246b3d0 --- /dev/null +++ b/crates/schema/public/enums_db/src/by_table/model_weights/mod.rs @@ -0,0 +1,3 @@ +pub mod weights_category; +pub mod weights_file_type; +pub mod weights_types; diff --git a/crates/schema/public/enums_db/src/by_table/model_weights/weights_category.rs b/crates/schema/public/enums_db/src/by_table/model_weights/weights_category.rs new file mode 100644 index 0000000000..976a4c98f0 --- /dev/null +++ b/crates/schema/public/enums_db/src/by_table/model_weights/weights_category.rs @@ -0,0 +1,92 @@ +use strum::EnumCount; +use strum::EnumIter; + +#[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, Deserialize, Serialize, EnumIter, EnumCount)] +pub enum WeightsCategory { + #[serde(rename = "image_generation")] + ImageGeneration, + #[serde(rename = "text_to_speech")] + TextToSpeech, + #[serde(rename = "vocoder")] + Vocoder, + #[serde(rename = "voice_conversion")] + VoiceConversion, + #[serde(rename = "workflow_config")] + WorkflowConfig, +} + +impl WeightsCategory { + pub fn to_str(&self) -> &'static str { + match self { + Self::ImageGeneration => "image_generation", + Self::TextToSpeech => "text_to_speech", + Self::Vocoder => "vocoder", + Self::VoiceConversion => "voice_conversion", + Self::WorkflowConfig => "workflow_config", + } + } + + pub fn from_str(value: &str) -> Result { + match value { + "image_generation" => Ok(Self::ImageGeneration), + "text_to_speech" => Ok(Self::TextToSpeech), + "vocoder" => Ok(Self::Vocoder), + "voice_conversion" => Ok(Self::VoiceConversion), + "workflow_config" => Ok(Self::WorkflowConfig), + _ => Err(format!("invalid value: {:?}", value)), + } + } + +} +impl_enum_display_and_debug_using_to_str!(WeightsCategory); +impl_mysql_enum_coders!(WeightsCategory); +impl_mysql_from_row!(WeightsCategory); + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_to_str() { + assert_eq!(WeightsCategory::ImageGeneration.to_str(), "image_generation"); + assert_eq!(WeightsCategory::TextToSpeech.to_str(), "text_to_speech"); + assert_eq!(WeightsCategory::Vocoder.to_str(), "vocoder"); + assert_eq!(WeightsCategory::VoiceConversion.to_str(), "voice_conversion"); + assert_eq!(WeightsCategory::WorkflowConfig.to_str(), "workflow_config"); + } + + #[test] + fn test_from_str() { + assert_eq!(WeightsCategory::from_str("image_generation").unwrap(), WeightsCategory::ImageGeneration); + assert_eq!(WeightsCategory::from_str("text_to_speech").unwrap(), WeightsCategory::TextToSpeech); + assert_eq!(WeightsCategory::from_str("vocoder").unwrap(), WeightsCategory::Vocoder); + assert_eq!(WeightsCategory::from_str("voice_conversion").unwrap(), WeightsCategory::VoiceConversion); + assert_eq!(WeightsCategory::from_str("workflow_config").unwrap(), WeightsCategory::WorkflowConfig); + assert!(WeightsCategory::from_str("invalid").is_err()); + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip() { + use strum::IntoEnumIterator; + for variant in WeightsCategory::iter() { + assert_eq!(variant, WeightsCategory::from_str(variant.to_str()).unwrap()); + assert_eq!(variant, WeightsCategory::from_str(&format!("{}", variant)).unwrap()); + assert_eq!(variant, WeightsCategory::from_str(&format!("{:?}", variant)).unwrap()); + } + } + + #[test] + fn serialized_length_ok_for_database() { + const MAX_LENGTH: usize = 32; // TODO(bt): Confirm database column width, then remove this comment. + use strum::IntoEnumIterator; + for variant in WeightsCategory::iter() { + let serialized = variant.to_str(); + assert!(!serialized.is_empty(), "variant {:?} is too short", variant); + assert!(serialized.len() <= MAX_LENGTH, "variant {:?} is too long", variant); + } + } + } +} \ No newline at end of file diff --git a/crates/schema/public/enums_db/src/by_table/model_weights/weights_file_type.rs b/crates/schema/public/enums_db/src/by_table/model_weights/weights_file_type.rs new file mode 100644 index 0000000000..106a2bb3ad --- /dev/null +++ b/crates/schema/public/enums_db/src/by_table/model_weights/weights_file_type.rs @@ -0,0 +1,76 @@ +use strum::EnumCount; +use strum::EnumIter; + +// TODO we will need to scan the checkpoints for malicious code. We can't just trust the file extension. +#[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, Deserialize, Serialize, EnumIter, EnumCount)] +pub enum WeightsFileType { + #[serde(rename = "checkpoint")] + Checkpoint, + #[serde(rename = "safetensors")] + SafeTensors, +} + +impl WeightsFileType { + pub fn to_str(&self) -> &'static str { + match self { + Self::Checkpoint => "checkpoint", + Self::SafeTensors => "safetensors", + } + } + + pub fn from_str(value: &str) -> Result { + match value { + "checkpoint" => Ok(Self::Checkpoint), + "safetensors" => Ok(Self::SafeTensors), + _ => Err(format!("invalid value: {:?}", value)), + } + } + +} + +impl_enum_display_and_debug_using_to_str!(WeightsFileType); +impl_mysql_enum_coders!(WeightsFileType); +impl_mysql_from_row!(WeightsFileType); + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_to_str() { + assert_eq!(WeightsFileType::Checkpoint.to_str(), "checkpoint"); + assert_eq!(WeightsFileType::SafeTensors.to_str(), "safetensors"); + } + + #[test] + fn test_from_str() { + assert_eq!(WeightsFileType::from_str("checkpoint").unwrap(), WeightsFileType::Checkpoint); + assert_eq!(WeightsFileType::from_str("safetensors").unwrap(), WeightsFileType::SafeTensors); + assert!(WeightsFileType::from_str("invalid").is_err()); + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip() { + use strum::IntoEnumIterator; + for variant in WeightsFileType::iter() { + assert_eq!(variant, WeightsFileType::from_str(variant.to_str()).unwrap()); + assert_eq!(variant, WeightsFileType::from_str(&format!("{}", variant)).unwrap()); + assert_eq!(variant, WeightsFileType::from_str(&format!("{:?}", variant)).unwrap()); + } + } + + #[test] + fn serialized_length_ok_for_database() { + const MAX_LENGTH: usize = 32; // TODO(bt): Confirm database column width, then remove this comment. + use strum::IntoEnumIterator; + for variant in WeightsFileType::iter() { + let serialized = variant.to_str(); + assert!(!serialized.is_empty(), "variant {:?} is too short", variant); + assert!(serialized.len() <= MAX_LENGTH, "variant {:?} is too long", variant); + } + } + } +} \ No newline at end of file diff --git a/crates/schema/public/enums_db/src/by_table/model_weights/weights_types.rs b/crates/schema/public/enums_db/src/by_table/model_weights/weights_types.rs new file mode 100644 index 0000000000..7a08a41540 --- /dev/null +++ b/crates/schema/public/enums_db/src/by_table/model_weights/weights_types.rs @@ -0,0 +1,131 @@ +use strum::EnumCount; +use strum::EnumIter; + +#[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, Deserialize, Serialize, EnumIter, EnumCount)] +pub enum WeightsType { + #[serde(rename = "hifigan_tt2")] + HifiganTacotron2, + #[serde(rename = "rvc_v2")] + RvcV2, + #[serde(rename = "sd_1.5")] + StableDiffusion15, + #[serde(rename = "sdxl")] + StableDiffusionXL, + #[serde(rename = "so_vits_svc")] + SoVitsSvc, + #[serde(rename = "tt2")] + Tacotron2, + #[serde(rename = "loRA")] + LoRA, + #[serde(rename = "vall_e")] + VallE, + #[serde(rename = "comfy_ui")] + ComfyUi, + /// NB: In production these are filtered to the API's `Tacotron2_5`. + #[serde(rename = "gpt_so_vits")] + GptSoVits, +} + +impl WeightsType { + pub fn to_str(&self) -> &'static str { + match self { + Self::HifiganTacotron2 => "hifigan_tt2", + Self::RvcV2 => "rvc_v2", + Self::StableDiffusion15 => "sd_1.5", + Self::StableDiffusionXL => "sdxl", + Self::SoVitsSvc => "so_vits_svc", + Self::Tacotron2 => "tt2", + Self::LoRA => "loRA", + Self::VallE => "vall_e", + Self::ComfyUi => "comfy_ui", + Self::GptSoVits => "gpt_so_vits", + } + } + + pub fn from_str(value: &str) -> Result { + match value { + "hifigan_tt2" => Ok(Self::HifiganTacotron2), + "rvc_v2" => Ok(Self::RvcV2), + "sd_1.5" => Ok(Self::StableDiffusion15), + "sdxl" => Ok(Self::StableDiffusionXL), + "so_vits_svc" => Ok(Self::SoVitsSvc), + "tt2" => Ok(Self::Tacotron2), + "loRA" => Ok(Self::LoRA), + "vall_e" => Ok(Self::VallE), + "comfy_ui" => Ok(Self::ComfyUi), + "gpt_so_vits" => Ok(Self::GptSoVits), + _ => Err(format!("invalid value: {:?}", value)), + } + } + +} + +impl_enum_display_and_debug_using_to_str!(WeightsType); +impl_mysql_enum_coders!(WeightsType); +impl_mysql_from_row!(WeightsType); + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_to_str() { + assert_eq!(WeightsType::HifiganTacotron2.to_str(), "hifigan_tt2"); + assert_eq!(WeightsType::RvcV2.to_str(), "rvc_v2"); + assert_eq!(WeightsType::StableDiffusion15.to_str(), "sd_1.5"); + assert_eq!(WeightsType::StableDiffusionXL.to_str(), "sdxl"); + assert_eq!(WeightsType::SoVitsSvc.to_str(), "so_vits_svc"); + assert_eq!(WeightsType::Tacotron2.to_str(), "tt2"); + assert_eq!(WeightsType::LoRA.to_str(), "loRA"); + assert_eq!(WeightsType::VallE.to_str(), "vall_e"); + assert_eq!(WeightsType::ComfyUi.to_str(), "comfy_ui"); + assert_eq!(WeightsType::GptSoVits.to_str(), "gpt_so_vits"); + } + + #[test] + fn test_from_str() { + assert_eq!(WeightsType::from_str("hifigan_tt2").unwrap(), WeightsType::HifiganTacotron2); + assert_eq!(WeightsType::from_str("rvc_v2").unwrap(), WeightsType::RvcV2); + assert_eq!(WeightsType::from_str("sd_1.5").unwrap(), WeightsType::StableDiffusion15); + assert_eq!(WeightsType::from_str("sdxl").unwrap(), WeightsType::StableDiffusionXL); + assert_eq!(WeightsType::from_str("so_vits_svc").unwrap(), WeightsType::SoVitsSvc); + assert_eq!(WeightsType::from_str("tt2").unwrap(), WeightsType::Tacotron2); + assert_eq!(WeightsType::from_str("loRA").unwrap(), WeightsType::LoRA); + assert_eq!(WeightsType::from_str("vall_e").unwrap(), WeightsType::VallE); + assert_eq!(WeightsType::from_str("comfy_ui").unwrap(), WeightsType::ComfyUi); + assert_eq!(WeightsType::from_str("gpt_so_vits").unwrap(), WeightsType::GptSoVits); + assert!(WeightsType::from_str("invalid").is_err()); + } + + #[test] + fn test_all_variants() { + use strum::IntoEnumIterator; + let variants = WeightsType::iter(); + assert_eq!(variants.len(), 10); + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip() { + use strum::IntoEnumIterator; + for variant in WeightsType::iter() { + assert_eq!(variant, WeightsType::from_str(variant.to_str()).unwrap()); + assert_eq!(variant, WeightsType::from_str(&format!("{}", variant)).unwrap()); + assert_eq!(variant, WeightsType::from_str(&format!("{:?}", variant)).unwrap()); + } + } + + #[test] + fn serialized_length_ok_for_database() { + use strum::IntoEnumIterator; + const MAX_LENGTH: usize = 16; // TODO(bt): Confirm database column width, then remove this comment. + for variant in WeightsType::iter() { + let serialized = variant.to_str(); + assert!(!serialized.is_empty(), "variant {:?} is too short", variant); + assert!(serialized.len() <= MAX_LENGTH, "variant {:?} is too long", variant); + } + } + } +} diff --git a/crates/schema/public/enums_db/src/by_table/prompt_context_items/mod.rs b/crates/schema/public/enums_db/src/by_table/prompt_context_items/mod.rs new file mode 100644 index 0000000000..9a47938052 --- /dev/null +++ b/crates/schema/public/enums_db/src/by_table/prompt_context_items/mod.rs @@ -0,0 +1 @@ +pub mod prompt_context_semantic_type; diff --git a/crates/schema/public/enums_db/src/by_table/prompt_context_items/prompt_context_semantic_type.rs b/crates/schema/public/enums_db/src/by_table/prompt_context_items/prompt_context_semantic_type.rs new file mode 100644 index 0000000000..ce2b0147b7 --- /dev/null +++ b/crates/schema/public/enums_db/src/by_table/prompt_context_items/prompt_context_semantic_type.rs @@ -0,0 +1,167 @@ +use strum::EnumCount; +use strum::EnumIter; + +/* +Current DB values - this is in conflict with API serializations. Need to fix! +imgref +imgsrc +imgmask +vid_start_frame +vid_end_frame +vidref +*/ + +/// Used in the `prompt_context_items` table in a `VARCHAR(16)` field. +/// +/// DO NOT CHANGE VALUES WITHOUT A MIGRATION STRATEGY. +#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Deserialize, Serialize, EnumIter, EnumCount)] +#[serde(rename_all = "snake_case")] +pub enum PromptContextSemanticType { + /// Image-to-Video starting frame + VidStartFrame, + + /// Image-to-Video ending frame + VidEndFrame, + + /// Reference image for video generation (e.g. Seedance "vidref" mode) + #[serde(rename = "vidref")] + VidRef, + + /// Source image, eg. for inpainting. + Imgsrc, + + /// Image mask, eg. for inpainting. + Imgmask, + + /// Standard image reference without a semantic type (e.g. Sora/ChatGPT 4o/gpt-image-1) + Imgref, + + ImgrefCharacter, + ImgrefStyle, + ImgrefBg, + + /// Audio reference (e.g. for audio-to-video generation) + Audioref, +} + +// TODO(bt, 2022-12-21): This desperately needs MySQL integration tests! +impl_enum_display_and_debug_using_to_str!(PromptContextSemanticType); +impl_mysql_enum_coders!(PromptContextSemanticType); +impl_mysql_from_row!(PromptContextSemanticType); + +/// NB: Legacy API for older code. +impl PromptContextSemanticType { + pub fn to_str(&self) -> &'static str { + match self { + Self::VidStartFrame => "vid_start_frame", + Self::VidEndFrame => "vid_end_frame", + Self::VidRef => "vidref", + Self::Imgsrc => "imgsrc", + Self::Imgmask => "imgmask", + Self::Imgref => "imgref", + Self::ImgrefCharacter => "imgref_character", + Self::ImgrefStyle => "imgref_style", + Self::ImgrefBg => "imgref_bg", + Self::Audioref => "audioref", + } + } + + pub fn from_str(value: &str) -> Result { + match value { + "vid_start_frame" => Ok(Self::VidStartFrame), + "vid_end_frame" => Ok(Self::VidEndFrame), + "vidref" => Ok(Self::VidRef), + "imgsrc" => Ok(Self::Imgsrc), + "imgmask" => Ok(Self::Imgmask), + "imgref" => Ok(Self::Imgref), + "imgref_character" => Ok(Self::ImgrefCharacter), + "imgref_style" => Ok(Self::ImgrefStyle), + "imgref_bg" => Ok(Self::ImgrefBg), + "audioref" => Ok(Self::Audioref), + _ => Err(format!("invalid value: {:?}", value)), + } + } + +} + +#[cfg(test)] +mod tests { + use super::super::prompt_context_semantic_type::PromptContextSemanticType; + use enums_shared::test_helpers::assert_serialization; + + mod serde { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(PromptContextSemanticType::VidStartFrame, "vid_start_frame"); + assert_serialization(PromptContextSemanticType::VidEndFrame, "vid_end_frame"); + assert_serialization(PromptContextSemanticType::VidRef, "vidref"); + assert_serialization(PromptContextSemanticType::Imgsrc, "imgsrc"); + assert_serialization(PromptContextSemanticType::Imgmask, "imgmask"); + assert_serialization(PromptContextSemanticType::Imgref, "imgref"); + assert_serialization(PromptContextSemanticType::ImgrefCharacter, "imgref_character"); + assert_serialization(PromptContextSemanticType::ImgrefStyle, "imgref_style"); + assert_serialization(PromptContextSemanticType::ImgrefBg, "imgref_bg"); + assert_serialization(PromptContextSemanticType::Audioref, "audioref"); + } + } + + mod impl_methods { + use super::*; + + #[test] + fn to_str() { + assert_eq!(PromptContextSemanticType::VidStartFrame.to_str(), "vid_start_frame"); + assert_eq!(PromptContextSemanticType::VidEndFrame.to_str(), "vid_end_frame"); + assert_eq!(PromptContextSemanticType::VidRef.to_str(), "vidref"); + assert_eq!(PromptContextSemanticType::Imgsrc.to_str(), "imgsrc"); + assert_eq!(PromptContextSemanticType::Imgmask.to_str(), "imgmask"); + assert_eq!(PromptContextSemanticType::Imgref.to_str(), "imgref"); + assert_eq!(PromptContextSemanticType::ImgrefCharacter.to_str(), "imgref_character"); + assert_eq!(PromptContextSemanticType::ImgrefStyle.to_str(), "imgref_style"); + assert_eq!(PromptContextSemanticType::ImgrefBg.to_str(), "imgref_bg"); + assert_eq!(PromptContextSemanticType::Audioref.to_str(), "audioref"); + } + + #[test] + fn from_str() { + assert_eq!(PromptContextSemanticType::from_str("vid_start_frame").unwrap(), PromptContextSemanticType::VidStartFrame); + assert_eq!(PromptContextSemanticType::from_str("vid_end_frame").unwrap(), PromptContextSemanticType::VidEndFrame); + assert_eq!(PromptContextSemanticType::from_str("vidref").unwrap(), PromptContextSemanticType::VidRef); + assert_eq!(PromptContextSemanticType::from_str("imgsrc").unwrap(), PromptContextSemanticType::Imgsrc); + assert_eq!(PromptContextSemanticType::from_str("imgmask").unwrap(), PromptContextSemanticType::Imgmask); + assert_eq!(PromptContextSemanticType::from_str("imgref").unwrap(), PromptContextSemanticType::Imgref); + assert_eq!(PromptContextSemanticType::from_str("imgref_character").unwrap(), PromptContextSemanticType::ImgrefCharacter); + assert_eq!(PromptContextSemanticType::from_str("imgref_style").unwrap(), PromptContextSemanticType::ImgrefStyle); + assert_eq!(PromptContextSemanticType::from_str("imgref_bg").unwrap(), PromptContextSemanticType::ImgrefBg); + assert_eq!(PromptContextSemanticType::from_str("audioref").unwrap(), PromptContextSemanticType::Audioref); + assert!(PromptContextSemanticType::from_str("foo").is_err()); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip() { + use strum::IntoEnumIterator; + for variant in PromptContextSemanticType::iter() { + assert_eq!(variant, PromptContextSemanticType::from_str(variant.to_str()).unwrap()); + assert_eq!(variant, PromptContextSemanticType::from_str(&format!("{}", variant)).unwrap()); + assert_eq!(variant, PromptContextSemanticType::from_str(&format!("{:?}", variant)).unwrap()); + } + } + + #[test] + fn serialized_length_ok_for_database() { + use strum::IntoEnumIterator; + const MAX_LENGTH : usize = 16; + for variant in PromptContextSemanticType::iter() { + let serialized = variant.to_str(); + assert!(serialized.len() > 0, "variant {:?} is too short", variant); + assert!(serialized.len() <= MAX_LENGTH, "variant {:?} is too long", variant); + } + } + } +} diff --git a/crates/schema/public/enums_db/src/by_table/prompts/mod.rs b/crates/schema/public/enums_db/src/by_table/prompts/mod.rs new file mode 100644 index 0000000000..1dd09b23cd --- /dev/null +++ b/crates/schema/public/enums_db/src/by_table/prompts/mod.rs @@ -0,0 +1 @@ +pub mod prompt_type; diff --git a/crates/schema/public/enums_db/src/by_table/prompts/prompt_type.rs b/crates/schema/public/enums_db/src/by_table/prompts/prompt_type.rs new file mode 100644 index 0000000000..df96428b7e --- /dev/null +++ b/crates/schema/public/enums_db/src/by_table/prompts/prompt_type.rs @@ -0,0 +1,107 @@ +use strum::EnumCount; +use strum::EnumIter; + +/// Used in the `prompts` table in a `VARCHAR(16)` field. +/// +/// DO NOT CHANGE VALUES WITHOUT A MIGRATION STRATEGY. +#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Deserialize, Serialize, EnumIter, EnumCount)] +#[serde(rename_all = "snake_case")] +pub enum PromptType { + /// Artcraft (App) + ArtcraftApp, + + /// Stable diffusion + #[deprecated] + StableDiffusion, + + /// Comfy UI + #[deprecated] + ComfyUi, +} + +// TODO(bt, 2022-12-21): This desperately needs MySQL integration tests! +impl_enum_display_and_debug_using_to_str!(PromptType); +impl_mysql_enum_coders!(PromptType); +impl_mysql_from_row!(PromptType); + +/// NB: Legacy API for older code. +impl PromptType { + pub fn to_str(&self) -> &'static str { + match self { + Self::ArtcraftApp => "artcraft_app", + Self::StableDiffusion => "stable_diffusion", + Self::ComfyUi => "comfy_ui", + } + } + + pub fn from_str(value: &str) -> Result { + match value { + "artcraft_app" => Ok(Self::ArtcraftApp), + "stable_diffusion" => Ok(Self::StableDiffusion), + "comfy_ui" => Ok(Self::ComfyUi), + _ => Err(format!("invalid value: {:?}", value)), + } + } + +} + +#[cfg(test)] +mod tests { + use super::super::prompt_type::PromptType; + use enums_shared::test_helpers::assert_serialization; + + mod serde { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(PromptType::ArtcraftApp, "artcraft_app"); + assert_serialization(PromptType::StableDiffusion, "stable_diffusion"); + assert_serialization(PromptType::ComfyUi, "comfy_ui"); + } + } + + mod impl_methods { + use super::*; + + #[test] + fn to_str() { + assert_eq!(PromptType::ArtcraftApp.to_str(), "artcraft_app"); + assert_eq!(PromptType::StableDiffusion.to_str(), "stable_diffusion"); + assert_eq!(PromptType::ComfyUi.to_str(), "comfy_ui"); + } + + #[test] + fn from_str() { + assert_eq!(PromptType::from_str("artcraft_app").unwrap(), PromptType::ArtcraftApp); + assert_eq!(PromptType::from_str("stable_diffusion").unwrap(), PromptType::StableDiffusion); + assert_eq!(PromptType::from_str("comfy_ui").unwrap(), PromptType::ComfyUi); + assert!(PromptType::from_str("foo").is_err()); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip() { + use strum::IntoEnumIterator; + for variant in PromptType::iter() { + assert_eq!(variant, PromptType::from_str(variant.to_str()).unwrap()); + assert_eq!(variant, PromptType::from_str(&format!("{}", variant)).unwrap()); + assert_eq!(variant, PromptType::from_str(&format!("{:?}", variant)).unwrap()); + } + } + + #[test] + fn serialized_length_ok_for_database() { + use strum::IntoEnumIterator; + const MAX_LENGTH : usize = 16; + for variant in PromptType::iter() { + let serialized = variant.to_str(); + assert!(serialized.len() > 0, "variant {:?} is too short", variant); + assert!(serialized.len() <= MAX_LENGTH, "variant {:?} is too long", variant); + } + } + } +} diff --git a/crates/schema/public/enums_db/src/by_table/tag_uses/mod.rs b/crates/schema/public/enums_db/src/by_table/tag_uses/mod.rs new file mode 100644 index 0000000000..08e9530e42 --- /dev/null +++ b/crates/schema/public/enums_db/src/by_table/tag_uses/mod.rs @@ -0,0 +1 @@ +pub mod tag_use_entity_type; diff --git a/crates/schema/public/enums_db/src/by_table/tag_uses/tag_use_entity_type.rs b/crates/schema/public/enums_db/src/by_table/tag_uses/tag_use_entity_type.rs new file mode 100644 index 0000000000..dc947c5ff8 --- /dev/null +++ b/crates/schema/public/enums_db/src/by_table/tag_uses/tag_use_entity_type.rs @@ -0,0 +1,96 @@ +use strum::EnumCount; +use strum::EnumIter; + +/// Used in the `tag_uses` table in a `VARCHAR(32)` field named `entity_type`. +#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash, Deserialize, Serialize, EnumIter, EnumCount)] +pub enum TagUseEntityType { + /// Media files + #[serde(rename = "media_file")] + MediaFile, + + /// Model weights + #[serde(rename = "model_weight")] + ModelWeight, +} + +// TODO(bt, 2023-01-17): This desperately needs MySQL integration tests! +impl_enum_display_and_debug_using_to_str!(TagUseEntityType); +impl_mysql_enum_coders!(TagUseEntityType); +impl_mysql_from_row!(TagUseEntityType); + +/// NB: Legacy API for older code. +impl TagUseEntityType { + pub fn to_str(&self) -> &'static str { + match self { + Self::MediaFile => "media_file", + Self::ModelWeight => "model_weight", + } + } + + pub fn from_str(value: &str) -> Result { + match value { + "media_file" => Ok(Self::MediaFile), + "model_weight" => Ok(Self::ModelWeight), + _ => Err(format!("invalid value: {:?}", value)), + } + } + +} + +#[cfg(test)] +mod tests { + use enums_shared::test_helpers::assert_serialization; + use super::super::tag_use_entity_type::TagUseEntityType; + + mod serde { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(TagUseEntityType::MediaFile, "media_file"); + assert_serialization(TagUseEntityType::ModelWeight, "model_weight"); + } + } + + mod impl_methods { + use super::*; + + #[test] + fn test_to_str() { + assert_eq!(TagUseEntityType::MediaFile.to_str(), "media_file"); + assert_eq!(TagUseEntityType::ModelWeight.to_str(), "model_weight"); + } + + #[test] + fn test_from_str() { + assert_eq!(TagUseEntityType::from_str("media_file").unwrap(), TagUseEntityType::MediaFile); + assert_eq!(TagUseEntityType::from_str("model_weight").unwrap(), TagUseEntityType::ModelWeight); + assert!(TagUseEntityType::from_str("foo").is_err()); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip() { + use strum::IntoEnumIterator; + for variant in TagUseEntityType::iter() { + assert_eq!(variant, TagUseEntityType::from_str(variant.to_str()).unwrap()); + assert_eq!(variant, TagUseEntityType::from_str(&format!("{}", variant)).unwrap()); + assert_eq!(variant, TagUseEntityType::from_str(&format!("{:?}", variant)).unwrap()); + } + } + + #[test] + fn serialized_length_ok_for_database() { + use strum::IntoEnumIterator; + const MAX_LENGTH : usize = 32; + for variant in TagUseEntityType::iter() { + let serialized = variant.to_str(); + assert!(serialized.len() > 0, "variant {:?} is too short", variant); + assert!(serialized.len() <= MAX_LENGTH, "variant {:?} is too long", variant); + } + } + } +} diff --git a/crates/schema/public/enums_db/src/by_table/trending_model_analytics/mod.rs b/crates/schema/public/enums_db/src/by_table/trending_model_analytics/mod.rs new file mode 100644 index 0000000000..b7f654af7e --- /dev/null +++ b/crates/schema/public/enums_db/src/by_table/trending_model_analytics/mod.rs @@ -0,0 +1,2 @@ +pub mod model_type; +pub mod window_name; diff --git a/crates/schema/public/enums_db/src/by_table/trending_model_analytics/model_type.rs b/crates/schema/public/enums_db/src/by_table/trending_model_analytics/model_type.rs new file mode 100644 index 0000000000..6393677f28 --- /dev/null +++ b/crates/schema/public/enums_db/src/by_table/trending_model_analytics/model_type.rs @@ -0,0 +1,83 @@ +use strum::EnumCount; +use strum::EnumIter; + +/// Used in the `trending_model_analytics` table in a `VARCHAR` field. +/// +/// DO NOT CHANGE VALUES WITHOUT A MIGRATION STRATEGY. +#[derive(Clone, Copy, Eq, PartialEq, Deserialize, Serialize, EnumIter, EnumCount)] +#[serde(rename_all = "lowercase")] +pub enum ModelType { + /// TTS models + Tts, + + // NB: It's assumed we'll use this same system to track + // trending VC models too, so the next type would be "VC". +} + +// TODO(bt, 2023-01-17): This desperately needs MySQL integration tests! +impl_enum_display_and_debug_using_to_str!(ModelType); +impl_mysql_enum_coders!(ModelType); +impl_mysql_from_row!(ModelType); + +/// NB: Legacy API for older code. +impl ModelType { + pub fn to_str(&self) -> &'static str { + match self { + Self::Tts => "tts", + } + } + + pub fn from_str(value: &str) -> Result { + match value { + "tts" => Ok(Self::Tts), + _ => Err(format!("invalid value: {:?}", value)), + } + } +} + +#[cfg(test)] +mod tests { + use super::super::model_type::ModelType; + use enums_shared::test_helpers::assert_serialization; + + #[test] + fn test_serialization() { + assert_serialization(ModelType::Tts, "tts"); + } + + #[test] + fn test_to_str() { + assert_eq!(ModelType::Tts.to_str(), "tts"); + } + + #[test] + fn test_from_str() { + assert_eq!(ModelType::from_str("tts").unwrap(), ModelType::Tts); + assert!(ModelType::from_str("foo").is_err()); + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip() { + use strum::IntoEnumIterator; + for variant in ModelType::iter() { + assert_eq!(variant, ModelType::from_str(variant.to_str()).unwrap()); + assert_eq!(variant, ModelType::from_str(&format!("{}", variant)).unwrap()); + assert_eq!(variant, ModelType::from_str(&format!("{:?}", variant)).unwrap()); + } + } + + #[test] + fn serialized_length_ok_for_database() { + const MAX_LENGTH: usize = 32; // TODO(bt): Confirm database column width, then remove this comment. + use strum::IntoEnumIterator; + for variant in ModelType::iter() { + let serialized = variant.to_str(); + assert!(!serialized.is_empty(), "variant {:?} is too short", variant); + assert!(serialized.len() <= MAX_LENGTH, "variant {:?} is too long", variant); + } + } + } +} diff --git a/crates/schema/public/enums_db/src/by_table/trending_model_analytics/window_name.rs b/crates/schema/public/enums_db/src/by_table/trending_model_analytics/window_name.rs new file mode 100644 index 0000000000..b693ee9839 --- /dev/null +++ b/crates/schema/public/enums_db/src/by_table/trending_model_analytics/window_name.rs @@ -0,0 +1,108 @@ +use strum::EnumCount; +use strum::EnumIter; + +/// Used in the `window_name` table in a `VARCHAR` field. +/// +/// Contrary to most of this crate and unlike most "enum"-types +/// that are inflexible, new window names can be added/removed +/// without breaking too much. +#[derive(Clone, Copy, Eq, PartialEq, Hash, Deserialize, Serialize, EnumIter, EnumCount)] +pub enum WindowName { + /// Analytics over the last three hours + #[serde(rename = "last_3_hours")] + Last3Hours, + + /// Analytics over the last three hours + #[serde(rename = "last_3_days")] + Last3Days, + + /// Analytics over all historical records + #[serde(rename = "all_time")] + AllTime, +} + +// TODO(bt, 2023-01-17): This desperately needs MySQL integration tests! +impl_enum_display_and_debug_using_to_str!(WindowName); +impl_mysql_enum_coders!(WindowName); +impl_mysql_from_row!(WindowName); + +/// NB: Legacy API for older code. +impl WindowName { + pub fn to_str(&self) -> &'static str { + match self { + Self::Last3Hours => "last_3_hours", + Self::Last3Days => "last_3_days", + Self::AllTime => "all_time", + } + } + + pub fn from_str(value: &str) -> Result { + match value { + "last_3_hours" => Ok(Self::Last3Hours), + "last_3_days" => Ok(Self::Last3Days), + "all_time" => Ok(Self::AllTime), + _ => Err(format!("invalid value: {:?}", value)), + } + } +} + +#[cfg(test)] +mod tests { + use super::super::window_name::WindowName; + use enums_shared::test_helpers::assert_serialization; + + mod serde { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(WindowName::Last3Hours, "last_3_hours"); + assert_serialization(WindowName::Last3Days, "last_3_days"); + assert_serialization(WindowName::AllTime, "all_time"); + } + } + + mod impl_methods { + use super::*; + + #[test] + fn test_to_str() { + assert_eq!(WindowName::Last3Hours.to_str(), "last_3_hours"); + assert_eq!(WindowName::Last3Days.to_str(), "last_3_days"); + assert_eq!(WindowName::AllTime.to_str(), "all_time"); + } + + #[test] + fn test_from_str() { + assert_eq!(WindowName::from_str("last_3_hours").unwrap(), WindowName::Last3Hours); + assert_eq!(WindowName::from_str("last_3_days").unwrap(), WindowName::Last3Days); + assert_eq!(WindowName::from_str("all_time").unwrap(), WindowName::AllTime); + assert!(WindowName::from_str("foo").is_err()); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip() { + use strum::IntoEnumIterator; + for variant in WindowName::iter() { + assert_eq!(variant, WindowName::from_str(variant.to_str()).unwrap()); + assert_eq!(variant, WindowName::from_str(&format!("{}", variant)).unwrap()); + assert_eq!(variant, WindowName::from_str(&format!("{:?}", variant)).unwrap()); + } + } + + #[test] + fn serialized_length_ok_for_database() { + const MAX_LENGTH: usize = 32; // TODO(bt): Confirm database column width, then remove this comment. + use strum::IntoEnumIterator; + for variant in WindowName::iter() { + let serialized = variant.to_str(); + assert!(!serialized.is_empty(), "variant {:?} is too short", variant); + assert!(serialized.len() <= MAX_LENGTH, "variant {:?} is too long", variant); + } + } + } +} diff --git a/crates/schema/public/enums_db/src/by_table/tts_models/mod.rs b/crates/schema/public/enums_db/src/by_table/tts_models/mod.rs new file mode 100644 index 0000000000..f2bd5d5cae --- /dev/null +++ b/crates/schema/public/enums_db/src/by_table/tts_models/mod.rs @@ -0,0 +1 @@ +pub mod tts_model_type; diff --git a/crates/schema/public/enums_db/src/by_table/tts_models/tts_model_type.rs b/crates/schema/public/enums_db/src/by_table/tts_models/tts_model_type.rs new file mode 100644 index 0000000000..bf2d9270ed --- /dev/null +++ b/crates/schema/public/enums_db/src/by_table/tts_models/tts_model_type.rs @@ -0,0 +1,88 @@ +use strum::EnumCount; +use strum::EnumIter; + +/// Used in the `tts_models` table in an `ENUM` field. +/// -- Furthermore -- not all enum values are represented !! +/// +/// DO NOT CHANGE VALUES WITHOUT A MIGRATION STRATEGY. +#[derive(Clone, Copy, Eq, PartialEq, Deserialize, Serialize, EnumIter, EnumCount)] +pub enum TtsModelType { + #[serde(rename = "tacotron2")] + Tacotron2, + + #[serde(rename = "vits")] + Vits, +} + +// TODO(bt, 2023-04-03): This desperately needs MySQL integration tests! +impl_enum_display_and_debug_using_to_str!(TtsModelType); +impl_mysql_enum_coders!(TtsModelType); +impl_mysql_from_row!(TtsModelType); + +/// NB: Legacy API for older code. +impl TtsModelType { + pub fn to_str(&self) -> &'static str { + match self { + Self::Tacotron2 => "tacotron2", + Self::Vits => "vits", + } + } + + pub fn from_str(value: &str) -> Result { + match value { + "tacotron2" => Ok(Self::Tacotron2), + "vits" => Ok(Self::Vits), + _ => Err(format!("invalid value: {:?}", value)), + } + } +} + +#[cfg(test)] +mod tests { + use super::super::tts_model_type::TtsModelType; + use enums_shared::test_helpers::assert_serialization; + + #[test] + fn test_serialization() { + assert_serialization(TtsModelType::Tacotron2, "tacotron2"); + assert_serialization(TtsModelType::Vits, "vits"); + } + + #[test] + fn test_to_str() { + assert_eq!(TtsModelType::Tacotron2.to_str(), "tacotron2"); + assert_eq!(TtsModelType::Vits.to_str(), "vits"); + } + + #[test] + fn test_from_str() { + assert_eq!(TtsModelType::from_str("tacotron2").unwrap(), TtsModelType::Tacotron2); + assert_eq!(TtsModelType::from_str("vits").unwrap(), TtsModelType::Vits); + assert!(TtsModelType::from_str("foo").is_err()); + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip() { + use strum::IntoEnumIterator; + for variant in TtsModelType::iter() { + assert_eq!(variant, TtsModelType::from_str(variant.to_str()).unwrap()); + assert_eq!(variant, TtsModelType::from_str(&format!("{}", variant)).unwrap()); + assert_eq!(variant, TtsModelType::from_str(&format!("{:?}", variant)).unwrap()); + } + } + + #[test] + fn serialized_length_ok_for_database() { + const MAX_LENGTH: usize = 32; // TODO(bt): Confirm database column width, then remove this comment. + use strum::IntoEnumIterator; + for variant in TtsModelType::iter() { + let serialized = variant.to_str(); + assert!(!serialized.is_empty(), "variant {:?} is too short", variant); + assert!(serialized.len() <= MAX_LENGTH, "variant {:?} is too long", variant); + } + } + } +} diff --git a/crates/schema/public/enums_db/src/by_table/tts_render_tasks/mod.rs b/crates/schema/public/enums_db/src/by_table/tts_render_tasks/mod.rs new file mode 100644 index 0000000000..2fd09fffe5 --- /dev/null +++ b/crates/schema/public/enums_db/src/by_table/tts_render_tasks/mod.rs @@ -0,0 +1 @@ +pub mod tts_render_status; diff --git a/crates/schema/public/enums_db/src/by_table/tts_render_tasks/tts_render_status.rs b/crates/schema/public/enums_db/src/by_table/tts_render_tasks/tts_render_status.rs new file mode 100644 index 0000000000..04f1aeee40 --- /dev/null +++ b/crates/schema/public/enums_db/src/by_table/tts_render_tasks/tts_render_status.rs @@ -0,0 +1,125 @@ +use strum::EnumCount; +use strum::EnumIter; + +/// Used in the SqLite `tts_render_tasks` table in a `TEXT` field named `tts_render_status`. +#[derive(Clone, Copy, Eq, PartialEq, Hash, Deserialize, Serialize, EnumIter, EnumCount)] +pub enum TtsRenderStatus { + #[serde(rename = "new")] + New, + + // TODO: Added to fix a big. This whole enum should die. + #[serde(rename = "processing")] + Processing, + + #[serde(rename = "skipped")] + Skipped, + + #[serde(rename = "failed")] + Failed, + + #[serde(rename = "permanently_failed")] + PermanentlyFailed, + + #[serde(rename = "success")] + Success, +} + +// TODO(bt, 2023-01-17): This desperately needs Sqlite integration tests! +impl_enum_display_and_debug_using_to_str!(TtsRenderStatus); +impl_sqlite_enum_coders!(TtsRenderStatus); + +/// NB: Legacy API for older code. +impl TtsRenderStatus { + pub fn to_str(&self) -> &'static str { + match self { + Self::New => "new", + Self::Processing => "processing", + Self::Skipped => "skipped", + Self::Failed => "failed", + Self::PermanentlyFailed => "permanently_failed", + Self::Success => "success", + } + } + + pub fn from_str(value: &str) -> Result { + match value { + "new" => Ok(Self::New), + "processing" => Ok(Self::Processing), + "skipped" => Ok(Self::Skipped), + "failed" => Ok(Self::Failed), + "permanently_failed" => Ok(Self::PermanentlyFailed), + "success" => Ok(Self::Success), + _ => Err(format!("invalid value: {:?}", value)), + } + } +} + +#[cfg(test)] +mod tests { + use super::super::tts_render_status::TtsRenderStatus; + use enums_shared::test_helpers::assert_serialization; + + mod serde { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(TtsRenderStatus::New, "new"); + assert_serialization(TtsRenderStatus::Processing, "processing"); + assert_serialization(TtsRenderStatus::Skipped, "skipped"); + assert_serialization(TtsRenderStatus::Failed, "failed"); + assert_serialization(TtsRenderStatus::PermanentlyFailed, "permanently_failed"); + assert_serialization(TtsRenderStatus::Success, "success"); + } + } + + mod impl_methods { + use super::*; + + #[test] + fn test_to_str() { + assert_eq!(TtsRenderStatus::New.to_str(), "new"); + assert_eq!(TtsRenderStatus::Processing.to_str(), "processing"); + assert_eq!(TtsRenderStatus::Skipped.to_str(), "skipped"); + assert_eq!(TtsRenderStatus::Failed.to_str(), "failed"); + assert_eq!(TtsRenderStatus::PermanentlyFailed.to_str(), "permanently_failed"); + assert_eq!(TtsRenderStatus::Success.to_str(), "success"); + } + + #[test] + fn test_from_str() { + assert_eq!(TtsRenderStatus::from_str("new").unwrap(), TtsRenderStatus::New); + assert_eq!(TtsRenderStatus::from_str("processing").unwrap(), TtsRenderStatus::Processing); + assert_eq!(TtsRenderStatus::from_str("skipped").unwrap(), TtsRenderStatus::Skipped); + assert_eq!(TtsRenderStatus::from_str("failed").unwrap(), TtsRenderStatus::Failed); + assert_eq!(TtsRenderStatus::from_str("permanently_failed").unwrap(), TtsRenderStatus::PermanentlyFailed); + assert_eq!(TtsRenderStatus::from_str("success").unwrap(), TtsRenderStatus::Success); + assert!(TtsRenderStatus::from_str("foo").is_err()); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip() { + use strum::IntoEnumIterator; + for variant in TtsRenderStatus::iter() { + assert_eq!(variant, TtsRenderStatus::from_str(variant.to_str()).unwrap()); + assert_eq!(variant, TtsRenderStatus::from_str(&format!("{}", variant)).unwrap()); + assert_eq!(variant, TtsRenderStatus::from_str(&format!("{:?}", variant)).unwrap()); + } + } + + #[test] + fn serialized_length_ok_for_database() { + const MAX_LENGTH: usize = 32; // TODO(bt): Confirm database column width, then remove this comment. + use strum::IntoEnumIterator; + for variant in TtsRenderStatus::iter() { + let serialized = variant.to_str(); + assert!(!serialized.is_empty(), "variant {:?} is too short", variant); + assert!(serialized.len() <= MAX_LENGTH, "variant {:?} is too long", variant); + } + } + } +} diff --git a/crates/schema/public/enums_db/src/by_table/usages/mod.rs b/crates/schema/public/enums_db/src/by_table/usages/mod.rs new file mode 100644 index 0000000000..cd5a40cf1b --- /dev/null +++ b/crates/schema/public/enums_db/src/by_table/usages/mod.rs @@ -0,0 +1 @@ +pub mod usages_type; diff --git a/crates/schema/public/enums_db/src/by_table/usages/usages_type.rs b/crates/schema/public/enums_db/src/by_table/usages/usages_type.rs new file mode 100644 index 0000000000..4c26f37d9a --- /dev/null +++ b/crates/schema/public/enums_db/src/by_table/usages/usages_type.rs @@ -0,0 +1,97 @@ +use strum::EnumCount; +use strum::EnumIter; + +/// Used in the `usages` table in a `VARCHAR(16)` field. (Two fields!) +/// +/// DO NOT CHANGE VALUES WITHOUT A MIGRATION STRATEGY. +#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Deserialize, Serialize, EnumIter, EnumCount)] +#[serde(rename_all = "snake_case")] +pub enum UsagesType { + /// Represents a foreign key link against a model_weights record + ModelWeight, + + /// Represents a foreign key link against a media_files record + MediaFile, +} + +// TODO(bt, 2022-12-21): This desperately needs MySQL integration tests! +impl_enum_display_and_debug_using_to_str!(UsagesType); +impl_mysql_enum_coders!(UsagesType); +impl_mysql_from_row!(UsagesType); + +/// NB: Legacy API for older code. +impl UsagesType { + pub fn to_str(&self) -> &'static str { + match self { + Self::ModelWeight => "model_weight", + Self::MediaFile => "media_file", + } + } + + pub fn from_str(value: &str) -> Result { + match value { + "model_weight" => Ok(Self::ModelWeight), + "media_file" => Ok(Self::MediaFile), + _ => Err(format!("invalid value: {:?}", value)), + } + } + +} + +#[cfg(test)] +mod tests { + use super::super::usages_type::UsagesType; + use enums_shared::test_helpers::assert_serialization; + + mod serde { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(UsagesType::ModelWeight, "model_weight"); + assert_serialization(UsagesType::MediaFile, "media_file"); + } + } + + mod impl_methods { + use super::*; + + #[test] + fn to_str() { + assert_eq!(UsagesType::ModelWeight.to_str(), "model_weight"); + assert_eq!(UsagesType::MediaFile.to_str(), "media_file"); + } + + #[test] + fn from_str() { + assert_eq!(UsagesType::from_str("model_weight").unwrap(), UsagesType::ModelWeight); + assert_eq!(UsagesType::from_str("media_file").unwrap(), UsagesType::MediaFile); + assert!(UsagesType::from_str("foo").is_err()); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip() { + use strum::IntoEnumIterator; + for variant in UsagesType::iter() { + assert_eq!(variant, UsagesType::from_str(variant.to_str()).unwrap()); + assert_eq!(variant, UsagesType::from_str(&format!("{}", variant)).unwrap()); + assert_eq!(variant, UsagesType::from_str(&format!("{:?}", variant)).unwrap()); + } + } + + #[test] + fn serialized_length_ok_for_database() { + use strum::IntoEnumIterator; + const MAX_LENGTH : usize = 16; + for variant in UsagesType::iter() { + let serialized = variant.to_str(); + assert!(serialized.len() > 0, "variant {:?} is too short", variant); + assert!(serialized.len() <= MAX_LENGTH, "variant {:?} is too long", variant); + } + } + } +} diff --git a/crates/schema/public/enums_db/src/by_table/user_bookmarks/mod.rs b/crates/schema/public/enums_db/src/by_table/user_bookmarks/mod.rs new file mode 100644 index 0000000000..49689232da --- /dev/null +++ b/crates/schema/public/enums_db/src/by_table/user_bookmarks/mod.rs @@ -0,0 +1 @@ +pub mod user_bookmark_entity_type; diff --git a/crates/schema/public/enums_db/src/by_table/user_bookmarks/user_bookmark_entity_type.rs b/crates/schema/public/enums_db/src/by_table/user_bookmarks/user_bookmark_entity_type.rs new file mode 100644 index 0000000000..87d5c0cfa6 --- /dev/null +++ b/crates/schema/public/enums_db/src/by_table/user_bookmarks/user_bookmark_entity_type.rs @@ -0,0 +1,158 @@ +use strum::EnumCount; +use strum::EnumIter; + +/// Used in the `user_bookmarks` table in a `VARCHAR(32)` field named `entity_type`. +#[derive(Clone, Copy, Eq, PartialEq, Hash, Deserialize, Serialize, EnumIter, EnumCount)] +pub enum UserBookmarkEntityType { + /// User + #[serde(rename = "user")] + User, + + /// TTS model (architecture does not matter) + #[serde(rename = "tts_model")] + TtsModel, + + /// TTS result (architecture does not matter) + #[serde(rename = "tts_result")] + TtsResult, + + /// W2L template + #[serde(rename = "w2l_template")] + W2lTemplate, + + /// W2L result + #[serde(rename = "w2l_result")] + W2lResult, + + /// MediaFile + #[serde(rename = "media_file")] + MediaFile, + + /// ModelWeight (the new way to store models) + #[serde(rename = "model_weight")] + ModelWeight, + + /// VoiceConversionModel + #[serde(rename = "voice_conversion_model")] + VoiceConversionModel, + + /// ZsVoice + #[serde(rename = "zs_voice")] + ZsVoice, +} + +// TODO(bt, 2023-01-17): This desperately needs MySQL integration tests! +impl_enum_display_and_debug_using_to_str!(UserBookmarkEntityType); +impl_mysql_enum_coders!(UserBookmarkEntityType); +impl_mysql_from_row!(UserBookmarkEntityType); + +/// NB: Legacy API for older code. +impl UserBookmarkEntityType { + pub fn to_str(&self) -> &'static str { + match self { + Self::User => "user", + Self::TtsModel => "tts_model", + Self::TtsResult => "tts_result", + Self::W2lTemplate => "w2l_template", + Self::W2lResult => "w2l_result", + Self::MediaFile => "media_file", + Self::ModelWeight => "model_weight", + Self::VoiceConversionModel => "voice_conversion_model", + Self::ZsVoice => "zs_voice", + } + } + + pub fn from_str(value: &str) -> Result { + match value { + "user" => Ok(Self::User), + "tts_model" => Ok(Self::TtsModel), + "tts_result" => Ok(Self::TtsResult), + "w2l_template" => Ok(Self::W2lTemplate), + "w2l_result" => Ok(Self::W2lResult), + "media_file" => Ok(Self::MediaFile), + "model_weight" => Ok(Self::ModelWeight), + "voice_conversion_model" => Ok(Self::VoiceConversionModel), + "zs_voice" => Ok(Self::ZsVoice), + _ => Err(format!("invalid value: {:?}", value)), + } + } +} + +#[cfg(test)] +mod tests { + use super::super::user_bookmark_entity_type::UserBookmarkEntityType; + use enums_shared::test_helpers::assert_serialization; + + mod serde { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(UserBookmarkEntityType::User, "user"); + assert_serialization(UserBookmarkEntityType::TtsModel, "tts_model"); + assert_serialization(UserBookmarkEntityType::TtsResult, "tts_result"); + assert_serialization(UserBookmarkEntityType::W2lTemplate, "w2l_template"); + assert_serialization(UserBookmarkEntityType::W2lResult, "w2l_result"); + assert_serialization(UserBookmarkEntityType::MediaFile, "media_file"); + assert_serialization(UserBookmarkEntityType::ModelWeight, "model_weight"); + assert_serialization(UserBookmarkEntityType::VoiceConversionModel, "voice_conversion_model"); + assert_serialization(UserBookmarkEntityType::ZsVoice, "zs_voice"); + } + } + + mod impl_methods { + use super::*; + + #[test] + fn test_to_str() { + assert_eq!(UserBookmarkEntityType::User.to_str(), "user"); + assert_eq!(UserBookmarkEntityType::TtsModel.to_str(), "tts_model"); + assert_eq!(UserBookmarkEntityType::TtsResult.to_str(), "tts_result"); + assert_eq!(UserBookmarkEntityType::W2lTemplate.to_str(), "w2l_template"); + assert_eq!(UserBookmarkEntityType::W2lResult.to_str(), "w2l_result"); + assert_eq!(UserBookmarkEntityType::MediaFile.to_str(), "media_file"); + assert_eq!(UserBookmarkEntityType::ModelWeight.to_str(), "model_weight"); + assert_eq!(UserBookmarkEntityType::VoiceConversionModel.to_str(), "voice_conversion_model"); + assert_eq!(UserBookmarkEntityType::ZsVoice.to_str(), "zs_voice"); + } + + #[test] + fn test_from_str() { + assert_eq!(UserBookmarkEntityType::from_str("user").unwrap(), UserBookmarkEntityType::User); + assert_eq!(UserBookmarkEntityType::from_str("tts_model").unwrap(), UserBookmarkEntityType::TtsModel); + assert_eq!(UserBookmarkEntityType::from_str("tts_result").unwrap(), UserBookmarkEntityType::TtsResult); + assert_eq!(UserBookmarkEntityType::from_str("w2l_template").unwrap(), UserBookmarkEntityType::W2lTemplate); + assert_eq!(UserBookmarkEntityType::from_str("w2l_result").unwrap(), UserBookmarkEntityType::W2lResult); + assert_eq!(UserBookmarkEntityType::from_str("media_file").unwrap(), UserBookmarkEntityType::MediaFile); + assert_eq!(UserBookmarkEntityType::from_str("model_weight").unwrap(), UserBookmarkEntityType::ModelWeight); + assert_eq!(UserBookmarkEntityType::from_str("voice_conversion_model").unwrap(), UserBookmarkEntityType::VoiceConversionModel); + assert_eq!(UserBookmarkEntityType::from_str("zs_voice").unwrap(), UserBookmarkEntityType::ZsVoice); + assert!(UserBookmarkEntityType::from_str("foo").is_err()); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip() { + use strum::IntoEnumIterator; + for variant in UserBookmarkEntityType::iter() { + assert_eq!(variant, UserBookmarkEntityType::from_str(variant.to_str()).unwrap()); + assert_eq!(variant, UserBookmarkEntityType::from_str(&format!("{}", variant)).unwrap()); + assert_eq!(variant, UserBookmarkEntityType::from_str(&format!("{:?}", variant)).unwrap()); + } + } + + #[test] + fn serialized_length_ok_for_database() { + const MAX_LENGTH: usize = 32; // TODO(bt): Confirm database column width, then remove this comment. + use strum::IntoEnumIterator; + for variant in UserBookmarkEntityType::iter() { + let serialized = variant.to_str(); + assert!(!serialized.is_empty(), "variant {:?} is too short", variant); + assert!(serialized.len() <= MAX_LENGTH, "variant {:?} is too long", variant); + } + } + } +} diff --git a/crates/schema/public/enums_db/src/by_table/user_ratings/entity_type.rs b/crates/schema/public/enums_db/src/by_table/user_ratings/entity_type.rs new file mode 100644 index 0000000000..1f932557aa --- /dev/null +++ b/crates/schema/public/enums_db/src/by_table/user_ratings/entity_type.rs @@ -0,0 +1,131 @@ +use strum::EnumCount; +use strum::EnumIter; + +/// Used in the `user_ratings` table in a `VARCHAR(32)` field named `entity_type`. +#[derive(Clone, Copy, Eq, PartialEq, Hash, Deserialize, Serialize, EnumIter, EnumCount)] +pub enum UserRatingEntityType { + /// Media files (inference results, uploads, etc.) + #[serde(rename = "media_file")] + MediaFile, + + /// Model weights (modern, polymorphic, type agnostic) + #[serde(rename = "model_weight")] + ModelWeight, + + /// TTS model (architecture does not matter) + #[serde(rename = "tts_model")] + TtsModel, + + /// TTS result (architecture does not matter) + #[serde(rename = "tts_result")] + TtsResult, + + /// W2L template + #[serde(rename = "w2l_template")] + W2lTemplate, + + /// W2L result + #[serde(rename = "w2l_result")] + W2lResult, +} + +// TODO(bt, 2023-01-17): This desperately needs MySQL integration tests! +impl_enum_display_and_debug_using_to_str!(UserRatingEntityType); +impl_mysql_enum_coders!(UserRatingEntityType); +impl_mysql_from_row!(UserRatingEntityType); + +/// NB: Legacy API for older code. +impl UserRatingEntityType { + pub fn to_str(&self) -> &'static str { + match self { + Self::MediaFile => "media_file", + Self::ModelWeight => "model_weight", + Self::TtsModel => "tts_model", + Self::TtsResult => "tts_result", + Self::W2lTemplate => "w2l_template", + Self::W2lResult => "w2l_result", + } + } + + pub fn from_str(value: &str) -> Result { + match value { + "media_file" => Ok(Self::MediaFile), + "model_weight" => Ok(Self::ModelWeight), + "tts_model" => Ok(Self::TtsModel), + "tts_result" => Ok(Self::TtsResult), + "w2l_template" => Ok(Self::W2lTemplate), + "w2l_result" => Ok(Self::W2lResult), + _ => Err(format!("invalid value: {:?}", value)), + } + } +} + +#[cfg(test)] +mod tests { + use super::super::entity_type::UserRatingEntityType; + use enums_shared::test_helpers::assert_serialization; + + mod serde { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(UserRatingEntityType::MediaFile, "media_file"); + assert_serialization(UserRatingEntityType::ModelWeight, "model_weight"); + assert_serialization(UserRatingEntityType::TtsModel, "tts_model"); + assert_serialization(UserRatingEntityType::TtsResult, "tts_result"); + assert_serialization(UserRatingEntityType::W2lTemplate, "w2l_template"); + assert_serialization(UserRatingEntityType::W2lResult, "w2l_result"); + } + } + + mod impl_methods { + use super::*; + + #[test] + fn test_to_str() { + assert_eq!(UserRatingEntityType::MediaFile.to_str(), "media_file"); + assert_eq!(UserRatingEntityType::ModelWeight.to_str(), "model_weight"); + assert_eq!(UserRatingEntityType::TtsModel.to_str(), "tts_model"); + assert_eq!(UserRatingEntityType::TtsResult.to_str(), "tts_result"); + assert_eq!(UserRatingEntityType::W2lTemplate.to_str(), "w2l_template"); + assert_eq!(UserRatingEntityType::W2lResult.to_str(), "w2l_result"); + } + + #[test] + fn test_from_str() { + assert_eq!(UserRatingEntityType::from_str("media_file").unwrap(), UserRatingEntityType::MediaFile); + assert_eq!(UserRatingEntityType::from_str("model_weight").unwrap(), UserRatingEntityType::ModelWeight); + assert_eq!(UserRatingEntityType::from_str("tts_model").unwrap(), UserRatingEntityType::TtsModel); + assert_eq!(UserRatingEntityType::from_str("tts_result").unwrap(), UserRatingEntityType::TtsResult); + assert_eq!(UserRatingEntityType::from_str("w2l_template").unwrap(), UserRatingEntityType::W2lTemplate); + assert_eq!(UserRatingEntityType::from_str("w2l_result").unwrap(), UserRatingEntityType::W2lResult); + assert!(UserRatingEntityType::from_str("foo").is_err()); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip() { + use strum::IntoEnumIterator; + for variant in UserRatingEntityType::iter() { + assert_eq!(variant, UserRatingEntityType::from_str(variant.to_str()).unwrap()); + assert_eq!(variant, UserRatingEntityType::from_str(&format!("{}", variant)).unwrap()); + assert_eq!(variant, UserRatingEntityType::from_str(&format!("{:?}", variant)).unwrap()); + } + } + + #[test] + fn serialized_length_ok_for_database() { + const MAX_LENGTH: usize = 32; // TODO(bt): Confirm database column width, then remove this comment. + use strum::IntoEnumIterator; + for variant in UserRatingEntityType::iter() { + let serialized = variant.to_str(); + assert!(!serialized.is_empty(), "variant {:?} is too short", variant); + assert!(serialized.len() <= MAX_LENGTH, "variant {:?} is too long", variant); + } + } + } +} diff --git a/crates/schema/public/enums_db/src/by_table/user_ratings/mod.rs b/crates/schema/public/enums_db/src/by_table/user_ratings/mod.rs new file mode 100644 index 0000000000..cd3855acfb --- /dev/null +++ b/crates/schema/public/enums_db/src/by_table/user_ratings/mod.rs @@ -0,0 +1,2 @@ +pub mod entity_type; +pub mod rating_value; diff --git a/crates/schema/public/enums_db/src/by_table/user_ratings/rating_value.rs b/crates/schema/public/enums_db/src/by_table/user_ratings/rating_value.rs new file mode 100644 index 0000000000..ac7572aaed --- /dev/null +++ b/crates/schema/public/enums_db/src/by_table/user_ratings/rating_value.rs @@ -0,0 +1,182 @@ +use strum::EnumCount; +use strum::EnumIter; + +/// UserRatingValue +/// +/// - Used in the `user_ratings` table as an `ENUM` field named `rating_type`. +/// - Used in the HTTP API. +/// +/// To use this in a query, the query must have type annotations. +/// See: https://www.gitmemory.com/issue/launchbadge/sqlx/1241/847154375 +/// eg. preferred_tts_result_visibility as `rating_type: enums::by_table::user_ratings::rating_type::UserRatingValue` +/// +/// See also: https://docs.rs/sqlx/0.4.0-beta.1/sqlx/trait.Type.html +/// +/// *DO NOT CHANGE VALUES WITHOUT A MIGRATION STRATEGY!* +/// +#[derive(Clone, Copy, Eq, PartialEq, Deserialize, Serialize, sqlx::Type, EnumIter, EnumCount)] +#[sqlx(rename_all = "lowercase")] +#[serde(rename_all = "lowercase")] +pub enum UserRatingValue { + /// This is considered a ratings "soft deletion" and does not count towards a total score. + /// This is the default rating. + Neutral, + /// This is a positive vote / upvote / like. + /// They are available to non-logged-in users as long as they have the URL. + Positive, + /// This is a negative vote / downvote / dislike. + Negative, +} + +impl_enum_display_and_debug_using_to_str!(UserRatingValue); + +impl Default for UserRatingValue { + fn default() -> Self { Self::Neutral } +} + +/// NB: Legacy API for older code. +impl UserRatingValue { + pub fn to_str(&self) -> &'static str { + match self { + Self::Neutral => "neutral", + Self::Positive => "positive", + Self::Negative => "negative", + } + } + + pub fn from_str(value: &str) -> Result { + match value { + "neutral" => Ok(Self::Neutral), + "positive" => Ok(Self::Positive), + "negative" => Ok(Self::Negative), + _ => Err(format!("invalid value: {:?}", value)), + } + } +} + +#[cfg(test)] +mod tests { + use super::super::rating_value::UserRatingValue; + use enums_shared::test_helpers::assert_serialization; + + #[test] + fn test_serialization() { + assert_serialization(UserRatingValue::Neutral, "neutral"); + assert_serialization(UserRatingValue::Positive, "positive"); + assert_serialization(UserRatingValue::Negative, "negative"); + } + + mod impl_methods { + use super::*; + + #[test] + fn to_str() { + assert_eq!(UserRatingValue::Neutral.to_str(), "neutral"); + assert_eq!(UserRatingValue::Positive.to_str(), "positive"); + assert_eq!(UserRatingValue::Negative.to_str(), "negative"); + } + + #[test] + fn from_str() { + assert_eq!(UserRatingValue::from_str("neutral").unwrap(), UserRatingValue::Neutral); + assert_eq!(UserRatingValue::from_str("positive").unwrap(), UserRatingValue::Positive); + assert_eq!(UserRatingValue::from_str("negative").unwrap(), UserRatingValue::Negative); + assert!(UserRatingValue::from_str("foo").is_err()); + } + } + + mod traits { + use super::*; + + #[test] + fn default() { + assert_eq!(UserRatingValue::default(), UserRatingValue::Neutral); + } + + #[test] + fn display() { + let visibility = UserRatingValue::Positive; + assert_eq!(format!("{}", visibility), "positive".to_string()); + } + + #[test] + fn debug() { + let visibility = UserRatingValue::Negative; + assert_eq!(format!("{:?}", visibility), "negative".to_string()); + } + } + + #[derive(Serialize, Deserialize, PartialEq, Debug)] + struct CompositeType { + visibility: UserRatingValue, + string: String, + } + + mod serde_serialization { + use super::*; + + #[test] + fn serialize() { + let expected = "\"positive\"".to_string(); // NB: Quoted + + assert_eq!(expected, serde_json::to_string(&UserRatingValue::Positive).unwrap()); + + // Just to show this serializes the same as a string + assert_eq!(expected, serde_json::to_string("positive").unwrap()); + } + + #[test] + fn nested_serialize() { + let value = CompositeType { visibility: UserRatingValue::Negative, string: "bar".to_string() }; + let expected = r#"{"visibility":"negative","string":"bar"}"#.to_string(); + assert_eq!(expected, serde_json::to_string(&value).unwrap()); + } + } + + mod serde_deserialization { + use super::*; + + #[test] + fn deserialize() { + let payload = "\"positive\""; // NB: Quoted + let value: UserRatingValue = serde_json::from_str(payload).unwrap(); + assert_eq!(value, UserRatingValue::Positive); + } + + #[test] + fn nested_deserialize() { + let payload = r#"{"visibility":"neutral","string":"bar"}"#.to_string(); + let expected = CompositeType { + visibility: UserRatingValue::Neutral, + string: "bar".to_string(), + }; + + assert_eq!(expected, serde_json::from_str::(&payload).unwrap()); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip() { + use strum::IntoEnumIterator; + for variant in UserRatingValue::iter() { + assert_eq!(variant, UserRatingValue::from_str(variant.to_str()).unwrap()); + assert_eq!(variant, UserRatingValue::from_str(&format!("{}", variant)).unwrap()); + assert_eq!(variant, UserRatingValue::from_str(&format!("{:?}", variant)).unwrap()); + } + } + + #[test] + fn serialized_length_ok_for_database() { + const MAX_LENGTH: usize = 32; // TODO(bt): Confirm database column width, then remove this comment. + use strum::IntoEnumIterator; + for variant in UserRatingValue::iter() { + let serialized = variant.to_str(); + assert!(!serialized.is_empty(), "variant {:?} is too short", variant); + assert!(serialized.len() <= MAX_LENGTH, "variant {:?} is too long", variant); + } + } + } +} diff --git a/crates/schema/public/enums_db/src/by_table/users/mod.rs b/crates/schema/public/enums_db/src/by_table/users/mod.rs new file mode 100644 index 0000000000..e4f4741f1b --- /dev/null +++ b/crates/schema/public/enums_db/src/by_table/users/mod.rs @@ -0,0 +1,3 @@ +pub mod user_feature_flag; +pub mod user_signup_method; +pub mod user_signup_source; diff --git a/crates/schema/public/enums_db/src/by_table/users/user_feature_flag.rs b/crates/schema/public/enums_db/src/by_table/users/user_feature_flag.rs new file mode 100644 index 0000000000..b9e2e9b903 --- /dev/null +++ b/crates/schema/public/enums_db/src/by_table/users/user_feature_flag.rs @@ -0,0 +1,112 @@ +use strum::EnumCount; +use strum::EnumIter; + +/// Used in the `users` table in a `VARCHAR` field (stored as comma separated set). +/// +/// DO NOT CHANGE VALUES WITHOUT A MIGRATION STRATEGY. +#[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, Deserialize, Serialize, EnumIter, EnumCount)] +#[serde(rename_all = "snake_case")] +pub enum UserFeatureFlag { + /// Grants a user the ability to list media + /// (For now, it's hidden until we get an NSFW filter.) + ExploreMedia, + + /// Access to studio features + Studio, + + /// Whether users are allowed to upload 3D models + #[serde(rename = "upload_3d")] + Upload3d, + + /// Access to video style transfer + VideoStyleTransfer, +} + +// TODO(bt, 2022-12-21): This desperately needs MySQL integration tests! +impl_enum_display_and_debug_using_to_str!(UserFeatureFlag); +impl_mysql_enum_coders!(UserFeatureFlag); +impl_mysql_from_row!(UserFeatureFlag); + +/// NB: Legacy API for older code. +impl UserFeatureFlag { + pub fn to_str(&self) -> &'static str { + match self { + Self::ExploreMedia => "explore_media", + Self::Studio => "studio", + Self::Upload3d => "upload_3d", + Self::VideoStyleTransfer => "video_style_transfer", + } + } + + pub fn from_str(value: &str) -> Result { + match value { + "explore_media" => Ok(Self::ExploreMedia), + "studio" => Ok(Self::Studio), + "upload_3d" => Ok(Self::Upload3d), + "video_style_transfer" => Ok(Self::VideoStyleTransfer), + _ => Err(format!("invalid value: {:?}", value)), + } + } + +} + +#[cfg(test)] +mod tests { + use super::super::user_feature_flag::UserFeatureFlag; + use enums_shared::test_helpers::assert_serialization; + + mod explicit_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(UserFeatureFlag::ExploreMedia, "explore_media"); + assert_serialization(UserFeatureFlag::Studio, "studio"); + assert_serialization(UserFeatureFlag::Upload3d, "upload_3d"); + assert_serialization(UserFeatureFlag::VideoStyleTransfer, "video_style_transfer"); + } + + #[test] + fn test_to_str() { + assert_eq!(UserFeatureFlag::ExploreMedia.to_str(), "explore_media"); + assert_eq!(UserFeatureFlag::Studio.to_str(), "studio"); + assert_eq!(UserFeatureFlag::Upload3d.to_str(), "upload_3d"); + assert_eq!(UserFeatureFlag::VideoStyleTransfer.to_str(), "video_style_transfer"); + } + + #[test] + fn test_from_str() { + assert_eq!(UserFeatureFlag::from_str("explore_media").unwrap(), UserFeatureFlag::ExploreMedia); + assert_eq!(UserFeatureFlag::from_str("studio").unwrap(), UserFeatureFlag::Studio); + assert_eq!(UserFeatureFlag::from_str("upload_3d").unwrap(), UserFeatureFlag::Upload3d); + assert_eq!(UserFeatureFlag::from_str("video_style_transfer").unwrap(), UserFeatureFlag::VideoStyleTransfer); + assert!(UserFeatureFlag::from_str("foo").is_err()); + } + + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip() { + use strum::IntoEnumIterator; + for variant in UserFeatureFlag::iter() { + assert_eq!(variant, UserFeatureFlag::from_str(variant.to_str()).unwrap()); + assert_eq!(variant, UserFeatureFlag::from_str(&format!("{}", variant)).unwrap()); + assert_eq!(variant, UserFeatureFlag::from_str(&format!("{:?}", variant)).unwrap()); + } + } + + #[test] + fn serialized_length_ok_for_database() { + use strum::IntoEnumIterator; + const MAX_LENGTH : usize = 32; + for variant in UserFeatureFlag::iter() { + let serialized = variant.to_str(); + assert!(serialized.len() > 0, "variant {:?} is too short", variant); + assert!(serialized.len() <= MAX_LENGTH, "variant {:?} is too long", variant); + } + } + } +} diff --git a/crates/schema/public/enums_db/src/by_table/users/user_signup_method.rs b/crates/schema/public/enums_db/src/by_table/users/user_signup_method.rs new file mode 100644 index 0000000000..2023ce812c --- /dev/null +++ b/crates/schema/public/enums_db/src/by_table/users/user_signup_method.rs @@ -0,0 +1,107 @@ +use strum::EnumCount; +use strum::EnumIter; + +/// Used in the `users` table in a `VARCHAR(16)` field. +/// +/// DO NOT CHANGE VALUES WITHOUT A MIGRATION STRATEGY. +#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Deserialize, Serialize, EnumIter, EnumCount)] +#[serde(rename_all = "snake_case")] +pub enum UserSignupMethod { + /// Email + Password + EmailPassword, + + /// "Sign in With Google" SSO + GoogleSignIn, + + /// Stripe Checkout flow, where we provision user accounts for users with a + /// synthetic/fake email address and no password. After checkout completes, + /// the user gets a real email and password - or the user can set them. + StripeCheckout, +} + +// TODO(bt, 2022-12-21): This desperately needs MySQL integration tests! +impl_enum_display_and_debug_using_to_str!(UserSignupMethod); +impl_mysql_enum_coders!(UserSignupMethod); +impl_mysql_from_row!(UserSignupMethod); + +/// NB: Legacy API for older code. +impl UserSignupMethod { + pub fn to_str(&self) -> &'static str { + match self { + Self::EmailPassword => "email_password", + Self::GoogleSignIn=> "google_sign_in", + Self::StripeCheckout => "stripe_checkout", + } + } + + pub fn from_str(value: &str) -> Result { + match value { + "email_password" => Ok(Self::EmailPassword), + "google_sign_in" => Ok(Self::GoogleSignIn), + "stripe_checkout" => Ok(Self::StripeCheckout), + _ => Err(format!("invalid value: {:?}", value)), + } + } + +} + +#[cfg(test)] +mod tests { + use super::super::user_signup_method::UserSignupMethod; + use enums_shared::test_helpers::assert_serialization; + + mod serde { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(UserSignupMethod::EmailPassword, "email_password"); + assert_serialization(UserSignupMethod::GoogleSignIn, "google_sign_in"); + assert_serialization(UserSignupMethod::StripeCheckout, "stripe_checkout"); + } + } + + mod impl_methods { + use super::*; + + #[test] + fn to_str() { + assert_eq!(UserSignupMethod::EmailPassword.to_str(), "email_password"); + assert_eq!(UserSignupMethod::GoogleSignIn.to_str(), "google_sign_in"); + assert_eq!(UserSignupMethod::StripeCheckout.to_str(), "stripe_checkout"); + } + + #[test] + fn from_str() { + assert_eq!(UserSignupMethod::from_str("email_password").unwrap(), UserSignupMethod::EmailPassword); + assert_eq!(UserSignupMethod::from_str("google_sign_in").unwrap(), UserSignupMethod::GoogleSignIn); + assert_eq!(UserSignupMethod::from_str("stripe_checkout").unwrap(), UserSignupMethod::StripeCheckout); + assert!(UserSignupMethod::from_str("foo").is_err()); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip() { + use strum::IntoEnumIterator; + for variant in UserSignupMethod::iter() { + assert_eq!(variant, UserSignupMethod::from_str(variant.to_str()).unwrap()); + assert_eq!(variant, UserSignupMethod::from_str(&format!("{}", variant)).unwrap()); + assert_eq!(variant, UserSignupMethod::from_str(&format!("{:?}", variant)).unwrap()); + } + } + + #[test] + fn serialized_length_ok_for_database() { + use strum::IntoEnumIterator; + const MAX_LENGTH : usize = 16; + for variant in UserSignupMethod::iter() { + let serialized = variant.to_str(); + assert!(serialized.len() > 0, "variant {:?} is too short", variant); + assert!(serialized.len() <= MAX_LENGTH, "variant {:?} is too long", variant); + } + } + } +} diff --git a/crates/schema/public/enums_db/src/by_table/users/user_signup_source.rs b/crates/schema/public/enums_db/src/by_table/users/user_signup_source.rs new file mode 100644 index 0000000000..a6a8c9f561 --- /dev/null +++ b/crates/schema/public/enums_db/src/by_table/users/user_signup_source.rs @@ -0,0 +1,150 @@ +use strum::EnumCount; +use strum::EnumIter; + +/// Used in the `users` table in a `VARCHAR(255)` (which should be a `VARCHAR(16)`) field, `maybe_source`. +/// +/// DO NOT CHANGE VALUES WITHOUT A MIGRATION STRATEGY. +#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Deserialize, Serialize, EnumIter, EnumCount)] +#[serde(rename_all = "snake_case")] +pub enum UserSignupSource { + #[deprecated(since = "2026-01-30", note = "Use other Artcraft* enum variants instead")] + #[serde(rename = "artcraft")] + ArtCraft, + + /// ArtCraft Tauri App Onboard Flow + #[serde(rename = "artcraft_app")] + ArtCraftApp, + + /// artcraft.ai normal onboard flow + #[serde(rename = "artcraft_ai_web")] + ArtCraftAiWeb, + + /// artcraft.ai stripe checkout flow + #[serde(rename = "artcraft_ai_s")] + ArtCraftAiStripe, + + /// getartcraft.com normal onboard flow + #[serde(rename = "artcraft_get_web")] + ArtCraftGetWeb, + + /// getartcraft.com stripe checkout flow + #[serde(rename = "artcraft_get_s")] + ArtCraftGetStripe, + + #[serde(rename = "fakeyou")] + FakeYou, + + #[serde(rename = "storyteller")] + Storyteller, +} + +// TODO(bt, 2022-12-21): This desperately needs MySQL integration tests! +impl_enum_display_and_debug_using_to_str!(UserSignupSource); +impl_mysql_enum_coders!(UserSignupSource); +impl_mysql_from_row!(UserSignupSource); + +/// NB: Legacy API for older code. +impl UserSignupSource { + pub fn to_str(&self) -> &'static str { + match self { + Self::ArtCraft => "artcraft", + Self::ArtCraftApp => "artcraft_app", + Self::ArtCraftAiWeb => "artcraft_ai_web", + Self::ArtCraftAiStripe => "artcraft_ai_s", + Self::ArtCraftGetWeb => "artcraft_get_web", + Self::ArtCraftGetStripe => "artcraft_get_s", + Self::FakeYou => "fakeyou", + Self::Storyteller => "storyteller", + } + } + + pub fn from_str(value: &str) -> Result { + match value { + "artcraft" => Ok(Self::ArtCraft), + "artcraft_app" => Ok(Self::ArtCraftApp), + "artcraft_ai_web" => Ok(Self::ArtCraftAiWeb), + "artcraft_ai_s" => Ok(Self::ArtCraftAiStripe), + "artcraft_get_web" => Ok(Self::ArtCraftGetWeb), + "artcraft_get_s" => Ok(Self::ArtCraftGetStripe), + "fakeyou" => Ok(Self::FakeYou), + "storyteller" => Ok(Self::Storyteller), + _ => Err(format!("invalid value: {:?}", value)), + } + } + +} + +#[cfg(test)] +mod tests { + use super::super::user_signup_source::UserSignupSource; + use enums_shared::test_helpers::assert_serialization; + + mod serde { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(UserSignupSource::ArtCraft, "artcraft"); + assert_serialization(UserSignupSource::ArtCraftApp, "artcraft_app"); + assert_serialization(UserSignupSource::ArtCraftAiWeb, "artcraft_ai_web"); + assert_serialization(UserSignupSource::ArtCraftAiStripe, "artcraft_ai_s"); + assert_serialization(UserSignupSource::ArtCraftGetWeb, "artcraft_get_web"); + assert_serialization(UserSignupSource::ArtCraftGetStripe, "artcraft_get_s"); + assert_serialization(UserSignupSource::FakeYou, "fakeyou"); + assert_serialization(UserSignupSource::Storyteller, "storyteller"); + } + } + + mod impl_methods { + use super::*; + + #[test] + fn to_str() { + assert_eq!(UserSignupSource::ArtCraft.to_str(), "artcraft"); + assert_eq!(UserSignupSource::ArtCraftApp.to_str(), "artcraft_app"); + assert_eq!(UserSignupSource::ArtCraftAiWeb.to_str(), "artcraft_ai_web"); + assert_eq!(UserSignupSource::ArtCraftAiStripe.to_str(), "artcraft_ai_s"); + assert_eq!(UserSignupSource::ArtCraftGetWeb.to_str(), "artcraft_get_web"); + assert_eq!(UserSignupSource::FakeYou.to_str(), "fakeyou"); + assert_eq!(UserSignupSource::Storyteller.to_str(), "storyteller"); + } + + #[test] + fn from_str() { + assert_eq!(UserSignupSource::from_str("artcraft").unwrap(), UserSignupSource::ArtCraft); + assert_eq!(UserSignupSource::from_str("artcraft_app").unwrap(), UserSignupSource::ArtCraftApp); + assert_eq!(UserSignupSource::from_str("artcraft_ai_web").unwrap(), UserSignupSource::ArtCraftAiWeb); + assert_eq!(UserSignupSource::from_str("artcraft_ai_s").unwrap(), UserSignupSource::ArtCraftAiStripe); + assert_eq!(UserSignupSource::from_str("artcraft_get_web").unwrap(), UserSignupSource::ArtCraftGetWeb); + assert_eq!(UserSignupSource::from_str("artcraft_get_s").unwrap(), UserSignupSource::ArtCraftGetStripe); + assert_eq!(UserSignupSource::from_str("fakeyou").unwrap(), UserSignupSource::FakeYou); + assert_eq!(UserSignupSource::from_str("storyteller").unwrap(), UserSignupSource::Storyteller); + assert!(UserSignupSource::from_str("foo").is_err()); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip() { + use strum::IntoEnumIterator; + for variant in UserSignupSource::iter() { + assert_eq!(variant, UserSignupSource::from_str(variant.to_str()).unwrap()); + assert_eq!(variant, UserSignupSource::from_str(&format!("{}", variant)).unwrap()); + assert_eq!(variant, UserSignupSource::from_str(&format!("{:?}", variant)).unwrap()); + } + } + + #[test] + fn serialized_length_ok_for_database() { + use strum::IntoEnumIterator; + const MAX_LENGTH : usize = 16; + for variant in UserSignupSource::iter() { + let serialized = variant.to_str(); + assert!(serialized.len() > 0, "variant {:?} is too short", variant); + assert!(serialized.len() <= MAX_LENGTH, "variant {:?} is too long", variant); + } + } + } +} diff --git a/crates/schema/public/enums_db/src/by_table/voice_conversion_models/mod.rs b/crates/schema/public/enums_db/src/by_table/voice_conversion_models/mod.rs new file mode 100644 index 0000000000..25778ac3ec --- /dev/null +++ b/crates/schema/public/enums_db/src/by_table/voice_conversion_models/mod.rs @@ -0,0 +1 @@ +pub mod voice_conversion_model_type; diff --git a/crates/schema/public/enums_db/src/by_table/voice_conversion_models/voice_conversion_model_type.rs b/crates/schema/public/enums_db/src/by_table/voice_conversion_models/voice_conversion_model_type.rs new file mode 100644 index 0000000000..f46c18f975 --- /dev/null +++ b/crates/schema/public/enums_db/src/by_table/voice_conversion_models/voice_conversion_model_type.rs @@ -0,0 +1,97 @@ +use strum::EnumCount; +use strum::EnumIter; + +/// Used in the `voice_conversion_models` table in `VARCHAR(32)` field `model_type`. +/// +/// DO NOT CHANGE VALUES WITHOUT A MIGRATION STRATEGY. +#[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, Deserialize, Serialize, EnumIter, EnumCount)] +pub enum VoiceConversionModelType { + // We're skipping RVC "v1" models as "v2" are much higher quality. + // Future incompatible upgrades may deserve a different enum variant. + #[serde(rename = "rvc_v2")] + RvcV2, + + #[serde(rename = "soft_vc")] + SoftVc, + + #[serde(rename = "so_vits_svc")] + SoVitsSvc, +} + +// TODO(bt, 2022-12-21): This desperately needs MySQL integration tests! +impl_enum_display_and_debug_using_to_str!(VoiceConversionModelType); +impl_mysql_enum_coders!(VoiceConversionModelType); +impl_mysql_from_row!(VoiceConversionModelType); + +/// NB: Legacy API for older code. +impl VoiceConversionModelType { + pub fn to_str(&self) -> &'static str { + match self { + Self::RvcV2 => "rvc_v2", + Self::SoftVc => "soft_vc", + Self::SoVitsSvc => "so_vits_svc", + } + } + + pub fn from_str(value: &str) -> Result { + match value { + "rvc_v2" => Ok(Self::RvcV2), + "soft_vc" => Ok(Self::SoftVc), + "so_vits_svc" => Ok(Self::SoVitsSvc), + _ => Err(format!("invalid value: {:?}", value)), + } + } + +} + +#[cfg(test)] +mod tests { + use super::super::voice_conversion_model_type::VoiceConversionModelType; + use enums_shared::test_helpers::assert_serialization; + + #[test] + fn test_serialization() { + assert_serialization(VoiceConversionModelType::RvcV2, "rvc_v2"); + assert_serialization(VoiceConversionModelType::SoftVc, "soft_vc"); + assert_serialization(VoiceConversionModelType::SoVitsSvc, "so_vits_svc"); + } + + #[test] + fn to_str() { + assert_eq!(VoiceConversionModelType::RvcV2.to_str(), "rvc_v2"); + assert_eq!(VoiceConversionModelType::SoftVc.to_str(), "soft_vc"); + assert_eq!(VoiceConversionModelType::SoVitsSvc.to_str(), "so_vits_svc"); + } + + #[test] + fn from_str() { + assert_eq!(VoiceConversionModelType::from_str("rvc_v2").unwrap(), VoiceConversionModelType::RvcV2); + assert_eq!(VoiceConversionModelType::from_str("soft_vc").unwrap(), VoiceConversionModelType::SoftVc); + assert_eq!(VoiceConversionModelType::from_str("so_vits_svc").unwrap(), VoiceConversionModelType::SoVitsSvc); + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip() { + use strum::IntoEnumIterator; + for variant in VoiceConversionModelType::iter() { + assert_eq!(variant, VoiceConversionModelType::from_str(variant.to_str()).unwrap()); + assert_eq!(variant, VoiceConversionModelType::from_str(&format!("{}", variant)).unwrap()); + assert_eq!(variant, VoiceConversionModelType::from_str(&format!("{:?}", variant)).unwrap()); + } + } + + #[test] + fn serialized_length_ok_for_database() { + const MAX_LENGTH: usize = 32; // TODO(bt): Confirm database column width, then remove this comment. + use strum::IntoEnumIterator; + for variant in VoiceConversionModelType::iter() { + let serialized = variant.to_str(); + assert!(!serialized.is_empty(), "variant {:?} is too short", variant); + assert!(serialized.len() <= MAX_LENGTH, "variant {:?} is too long", variant); + } + } + } +} diff --git a/crates/schema/public/enums_db/src/by_table/voice_conversion_results/mod.rs b/crates/schema/public/enums_db/src/by_table/voice_conversion_results/mod.rs new file mode 100644 index 0000000000..4568dc03ed --- /dev/null +++ b/crates/schema/public/enums_db/src/by_table/voice_conversion_results/mod.rs @@ -0,0 +1 @@ +pub mod voice_conversion_media_token_type; diff --git a/crates/schema/public/enums_db/src/by_table/voice_conversion_results/voice_conversion_media_token_type.rs b/crates/schema/public/enums_db/src/by_table/voice_conversion_results/voice_conversion_media_token_type.rs new file mode 100644 index 0000000000..6096e70e03 --- /dev/null +++ b/crates/schema/public/enums_db/src/by_table/voice_conversion_results/voice_conversion_media_token_type.rs @@ -0,0 +1,80 @@ +use strum::EnumCount; +use strum::EnumIter; + +/// Used in the `voice_conversion_results` table in a `VARCHAR` field. +/// +/// DO NOT CHANGE VALUES WITHOUT A MIGRATION STRATEGY. +#[derive(Clone, Copy, Eq, PartialEq, Deserialize, Serialize, EnumIter, EnumCount)] +#[serde(rename_all = "snake_case")] +pub enum VoiceConversionMediaTokenType { + /// Media token refers to record in `media_uploads` table. + MediaUpload, +} + +// TODO(bt, 2022-12-21): This desperately needs MySQL integration tests! +impl_enum_display_and_debug_using_to_str!(VoiceConversionMediaTokenType); +impl_mysql_enum_coders!(VoiceConversionMediaTokenType); +impl_mysql_from_row!(VoiceConversionMediaTokenType); + +/// NB: Legacy API for older code. +impl VoiceConversionMediaTokenType { + pub fn to_str(&self) -> &'static str { + match self { + Self::MediaUpload => "media_upload", + } + } + + pub fn from_str(value: &str) -> Result { + match value { + "media_upload" => Ok(Self::MediaUpload), + _ => Err(format!("invalid value: {:?}", value)), + } + } +} + +#[cfg(test)] +mod tests { + use super::super::voice_conversion_media_token_type::VoiceConversionMediaTokenType; + use enums_shared::test_helpers::assert_serialization; + + #[test] + fn test_serialization() { + assert_serialization(VoiceConversionMediaTokenType::MediaUpload, "media_upload"); + } + + #[test] + fn test_to_str() { + assert_eq!(VoiceConversionMediaTokenType::MediaUpload.to_str(), "media_upload"); + } + + #[test] + fn test_from_str() { + assert_eq!(VoiceConversionMediaTokenType::from_str("media_upload").unwrap(), VoiceConversionMediaTokenType::MediaUpload); + assert!(VoiceConversionMediaTokenType::from_str("foo").is_err()); + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip() { + use strum::IntoEnumIterator; + for variant in VoiceConversionMediaTokenType::iter() { + assert_eq!(variant, VoiceConversionMediaTokenType::from_str(variant.to_str()).unwrap()); + assert_eq!(variant, VoiceConversionMediaTokenType::from_str(&format!("{}", variant)).unwrap()); + assert_eq!(variant, VoiceConversionMediaTokenType::from_str(&format!("{:?}", variant)).unwrap()); + } + } + + #[test] + fn serialized_length_ok_for_database() { + const MAX_LENGTH: usize = 32; // TODO(bt): Confirm database column width, then remove this comment. + use strum::IntoEnumIterator; + for variant in VoiceConversionMediaTokenType::iter() { + let serialized = variant.to_str(); + assert!(!serialized.is_empty(), "variant {:?} is too short", variant); + assert!(serialized.len() <= MAX_LENGTH, "variant {:?} is too long", variant); + } + } + } +} diff --git a/crates/schema/public/enums_db/src/by_table/wallet_ledger_entries/mod.rs b/crates/schema/public/enums_db/src/by_table/wallet_ledger_entries/mod.rs new file mode 100644 index 0000000000..385570f7f1 --- /dev/null +++ b/crates/schema/public/enums_db/src/by_table/wallet_ledger_entries/mod.rs @@ -0,0 +1 @@ +pub mod wallet_ledger_entry_type; diff --git a/crates/schema/public/enums_db/src/by_table/wallet_ledger_entries/wallet_ledger_entry_type.rs b/crates/schema/public/enums_db/src/by_table/wallet_ledger_entries/wallet_ledger_entry_type.rs new file mode 100644 index 0000000000..ca0426539c --- /dev/null +++ b/crates/schema/public/enums_db/src/by_table/wallet_ledger_entries/wallet_ledger_entry_type.rs @@ -0,0 +1,161 @@ +use strum::EnumCount; +use strum::EnumIter; + +/// Used in the `wallet_ledger_entries` table in a `VARCHAR(16)` field. +/// +/// DO NOT CHANGE VALUES WITHOUT A MIGRATION STRATEGY. +#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash, Deserialize, Serialize, EnumIter, EnumCount)] +#[serde(rename_all = "snake_case")] +pub enum WalletLedgerEntryType { + /// Wallet created + #[serde(rename = "create")] + Create, + + /// Credit durable banked balance + #[serde(rename = "credit_banked")] + CreditBanked, + + /// Credit monthly refill + #[serde(rename = "credit_monthly")] + CreditMonthly, + + /// Deduct credits (mixed durable and monthly deduction) + #[serde(rename = "deduct_mixed")] + DeductMixed, + + /// Deduct durable banked credits + #[serde(rename = "deduct_banked")] + DeductBanked, + + /// Deduct monthly credits + #[serde(rename = "deduct_monthly")] + DeductMonthly, + + /// Refund banked credits + #[serde(rename = "refund_banked")] + RefundBanked, + + /// Support staff manually credit account + #[serde(rename = "staff_add_banked")] + StaffAddBanked, + + // TODO: No clean way to do "mixed" refunds yet, and if we + // refund close to the cutoff it might be unfair. Let's + // just not do monthly refunds yet and instead credit our + // users with banked credits. + // /// Refund monthly credits + // #[serde(rename = "refund_monthly")] + // RefundMonthly, +} + +// TODO(bt, 2022-12-21): This desperately needs MySQL integration tests! +impl_enum_display_and_debug_using_to_str!(WalletLedgerEntryType); +impl_mysql_enum_coders!(WalletLedgerEntryType); +impl_mysql_from_row!(WalletLedgerEntryType); + +/// NB: Legacy API for older code. +impl WalletLedgerEntryType { + pub fn to_str(&self) -> &'static str { + match self { + Self::Create => "create", + Self::CreditBanked => "credit_banked", + Self::CreditMonthly => "credit_monthly", + Self::DeductMixed => "deduct_mixed", + Self::DeductBanked => "deduct_banked", + Self::DeductMonthly => "deduct_monthly", + Self::RefundBanked => "refund_banked", + Self::StaffAddBanked => "staff_add_banked", + } + } + + pub fn from_str(value: &str) -> Result { + match value { + "create" => Ok(Self::Create), + "credit_banked" => Ok(Self::CreditBanked), + "credit_monthly" => Ok(Self::CreditMonthly), + "deduct_mixed" => Ok(Self::DeductMixed), + "deduct_banked" => Ok(Self::DeductBanked), + "deduct_monthly" => Ok(Self::DeductMonthly), + "refund_banked" => Ok(Self::RefundBanked), + "staff_add_banked" => Ok(Self::StaffAddBanked), + _ => Err(format!("invalid value: {:?}", value)), + } + } + +} + +#[cfg(test)] +mod tests { + use super::super::wallet_ledger_entry_type::WalletLedgerEntryType; + use enums_shared::test_helpers::assert_serialization; + + mod serde { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(WalletLedgerEntryType::Create, "create"); + assert_serialization(WalletLedgerEntryType::CreditBanked, "credit_banked"); + assert_serialization(WalletLedgerEntryType::CreditMonthly, "credit_monthly"); + assert_serialization(WalletLedgerEntryType::DeductMixed, "deduct_mixed"); + assert_serialization(WalletLedgerEntryType::DeductBanked, "deduct_banked"); + assert_serialization(WalletLedgerEntryType::DeductMonthly, "deduct_monthly"); + assert_serialization(WalletLedgerEntryType::RefundBanked, "refund_banked"); + assert_serialization(WalletLedgerEntryType::StaffAddBanked, "staff_add_banked"); + } + } + + mod impl_methods { + use super::*; + + #[test] + fn to_str() { + assert_eq!(WalletLedgerEntryType::Create.to_str(), "create"); + assert_eq!(WalletLedgerEntryType::CreditBanked.to_str(), "credit_banked"); + assert_eq!(WalletLedgerEntryType::CreditMonthly.to_str(), "credit_monthly"); + assert_eq!(WalletLedgerEntryType::DeductMixed.to_str(), "deduct_mixed"); + assert_eq!(WalletLedgerEntryType::DeductBanked.to_str(), "deduct_banked"); + assert_eq!(WalletLedgerEntryType::DeductMonthly.to_str(), "deduct_monthly"); + assert_eq!(WalletLedgerEntryType::RefundBanked.to_str(), "refund_banked"); + assert_eq!(WalletLedgerEntryType::StaffAddBanked.to_str(), "staff_add_banked"); + } + + #[test] + fn from_str() { + assert_eq!(WalletLedgerEntryType::from_str("create").unwrap(), WalletLedgerEntryType::Create); + assert_eq!(WalletLedgerEntryType::from_str("credit_banked").unwrap(), WalletLedgerEntryType::CreditBanked); + assert_eq!(WalletLedgerEntryType::from_str("credit_monthly").unwrap(), WalletLedgerEntryType::CreditMonthly); + assert_eq!(WalletLedgerEntryType::from_str("deduct_mixed").unwrap(), WalletLedgerEntryType::DeductMixed); + assert_eq!(WalletLedgerEntryType::from_str("deduct_banked").unwrap(), WalletLedgerEntryType::DeductBanked); + assert_eq!(WalletLedgerEntryType::from_str("deduct_monthly").unwrap(), WalletLedgerEntryType::DeductMonthly); + assert_eq!(WalletLedgerEntryType::from_str("refund_banked").unwrap(), WalletLedgerEntryType::RefundBanked); + assert_eq!(WalletLedgerEntryType::from_str("staff_add_banked").unwrap(), WalletLedgerEntryType::StaffAddBanked); + assert!(WalletLedgerEntryType::from_str("foo").is_err()); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip() { + use strum::IntoEnumIterator; + for variant in WalletLedgerEntryType::iter() { + assert_eq!(variant, WalletLedgerEntryType::from_str(variant.to_str()).unwrap()); + assert_eq!(variant, WalletLedgerEntryType::from_str(&format!("{}", variant)).unwrap()); + assert_eq!(variant, WalletLedgerEntryType::from_str(&format!("{:?}", variant)).unwrap()); + } + } + + #[test] + fn serialized_length_ok_for_database() { + use strum::IntoEnumIterator; + const MAX_LENGTH : usize = 16; + for variant in WalletLedgerEntryType::iter() { + let serialized = variant.to_str(); + assert!(serialized.len() > 0, "variant {:?} is too short", variant); + assert!(serialized.len() <= MAX_LENGTH, "variant {:?} is too long", variant); + } + } + } +} diff --git a/crates/schema/public/enums_db/src/by_table/web_rendition_targets/mod.rs b/crates/schema/public/enums_db/src/by_table/web_rendition_targets/mod.rs new file mode 100644 index 0000000000..371fe4d32f --- /dev/null +++ b/crates/schema/public/enums_db/src/by_table/web_rendition_targets/mod.rs @@ -0,0 +1 @@ +pub mod rendition_status; diff --git a/crates/schema/public/enums_db/src/by_table/web_rendition_targets/rendition_status.rs b/crates/schema/public/enums_db/src/by_table/web_rendition_targets/rendition_status.rs new file mode 100644 index 0000000000..f3f85c9d9c --- /dev/null +++ b/crates/schema/public/enums_db/src/by_table/web_rendition_targets/rendition_status.rs @@ -0,0 +1,116 @@ +use strum::EnumCount; +use strum::EnumIter; + +/// Used in the SqLite `web_scraping_targets` table in a `TEXT` field named `scraping_status`. +#[derive(Clone, Copy, Eq, PartialEq, Hash, Deserialize, Serialize, EnumIter, EnumCount)] +pub enum RenditionStatus { + #[serde(rename = "new")] + New, + + #[serde(rename = "skipped")] + Skipped, + + #[serde(rename = "failed")] + Failed, + + #[serde(rename = "permanently_failed")] + PermanentlyFailed, + + #[serde(rename = "success")] + Success, +} + +// TODO(bt, 2023-01-17): This desperately needs MySQL integration tests! +impl_enum_display_and_debug_using_to_str!(RenditionStatus); +impl_sqlite_enum_coders!(RenditionStatus); + +/// NB: Legacy API for older code. +impl RenditionStatus { + pub fn to_str(&self) -> &'static str { + match self { + Self::New => "new", + Self::Skipped => "skipped", + Self::Failed => "failed", + Self::PermanentlyFailed => "permanently_failed", + Self::Success => "success", + } + } + + pub fn from_str(value: &str) -> Result { + match value { + "new" => Ok(Self::New), + "skipped" => Ok(Self::Skipped), + "failed" => Ok(Self::Failed), + "permanently_failed" => Ok(Self::PermanentlyFailed), + "success" => Ok(Self::Success), + _ => Err(format!("invalid value: {:?}", value)), + } + } +} + +#[cfg(test)] +mod tests { + use super::super::rendition_status::RenditionStatus; + use enums_shared::test_helpers::assert_serialization; + + mod serde { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(RenditionStatus::New, "new"); + assert_serialization(RenditionStatus::Skipped, "skipped"); + assert_serialization(RenditionStatus::Failed, "failed"); + assert_serialization(RenditionStatus::PermanentlyFailed, "permanently_failed"); + assert_serialization(RenditionStatus::Success, "success"); + } + } + + mod impl_methods { + use super::*; + + #[test] + fn test_to_str() { + assert_eq!(RenditionStatus::New.to_str(), "new"); + assert_eq!(RenditionStatus::Skipped.to_str(), "skipped"); + assert_eq!(RenditionStatus::Failed.to_str(), "failed"); + assert_eq!(RenditionStatus::PermanentlyFailed.to_str(), "permanently_failed"); + assert_eq!(RenditionStatus::Success.to_str(), "success"); + } + + #[test] + fn test_from_str() { + assert_eq!(RenditionStatus::from_str("new").unwrap(), RenditionStatus::New); + assert_eq!(RenditionStatus::from_str("skipped").unwrap(), RenditionStatus::Skipped); + assert_eq!(RenditionStatus::from_str("failed").unwrap(), RenditionStatus::Failed); + assert_eq!(RenditionStatus::from_str("permanently_failed").unwrap(), RenditionStatus::PermanentlyFailed); + assert_eq!(RenditionStatus::from_str("success").unwrap(), RenditionStatus::Success); + assert!(RenditionStatus::from_str("foo").is_err()); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip() { + use strum::IntoEnumIterator; + for variant in RenditionStatus::iter() { + assert_eq!(variant, RenditionStatus::from_str(variant.to_str()).unwrap()); + assert_eq!(variant, RenditionStatus::from_str(&format!("{}", variant)).unwrap()); + assert_eq!(variant, RenditionStatus::from_str(&format!("{:?}", variant)).unwrap()); + } + } + + #[test] + fn serialized_length_ok_for_database() { + const MAX_LENGTH: usize = 32; // TODO(bt): Confirm database column width, then remove this comment. + use strum::IntoEnumIterator; + for variant in RenditionStatus::iter() { + let serialized = variant.to_str(); + assert!(!serialized.is_empty(), "variant {:?} is too short", variant); + assert!(serialized.len() <= MAX_LENGTH, "variant {:?} is too long", variant); + } + } + } +} diff --git a/crates/schema/public/enums_db/src/by_table/web_scraping_targets/mod.rs b/crates/schema/public/enums_db/src/by_table/web_scraping_targets/mod.rs new file mode 100644 index 0000000000..2dea4d4509 --- /dev/null +++ b/crates/schema/public/enums_db/src/by_table/web_scraping_targets/mod.rs @@ -0,0 +1 @@ +pub mod scraping_status; diff --git a/crates/schema/public/enums_db/src/by_table/web_scraping_targets/scraping_status.rs b/crates/schema/public/enums_db/src/by_table/web_scraping_targets/scraping_status.rs new file mode 100644 index 0000000000..6fc87378db --- /dev/null +++ b/crates/schema/public/enums_db/src/by_table/web_scraping_targets/scraping_status.rs @@ -0,0 +1,116 @@ +use strum::EnumCount; +use strum::EnumIter; + +/// Used in the SqLite `web_scraping_targets` table in a `TEXT` field named `scraping_status`. +#[derive(Clone, Copy, Eq, PartialEq, Hash, Deserialize, Serialize, EnumIter, EnumCount)] +pub enum ScrapingStatus { + #[serde(rename = "new")] + New, + + #[serde(rename = "skipped")] + Skipped, + + #[serde(rename = "failed")] + Failed, + + #[serde(rename = "permanently_failed")] + PermanentlyFailed, + + #[serde(rename = "success")] + Success, +} + +// TODO(bt, 2023-01-17): This desperately needs MySQL integration tests! +impl_enum_display_and_debug_using_to_str!(ScrapingStatus); +impl_sqlite_enum_coders!(ScrapingStatus); + +/// NB: Legacy API for older code. +impl ScrapingStatus { + pub fn to_str(&self) -> &'static str { + match self { + Self::New => "new", + Self::Skipped => "skipped", + Self::Failed => "failed", + Self::PermanentlyFailed => "permanently_failed", + Self::Success => "success", + } + } + + pub fn from_str(value: &str) -> Result { + match value { + "new" => Ok(Self::New), + "skipped" => Ok(Self::Skipped), + "failed" => Ok(Self::Failed), + "permanently_failed" => Ok(Self::PermanentlyFailed), + "success" => Ok(Self::Success), + _ => Err(format!("invalid value: {:?}", value)), + } + } +} + +#[cfg(test)] +mod tests { + use super::super::scraping_status::ScrapingStatus; + use enums_shared::test_helpers::assert_serialization; + + mod serde { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(ScrapingStatus::New, "new"); + assert_serialization(ScrapingStatus::Skipped, "skipped"); + assert_serialization(ScrapingStatus::Failed, "failed"); + assert_serialization(ScrapingStatus::PermanentlyFailed, "permanently_failed"); + assert_serialization(ScrapingStatus::Success, "success"); + } + } + + mod impl_methods { + use super::*; + + #[test] + fn test_to_str() { + assert_eq!(ScrapingStatus::New.to_str(), "new"); + assert_eq!(ScrapingStatus::Skipped.to_str(), "skipped"); + assert_eq!(ScrapingStatus::Failed.to_str(), "failed"); + assert_eq!(ScrapingStatus::PermanentlyFailed.to_str(), "permanently_failed"); + assert_eq!(ScrapingStatus::Success.to_str(), "success"); + } + + #[test] + fn test_from_str() { + assert_eq!(ScrapingStatus::from_str("new").unwrap(), ScrapingStatus::New); + assert_eq!(ScrapingStatus::from_str("skipped").unwrap(), ScrapingStatus::Skipped); + assert_eq!(ScrapingStatus::from_str("failed").unwrap(), ScrapingStatus::Failed); + assert_eq!(ScrapingStatus::from_str("permanently_failed").unwrap(), ScrapingStatus::PermanentlyFailed); + assert_eq!(ScrapingStatus::from_str("success").unwrap(), ScrapingStatus::Success); + assert!(ScrapingStatus::from_str("foo").is_err()); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip() { + use strum::IntoEnumIterator; + for variant in ScrapingStatus::iter() { + assert_eq!(variant, ScrapingStatus::from_str(variant.to_str()).unwrap()); + assert_eq!(variant, ScrapingStatus::from_str(&format!("{}", variant)).unwrap()); + assert_eq!(variant, ScrapingStatus::from_str(&format!("{:?}", variant)).unwrap()); + } + } + + #[test] + fn serialized_length_ok_for_database() { + const MAX_LENGTH: usize = 32; // TODO(bt): Confirm database column width, then remove this comment. + use strum::IntoEnumIterator; + for variant in ScrapingStatus::iter() { + let serialized = variant.to_str(); + assert!(!serialized.is_empty(), "variant {:?} is too short", variant); + assert!(serialized.len() <= MAX_LENGTH, "variant {:?} is too long", variant); + } + } + } +} diff --git a/crates/schema/public/enums_db/src/by_table/zs_voices/encoding_type.rs b/crates/schema/public/enums_db/src/by_table/zs_voices/encoding_type.rs new file mode 100644 index 0000000000..15697c5f1a --- /dev/null +++ b/crates/schema/public/enums_db/src/by_table/zs_voices/encoding_type.rs @@ -0,0 +1,91 @@ +use strum::EnumCount; +use strum::EnumIter; + +/// Used in the `zs_voices` table in a `VARCHAR(16)` field named `encoding_type`. +/// +/// This indicates what type of features are used in the embeddings. +/// +/// DO NOT CHANGE VALUES WITHOUT A MIGRATION STRATEGY. +#[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, Deserialize, Serialize, EnumIter, EnumCount)] +pub enum ZsVoiceEncodingType { + /// Encodec features + #[serde(rename = "encodec")] + Encodec, +} + +// TODO(bt, 2023-01-17): This desperately needs MySQL integration tests! +impl_enum_display_and_debug_using_to_str!(ZsVoiceEncodingType); +impl_mysql_enum_coders!(ZsVoiceEncodingType); +impl_mysql_from_row!(ZsVoiceEncodingType); + +/// NB: Legacy API for older code. +impl ZsVoiceEncodingType { + pub fn to_str(&self) -> &'static str { + match self { + Self::Encodec => "encodec", + } + } + + pub fn from_str(value: &str) -> Result { + match value { + "encodec" => Ok(Self::Encodec), + _ => Err(format!("invalid value: {:?}", value)), + } + } + +} + +#[cfg(test)] +mod tests { + use super::super::encoding_type::ZsVoiceEncodingType; + use enums_shared::test_helpers::assert_serialization; + + mod serde { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(ZsVoiceEncodingType::Encodec, "encodec"); + } + } + + mod impl_methods { + use super::*; + + #[test] + fn to_str() { + assert_eq!(ZsVoiceEncodingType::Encodec.to_str(), "encodec"); + } + + #[test] + fn from_str() { + assert_eq!(ZsVoiceEncodingType::from_str("encodec").unwrap(), ZsVoiceEncodingType::Encodec); + assert!(ZsVoiceEncodingType::from_str("foo").is_err()); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip() { + use strum::IntoEnumIterator; + for variant in ZsVoiceEncodingType::iter() { + assert_eq!(variant, ZsVoiceEncodingType::from_str(variant.to_str()).unwrap()); + assert_eq!(variant, ZsVoiceEncodingType::from_str(&format!("{}", variant)).unwrap()); + assert_eq!(variant, ZsVoiceEncodingType::from_str(&format!("{:?}", variant)).unwrap()); + } + } + + #[test] + fn serialized_length_ok_for_database() { + const MAX_LENGTH: usize = 16; // TODO(bt): Confirm database column width, then remove this comment. + use strum::IntoEnumIterator; + for variant in ZsVoiceEncodingType::iter() { + let serialized = variant.to_str(); + assert!(!serialized.is_empty(), "variant {:?} is too short", variant); + assert!(serialized.len() <= MAX_LENGTH, "variant {:?} is too long", variant); + } + } + } +} diff --git a/crates/schema/public/enums_db/src/by_table/zs_voices/mod.rs b/crates/schema/public/enums_db/src/by_table/zs_voices/mod.rs new file mode 100644 index 0000000000..45e42bce9c --- /dev/null +++ b/crates/schema/public/enums_db/src/by_table/zs_voices/mod.rs @@ -0,0 +1,3 @@ +pub mod encoding_type; +pub mod model_category; +pub mod model_type; diff --git a/crates/schema/public/enums_db/src/by_table/zs_voices/model_category.rs b/crates/schema/public/enums_db/src/by_table/zs_voices/model_category.rs new file mode 100644 index 0000000000..fef31dbc86 --- /dev/null +++ b/crates/schema/public/enums_db/src/by_table/zs_voices/model_category.rs @@ -0,0 +1,91 @@ +use strum::EnumCount; +use strum::EnumIter; + +/// Used in the `zs_voices` table in a `VARCHAR(16)` field named `model_category`. +/// +/// This indicates what type of features are used in the embeddings. +/// +/// DO NOT CHANGE VALUES WITHOUT A MIGRATION STRATEGY. +#[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, Deserialize, Serialize, EnumIter, EnumCount)] +pub enum ZsVoiceModelCategory { + /// TTS-type zero shot models + #[serde(rename = "tts")] + Tts, +} + +// TODO(bt, 2023-01-17): This desperately needs MySQL integration tests! +impl_enum_display_and_debug_using_to_str!(ZsVoiceModelCategory); +impl_mysql_enum_coders!(ZsVoiceModelCategory); +impl_mysql_from_row!(ZsVoiceModelCategory); + +/// NB: Legacy API for older code. +impl ZsVoiceModelCategory { + pub fn to_str(&self) -> &'static str { + match self { + Self::Tts => "tts", + } + } + + pub fn from_str(value: &str) -> Result { + match value { + "tts" => Ok(Self::Tts), + _ => Err(format!("invalid value: {:?}", value)), + } + } + +} + +#[cfg(test)] +mod tests { + use super::super::model_category::ZsVoiceModelCategory; + use enums_shared::test_helpers::assert_serialization; + + mod serde { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(ZsVoiceModelCategory::Tts, "tts"); + } + } + + mod impl_methods { + use super::*; + + #[test] + fn to_str() { + assert_eq!(ZsVoiceModelCategory::Tts.to_str(), "tts"); + } + + #[test] + fn from_str() { + assert_eq!(ZsVoiceModelCategory::from_str("tts").unwrap(), ZsVoiceModelCategory::Tts); + assert!(ZsVoiceModelCategory::from_str("foo").is_err()); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip() { + use strum::IntoEnumIterator; + for variant in ZsVoiceModelCategory::iter() { + assert_eq!(variant, ZsVoiceModelCategory::from_str(variant.to_str()).unwrap()); + assert_eq!(variant, ZsVoiceModelCategory::from_str(&format!("{}", variant)).unwrap()); + assert_eq!(variant, ZsVoiceModelCategory::from_str(&format!("{:?}", variant)).unwrap()); + } + } + + #[test] + fn serialized_length_ok_for_database() { + const MAX_LENGTH: usize = 16; // TODO(bt): Confirm database column width, then remove this comment. + use strum::IntoEnumIterator; + for variant in ZsVoiceModelCategory::iter() { + let serialized = variant.to_str(); + assert!(!serialized.is_empty(), "variant {:?} is too short", variant); + assert!(serialized.len() <= MAX_LENGTH, "variant {:?} is too long", variant); + } + } + } +} diff --git a/crates/schema/public/enums_db/src/by_table/zs_voices/model_type.rs b/crates/schema/public/enums_db/src/by_table/zs_voices/model_type.rs new file mode 100644 index 0000000000..daf91171c5 --- /dev/null +++ b/crates/schema/public/enums_db/src/by_table/zs_voices/model_type.rs @@ -0,0 +1,97 @@ +use strum::EnumCount; +use strum::EnumIter; + +/// Used in the `zs_voices` table in a `VARCHAR(16)` field named `model_type`. +/// +/// This indicates what type of features are used in the embeddings. +/// +/// DO NOT CHANGE VALUES WITHOUT A MIGRATION STRATEGY. +#[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, Deserialize, Serialize, EnumIter, EnumCount)] +pub enum ZsVoiceModelType { + /// TTS-type zero shot models + #[serde(rename = "vall-e-x")] + VallEX, + #[serde(rename = "styletts2")] + StyleTTS2, +} + +// TODO(bt, 2023-01-17): This desperately needs MySQL integration tests! +impl_enum_display_and_debug_using_to_str!(ZsVoiceModelType); +impl_mysql_enum_coders!(ZsVoiceModelType); +impl_mysql_from_row!(ZsVoiceModelType); + +/// NB: Legacy API for older code. +impl ZsVoiceModelType { + pub fn to_str(&self) -> &'static str { + match self { + Self::VallEX=> "vall-e-x", + Self::StyleTTS2 => "styletts2", + } + } + + pub fn from_str(value: &str) -> Result { + match value { + "vall-e-x" => Ok(Self::VallEX), + "styletts2" => Ok(Self::StyleTTS2), + _ => Err(format!("invalid value: {:?}", value)), + } + } + +} + +#[cfg(test)] +mod tests { + use super::super::model_type::ZsVoiceModelType; + use enums_shared::test_helpers::assert_serialization; + + mod serde { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(ZsVoiceModelType::VallEX, "vall-e-x"); + } + } + + mod impl_methods { + use super::*; + + #[test] + fn to_str() { + assert_eq!(ZsVoiceModelType::VallEX.to_str(), "vall-e-x"); + assert_eq!(ZsVoiceModelType::StyleTTS2.to_str(), "styletts2"); + } + + #[test] + fn from_str() { + assert_eq!(ZsVoiceModelType::from_str("vall-e-x").unwrap(), ZsVoiceModelType::VallEX); + assert_eq!(ZsVoiceModelType::from_str("styletts2").unwrap(), ZsVoiceModelType::StyleTTS2); + assert!(ZsVoiceModelType::from_str("foo").is_err()); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip() { + use strum::IntoEnumIterator; + for variant in ZsVoiceModelType::iter() { + assert_eq!(variant, ZsVoiceModelType::from_str(variant.to_str()).unwrap()); + assert_eq!(variant, ZsVoiceModelType::from_str(&format!("{}", variant)).unwrap()); + assert_eq!(variant, ZsVoiceModelType::from_str(&format!("{:?}", variant)).unwrap()); + } + } + + #[test] + fn serialized_length_ok_for_database() { + const MAX_LENGTH: usize = 16; // TODO(bt): Confirm database column width, then remove this comment. + use strum::IntoEnumIterator; + for variant in ZsVoiceModelType::iter() { + let serialized = variant.to_str(); + assert!(!serialized.is_empty(), "variant {:?} is too short", variant); + assert!(serialized.len() <= MAX_LENGTH, "variant {:?} is too long", variant); + } + } + } +} diff --git a/crates/schema/public/enums_db/src/common/artcraft_credits_pack_slug.rs b/crates/schema/public/enums_db/src/common/artcraft_credits_pack_slug.rs new file mode 100644 index 0000000000..6ea3af31dd --- /dev/null +++ b/crates/schema/public/enums_db/src/common/artcraft_credits_pack_slug.rs @@ -0,0 +1,121 @@ +use strum::EnumCount; +use strum::EnumIter; + +/// NB: This will be used by a variety of tables (MySQL and sqlite)! +/// Keep the max length to 16 characters. +#[derive(Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd, Serialize, Deserialize, EnumIter, EnumCount)] +#[serde(rename_all = "snake_case")] +pub enum ArtcraftCreditsPackSlug { + #[serde(rename= "artcraft_1000")] + Artcraft1000, + #[serde(rename= "artcraft_2500")] + Artcraft2500, + #[serde(rename= "artcraft_5000")] + Artcraft5000, + #[serde(rename= "artcraft_10000")] + Artcraft10000, + #[serde(rename= "artcraft_25000")] + Artcraft25000, + #[serde(rename= "artcraft_50000")] + Artcraft50000, +} + +impl_enum_display_and_debug_using_to_str!(ArtcraftCreditsPackSlug); +impl_mysql_enum_coders!(ArtcraftCreditsPackSlug); +impl_mysql_from_row!(ArtcraftCreditsPackSlug); + +// NB: We can derive `sqlx::Type` instead of using `impl_mysql_enum_coders` + +impl ArtcraftCreditsPackSlug { + pub fn to_str(&self) -> &'static str { + match self { + Self::Artcraft1000 => "artcraft_1000", + Self::Artcraft2500 => "artcraft_2500", + Self::Artcraft5000 => "artcraft_5000", + Self::Artcraft10000 => "artcraft_10000", + Self::Artcraft25000 => "artcraft_25000", + Self::Artcraft50000 => "artcraft_50000", + } + } + + pub fn from_str(s: &str) -> Result { + match s { + "artcraft_1000" => Ok(Self::Artcraft1000), + "artcraft_2500" => Ok(Self::Artcraft2500), + "artcraft_5000" => Ok(Self::Artcraft5000), + "artcraft_10000" => Ok(Self::Artcraft10000), + "artcraft_25000" => Ok(Self::Artcraft25000), + "artcraft_50000" => Ok(Self::Artcraft50000), + _ => Err(format!("invalid artcraft_credits_pack_slug: {:?}", s)), + } + } + +} + +#[cfg(test)] +mod tests { + use enums_shared::test_helpers::assert_serialization; + use super::ArtcraftCreditsPackSlug; + + mod explicit_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(ArtcraftCreditsPackSlug::Artcraft1000, "artcraft_1000"); + assert_serialization(ArtcraftCreditsPackSlug::Artcraft2500, "artcraft_2500"); + assert_serialization(ArtcraftCreditsPackSlug::Artcraft5000, "artcraft_5000"); + assert_serialization(ArtcraftCreditsPackSlug::Artcraft10000, "artcraft_10000"); + assert_serialization(ArtcraftCreditsPackSlug::Artcraft25000, "artcraft_25000"); + assert_serialization(ArtcraftCreditsPackSlug::Artcraft50000, "artcraft_50000"); + } + + #[test] + fn to_str() { + assert_eq!(ArtcraftCreditsPackSlug::Artcraft1000.to_str(), "artcraft_1000"); + assert_eq!(ArtcraftCreditsPackSlug::Artcraft2500.to_str(), "artcraft_2500"); + assert_eq!(ArtcraftCreditsPackSlug::Artcraft5000.to_str(), "artcraft_5000"); + assert_eq!(ArtcraftCreditsPackSlug::Artcraft10000.to_str(), "artcraft_10000"); + assert_eq!(ArtcraftCreditsPackSlug::Artcraft25000.to_str(), "artcraft_25000"); + assert_eq!(ArtcraftCreditsPackSlug::Artcraft50000.to_str(), "artcraft_50000"); + } + + #[test] + fn from_str() { + assert_eq!(ArtcraftCreditsPackSlug::from_str("artcraft_1000").unwrap(), ArtcraftCreditsPackSlug::Artcraft1000); + assert_eq!(ArtcraftCreditsPackSlug::from_str("artcraft_2500").unwrap(), ArtcraftCreditsPackSlug::Artcraft2500); + assert_eq!(ArtcraftCreditsPackSlug::from_str("artcraft_5000").unwrap(), ArtcraftCreditsPackSlug::Artcraft5000); + assert_eq!(ArtcraftCreditsPackSlug::from_str("artcraft_10000").unwrap(), ArtcraftCreditsPackSlug::Artcraft10000); + assert_eq!(ArtcraftCreditsPackSlug::from_str("artcraft_25000").unwrap(), ArtcraftCreditsPackSlug::Artcraft25000); + assert_eq!(ArtcraftCreditsPackSlug::from_str("artcraft_50000").unwrap(), ArtcraftCreditsPackSlug::Artcraft50000); + + } + + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip() { + use strum::IntoEnumIterator; + for variant in ArtcraftCreditsPackSlug::iter() { + // Test to_str(), from_str(), Display, and Debug. + assert_eq!(variant, ArtcraftCreditsPackSlug::from_str(variant.to_str()).unwrap()); + assert_eq!(variant, ArtcraftCreditsPackSlug::from_str(&format!("{}", variant)).unwrap()); + assert_eq!(variant, ArtcraftCreditsPackSlug::from_str(&format!("{:?}", variant)).unwrap()); + } + } + + #[test] + fn serialized_length_ok_for_database() { + use strum::IntoEnumIterator; + const MAX_LENGTH : usize = 16; + for variant in ArtcraftCreditsPackSlug::iter() { + let serialized = variant.to_str(); + assert!(serialized.len() > 0, "variant {:?} is too short", variant); + assert!(serialized.len() <= MAX_LENGTH, "variant {:?} is too long", variant); + } + } + } +} diff --git a/crates/schema/public/enums_db/src/common/artcraft_subscription_slug.rs b/crates/schema/public/enums_db/src/common/artcraft_subscription_slug.rs new file mode 100644 index 0000000000..d47d93c33f --- /dev/null +++ b/crates/schema/public/enums_db/src/common/artcraft_subscription_slug.rs @@ -0,0 +1,96 @@ +use strum::EnumCount; +use strum::EnumIter; + +/// NB: This will be used by a variety of tables (MySQL and sqlite)! +/// Keep the max length to 16 characters. +#[derive(Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd, Serialize, Deserialize, EnumIter, EnumCount)] +#[serde(rename_all = "snake_case")] +pub enum ArtcraftSubscriptionSlug { + ArtcraftBasic, + ArtcraftPro, + ArtcraftMax, +} + +impl_enum_display_and_debug_using_to_str!(ArtcraftSubscriptionSlug); +impl_mysql_enum_coders!(ArtcraftSubscriptionSlug); +impl_mysql_from_row!(ArtcraftSubscriptionSlug); + +// NB: We can derive `sqlx::Type` instead of using `impl_mysql_enum_coders` + +impl ArtcraftSubscriptionSlug { + pub fn to_str(&self) -> &'static str { + match self { + Self::ArtcraftBasic => "artcraft_basic", + Self::ArtcraftPro => "artcraft_pro", + Self::ArtcraftMax => "artcraft_max", + } + } + + pub fn from_str(s: &str) -> Result { + match s { + "artcraft_basic" => Ok(Self::ArtcraftBasic), + "artcraft_pro" => Ok(Self::ArtcraftPro), + "artcraft_max" => Ok(Self::ArtcraftMax), + _ => Err(format!("invalid artcraft_subscription_slug: {:?}", s)), + } + } + +} + +#[cfg(test)] +mod tests { + use super::ArtcraftSubscriptionSlug; + use enums_shared::test_helpers::assert_serialization; + + mod explicit_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(ArtcraftSubscriptionSlug::ArtcraftBasic, "artcraft_basic"); + assert_serialization(ArtcraftSubscriptionSlug::ArtcraftPro, "artcraft_pro"); + assert_serialization(ArtcraftSubscriptionSlug::ArtcraftMax, "artcraft_max"); + } + + #[test] + fn to_str() { + assert_eq!(ArtcraftSubscriptionSlug::ArtcraftBasic.to_str(), "artcraft_basic"); + assert_eq!(ArtcraftSubscriptionSlug::ArtcraftPro.to_str(), "artcraft_pro"); + assert_eq!(ArtcraftSubscriptionSlug::ArtcraftMax.to_str(), "artcraft_max"); + } + + #[test] + fn from_str() { + assert_eq!(ArtcraftSubscriptionSlug::from_str("artcraft_basic").unwrap(), ArtcraftSubscriptionSlug::ArtcraftBasic); + assert_eq!(ArtcraftSubscriptionSlug::from_str("artcraft_pro").unwrap(), ArtcraftSubscriptionSlug::ArtcraftPro); + assert_eq!(ArtcraftSubscriptionSlug::from_str("artcraft_max").unwrap(), ArtcraftSubscriptionSlug::ArtcraftMax); + } + + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip() { + use strum::IntoEnumIterator; + for variant in ArtcraftSubscriptionSlug::iter() { + // Test to_str(), from_str(), Display, and Debug. + assert_eq!(variant, ArtcraftSubscriptionSlug::from_str(variant.to_str()).unwrap()); + assert_eq!(variant, ArtcraftSubscriptionSlug::from_str(&format!("{}", variant)).unwrap()); + assert_eq!(variant, ArtcraftSubscriptionSlug::from_str(&format!("{:?}", variant)).unwrap()); + } + } + + #[test] + fn serialized_length_ok_for_database() { + use strum::IntoEnumIterator; + const MAX_LENGTH : usize = 16; + for variant in ArtcraftSubscriptionSlug::iter() { + let serialized = variant.to_str(); + assert!(serialized.len() > 0, "variant {:?} is too short", variant); + assert!(serialized.len() <= MAX_LENGTH, "variant {:?} is too long", variant); + } + } + } +} diff --git a/crates/schema/public/enums_db/src/common/generation/generation_provider.rs b/crates/schema/public/enums_db/src/common/generation/generation_provider.rs new file mode 100644 index 0000000000..d6f1db195c --- /dev/null +++ b/crates/schema/public/enums_db/src/common/generation/generation_provider.rs @@ -0,0 +1,135 @@ +//! This is an important enum. +//! +//! Database version of GenerationProvider. Used in MySQL/SQLite queries. +//! +//! Do not change the values here without cause or care. + +use enums_shared::error::enums_error::EnumsError; +use strum::EnumCount; +use strum::EnumIter; + +/// NB: This will be used by a variety of tables (MySQL and sqlite)! +/// Keep the max length to 16 characters. +#[derive(Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd, Serialize, Deserialize, EnumIter, EnumCount)] +#[serde(rename_all = "snake_case")] +pub enum GenerationProvider { + Artcraft, + Fal, + Grok, + Midjourney, + Sora, + WorldLabs, +} + +impl_enum_display_and_debug_using_to_str!(GenerationProvider); +impl_mysql_enum_coders!(GenerationProvider); +impl_mysql_from_row!(GenerationProvider); +impl_sqlite_enum_coders!(GenerationProvider); + +impl GenerationProvider { + pub fn to_str(&self) -> &'static str { + match self { + Self::Artcraft => "artcraft", + Self::Fal => "fal", + Self::Grok => "grok", + Self::Midjourney => "midjourney", + Self::Sora => "sora", + Self::WorldLabs => "world_labs", + } + } + + pub fn from_str(value: &str) -> Result { + match value { + "artcraft" => Ok(Self::Artcraft), + "fal" => Ok(Self::Fal), + "grok" => Ok(Self::Grok), + "midjourney" => Ok(Self::Midjourney), + "sora" => Ok(Self::Sora), + "world_labs" => Ok(Self::WorldLabs), + _ => Err(EnumsError::CouldNotConvertFromString(value.to_string())), + } + } + + // Conversion methods (from_db/to_db) live on the API type in enums_api, + // since enums_api depends on enums_db (not the other way around). +} + +#[cfg(test)] +mod tests { + use super::GenerationProvider; + use enums_shared::error::enums_error::EnumsError; + use enums_shared::test_helpers::assert_serialization; + + mod explicit_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(GenerationProvider::Artcraft, "artcraft"); + assert_serialization(GenerationProvider::Fal, "fal"); + assert_serialization(GenerationProvider::Grok, "grok"); + assert_serialization(GenerationProvider::Midjourney, "midjourney"); + assert_serialization(GenerationProvider::Sora, "sora"); + assert_serialization(GenerationProvider::WorldLabs, "world_labs"); + } + + #[test] + fn to_str() { + assert_eq!(GenerationProvider::Artcraft.to_str(), "artcraft"); + assert_eq!(GenerationProvider::Fal.to_str(), "fal"); + assert_eq!(GenerationProvider::Grok.to_str(), "grok"); + assert_eq!(GenerationProvider::Midjourney.to_str(), "midjourney"); + assert_eq!(GenerationProvider::Sora.to_str(), "sora"); + assert_eq!(GenerationProvider::WorldLabs.to_str(), "world_labs"); + } + + #[test] + fn from_str() { + assert_eq!(GenerationProvider::from_str("artcraft").unwrap(), GenerationProvider::Artcraft); + assert_eq!(GenerationProvider::from_str("fal").unwrap(), GenerationProvider::Fal); + assert_eq!(GenerationProvider::from_str("grok").unwrap(), GenerationProvider::Grok); + assert_eq!(GenerationProvider::from_str("midjourney").unwrap(), GenerationProvider::Midjourney); + assert_eq!(GenerationProvider::from_str("sora").unwrap(), GenerationProvider::Sora); + assert_eq!(GenerationProvider::from_str("world_labs").unwrap(), GenerationProvider::WorldLabs); + } + + #[test] + fn from_str_err() { + let result = GenerationProvider::from_str("asdf"); + assert!(result.is_err()); + if let Err(EnumsError::CouldNotConvertFromString(value)) = result { + assert_eq!(value, "asdf"); + } else { + panic!("Expected EnumsError::CouldNotConvertFromString"); + } + } + + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip() { + use strum::IntoEnumIterator; + for variant in GenerationProvider::iter() { + assert_eq!(variant, GenerationProvider::from_str(variant.to_str()).unwrap()); + assert_eq!(variant, GenerationProvider::from_str(&format!("{}", variant)).unwrap()); + assert_eq!(variant, GenerationProvider::from_str(&format!("{:?}", variant)).unwrap()); + } + } + + #[test] + fn serialized_length_ok_for_database() { + use strum::IntoEnumIterator; + const MAX_LENGTH: usize = 16; // TODO(bt): Confirm database column width, then remove this comment. + for variant in GenerationProvider::iter() { + let serialized = variant.to_str(); + assert!(!serialized.is_empty(), "variant {:?} is too short", variant); + assert!(serialized.len() <= MAX_LENGTH, "variant {:?} is too long", variant); + } + } + } + + // Conversion tests live in enums_api where from_db/to_db are defined. +} diff --git a/crates/schema/public/enums_db/src/common/generation/mod.rs b/crates/schema/public/enums_db/src/common/generation/mod.rs new file mode 100644 index 0000000000..37014dbd57 --- /dev/null +++ b/crates/schema/public/enums_db/src/common/generation/mod.rs @@ -0,0 +1 @@ +pub mod generation_provider; diff --git a/crates/schema/public/enums_db/src/common/job_status.rs b/crates/schema/public/enums_db/src/common/job_status.rs new file mode 100644 index 0000000000..19fce7052e --- /dev/null +++ b/crates/schema/public/enums_db/src/common/job_status.rs @@ -0,0 +1,125 @@ +use strum::EnumCount; +use strum::EnumIter; + +/// This is used in nearly every job system as an actual MySQL ENUM value: +/// +/// - tts_download_job +/// - tts_inference_job +/// - w2l_download_job +/// - w2l_inference_job +/// - generic_download_job +/// - (NOT generic_inference_job, which uses JobStatusPlus) +/// +/// See the documentation on the table for usage. +/// +/// DO NOT CHANGE VALUES WITHOUT A MIGRATION STRATEGY. + +#[derive(Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd, Serialize, Deserialize, EnumIter, EnumCount)] +#[derive(sqlx::Type)] +#[sqlx(rename_all = "snake_case")] +#[serde(rename_all = "snake_case")] +pub enum JobStatus { + Pending, + Started, + CompleteSuccess, + CompleteFailure, + AttemptFailed, + Dead, +} + +// TODO(bt, 2022-12-21): This desperately needs MySQL integration tests! +impl_enum_display_and_debug_using_to_str!(JobStatus); + +// NB: We can derive `sqlx::Type` instead of using `impl_mysql_enum_coders` + +impl JobStatus { + pub fn to_str(&self) -> &'static str { + match self { + Self::Pending => "pending", + Self::Started => "started", + Self::CompleteSuccess => "complete_success", + Self::CompleteFailure => "complete_failure", + Self::AttemptFailed => "attempt_failed", + Self::Dead => "dead", + } + } + + pub fn from_str(job_status: &str) -> Result { + match job_status { + "pending" => Ok(Self::Pending), + "started" => Ok(Self::Started), + "complete_success" => Ok(Self::CompleteSuccess), + "complete_failure" => Ok(Self::CompleteFailure), + "attempt_failed" => Ok(Self::AttemptFailed), + "dead" => Ok(Self::Dead), + _ => Err(format!("invalid job_status: {:?}", job_status)), + } + } + +} + +#[cfg(test)] +mod tests { + use super::JobStatus; + use enums_shared::test_helpers::assert_serialization; + + mod explicit_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(JobStatus::Pending, "pending"); + assert_serialization(JobStatus::Started, "started"); + assert_serialization(JobStatus::CompleteSuccess, "complete_success"); + assert_serialization(JobStatus::CompleteFailure, "complete_failure"); + assert_serialization(JobStatus::AttemptFailed, "attempt_failed"); + assert_serialization(JobStatus::Dead, "dead"); + } + + #[test] + fn to_str() { + assert_eq!(JobStatus::Pending.to_str(), "pending"); + assert_eq!(JobStatus::Started.to_str(), "started"); + assert_eq!(JobStatus::CompleteSuccess.to_str(), "complete_success"); + assert_eq!(JobStatus::CompleteFailure.to_str(), "complete_failure"); + assert_eq!(JobStatus::AttemptFailed.to_str(), "attempt_failed"); + assert_eq!(JobStatus::Dead.to_str(), "dead"); + } + + #[test] + fn from_str() { + assert_eq!(JobStatus::from_str("pending").unwrap(), JobStatus::Pending); + assert_eq!(JobStatus::from_str("started").unwrap(), JobStatus::Started); + assert_eq!(JobStatus::from_str("complete_success").unwrap(), JobStatus::CompleteSuccess); + assert_eq!(JobStatus::from_str("complete_failure").unwrap(), JobStatus::CompleteFailure); + assert_eq!(JobStatus::from_str("attempt_failed").unwrap(), JobStatus::AttemptFailed); + assert_eq!(JobStatus::from_str("dead").unwrap(), JobStatus::Dead); + } + + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip() { + use strum::IntoEnumIterator; + for variant in JobStatus::iter() { + assert_eq!(variant, JobStatus::from_str(variant.to_str()).unwrap()); + assert_eq!(variant, JobStatus::from_str(&format!("{}", variant)).unwrap()); + assert_eq!(variant, JobStatus::from_str(&format!("{:?}", variant)).unwrap()); + } + } + + #[test] + fn serialized_length_ok_for_database() { + const MAX_LENGTH: usize = 32; // TODO(bt): Confirm database column width, then remove this comment. + use strum::IntoEnumIterator; + for variant in JobStatus::iter() { + let serialized = variant.to_str(); + assert!(!serialized.is_empty(), "variant {:?} is too short", variant); + assert!(serialized.len() <= MAX_LENGTH, "variant {:?} is too long", variant); + } + } + } +} diff --git a/crates/schema/public/enums_db/src/common/job_status_plus.rs b/crates/schema/public/enums_db/src/common/job_status_plus.rs new file mode 100644 index 0000000000..1d00071a42 --- /dev/null +++ b/crates/schema/public/enums_db/src/common/job_status_plus.rs @@ -0,0 +1,145 @@ +use strum::EnumCount; +use strum::EnumIter; + +/// This is used in newer jobs (that add additional enum states) +/// +/// - generic_inference_job +/// - (no other jobs yet) +/// +/// See the documentation on the table for usage. +/// +/// DO NOT CHANGE VALUES WITHOUT A MIGRATION STRATEGY. + +#[derive(Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd, Serialize, Deserialize, EnumIter, EnumCount)] +#[serde(rename_all = "snake_case")] +pub enum JobStatusPlus { + Pending, + Started, + CompleteSuccess, + CompleteFailure, + AttemptFailed, + Dead, + CancelledByUser, + CancelledBySystem, +} + +// TODO(bt, 2022-12-21): This desperately needs MySQL integration tests! +impl_enum_display_and_debug_using_to_str!(JobStatusPlus); +impl_mysql_enum_coders!(JobStatusPlus); +impl_mysql_from_row!(JobStatusPlus); + +// NB: We can derive `sqlx::Type` instead of using `impl_mysql_enum_coders` + +impl Default for JobStatusPlus { + fn default() -> Self { + Self::Pending + } +} + +impl JobStatusPlus { + pub const fn to_str(&self) -> &'static str { + match self { + Self::Pending => "pending", + Self::Started => "started", + Self::CompleteSuccess => "complete_success", + Self::CompleteFailure => "complete_failure", + Self::AttemptFailed => "attempt_failed", + Self::Dead => "dead", + Self::CancelledByUser => "cancelled_by_user", + Self::CancelledBySystem => "cancelled_by_system", + } + } + + pub fn from_str(job_status: &str) -> Result { + match job_status { + "pending" => Ok(Self::Pending), + "started" => Ok(Self::Started), + "complete_success" => Ok(Self::CompleteSuccess), + "complete_failure" => Ok(Self::CompleteFailure), + "attempt_failed" => Ok(Self::AttemptFailed), + "dead" => Ok(Self::Dead), + "cancelled_by_user" => Ok(Self::CancelledByUser), + "cancelled_by_system" => Ok(Self::CancelledBySystem), + _ => Err(format!("invalid job_status: {:?}", job_status)), + } + } + +} + +#[cfg(test)] +mod tests { + use super::JobStatusPlus; + use enums_shared::test_helpers::assert_serialization; + + mod explicit_checks { + use super::*; + + #[test] + fn test_default() { + assert_eq!(JobStatusPlus::default(), JobStatusPlus::Pending); + } + + #[test] + fn test_serialization() { + assert_serialization(JobStatusPlus::Pending, "pending"); + assert_serialization(JobStatusPlus::Started, "started"); + assert_serialization(JobStatusPlus::CompleteSuccess, "complete_success"); + assert_serialization(JobStatusPlus::CompleteFailure, "complete_failure"); + assert_serialization(JobStatusPlus::AttemptFailed, "attempt_failed"); + assert_serialization(JobStatusPlus::Dead, "dead"); + assert_serialization(JobStatusPlus::CancelledByUser, "cancelled_by_user"); + assert_serialization(JobStatusPlus::CancelledBySystem, "cancelled_by_system"); + } + + #[test] + fn to_str() { + assert_eq!(JobStatusPlus::Pending.to_str(), "pending"); + assert_eq!(JobStatusPlus::Started.to_str(), "started"); + assert_eq!(JobStatusPlus::CompleteSuccess.to_str(), "complete_success"); + assert_eq!(JobStatusPlus::CompleteFailure.to_str(), "complete_failure"); + assert_eq!(JobStatusPlus::AttemptFailed.to_str(), "attempt_failed"); + assert_eq!(JobStatusPlus::Dead.to_str(), "dead"); + assert_eq!(JobStatusPlus::CancelledByUser.to_str(), "cancelled_by_user"); + assert_eq!(JobStatusPlus::CancelledBySystem.to_str(), "cancelled_by_system"); + } + + #[test] + fn from_str() { + assert_eq!(JobStatusPlus::from_str("pending").unwrap(), JobStatusPlus::Pending); + assert_eq!(JobStatusPlus::from_str("started").unwrap(), JobStatusPlus::Started); + assert_eq!(JobStatusPlus::from_str("complete_success").unwrap(), JobStatusPlus::CompleteSuccess); + assert_eq!(JobStatusPlus::from_str("complete_failure").unwrap(), JobStatusPlus::CompleteFailure); + assert_eq!(JobStatusPlus::from_str("attempt_failed").unwrap(), JobStatusPlus::AttemptFailed); + assert_eq!(JobStatusPlus::from_str("dead").unwrap(), JobStatusPlus::Dead); + assert_eq!(JobStatusPlus::from_str("cancelled_by_user").unwrap(), JobStatusPlus::CancelledByUser); + assert_eq!(JobStatusPlus::from_str("cancelled_by_system").unwrap(), JobStatusPlus::CancelledBySystem); + } + + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip() { + use strum::IntoEnumIterator; + for variant in JobStatusPlus::iter() { + // Test to_str(), from_str(), Display, and Debug. + assert_eq!(variant, JobStatusPlus::from_str(variant.to_str()).unwrap()); + assert_eq!(variant, JobStatusPlus::from_str(&format!("{}", variant)).unwrap()); + assert_eq!(variant, JobStatusPlus::from_str(&format!("{:?}", variant)).unwrap()); + } + } + + #[test] + fn serialized_length_ok_for_database() { + const MAX_LENGTH: usize = 32; // TODO(bt): Confirm database column width, then remove this comment. + use strum::IntoEnumIterator; + for variant in JobStatusPlus::iter() { + let serialized = variant.to_str(); + assert!(!serialized.is_empty(), "variant {:?} is too short", variant); + assert!(serialized.len() <= MAX_LENGTH, "variant {:?} is too long", variant); + } + } + } +} diff --git a/crates/schema/public/enums_db/src/common/mod.rs b/crates/schema/public/enums_db/src/common/mod.rs new file mode 100644 index 0000000000..972e0c2ae4 --- /dev/null +++ b/crates/schema/public/enums_db/src/common/mod.rs @@ -0,0 +1,12 @@ +pub mod artcraft_credits_pack_slug; +pub mod artcraft_subscription_slug; +pub mod generation; +pub mod job_status; +pub mod job_status_plus; +pub mod model_type; +pub mod payments_namespace; +pub mod sqlite; +pub mod stripe_subscription_status; +pub mod view_as; +pub mod visibility; +pub mod vocoder_type; diff --git a/crates/schema/public/enums_db/src/common/model_type.rs b/crates/schema/public/enums_db/src/common/model_type.rs new file mode 100644 index 0000000000..5763a97708 --- /dev/null +++ b/crates/schema/public/enums_db/src/common/model_type.rs @@ -0,0 +1,503 @@ +use strum::EnumCount; +use strum::EnumIter; + +/// NB: This will be used by a variety of tables (MySQL and sqlite)! +/// Keep the max length to 24 characters. +#[derive(Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd, Serialize, Deserialize, EnumIter, EnumCount)] +#[serde(rename_all = "snake_case")] +pub enum ModelType { + // Image models + #[serde(rename = "flux_1_dev")] + Flux1Dev, + #[serde(rename = "flux_1_schnell")] + Flux1Schnell, + #[serde(rename = "flux_dev_juggernaut")] + FluxDevJuggernaut, + #[serde(rename = "flux_pro_1")] + FluxPro1, + #[serde(rename = "flux_pro_1p1")] + FluxPro11, + #[serde(rename = "flux_pro_1p1_ultra")] + FluxPro11Ultra, + #[serde(rename = "flux_pro_kontext_max")] + FluxProKontextMax, + #[serde(rename = "flux_2_lora_angles")] + Flux2LoraAngles, + #[serde(rename = "gpt_image_1")] + GptImage1, + #[serde(rename = "gpt_image_1p5")] + GptImage1p5, + // Generic grok image model without a version + #[serde(rename = "grok_image")] + GrokImage, + #[serde(rename = "recraft_3")] + Recraft3, + #[serde(rename = "seededit_3")] + SeedEdit3, + #[serde(rename = "qwen")] + Qwen, + #[serde(rename = "qwen_edit_2511_angles")] + QwenEdit2511Angles, + /// Gemini 2.5 Flash, AKA "Nano Banana" + #[serde(rename = "gemini_25_flash")] + Gemini25Flash, + #[serde(rename = "nano_banana")] + NanoBanana, + #[serde(rename = "nano_banana_2")] + NanoBanana2, + #[serde(rename = "nano_banana_pro")] + NanoBananaPro, + #[serde(rename = "seedream_4")] + Seedream4, + #[serde(rename = "seedream_4p5")] + Seedream4p5, + #[serde(rename = "seedream_5_lite")] + Seedream5Lite, + + /// Midjourney without distinguishing a model type or version + #[serde(rename = "midjourney")] + Midjourney, + #[serde(rename = "midjourney_v6")] + MidjourneyV6, + #[serde(rename = "midjourney_v6p1")] + MidjourneyV6p1, + #[serde(rename = "midjourney_v6p1_raw")] + MidjourneyV6p1Raw, + #[serde(rename = "midjourney_v7")] + MidjourneyV7, + #[serde(rename = "midjourney_v7_draft")] + MidjourneyV7Draft, + #[serde(rename = "midjourney_v7_draft_raw")] + MidjourneyV7DraftRaw, + #[serde(rename = "midjourney_v7_raw")] + MidjourneyV7Raw, + + //// Image Infill models + //#[serde(rename = "flux_pro_1_infill")] + //FluxPro1Infill, + + // Video models + + // Generic grok video model without a version + #[serde(rename = "grok_video")] + GrokVideo, + #[serde(rename = "kling_1p6_pro")] + Kling16Pro, + #[serde(rename = "kling_2p1_pro")] + Kling21Pro, + #[serde(rename = "kling_2p1_master")] + Kling21Master, + #[serde(rename = "kling_2p5_turbo_pro")] + Kling2p5TurboPro, + #[serde(rename = "kling_2p6_pro")] + Kling2p6Pro, + #[serde(rename = "kling_3p0_standard")] + Kling3p0Standard, + #[serde(rename = "kling_3p0_pro")] + Kling3p0Pro, + #[serde(rename = "seedance_1p0_lite")] + Seedance10Lite, + #[serde(rename = "seedance_1p0_pro")] + Seedance10Pro, + #[serde(rename = "seedance_1p5_pro")] + Seedance1p5Pro, + #[serde(rename = "seedance_2p0")] + Seedance2p0, + #[serde(rename = "sora_2")] + Sora2, + #[serde(rename = "sora_2_pro")] + Sora2Pro, + #[serde(rename = "veo_2")] + Veo2, + #[serde(rename = "veo_3")] + Veo3, + #[serde(rename = "veo_3_fast")] + Veo3Fast, + #[serde(rename = "veo_3p1")] + Veo3p1, + #[serde(rename = "veo_3p1_fast")] + Veo3p1Fast, + + // 3D Object generation models + #[serde(rename = "hunyuan_3d_2p0")] + Hunyuan3d2_0, + #[serde(rename = "hunyuan_3d_2p1")] + Hunyuan3d2_1, + #[serde(rename = "hunyuan_3d_3")] + Hunyuan3d3, + + // Splat generation models (World Labs) + #[serde(rename = "marble_0p1_mini")] + Marble0p1Mini, + #[serde(rename = "marble_0p1_plus")] + Marble0p1Plus, +} + +impl_enum_display_and_debug_using_to_str!(ModelType); +impl_mysql_enum_coders!(ModelType); +impl_mysql_from_row!(ModelType); + +// NB: We can derive `sqlx::Type` instead of using `impl_mysql_enum_coders` + +impl ModelType { + pub fn to_str(&self) -> &'static str { + match self { + // Image models + Self::Flux1Dev => "flux_1_dev", + Self::Flux1Schnell => "flux_1_schnell", + Self::FluxDevJuggernaut => "flux_dev_juggernaut", + Self::FluxPro1 => "flux_pro_1", + Self::FluxPro11 => "flux_pro_1p1", + Self::FluxPro11Ultra => "flux_pro_1p1_ultra", + Self::FluxProKontextMax => "flux_pro_kontext_max", + Self::Flux2LoraAngles => "flux_2_lora_angles", + Self::GptImage1 => "gpt_image_1", + Self::GptImage1p5 => "gpt_image_1p5", + Self::GrokImage => "grok_image", + Self::Recraft3 => "recraft_3", + Self::SeedEdit3 => "seededit_3", + Self::Qwen => "qwen", + Self::QwenEdit2511Angles => "qwen_edit_2511_angles", + Self::Gemini25Flash => "gemini_25_flash", + Self::NanoBanana => "nano_banana", + Self::NanoBanana2 => "nano_banana_2", + Self::NanoBananaPro => "nano_banana_pro", + Self::Seedream4 => "seedream_4", + Self::Seedream4p5 => "seedream_4p5", + Self::Seedream5Lite => "seedream_5_lite", + Self::Midjourney => "midjourney", + Self::MidjourneyV6 => "midjourney_v6", + Self::MidjourneyV6p1 => "midjourney_v6p1", + Self::MidjourneyV6p1Raw => "midjourney_v6p1_raw", + Self::MidjourneyV7 => "midjourney_v7", + Self::MidjourneyV7Draft => "midjourney_v7_draft", + Self::MidjourneyV7DraftRaw => "midjourney_v7_draft_raw", + Self::MidjourneyV7Raw => "midjourney_v7_raw", + + // Video models + Self::GrokVideo => "grok_video", + Self::Kling16Pro => "kling_1p6_pro", + Self::Kling21Pro => "kling_2p1_pro", + Self::Kling21Master => "kling_2p1_master", + Self::Kling2p5TurboPro => "kling_2p5_turbo_pro", + Self::Kling2p6Pro => "kling_2p6_pro", + Self::Kling3p0Standard => "kling_3p0_standard", + Self::Kling3p0Pro => "kling_3p0_pro", + Self::Seedance10Lite => "seedance_1p0_lite", + Self::Seedance10Pro => "seedance_1p0_pro", + Self::Seedance1p5Pro => "seedance_1p5_pro", + Self::Seedance2p0 => "seedance_2p0", + Self::Sora2 => "sora_2", + Self::Sora2Pro => "sora_2_pro", + Self::Veo2 => "veo_2", + Self::Veo3 => "veo_3", + Self::Veo3Fast => "veo_3_fast", + Self::Veo3p1 => "veo_3p1", + Self::Veo3p1Fast => "veo_3p1_fast", + + // 3D Object generation models + Self::Hunyuan3d2_0 => "hunyuan_3d_2p0", + Self::Hunyuan3d2_1 => "hunyuan_3d_2p1", + Self::Hunyuan3d3 => "hunyuan_3d_3", + + // Splat generation models (World Labs) + Self::Marble0p1Mini => "marble_0p1_mini", + Self::Marble0p1Plus => "marble_0p1_plus", + } + } + + pub fn from_str(job_status: &str) -> Result { + match job_status { + // Image models + "flux_1_dev" => Ok(Self::Flux1Dev), + "flux_1_schnell" => Ok(Self::Flux1Schnell), + "flux_dev_juggernaut" => Ok(Self::FluxDevJuggernaut), + "flux_pro_1" => Ok(Self::FluxPro1), + "flux_pro_1p1" => Ok(Self::FluxPro11), + "flux_pro_1p1_ultra" => Ok(Self::FluxPro11Ultra), + "flux_pro_kontext_max" => Ok(Self::FluxProKontextMax), + "flux_2_lora_angles" => Ok(Self::Flux2LoraAngles), + "gpt_image_1" => Ok(Self::GptImage1), + "gpt_image_1p5" => Ok(Self::GptImage1p5), + "grok_image" => Ok(Self::GrokImage), + "recraft_3" => Ok(Self::Recraft3), + "seededit_3" => Ok(Self::SeedEdit3), + "qwen" => Ok(Self::Qwen), + "qwen_edit_2511_angles" => Ok(Self::QwenEdit2511Angles), + "gemini_25_flash" => Ok(Self::Gemini25Flash), + "nano_banana" => Ok(Self::NanoBanana), + "nano_banana_2" => Ok(Self::NanoBanana2), + "nano_banana_pro" => Ok(Self::NanoBananaPro), + "seedream_4" => Ok(Self::Seedream4), + "seedream_4p5" => Ok(Self::Seedream4p5), + "seedream_5_lite" => Ok(Self::Seedream5Lite), + "midjourney" => Ok(Self::Midjourney), + "midjourney_v6" => Ok(Self::MidjourneyV6), + "midjourney_v6p1" => Ok(Self::MidjourneyV6p1), + "midjourney_v6p1_raw" => Ok(Self::MidjourneyV6p1Raw), + "midjourney_v7" => Ok(Self::MidjourneyV7), + "midjourney_v7_draft" => Ok(Self::MidjourneyV7Draft), + "midjourney_v7_draft_raw" => Ok(Self::MidjourneyV7DraftRaw), + "midjourney_v7_raw" => Ok(Self::MidjourneyV7Raw), + + // Video models + "grok_video" => Ok(Self::GrokVideo), + "kling_1p6_pro" => Ok(Self::Kling16Pro), + "kling_2p1_pro" => Ok(Self::Kling21Pro), + "kling_2p1_master" => Ok(Self::Kling21Master), + "kling_2p5_turbo_pro" => Ok(Self::Kling2p5TurboPro), + "kling_2p6_pro" => Ok(Self::Kling2p6Pro), + "kling_3p0_standard" => Ok(Self::Kling3p0Standard), + "kling_3p0_pro" => Ok(Self::Kling3p0Pro), + "seedance_1p0_lite" => Ok(Self::Seedance10Lite), + "seedance_1p0_pro" => Ok(Self::Seedance10Pro), + "seedance_1p5_pro" => Ok(Self::Seedance1p5Pro), + "seedance_2p0" => Ok(Self::Seedance2p0), + "sora_2" => Ok(Self::Sora2), + "sora_2_pro" => Ok(Self::Sora2Pro), + "veo_2" => Ok(Self::Veo2), + "veo_3" => Ok(Self::Veo3), + "veo_3_fast" => Ok(Self::Veo3Fast), + "veo_3p1" => Ok(Self::Veo3p1), + "veo_3p1_fast" => Ok(Self::Veo3p1Fast), + + // 3D Object generation models + "hunyuan_3d_2p0" => Ok(Self::Hunyuan3d2_0), + "hunyuan_3d_2p1" => Ok(Self::Hunyuan3d2_1), + "hunyuan_3d_3" => Ok(Self::Hunyuan3d3), + + // Splat generation models (World Labs) + "marble_0p1_mini" => Ok(Self::Marble0p1Mini), + "marble_0p1_plus" => Ok(Self::Marble0p1Plus), + + _ => Err(format!("invalid model_type: {:?}", job_status)), + } + } + +} + +#[cfg(test)] +mod tests { + use super::ModelType; + use enums_shared::test_helpers::assert_serialization; + + mod explicit_checks { + use super::*; + + #[test] + fn test_serialization() { + // Image models + assert_serialization(ModelType::Flux1Dev, "flux_1_dev"); + assert_serialization(ModelType::Flux1Schnell, "flux_1_schnell"); + assert_serialization(ModelType::FluxDevJuggernaut, "flux_dev_juggernaut"); + assert_serialization(ModelType::FluxPro1, "flux_pro_1"); + assert_serialization(ModelType::FluxPro11, "flux_pro_1p1"); + assert_serialization(ModelType::FluxPro11Ultra, "flux_pro_1p1_ultra"); + assert_serialization(ModelType::FluxProKontextMax, "flux_pro_kontext_max"); + assert_serialization(ModelType::Flux2LoraAngles, "flux_2_lora_angles"); + assert_serialization(ModelType::GptImage1, "gpt_image_1"); + assert_serialization(ModelType::GptImage1p5, "gpt_image_1p5"); + assert_serialization(ModelType::GrokImage, "grok_image"); + assert_serialization(ModelType::Recraft3, "recraft_3"); + assert_serialization(ModelType::SeedEdit3, "seededit_3"); + assert_serialization(ModelType::Qwen, "qwen"); + assert_serialization(ModelType::QwenEdit2511Angles, "qwen_edit_2511_angles"); + assert_serialization(ModelType::Gemini25Flash, "gemini_25_flash"); + assert_serialization(ModelType::NanoBanana, "nano_banana"); + assert_serialization(ModelType::NanoBanana2, "nano_banana_2"); + assert_serialization(ModelType::NanoBananaPro, "nano_banana_pro"); + assert_serialization(ModelType::Seedream4, "seedream_4"); + assert_serialization(ModelType::Seedream4p5, "seedream_4p5"); + assert_serialization(ModelType::Seedream5Lite, "seedream_5_lite"); + assert_serialization(ModelType::Midjourney, "midjourney"); + assert_serialization(ModelType::MidjourneyV6, "midjourney_v6"); + assert_serialization(ModelType::MidjourneyV6p1, "midjourney_v6p1"); + assert_serialization(ModelType::MidjourneyV6p1Raw, "midjourney_v6p1_raw"); + assert_serialization(ModelType::MidjourneyV7, "midjourney_v7"); + assert_serialization(ModelType::MidjourneyV7Draft, "midjourney_v7_draft"); + assert_serialization(ModelType::MidjourneyV7DraftRaw, "midjourney_v7_draft_raw"); + assert_serialization(ModelType::MidjourneyV7Raw, "midjourney_v7_raw"); + // Video models + assert_serialization(ModelType::GrokVideo, "grok_video"); + assert_serialization(ModelType::Kling16Pro, "kling_1p6_pro"); + assert_serialization(ModelType::Kling21Pro, "kling_2p1_pro"); + assert_serialization(ModelType::Kling21Master, "kling_2p1_master"); + assert_serialization(ModelType::Kling2p5TurboPro, "kling_2p5_turbo_pro"); + assert_serialization(ModelType::Kling2p6Pro, "kling_2p6_pro"); + assert_serialization(ModelType::Kling3p0Standard, "kling_3p0_standard"); + assert_serialization(ModelType::Kling3p0Pro, "kling_3p0_pro"); + assert_serialization(ModelType::Seedance10Lite, "seedance_1p0_lite"); + assert_serialization(ModelType::Seedance10Pro, "seedance_1p0_pro"); + assert_serialization(ModelType::Seedance1p5Pro, "seedance_1p5_pro"); + assert_serialization(ModelType::Seedance2p0, "seedance_2p0"); + assert_serialization(ModelType::Sora2, "sora_2"); + assert_serialization(ModelType::Sora2Pro, "sora_2_pro"); + assert_serialization(ModelType::Veo2, "veo_2"); + assert_serialization(ModelType::Veo3, "veo_3"); + assert_serialization(ModelType::Veo3Fast, "veo_3_fast"); + assert_serialization(ModelType::Veo3p1, "veo_3p1"); + assert_serialization(ModelType::Veo3p1Fast, "veo_3p1_fast"); + // 3D Object generation models + assert_serialization(ModelType::Hunyuan3d2_0, "hunyuan_3d_2p0"); + assert_serialization(ModelType::Hunyuan3d2_1, "hunyuan_3d_2p1"); + assert_serialization(ModelType::Hunyuan3d3, "hunyuan_3d_3"); + // Splat generation models (World Labs) + assert_serialization(ModelType::Marble0p1Mini, "marble_0p1_mini"); + assert_serialization(ModelType::Marble0p1Plus, "marble_0p1_plus"); + } + + #[test] + fn to_str() { + // Image models + assert_eq!(ModelType::Flux1Dev.to_str(), "flux_1_dev"); + assert_eq!(ModelType::Flux1Schnell.to_str(), "flux_1_schnell"); + assert_eq!(ModelType::FluxDevJuggernaut.to_str(), "flux_dev_juggernaut"); + assert_eq!(ModelType::FluxPro1.to_str(), "flux_pro_1"); + assert_eq!(ModelType::FluxPro11.to_str(), "flux_pro_1p1"); + assert_eq!(ModelType::FluxPro11Ultra.to_str(), "flux_pro_1p1_ultra"); + assert_eq!(ModelType::FluxProKontextMax.to_str(), "flux_pro_kontext_max"); + assert_eq!(ModelType::Flux2LoraAngles.to_str(), "flux_2_lora_angles"); + assert_eq!(ModelType::GptImage1.to_str(), "gpt_image_1"); + assert_eq!(ModelType::GptImage1p5.to_str(), "gpt_image_1p5"); + assert_eq!(ModelType::GrokImage.to_str(), "grok_image"); + assert_eq!(ModelType::Recraft3.to_str(), "recraft_3"); + assert_eq!(ModelType::SeedEdit3.to_str(), "seededit_3"); + assert_eq!(ModelType::Qwen.to_str(), "qwen"); + assert_eq!(ModelType::QwenEdit2511Angles.to_str(), "qwen_edit_2511_angles"); + assert_eq!(ModelType::Gemini25Flash.to_str(), "gemini_25_flash"); + assert_eq!(ModelType::NanoBanana.to_str(), "nano_banana"); + assert_eq!(ModelType::NanoBanana2.to_str(), "nano_banana_2"); + assert_eq!(ModelType::NanoBananaPro.to_str(), "nano_banana_pro"); + assert_eq!(ModelType::Seedream4.to_str(), "seedream_4"); + assert_eq!(ModelType::Seedream4p5.to_str(), "seedream_4p5"); + assert_eq!(ModelType::Seedream5Lite.to_str(), "seedream_5_lite"); + assert_eq!(ModelType::Midjourney.to_str(), "midjourney"); + assert_eq!(ModelType::MidjourneyV6.to_str(), "midjourney_v6"); + assert_eq!(ModelType::MidjourneyV6p1.to_str(), "midjourney_v6p1"); + assert_eq!(ModelType::MidjourneyV6p1Raw.to_str(), "midjourney_v6p1_raw"); + assert_eq!(ModelType::MidjourneyV7.to_str(), "midjourney_v7"); + assert_eq!(ModelType::MidjourneyV7Draft.to_str(), "midjourney_v7_draft"); + assert_eq!(ModelType::MidjourneyV7DraftRaw.to_str(), "midjourney_v7_draft_raw"); + assert_eq!(ModelType::MidjourneyV7Raw.to_str(), "midjourney_v7_raw"); + + // Video models + assert_eq!(ModelType::GrokVideo.to_str(), "grok_video"); + assert_eq!(ModelType::Kling16Pro.to_str(), "kling_1p6_pro"); + assert_eq!(ModelType::Kling21Pro.to_str(), "kling_2p1_pro"); + assert_eq!(ModelType::Kling21Master.to_str(), "kling_2p1_master"); + assert_eq!(ModelType::Kling2p5TurboPro.to_str(), "kling_2p5_turbo_pro"); + assert_eq!(ModelType::Kling2p6Pro.to_str(), "kling_2p6_pro"); + assert_eq!(ModelType::Kling3p0Standard.to_str(), "kling_3p0_standard"); + assert_eq!(ModelType::Kling3p0Pro.to_str(), "kling_3p0_pro"); + assert_eq!(ModelType::Seedance10Lite.to_str(), "seedance_1p0_lite"); + assert_eq!(ModelType::Seedance10Pro.to_str(), "seedance_1p0_pro"); + assert_eq!(ModelType::Seedance1p5Pro.to_str(), "seedance_1p5_pro"); + assert_eq!(ModelType::Seedance2p0.to_str(), "seedance_2p0"); + assert_eq!(ModelType::Sora2.to_str(), "sora_2"); + assert_eq!(ModelType::Sora2Pro.to_str(), "sora_2_pro"); + assert_eq!(ModelType::Veo2.to_str(), "veo_2"); + assert_eq!(ModelType::Veo3.to_str(), "veo_3"); + assert_eq!(ModelType::Veo3Fast.to_str(), "veo_3_fast"); + assert_eq!(ModelType::Veo3p1.to_str(), "veo_3p1"); + assert_eq!(ModelType::Veo3p1Fast.to_str(), "veo_3p1_fast"); + + // 3D Object generation models + assert_eq!(ModelType::Hunyuan3d2_0.to_str(), "hunyuan_3d_2p0"); + assert_eq!(ModelType::Hunyuan3d2_1.to_str(), "hunyuan_3d_2p1"); + assert_eq!(ModelType::Hunyuan3d3.to_str(), "hunyuan_3d_3"); + // Splat generation models (World Labs) + assert_eq!(ModelType::Marble0p1Mini.to_str(), "marble_0p1_mini"); + assert_eq!(ModelType::Marble0p1Plus.to_str(), "marble_0p1_plus"); + } + + #[test] + fn from_str() { + // Image models + assert_eq!(ModelType::from_str("flux_1_dev").unwrap(), ModelType::Flux1Dev); + assert_eq!(ModelType::from_str("flux_1_schnell").unwrap(), ModelType::Flux1Schnell); + assert_eq!(ModelType::from_str("flux_dev_juggernaut").unwrap(), ModelType::FluxDevJuggernaut); + assert_eq!(ModelType::from_str("flux_pro_1").unwrap(), ModelType::FluxPro1); + assert_eq!(ModelType::from_str("flux_pro_1p1").unwrap(), ModelType::FluxPro11); + assert_eq!(ModelType::from_str("flux_pro_1p1_ultra").unwrap(), ModelType::FluxPro11Ultra); + assert_eq!(ModelType::from_str("flux_pro_kontext_max").unwrap(), ModelType::FluxProKontextMax); + assert_eq!(ModelType::from_str("flux_2_lora_angles").unwrap(), ModelType::Flux2LoraAngles); + assert_eq!(ModelType::from_str("gpt_image_1").unwrap(), ModelType::GptImage1); + assert_eq!(ModelType::from_str("gpt_image_1p5").unwrap(), ModelType::GptImage1p5); + assert_eq!(ModelType::from_str("grok_image").unwrap(), ModelType::GrokImage); + assert_eq!(ModelType::from_str("recraft_3").unwrap(), ModelType::Recraft3); + assert_eq!(ModelType::from_str("seededit_3").unwrap(), ModelType::SeedEdit3); + assert_eq!(ModelType::from_str("qwen").unwrap(), ModelType::Qwen); + assert_eq!(ModelType::from_str("qwen_edit_2511_angles").unwrap(), ModelType::QwenEdit2511Angles); + assert_eq!(ModelType::from_str("gemini_25_flash").unwrap(), ModelType::Gemini25Flash); + assert_eq!(ModelType::from_str("nano_banana").unwrap(), ModelType::NanoBanana); + assert_eq!(ModelType::from_str("nano_banana_2").unwrap(), ModelType::NanoBanana2); + assert_eq!(ModelType::from_str("nano_banana_pro").unwrap(), ModelType::NanoBananaPro); + assert_eq!(ModelType::from_str("seedream_4").unwrap(), ModelType::Seedream4); + assert_eq!(ModelType::from_str("seedream_4p5").unwrap(), ModelType::Seedream4p5); + assert_eq!(ModelType::from_str("seedream_5_lite").unwrap(), ModelType::Seedream5Lite); + assert_eq!(ModelType::from_str("midjourney").unwrap(), ModelType::Midjourney); + assert_eq!(ModelType::from_str("midjourney_v6").unwrap(), ModelType::MidjourneyV6); + assert_eq!(ModelType::from_str("midjourney_v6p1").unwrap(), ModelType::MidjourneyV6p1); + assert_eq!(ModelType::from_str("midjourney_v6p1_raw").unwrap(), ModelType::MidjourneyV6p1Raw); + assert_eq!(ModelType::from_str("midjourney_v7").unwrap(), ModelType::MidjourneyV7); + assert_eq!(ModelType::from_str("midjourney_v7_draft").unwrap(), ModelType::MidjourneyV7Draft); + assert_eq!(ModelType::from_str("midjourney_v7_draft_raw").unwrap(), ModelType::MidjourneyV7DraftRaw); + assert_eq!(ModelType::from_str("midjourney_v7_raw").unwrap(), ModelType::MidjourneyV7Raw); + // Video models + assert_eq!(ModelType::from_str("grok_video").unwrap(), ModelType::GrokVideo); + assert_eq!(ModelType::from_str("kling_1p6_pro").unwrap(), ModelType::Kling16Pro); + assert_eq!(ModelType::from_str("kling_2p1_pro").unwrap(), ModelType::Kling21Pro); + assert_eq!(ModelType::from_str("kling_2p1_master").unwrap(), ModelType::Kling21Master); + assert_eq!(ModelType::from_str("kling_2p5_turbo_pro").unwrap(), ModelType::Kling2p5TurboPro); + assert_eq!(ModelType::from_str("kling_2p6_pro").unwrap(), ModelType::Kling2p6Pro); + assert_eq!(ModelType::from_str("kling_3p0_standard").unwrap(), ModelType::Kling3p0Standard); + assert_eq!(ModelType::from_str("kling_3p0_pro").unwrap(), ModelType::Kling3p0Pro); + assert_eq!(ModelType::from_str("seedance_1p0_lite").unwrap(), ModelType::Seedance10Lite); + assert_eq!(ModelType::from_str("seedance_1p0_pro").unwrap(), ModelType::Seedance10Pro); + assert_eq!(ModelType::from_str("seedance_1p5_pro").unwrap(), ModelType::Seedance1p5Pro); + assert_eq!(ModelType::from_str("seedance_2p0").unwrap(), ModelType::Seedance2p0); + assert_eq!(ModelType::from_str("sora_2").unwrap(), ModelType::Sora2); + assert_eq!(ModelType::from_str("sora_2_pro").unwrap(), ModelType::Sora2Pro); + assert_eq!(ModelType::from_str("veo_2").unwrap(), ModelType::Veo2); + assert_eq!(ModelType::from_str("veo_3").unwrap(), ModelType::Veo3); + assert_eq!(ModelType::from_str("veo_3_fast").unwrap(), ModelType::Veo3Fast); + assert_eq!(ModelType::from_str("veo_3p1").unwrap(), ModelType::Veo3p1); + assert_eq!(ModelType::from_str("veo_3p1_fast").unwrap(), ModelType::Veo3p1Fast); + + // 3D Object generation models + assert_eq!(ModelType::from_str("hunyuan_3d_2p0").unwrap(), ModelType::Hunyuan3d2_0); + assert_eq!(ModelType::from_str("hunyuan_3d_2p1").unwrap(), ModelType::Hunyuan3d2_1); + assert_eq!(ModelType::from_str("hunyuan_3d_3").unwrap(), ModelType::Hunyuan3d3); + // Splat generation models (World Labs) + assert_eq!(ModelType::from_str("marble_0p1_mini").unwrap(), ModelType::Marble0p1Mini); + assert_eq!(ModelType::from_str("marble_0p1_plus").unwrap(), ModelType::Marble0p1Plus); + } + + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip() { + use strum::IntoEnumIterator; + for variant in ModelType::iter() { + // Test to_str(), from_str(), Display, and Debug. + assert_eq!(variant, ModelType::from_str(variant.to_str()).unwrap()); + assert_eq!(variant, ModelType::from_str(&format!("{}", variant)).unwrap()); + assert_eq!(variant, ModelType::from_str(&format!("{:?}", variant)).unwrap()); + } + } + + #[test] + fn serialized_length_ok_for_database() { + use strum::IntoEnumIterator; + const MAX_LENGTH : usize = 24; + for variant in ModelType::iter() { + let serialized = variant.to_str(); + assert!(serialized.len() > 0, "variant {:?} is too short", variant); + assert!(serialized.len() <= MAX_LENGTH, "variant {:?} is too long", variant); + } + } + } +} diff --git a/crates/schema/public/enums_db/src/common/payments_namespace.rs b/crates/schema/public/enums_db/src/common/payments_namespace.rs new file mode 100644 index 0000000000..a0a16cd627 --- /dev/null +++ b/crates/schema/public/enums_db/src/common/payments_namespace.rs @@ -0,0 +1,92 @@ +use strum::EnumCount; +use strum::EnumIter; + +/// NB: This will be used by a variety of tables (MySQL and sqlite)! +/// Keep the max length to 16 characters. +#[derive(Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd, Serialize, Deserialize, EnumIter, EnumCount)] +#[serde(rename_all = "snake_case")] +pub enum PaymentsNamespace { + #[serde(rename = "artcraft")] + Artcraft, + #[serde(rename = "fakeyou")] + FakeYou, +} + +impl_enum_display_and_debug_using_to_str!(PaymentsNamespace); +impl_mysql_enum_coders!(PaymentsNamespace); +impl_mysql_from_row!(PaymentsNamespace); + +// NB: We can derive `sqlx::Type` instead of using `impl_mysql_enum_coders` + +impl PaymentsNamespace { + pub const fn to_str(&self) -> &'static str { + match self { + Self::Artcraft => "artcraft", + Self::FakeYou => "fakeyou", + } + } + + pub fn from_str(s: &str) -> Result { + match s { + "artcraft" => Ok(Self::Artcraft), + "fakeyou" => Ok(Self::FakeYou), + _ => Err(format!("invalid subscription_namespace: {:?}", s)), + } + } + +} + +#[cfg(test)] +mod tests { + use enums_shared::test_helpers::assert_serialization; + use super::PaymentsNamespace; + + mod explicit_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(PaymentsNamespace::Artcraft, "artcraft"); + assert_serialization(PaymentsNamespace::FakeYou, "fakeyou"); + } + + #[test] + fn to_str() { + assert_eq!(PaymentsNamespace::Artcraft.to_str(), "artcraft"); + assert_eq!(PaymentsNamespace::FakeYou.to_str(), "fakeyou"); + } + + #[test] + fn from_str() { + assert_eq!(PaymentsNamespace::from_str("artcraft").unwrap(), PaymentsNamespace::Artcraft); + assert_eq!(PaymentsNamespace::from_str("fakeyou").unwrap(), PaymentsNamespace::FakeYou); + } + + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip() { + use strum::IntoEnumIterator; + for variant in PaymentsNamespace::iter() { + // Test to_str(), from_str(), Display, and Debug. + assert_eq!(variant, PaymentsNamespace::from_str(variant.to_str()).unwrap()); + assert_eq!(variant, PaymentsNamespace::from_str(&format!("{}", variant)).unwrap()); + assert_eq!(variant, PaymentsNamespace::from_str(&format!("{:?}", variant)).unwrap()); + } + } + + #[test] + fn serialized_length_ok_for_database() { + use strum::IntoEnumIterator; + const MAX_LENGTH : usize = 16; + for variant in PaymentsNamespace::iter() { + let serialized = variant.to_str(); + assert!(serialized.len() > 0, "variant {:?} is too short", variant); + assert!(serialized.len() <= MAX_LENGTH, "variant {:?} is too long", variant); + } + } + } +} diff --git a/crates/schema/public/enums_db/src/common/sqlite/awaitable_job_status.rs b/crates/schema/public/enums_db/src/common/sqlite/awaitable_job_status.rs new file mode 100644 index 0000000000..3a55f38e93 --- /dev/null +++ b/crates/schema/public/enums_db/src/common/sqlite/awaitable_job_status.rs @@ -0,0 +1,135 @@ +use serde::Deserialize; +use serde::Serialize; +use strum::EnumCount; +use strum::EnumIter; + +/// Used in the following SqLite tables and columns: +/// `web_scraping_targets` . `maybe_skip_reason`. +#[derive(Clone, Copy, Eq, PartialEq, Hash, Deserialize, Serialize, EnumIter, EnumCount)] +pub enum AwaitableJobStatus { + #[serde(rename = "not_ready")] + NotReady, + + #[serde(rename = "ready_waiting")] + ReadyWaiting, + + #[serde(rename = "processing")] + Processing, + + #[serde(rename = "retryably_failed")] + RetryablyFailed, + + #[serde(rename = "permanently_failed")] + PermanentlyFailed, + + #[serde(rename = "skipped")] + Skipped, + + #[serde(rename = "done")] + Done, +} + +// TODO(bt, 2023-02-08): This desperately needs Sqlite integration tests! +impl_enum_display_and_debug_using_to_str!(AwaitableJobStatus); +impl_sqlite_enum_coders!(AwaitableJobStatus); + +/// NB: Legacy API for older code. +impl AwaitableJobStatus { + pub fn to_str(&self) -> &'static str { + match self { + Self::NotReady => "not_ready", + Self::ReadyWaiting => "ready_waiting", + Self::Processing => "processing", + Self::RetryablyFailed => "retryably_failed", + Self::PermanentlyFailed => "permanently_failed", + Self::Skipped => "skipped", + Self::Done => "done", + } + } + + pub fn from_str(value: &str) -> Result { + match value { + "not_ready" => Ok(Self::NotReady), + "ready_waiting" => Ok(Self::ReadyWaiting), + "processing" => Ok(Self::Processing), + "retryably_failed" => Ok(Self::RetryablyFailed), + "permanently_failed" => Ok(Self::PermanentlyFailed), + "skipped" => Ok(Self::Skipped), + "done" => Ok(Self::Done), + _ => Err(format!("invalid value: {:?}", value)), + } + } +} + +#[cfg(test)] +mod tests { + use super::AwaitableJobStatus; + use enums_shared::test_helpers::assert_serialization; + + mod serde { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(AwaitableJobStatus::NotReady, "not_ready"); + assert_serialization(AwaitableJobStatus::ReadyWaiting, "ready_waiting"); + assert_serialization(AwaitableJobStatus::Processing, "processing"); + assert_serialization(AwaitableJobStatus::RetryablyFailed, "retryably_failed"); + assert_serialization(AwaitableJobStatus::PermanentlyFailed, "permanently_failed"); + assert_serialization(AwaitableJobStatus::Skipped, "skipped"); + assert_serialization(AwaitableJobStatus::Done, "done"); + } + } + + mod impl_methods { + use super::*; + + #[test] + fn test_to_str() { + assert_eq!(AwaitableJobStatus::NotReady.to_str(), "not_ready"); + assert_eq!(AwaitableJobStatus::ReadyWaiting.to_str(), "ready_waiting"); + assert_eq!(AwaitableJobStatus::Processing.to_str(), "processing"); + assert_eq!(AwaitableJobStatus::RetryablyFailed.to_str(), "retryably_failed"); + assert_eq!(AwaitableJobStatus::PermanentlyFailed.to_str(), "permanently_failed"); + assert_eq!(AwaitableJobStatus::Skipped.to_str(), "skipped"); + assert_eq!(AwaitableJobStatus::Done.to_str(), "done"); + } + + #[test] + fn test_from_str() { + assert_eq!(AwaitableJobStatus::from_str("not_ready").unwrap(), AwaitableJobStatus::NotReady); + assert_eq!(AwaitableJobStatus::from_str("ready_waiting").unwrap(), AwaitableJobStatus::ReadyWaiting); + assert_eq!(AwaitableJobStatus::from_str("processing").unwrap(), AwaitableJobStatus::Processing); + assert_eq!(AwaitableJobStatus::from_str("retryably_failed").unwrap(), AwaitableJobStatus::RetryablyFailed); + assert_eq!(AwaitableJobStatus::from_str("permanently_failed").unwrap(), AwaitableJobStatus::PermanentlyFailed); + assert_eq!(AwaitableJobStatus::from_str("skipped").unwrap(), AwaitableJobStatus::Skipped); + assert_eq!(AwaitableJobStatus::from_str("done").unwrap(), AwaitableJobStatus::Done); + assert!(AwaitableJobStatus::from_str("foo").is_err()); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip() { + use strum::IntoEnumIterator; + for variant in AwaitableJobStatus::iter() { + assert_eq!(variant, AwaitableJobStatus::from_str(variant.to_str()).unwrap()); + assert_eq!(variant, AwaitableJobStatus::from_str(&format!("{}", variant)).unwrap()); + assert_eq!(variant, AwaitableJobStatus::from_str(&format!("{:?}", variant)).unwrap()); + } + } + + #[test] + fn serialized_length_ok_for_database() { + const MAX_LENGTH: usize = 32; // TODO(bt): Confirm database column width, then remove this comment. + use strum::IntoEnumIterator; + for variant in AwaitableJobStatus::iter() { + let serialized = variant.to_str(); + assert!(!serialized.is_empty(), "variant {:?} is too short", variant); + assert!(serialized.len() <= MAX_LENGTH, "variant {:?} is too long", variant); + } + } + } +} diff --git a/crates/schema/public/enums_db/src/common/sqlite/chatbot_job_status.rs b/crates/schema/public/enums_db/src/common/sqlite/chatbot_job_status.rs new file mode 100644 index 0000000000..67a9cdd26a --- /dev/null +++ b/crates/schema/public/enums_db/src/common/sqlite/chatbot_job_status.rs @@ -0,0 +1,118 @@ +use serde::Deserialize; +use serde::Serialize; +use strum::EnumCount; +use strum::EnumIter; + +/// Used in the SqLite `web_scraping_targets` table in a `TEXT` field named `scraping_status`. +#[derive(Clone, Copy, Eq, PartialEq, Hash, Deserialize, Serialize, EnumIter, EnumCount)] +pub enum ChatbotJobStatus { + #[serde(rename = "new")] + New, + + #[serde(rename = "skipped")] + Skipped, + + #[serde(rename = "failed")] + Failed, + + #[serde(rename = "permanently_failed")] + PermanentlyFailed, + + #[serde(rename = "success")] + Success, +} + +// TODO(bt, 2023-02-10): This desperately needs Sqlite integration tests! +impl_enum_display_and_debug_using_to_str!(ChatbotJobStatus); +impl_sqlite_enum_coders!(ChatbotJobStatus); + +/// NB: Legacy API for older code. +impl ChatbotJobStatus { + pub fn to_str(&self) -> &'static str { + match self { + Self::New => "new", + Self::Skipped => "skipped", + Self::Failed => "failed", + Self::PermanentlyFailed => "permanently_failed", + Self::Success => "success", + } + } + + pub fn from_str(value: &str) -> Result { + match value { + "new" => Ok(Self::New), + "skipped" => Ok(Self::Skipped), + "failed" => Ok(Self::Failed), + "permanently_failed" => Ok(Self::PermanentlyFailed), + "success" => Ok(Self::Success), + _ => Err(format!("invalid value: {:?}", value)), + } + } +} + +#[cfg(test)] +mod tests { + use super::ChatbotJobStatus; + use enums_shared::test_helpers::assert_serialization; + + mod serde { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(ChatbotJobStatus::New, "new"); + assert_serialization(ChatbotJobStatus::Skipped, "skipped"); + assert_serialization(ChatbotJobStatus::Failed, "failed"); + assert_serialization(ChatbotJobStatus::PermanentlyFailed, "permanently_failed"); + assert_serialization(ChatbotJobStatus::Success, "success"); + } + } + + mod impl_methods { + use super::*; + + #[test] + fn test_to_str() { + assert_eq!(ChatbotJobStatus::New.to_str(), "new"); + assert_eq!(ChatbotJobStatus::Skipped.to_str(), "skipped"); + assert_eq!(ChatbotJobStatus::Failed.to_str(), "failed"); + assert_eq!(ChatbotJobStatus::PermanentlyFailed.to_str(), "permanently_failed"); + assert_eq!(ChatbotJobStatus::Success.to_str(), "success"); + } + + #[test] + fn test_from_str() { + assert_eq!(ChatbotJobStatus::from_str("new").unwrap(), ChatbotJobStatus::New); + assert_eq!(ChatbotJobStatus::from_str("skipped").unwrap(), ChatbotJobStatus::Skipped); + assert_eq!(ChatbotJobStatus::from_str("failed").unwrap(), ChatbotJobStatus::Failed); + assert_eq!(ChatbotJobStatus::from_str("permanently_failed").unwrap(), ChatbotJobStatus::PermanentlyFailed); + assert_eq!(ChatbotJobStatus::from_str("success").unwrap(), ChatbotJobStatus::Success); + assert!(ChatbotJobStatus::from_str("foo").is_err()); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip() { + use strum::IntoEnumIterator; + for variant in ChatbotJobStatus::iter() { + assert_eq!(variant, ChatbotJobStatus::from_str(variant.to_str()).unwrap()); + assert_eq!(variant, ChatbotJobStatus::from_str(&format!("{}", variant)).unwrap()); + assert_eq!(variant, ChatbotJobStatus::from_str(&format!("{:?}", variant)).unwrap()); + } + } + + #[test] + fn serialized_length_ok_for_database() { + const MAX_LENGTH: usize = 32; // TODO(bt): Confirm database column width, then remove this comment. + use strum::IntoEnumIterator; + for variant in ChatbotJobStatus::iter() { + let serialized = variant.to_str(); + assert!(!serialized.is_empty(), "variant {:?} is too short", variant); + assert!(serialized.len() <= MAX_LENGTH, "variant {:?} is too long", variant); + } + } + } +} diff --git a/crates/schema/public/enums_db/src/common/sqlite/mod.rs b/crates/schema/public/enums_db/src/common/sqlite/mod.rs new file mode 100644 index 0000000000..7659a1e044 --- /dev/null +++ b/crates/schema/public/enums_db/src/common/sqlite/mod.rs @@ -0,0 +1,4 @@ +pub mod awaitable_job_status; +pub mod chatbot_job_status; +pub mod skip_reason; +pub mod web_content_type; diff --git a/crates/schema/public/enums_db/src/common/sqlite/skip_reason.rs b/crates/schema/public/enums_db/src/common/sqlite/skip_reason.rs new file mode 100644 index 0000000000..e1421b1190 --- /dev/null +++ b/crates/schema/public/enums_db/src/common/sqlite/skip_reason.rs @@ -0,0 +1,127 @@ +use serde::Deserialize; +use serde::Serialize; +use strum::EnumCount; +use strum::EnumIter; + +/// Used in the following SqLite tables and columns: +/// `web_scraping_targets` . `maybe_skip_reason`. +#[derive(Clone, Copy, Eq, PartialEq, Hash, Deserialize, Serialize, EnumIter, EnumCount)] +pub enum SkipReason { + #[serde(rename = "empty_content")] + EmptyContent, + + #[serde(rename = "advertisement")] + Advertisement, + + #[serde(rename = "video_content")] + VideoContent, + + #[serde(rename = "filtered_topic")] + FilteredTopic, + + #[serde(rename = "filtered_topic_politics")] + FilteredTopicPolitics, + + #[serde(rename = "nobody_cares")] + NobodyCares, +} + +// TODO(bt, 2023-02-08): This desperately needs Sqlite integration tests! +impl_enum_display_and_debug_using_to_str!(SkipReason); +impl_sqlite_enum_coders!(SkipReason); + +/// NB: Legacy API for older code. +impl SkipReason { + pub fn to_str(&self) -> &'static str { + match self { + Self::EmptyContent => "empty_content", + Self::Advertisement => "advertisement", + Self::VideoContent => "video_content", + Self::FilteredTopic => "filtered_topic", + Self::FilteredTopicPolitics => "filtered_topic_politics", + Self::NobodyCares => "nobody_cares", + } + } + + pub fn from_str(value: &str) -> Result { + match value { + "empty_content" => Ok(Self::EmptyContent), + "advertisement" => Ok(Self::Advertisement), + "video_content" => Ok(Self::VideoContent), + "filtered_topic" => Ok(Self::FilteredTopic), + "filtered_topic_politics" => Ok(Self::FilteredTopicPolitics), + "nobody_cares" => Ok(Self::NobodyCares), + _ => Err(format!("invalid value: {:?}", value)), + } + } +} + +#[cfg(test)] +mod tests { + use super::SkipReason; + use enums_shared::test_helpers::assert_serialization; + + mod serde { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(SkipReason::EmptyContent, "empty_content"); + assert_serialization(SkipReason::Advertisement, "advertisement"); + assert_serialization(SkipReason::VideoContent, "video_content"); + assert_serialization(SkipReason::FilteredTopic, "filtered_topic"); + assert_serialization(SkipReason::FilteredTopicPolitics, "filtered_topic_politics"); + assert_serialization(SkipReason::NobodyCares, "nobody_cares"); + } + } + + mod impl_methods { + use super::*; + + #[test] + fn test_to_str() { + assert_eq!(SkipReason::EmptyContent.to_str(), "empty_content"); + assert_eq!(SkipReason::Advertisement.to_str(), "advertisement"); + assert_eq!(SkipReason::VideoContent.to_str(), "video_content"); + assert_eq!(SkipReason::FilteredTopic.to_str(), "filtered_topic"); + assert_eq!(SkipReason::FilteredTopicPolitics.to_str(), "filtered_topic_politics"); + assert_eq!(SkipReason::NobodyCares.to_str(), "nobody_cares"); + } + + #[test] + fn test_from_str() { + assert_eq!(SkipReason::from_str("empty_content").unwrap(), SkipReason::EmptyContent); + assert_eq!(SkipReason::from_str("advertisement").unwrap(), SkipReason::Advertisement); + assert_eq!(SkipReason::from_str("video_content").unwrap(), SkipReason::VideoContent); + assert_eq!(SkipReason::from_str("filtered_topic").unwrap(), SkipReason::FilteredTopic); + assert_eq!(SkipReason::from_str("filtered_topic_politics").unwrap(), SkipReason::FilteredTopicPolitics); + assert_eq!(SkipReason::from_str("nobody_cares").unwrap(), SkipReason::NobodyCares); + assert!(SkipReason::from_str("foo").is_err()); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip() { + use strum::IntoEnumIterator; + for variant in SkipReason::iter() { + assert_eq!(variant, SkipReason::from_str(variant.to_str()).unwrap()); + assert_eq!(variant, SkipReason::from_str(&format!("{}", variant)).unwrap()); + assert_eq!(variant, SkipReason::from_str(&format!("{:?}", variant)).unwrap()); + } + } + + #[test] + fn serialized_length_ok_for_database() { + const MAX_LENGTH: usize = 32; // TODO(bt): Confirm database column width, then remove this comment. + use strum::IntoEnumIterator; + for variant in SkipReason::iter() { + let serialized = variant.to_str(); + assert!(!serialized.is_empty(), "variant {:?} is too short", variant); + assert!(serialized.len() <= MAX_LENGTH, "variant {:?} is too long", variant); + } + } + } +} diff --git a/crates/schema/public/enums_db/src/common/sqlite/web_content_type.rs b/crates/schema/public/enums_db/src/common/sqlite/web_content_type.rs new file mode 100644 index 0000000000..acbb4aa132 --- /dev/null +++ b/crates/schema/public/enums_db/src/common/sqlite/web_content_type.rs @@ -0,0 +1,160 @@ +use serde::Deserialize; +use serde::Serialize; +use strum::EnumCount; +use strum::EnumIter; + +/// Used in the SqLite `web_scraping_targets` table in a `TEXT` field named `web_content_type`. +/// Used in the SqLite `news_story_productions` table in a `TEXT` field named `web_content_type`. +/// Used in the SqLite `news_stories` table in a `TEXT` field named `web_content_type`. +#[derive(Clone, Copy, Eq, PartialEq, Hash, Deserialize, Serialize, EnumIter, EnumCount)] +pub enum WebContentType { + #[serde(rename = "cbs_news_article")] + CbsNewsArticle, + + #[serde(rename = "cnn_article")] + CnnArticle, + + #[serde(rename = "gizmodo_article")] + GizmodoArticle, + + #[serde(rename = "hacker_news_thread")] + HackerNewsThread, + + #[serde(rename = "kotaku_article")] + KotakuArticle, + + #[serde(rename = "reddit_thread")] + RedditThread, + + #[serde(rename = "slashdot_article")] + SlashdotArticle, + + #[serde(rename = "substack_post")] + SubstackPost, + + #[serde(rename = "techcrunch_article")] + TechCrunchArticle, + + #[serde(rename = "the_guardian_article")] + TheGuardianArticle, +} + +// TODO(bt, 2023-01-17): This desperately needs MySQL integration tests! +impl_enum_display_and_debug_using_to_str!(WebContentType); +impl_sqlite_enum_coders!(WebContentType); + +/// NB: Legacy API for older code. +impl WebContentType { + pub fn to_str(&self) -> &'static str { + match self { + Self::CbsNewsArticle => "cbs_news_article", + Self::CnnArticle => "cnn_article", + Self::GizmodoArticle => "gizmodo_article", + Self::HackerNewsThread => "hacker_news_thread", + Self::KotakuArticle => "kotaku_article", + Self::RedditThread => "reddit_thread", + Self::SlashdotArticle => "slashdot_article", + Self::SubstackPost => "substack_post", + Self::TechCrunchArticle => "techcrunch_article", + Self::TheGuardianArticle => "the_guardian_article", + } + } + + pub fn from_str(value: &str) -> Result { + match value { + "cbs_news_article" => Ok(Self::CbsNewsArticle), + "cnn_article" => Ok(Self::CnnArticle), + "gizmodo_article" => Ok(Self::GizmodoArticle), + "hacker_news_thread" => Ok(Self::HackerNewsThread), + "kotaku_article" => Ok(Self::KotakuArticle), + "reddit_thread" => Ok(Self::RedditThread), + "slashdot_article" => Ok(Self::SlashdotArticle), + "substack_post" => Ok(Self::SubstackPost), + "techcrunch_article" => Ok(Self::TechCrunchArticle), + "the_guardian_article" => Ok(Self::TheGuardianArticle), + _ => Err(format!("invalid value: {:?}", value)), + } + } +} + +#[cfg(test)] +mod tests { + use super::WebContentType; + use enums_shared::test_helpers::assert_serialization; + + mod serde { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(WebContentType::CbsNewsArticle, "cbs_news_article"); + assert_serialization(WebContentType::CnnArticle, "cnn_article"); + assert_serialization(WebContentType::GizmodoArticle, "gizmodo_article"); + assert_serialization(WebContentType::HackerNewsThread, "hacker_news_thread"); + assert_serialization(WebContentType::KotakuArticle, "kotaku_article"); + assert_serialization(WebContentType::RedditThread, "reddit_thread"); + assert_serialization(WebContentType::SlashdotArticle, "slashdot_article"); + assert_serialization(WebContentType::SubstackPost, "substack_post"); + assert_serialization(WebContentType::TechCrunchArticle, "techcrunch_article"); + assert_serialization(WebContentType::TheGuardianArticle, "the_guardian_article"); + } + } + + mod impl_methods { + use super::*; + + #[test] + fn test_to_str() { + assert_eq!(WebContentType::CbsNewsArticle.to_str(), "cbs_news_article"); + assert_eq!(WebContentType::CnnArticle.to_str(), "cnn_article"); + assert_eq!(WebContentType::GizmodoArticle.to_str(), "gizmodo_article"); + assert_eq!(WebContentType::HackerNewsThread.to_str(), "hacker_news_thread"); + assert_eq!(WebContentType::KotakuArticle.to_str(), "kotaku_article"); + assert_eq!(WebContentType::RedditThread.to_str(), "reddit_thread"); + assert_eq!(WebContentType::SlashdotArticle.to_str(), "slashdot_article"); + assert_eq!(WebContentType::SubstackPost.to_str(), "substack_post"); + assert_eq!(WebContentType::TechCrunchArticle.to_str(), "techcrunch_article"); + assert_eq!(WebContentType::TheGuardianArticle.to_str(), "the_guardian_article"); + } + + #[test] + fn test_from_str() { + assert_eq!(WebContentType::from_str("cbs_news_article").unwrap(), WebContentType::CbsNewsArticle); + assert_eq!(WebContentType::from_str("cnn_article").unwrap(), WebContentType::CnnArticle); + assert_eq!(WebContentType::from_str("gizmodo_article").unwrap(), WebContentType::GizmodoArticle); + assert_eq!(WebContentType::from_str("hacker_news_thread").unwrap(), WebContentType::HackerNewsThread); + assert_eq!(WebContentType::from_str("kotaku_article").unwrap(), WebContentType::KotakuArticle); + assert_eq!(WebContentType::from_str("reddit_thread").unwrap(), WebContentType::RedditThread); + assert_eq!(WebContentType::from_str("slashdot_article").unwrap(), WebContentType::SlashdotArticle); + assert_eq!(WebContentType::from_str("substack_post").unwrap(), WebContentType::SubstackPost); + assert_eq!(WebContentType::from_str("techcrunch_article").unwrap(), WebContentType::TechCrunchArticle); + assert_eq!(WebContentType::from_str("the_guardian_article").unwrap(), WebContentType::TheGuardianArticle); + assert!(WebContentType::from_str("foo").is_err()); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip() { + use strum::IntoEnumIterator; + for variant in WebContentType::iter() { + assert_eq!(variant, WebContentType::from_str(variant.to_str()).unwrap()); + assert_eq!(variant, WebContentType::from_str(&format!("{}", variant)).unwrap()); + assert_eq!(variant, WebContentType::from_str(&format!("{:?}", variant)).unwrap()); + } + } + + #[test] + fn serialized_length_ok_for_database() { + const MAX_LENGTH: usize = 32; // TODO(bt): Confirm database column width, then remove this comment. + use strum::IntoEnumIterator; + for variant in WebContentType::iter() { + let serialized = variant.to_str(); + assert!(!serialized.is_empty(), "variant {:?} is too short", variant); + assert!(serialized.len() <= MAX_LENGTH, "variant {:?} is too long", variant); + } + } + } +} diff --git a/crates/schema/public/enums_db/src/common/stripe_subscription_status.rs b/crates/schema/public/enums_db/src/common/stripe_subscription_status.rs new file mode 100644 index 0000000000..27ecc220ec --- /dev/null +++ b/crates/schema/public/enums_db/src/common/stripe_subscription_status.rs @@ -0,0 +1,182 @@ +//! This is copied from the stripe crate's `SubscriptionStatus`, +//! and then from `reusable_types`. + +// There are three changes from the source create: +// - Renamed the struct from SubscriptionStatus to StripeSubscriptionStatus +// - Added StripeSubscriptionStatus::from_str() +// - Added derive sqlx::Type and sqlx(rename_all) +// - Added Deref impl +// - Added tests +// +// Then, moving into enums: +// - Changed derives +// - as_st() -> to_str() (gross! but convention as of now...) +// - from_str() : changed error from string to EnumsError +// - Added all_variants() +// - commented out all other impls. +// + +use enums_shared::error::enums_error::EnumsError; +use strum::EnumCount; +use strum::EnumIter; + +// NB: Added "sqlx::Type". +#[derive(Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd, Serialize, Deserialize, EnumIter, EnumCount)] +#[serde(rename_all = "snake_case")] +pub enum StripeSubscriptionStatus { + Active, + Canceled, + Incomplete, + IncompleteExpired, + PastDue, + Trialing, + Unpaid, + Paused, +} + +impl_enum_display_and_debug_using_to_str!(StripeSubscriptionStatus); +impl_mysql_enum_coders!(StripeSubscriptionStatus); +impl_mysql_from_row!(StripeSubscriptionStatus); + +impl StripeSubscriptionStatus { + pub fn to_str(self) -> &'static str { + match self { + Self::Active => "active", + Self::Canceled => "canceled", + Self::Incomplete => "incomplete", + Self::IncompleteExpired => "incomplete_expired", + Self::PastDue => "past_due", + Self::Trialing => "trialing", + Self::Unpaid => "unpaid", + Self::Paused => "paused" + } + } + + pub fn from_str(value: &str) -> Result { + match value { + "active" => Ok(Self::Active), + "canceled" => Ok(Self::Canceled), + "incomplete" => Ok(Self::Incomplete), + "incomplete_expired" => Ok(Self::IncompleteExpired), + "past_due" => Ok(Self::PastDue), + "trialing" => Ok(Self::Trialing), + "unpaid" => Ok(Self::Unpaid), + "paused" => Ok(Self::Paused), + _ => Err(EnumsError::CouldNotConvertFromString(value.to_string())), + } + } + +} + +//impl AsRef for StripeSubscriptionStatus { +// fn as_ref(&self) -> &str { +// self.as_str() +// } +//} +// +//// NB: Added by us. +//impl std::ops::Deref for StripeSubscriptionStatus { +// type Target = str; +// +// fn deref(&self) -> &Self::Target { +// self.as_str() +// } +//} +// +//impl std::fmt::Display for StripeSubscriptionStatus { +// fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { +// self.as_str().fmt(f) +// } +//} +// +//impl std::default::Default for StripeSubscriptionStatus { +// fn default() -> Self { +// Self::Active +// } +//} + +#[cfg(test)] +mod tests { + use super::StripeSubscriptionStatus; + use enums_shared::error::enums_error::EnumsError; + use enums_shared::test_helpers::assert_serialization; + + mod explicit_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(StripeSubscriptionStatus::Active, "active"); + assert_serialization(StripeSubscriptionStatus::Canceled, "canceled"); + assert_serialization(StripeSubscriptionStatus::Incomplete, "incomplete"); + assert_serialization(StripeSubscriptionStatus::IncompleteExpired, "incomplete_expired"); + assert_serialization(StripeSubscriptionStatus::PastDue, "past_due"); + assert_serialization(StripeSubscriptionStatus::Trialing, "trialing"); + assert_serialization(StripeSubscriptionStatus::Unpaid, "unpaid"); + assert_serialization(StripeSubscriptionStatus::Paused, "paused"); + } + + #[test] + fn to_str() { + assert_eq!(StripeSubscriptionStatus::Active.to_str(), "active"); + assert_eq!(StripeSubscriptionStatus::Canceled.to_str(), "canceled"); + assert_eq!(StripeSubscriptionStatus::Incomplete.to_str(), "incomplete"); + assert_eq!(StripeSubscriptionStatus::IncompleteExpired.to_str(), "incomplete_expired"); + assert_eq!(StripeSubscriptionStatus::PastDue.to_str(), "past_due"); + assert_eq!(StripeSubscriptionStatus::Trialing.to_str(), "trialing"); + assert_eq!(StripeSubscriptionStatus::Unpaid.to_str(), "unpaid"); + assert_eq!(StripeSubscriptionStatus::Paused.to_str(), "paused"); + } + + #[test] + fn from_str() { + assert_eq!(StripeSubscriptionStatus::from_str("active").unwrap(), StripeSubscriptionStatus::Active); + assert_eq!(StripeSubscriptionStatus::from_str("canceled").unwrap(), StripeSubscriptionStatus::Canceled); + assert_eq!(StripeSubscriptionStatus::from_str("incomplete").unwrap(), StripeSubscriptionStatus::Incomplete); + assert_eq!(StripeSubscriptionStatus::from_str("incomplete_expired").unwrap(), StripeSubscriptionStatus::IncompleteExpired); + assert_eq!(StripeSubscriptionStatus::from_str("past_due").unwrap(), StripeSubscriptionStatus::PastDue); + assert_eq!(StripeSubscriptionStatus::from_str("trialing").unwrap(), StripeSubscriptionStatus::Trialing); + assert_eq!(StripeSubscriptionStatus::from_str("unpaid").unwrap(), StripeSubscriptionStatus::Unpaid); + assert_eq!(StripeSubscriptionStatus::from_str("paused").unwrap(), StripeSubscriptionStatus::Paused); + } + + #[test] + fn from_str_err() { + let result = StripeSubscriptionStatus::from_str("asdf"); + assert!(result.is_err()); + if let Err(EnumsError::CouldNotConvertFromString(value)) = result { + assert_eq!(value, "asdf"); + } else { + panic!("Expected EnumsError::CouldNotConvertFromString"); + } + } + + } + + mod mechanical_checks { + use super::StripeSubscriptionStatus; + + #[test] + fn round_trip() { + use strum::IntoEnumIterator; + for variant in StripeSubscriptionStatus::iter() { + // Test to_str(), from_str(), Display, and Debug. + assert_eq!(variant, StripeSubscriptionStatus::from_str(variant.to_str()).unwrap()); + assert_eq!(variant, StripeSubscriptionStatus::from_str(&format!("{}", variant)).unwrap()); + assert_eq!(variant, StripeSubscriptionStatus::from_str(&format!("{:?}", variant)).unwrap()); + } + } + + #[test] + fn serialized_length_ok_for_database() { + use strum::IntoEnumIterator; + const MAX_LENGTH : usize = 32; + for variant in StripeSubscriptionStatus::iter() { + let serialized = variant.to_str(); + assert!(serialized.len() > 0, "variant {:?} is too short", variant); + assert!(serialized.len() <= MAX_LENGTH, "variant {:?} is too long", variant); + } + } + } +} + diff --git a/crates/schema/public/enums_db/src/common/view_as.rs b/crates/schema/public/enums_db/src/common/view_as.rs new file mode 100644 index 0000000000..8082ac1f35 --- /dev/null +++ b/crates/schema/public/enums_db/src/common/view_as.rs @@ -0,0 +1,173 @@ +use strum::EnumCount; +use strum::EnumIter; + +#[derive(Clone, Copy, Eq, PartialEq, Deserialize, Serialize, EnumIter, EnumCount)] +#[derive(sqlx::Type)] +#[sqlx(rename_all = "snake_case")] +#[serde(rename_all = "snake_case")] +pub enum ViewAs { + /// Public entities are able to be listed in public lists. + /// It does not mean that they necessarily will be (eg. they could be "mod unapproved" or deleted). + Author, + /// Hidden entities are not shown in public lists, but the URL to them may be given out freely. + /// They are available to non-logged-in users as long as they have the URL. + Moderator, + /// Private entities should only be available to the creator, a list of approved users, and + /// website moderation staff. + AnotherUser, +} + +impl_enum_display_and_debug_using_to_str!(ViewAs); +impl_mysql_from_row!(ViewAs); + +impl Default for ViewAs { + fn default() -> Self { Self::AnotherUser } +} + +/// NB: Legacy API for older code. +impl ViewAs { + pub fn to_str(&self) -> &'static str { + match self { + Self::Author => "author", + Self::Moderator => "moderator", + Self::AnotherUser => "another_user", + } + } + + pub fn from_str(value: &str) -> Result { + match value { + "author" => Ok(Self::Author), + "moderator" => Ok(Self::Moderator), + "another_user" => Ok(Self::AnotherUser), + _ => Err(format!("invalid value: {:?}", value)), + } + } +} + +#[cfg(test)] +mod tests { + use super::ViewAs; + use enums_shared::test_helpers::assert_serialization; + + #[test] + fn test_default() { + assert_eq!(ViewAs::default(), ViewAs::AnotherUser); + + } + + #[test] + fn test_serialization() { + assert_serialization(ViewAs::Author, "author"); + assert_serialization(ViewAs::Moderator, "moderator"); + assert_serialization(ViewAs::AnotherUser, "another_user"); + } + + #[test] + fn test_to_str() { + assert_eq!(ViewAs::Author.to_str(), "author"); + assert_eq!(ViewAs::Moderator.to_str(), "moderator"); + assert_eq!(ViewAs::AnotherUser.to_str(), "another_user"); + } + + #[test] + fn test_from_str() { + assert_eq!(ViewAs::from_str("author").unwrap(), ViewAs::Author); + assert_eq!(ViewAs::from_str("moderator").unwrap(), ViewAs::Moderator); + assert_eq!(ViewAs::from_str("another_user").unwrap(), ViewAs::AnotherUser); + assert!(ViewAs::from_str("foo").is_err()); + } + + mod traits { + use super::ViewAs; + + #[test] + fn display() { + let view_as = ViewAs::Moderator; + assert_eq!(format!("{}", view_as), "moderator".to_string()); + } + + #[test] + fn debug() { + let view_as = ViewAs::Moderator; + assert_eq!(format!("{:?}", view_as), "moderator".to_string()); + } + } + + #[derive(Serialize, Deserialize, PartialEq, Debug)] + struct CompositeType { + view_as: ViewAs, + string: String, + } + + mod serde_serialization { + use super::ViewAs; + + use super::CompositeType; + + #[test] + fn serialize() { + let expected = "\"author\"".to_string(); // NB: Quoted + + assert_eq!(expected, serde_json::to_string(&ViewAs::Author).unwrap()); + + // Just to show this serializes the same as a string + assert_eq!(expected, serde_json::to_string("author").unwrap()); + } + + #[test] + fn nested_serialize() { + let value = CompositeType { view_as: ViewAs::Moderator, string: "bar".to_string() }; + let expected = r#"{"view_as":"moderator","string":"bar"}"#.to_string(); + assert_eq!(expected, serde_json::to_string(&value).unwrap()); + } + } + + mod serde_deserialization { + use super::ViewAs; + + use super::CompositeType; + + #[test] + fn deserialize() { + let payload = "\"another_user\""; // NB: Quoted + let value: ViewAs = serde_json::from_str(payload).unwrap(); + assert_eq!(value, ViewAs::AnotherUser); + } + + #[test] + fn nested_deserialize() { + let payload = r#"{"view_as":"another_user","string":"bar"}"#.to_string(); + let expected = CompositeType { + view_as: ViewAs::AnotherUser, + string: "bar".to_string(), + }; + + assert_eq!(expected, serde_json::from_str::(&payload).unwrap()); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip() { + use strum::IntoEnumIterator; + for variant in ViewAs::iter() { + assert_eq!(variant, ViewAs::from_str(variant.to_str()).unwrap()); + assert_eq!(variant, ViewAs::from_str(&format!("{}", variant)).unwrap()); + assert_eq!(variant, ViewAs::from_str(&format!("{:?}", variant)).unwrap()); + } + } + + #[test] + fn serialized_length_ok_for_database() { + const MAX_LENGTH: usize = 32; // TODO(bt): Confirm database column width, then remove this comment. + use strum::IntoEnumIterator; + for variant in ViewAs::iter() { + let serialized = variant.to_str(); + assert!(!serialized.is_empty(), "variant {:?} is too short", variant); + assert!(serialized.len() <= MAX_LENGTH, "variant {:?} is too long", variant); + } + } + } +} diff --git a/crates/schema/public/enums_db/src/common/visibility.rs b/crates/schema/public/enums_db/src/common/visibility.rs new file mode 100644 index 0000000000..8a338d5e8f --- /dev/null +++ b/crates/schema/public/enums_db/src/common/visibility.rs @@ -0,0 +1,213 @@ +use strum::EnumCount; +use strum::EnumIter; +/// Visibility +/// +/// Used in various database tables (as enums! careful!) and the HTTP API to convey +/// how the associated entity should be made visible to the public. +/// +/// To use this in a query, the query must have type annotations. +/// See: https://www.gitmemory.com/issue/launchbadge/sqlx/1241/847154375 +/// eg. preferred_tts_result_visibility as `preferred_tts_result_visibility: enums::common::visibility::Visibility` +/// +/// See also: https://docs.rs/sqlx/0.4.0-beta.1/sqlx/trait.Type.html +/// +/// *DO NOT CHANGE VALUES WITHOUT A MIGRATION STRATEGY!* + +#[derive(Clone, Copy, Eq, PartialEq, Deserialize, Serialize, EnumIter, EnumCount)] +#[derive(sqlx::Type)] +#[sqlx(rename_all = "lowercase")] +#[serde(rename_all = "lowercase")] +pub enum Visibility { + /// Public entities are able to be listed in public lists. + /// It does not mean that they necessarily will be (eg. they could be "mod unapproved" or deleted). + Public, + /// Hidden entities are not shown in public lists, but the URL to them may be given out freely. + /// They are available to non-logged-in users as long as they have the URL. + Hidden, + /// Private entities should only be available to the creator, a list of approved users, and + /// website moderation staff. + Private, + + // TODO(bt, 2022-12-20): We need a "Shared" option where users can share it with a specified group. + // This should perhaps be its own type, eg. VisibilityV2., so that we don't use it in tables that + // have not yet been migrated to this scheme. +} + +impl_enum_display_and_debug_using_to_str!(Visibility); +impl_mysql_from_row!(Visibility); + +// For reference, here's what the serde implementation might be if manually written. +// This may be useful for designing composite types in the future: +// +// use serde::{Deserializer, Serializer}; +// +// impl serde::Serialize for UserToken { +// fn serialize(&self, serializer: S) -> Result { +// serializer.serialize_str(&self.0) +// } +// } +// +// impl<'de> serde::Deserialize<'de> for UserToken { +// fn deserialize>(d: D) -> Result { +// let s = String::deserialize(d)?; +// Ok(UserToken(s)) +// } +// } + +//impl sqlx::Type for Visibility { +// fn type_info() -> sqlx_core::database::TypeInfo { +// todo!() +// } +//} + +impl Default for Visibility { + fn default() -> Self { Self::Public } +} + +/// NB: Legacy API for older code. +impl Visibility { + pub fn to_str(&self) -> &'static str { + match self { + Self::Public => "public", + Self::Hidden => "hidden", + Self::Private => "private", + } + } + + pub fn from_str(value: &str) -> Result { + match value { + "public" => Ok(Self::Public), + "hidden" => Ok(Self::Hidden), + "private" => Ok(Self::Private), + _ => Err(format!("invalid value: {:?}", value)), + } + } +} + +#[cfg(test)] +mod tests { + use super::Visibility; + use enums_shared::test_helpers::assert_serialization; + + #[test] + fn test_default() { + assert_eq!(Visibility::default(), Visibility::Public); + + } + + #[test] + fn test_serialization() { + assert_serialization(Visibility::Public, "public"); + assert_serialization(Visibility::Hidden, "hidden"); + assert_serialization(Visibility::Private, "private"); + } + + #[test] + fn test_to_str() { + assert_eq!(Visibility::Public.to_str(), "public"); + assert_eq!(Visibility::Hidden.to_str(), "hidden"); + assert_eq!(Visibility::Private.to_str(), "private"); + } + + #[test] + fn test_from_str() { + assert_eq!(Visibility::from_str("public").unwrap(), Visibility::Public); + assert_eq!(Visibility::from_str("hidden").unwrap(), Visibility::Hidden); + assert_eq!(Visibility::from_str("private").unwrap(), Visibility::Private); + assert!(Visibility::from_str("foo").is_err()); + } + + mod traits { + use super::Visibility; + + #[test] + fn display() { + let visibility = Visibility::Hidden; + assert_eq!(format!("{}", visibility), "hidden".to_string()); + } + + #[test] + fn debug() { + let visibility = Visibility::Private; + assert_eq!(format!("{:?}", visibility), "private".to_string()); + } + } + + #[derive(Serialize, Deserialize, PartialEq, Debug)] + struct CompositeType { + visibility: Visibility, + string: String, + } + + mod serde_serialization { + use super::Visibility; + + use super::CompositeType; + + #[test] + fn serialize() { + let expected = "\"public\"".to_string(); // NB: Quoted + + assert_eq!(expected, serde_json::to_string(&Visibility::Public).unwrap()); + + // Just to show this serializes the same as a string + assert_eq!(expected, serde_json::to_string("public").unwrap()); + } + + #[test] + fn nested_serialize() { + let value = CompositeType { visibility: Visibility::Hidden, string: "bar".to_string() }; + let expected = r#"{"visibility":"hidden","string":"bar"}"#.to_string(); + assert_eq!(expected, serde_json::to_string(&value).unwrap()); + } + } + + mod serde_deserialization { + use super::Visibility; + + use super::CompositeType; + + #[test] + fn deserialize() { + let payload = "\"private\""; // NB: Quoted + let value: Visibility = serde_json::from_str(payload).unwrap(); + assert_eq!(value, Visibility::Private); + } + + #[test] + fn nested_deserialize() { + let payload = r#"{"visibility":"hidden","string":"bar"}"#.to_string(); + let expected = CompositeType { + visibility: Visibility::Hidden, + string: "bar".to_string(), + }; + + assert_eq!(expected, serde_json::from_str::(&payload).unwrap()); + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip() { + use strum::IntoEnumIterator; + for variant in Visibility::iter() { + assert_eq!(variant, Visibility::from_str(variant.to_str()).unwrap()); + assert_eq!(variant, Visibility::from_str(&format!("{}", variant)).unwrap()); + assert_eq!(variant, Visibility::from_str(&format!("{:?}", variant)).unwrap()); + } + } + + #[test] + fn serialized_length_ok_for_database() { + const MAX_LENGTH: usize = 32; // TODO(bt): Confirm database column width, then remove this comment. + use strum::IntoEnumIterator; + for variant in Visibility::iter() { + let serialized = variant.to_str(); + assert!(!serialized.is_empty(), "variant {:?} is too short", variant); + assert!(serialized.len() <= MAX_LENGTH, "variant {:?} is too long", variant); + } + } + } +} diff --git a/crates/schema/public/enums_db/src/common/vocoder_type.rs b/crates/schema/public/enums_db/src/common/vocoder_type.rs new file mode 100644 index 0000000000..019e2249d0 --- /dev/null +++ b/crates/schema/public/enums_db/src/common/vocoder_type.rs @@ -0,0 +1,94 @@ +use strum::EnumCount; +use strum::EnumIter; + +#[derive(Clone, Copy, Eq, PartialEq, Debug, Deserialize, Serialize, EnumIter, EnumCount)] +#[derive(sqlx::Type)] +pub enum VocoderType { + /// NB: Note - this is hifigan for Tacotron2. + /// Some work will be needed to unify this with other hifigan types. + #[serde(rename = "hifigan")] + #[cfg_attr(feature = "database", sqlx(rename = "hifigan"))] + HifiGan, + + #[serde(rename = "hifigan-superres")] + #[cfg_attr(feature = "database", sqlx(rename = "hifigan-superres"))] + HifiGanSuperResolution, + + /// NB: Note - this is hifigan for SoftVC (our internal codename is "rocketvc"). + /// Some work will need to be done to unify this with other hifigan types. + /// NB(bt, 2025-07-09): It was so silly to try to obscure this. Both FakeYou and Uberduck are irrelevant now. + #[serde(rename = "hifigan_rocket_vc")] + #[cfg_attr(feature = "database", sqlx(rename = "hifigan_rocket_vc"))] + HifiGanRocketVc, + +} + +/// NB: Legacy API for older code. +impl VocoderType { + pub fn to_str(&self) -> &'static str { + match self { + Self::HifiGan=> "hifigan", + Self::HifiGanSuperResolution => "hifigan-superres", + Self::HifiGanRocketVc => "hifigan_rocket_vc", + } + } + + pub fn from_str(value: &str) -> Result { + match value { + "hifigan" => Ok(Self::HifiGan), + "hifigan-superres" => Ok(Self::HifiGanSuperResolution), + "hifigan_rocket_vc" => Ok(Self::HifiGanRocketVc), + _ => Err(format!("invalid value: {:?}", value)), + } + } +} + +#[cfg(test)] +mod tests { + use super::VocoderType; + use enums_shared::test_helpers::assert_serialization; + + #[test] + fn test_serialization() { + assert_serialization(VocoderType::HifiGan, "hifigan"); + assert_serialization(VocoderType::HifiGanSuperResolution, "hifigan-superres"); + assert_serialization(VocoderType::HifiGanRocketVc, "hifigan_rocket_vc"); + } + + #[test] + fn to_str() { + assert_eq!(VocoderType::HifiGan.to_str(), "hifigan"); + assert_eq!(VocoderType::HifiGanSuperResolution.to_str(), "hifigan-superres"); + assert_eq!(VocoderType::HifiGanRocketVc.to_str(), "hifigan_rocket_vc"); + } + + #[test] + fn from_str() { + assert_eq!(VocoderType::from_str("hifigan").unwrap(), VocoderType::HifiGan); + assert_eq!(VocoderType::from_str("hifigan-superres").unwrap(), VocoderType::HifiGanSuperResolution); + assert_eq!(VocoderType::from_str("hifigan_rocket_vc").unwrap(), VocoderType::HifiGanRocketVc); + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip() { + use strum::IntoEnumIterator; + for variant in VocoderType::iter() { + assert_eq!(variant, VocoderType::from_str(variant.to_str()).unwrap()); + } + } + + #[test] + fn serialized_length_ok_for_database() { + const MAX_LENGTH: usize = 32; // TODO(bt): Confirm database column width, then remove this comment. + use strum::IntoEnumIterator; + for variant in VocoderType::iter() { + let serialized = variant.to_str(); + assert!(!serialized.is_empty(), "variant {:?} is too short", variant); + assert!(serialized.len() <= MAX_LENGTH, "variant {:?} is too long", variant); + } + } + } +} diff --git a/crates/schema/public/enums_db/src/lib.rs b/crates/schema/public/enums_db/src/lib.rs new file mode 100644 index 0000000000..684205d279 --- /dev/null +++ b/crates/schema/public/enums_db/src/lib.rs @@ -0,0 +1,27 @@ +// Never allow these +#![forbid(private_bounds)] +#![forbid(private_interfaces)] +#![forbid(unused_must_use)] // NB: It's unsafe to not close/check some things + +// Okay to toggle +#![deny(unused_imports)] +#![forbid(unreachable_patterns)] +#![forbid(unused_mut)] +#![forbid(unused_variables)] + +// Always allow +#![allow(dead_code)] +#![allow(non_snake_case)] + +#[allow(unused_imports)] +#[macro_use] extern crate serde_derive; + +#[macro_use] pub mod macros; +pub mod traits; +pub mod by_table; +pub mod common; +pub mod no_table; +pub mod tauri; + +// Re-export shared types +pub use enums_shared::error; diff --git a/crates/schema/public/enums_db/src/macros/impl_enum_display_and_debug_using_to_str.rs b/crates/schema/public/enums_db/src/macros/impl_enum_display_and_debug_using_to_str.rs new file mode 100644 index 0000000000..4fd24683b3 --- /dev/null +++ b/crates/schema/public/enums_db/src/macros/impl_enum_display_and_debug_using_to_str.rs @@ -0,0 +1,43 @@ + +/// Implement `Display` and `Debug` for enums that have a `.to_str()` method. +/// This ensures that the casing follows whatever `.to_str()` specifies. +macro_rules! impl_enum_display_and_debug_using_to_str { + ($t:ident) => { + + // Debug trait. + // Requires that the type has `.to_str()`. + impl std::fmt::Debug for $t { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.to_str()) + } + } + + // Display trait. + // Requires that the type has `.to_str()`. + impl std::fmt::Display for $t { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.to_str()) + } + } + + // NB: This test requires `strum::{EnumIter}` on the enum + #[cfg(test)] + #[test] + fn test_display_trait_matches_to_str() { + use strum::IntoEnumIterator; + for variant in $t::iter() { + assert_eq!(format!("{}", variant), variant.to_str()); + } + } + + // NB: This test requires `strum::{EnumIter}` on the enum + #[cfg(test)] + #[test] + fn test_debug_trait_matches_to_str() { + use strum::IntoEnumIterator; + for variant in $t::iter() { + assert_eq!(format!("{:?}", variant), variant.to_str()); + } + } + } +} diff --git a/crates/schema/public/enums_db/src/macros/impl_mysql_enum_coders.rs b/crates/schema/public/enums_db/src/macros/impl_mysql_enum_coders.rs new file mode 100644 index 0000000000..71fe9e9e9c --- /dev/null +++ b/crates/schema/public/enums_db/src/macros/impl_mysql_enum_coders.rs @@ -0,0 +1,42 @@ +/// This overt approach is being taken because of the following error: +/// +/// `MySqlDatabaseError { code: Some("HY000"), number: 1210, message: "Incorrect arguments to mysqld_stmt_execute" }` +/// +/// Basically, sqlx can't turn our enum into a VARCHAR when using #[derive(sqlx::Type)]. +/// Unfortunately, by not using this, we also lose the ability to `#[sqlx(rename_all="lowercase")]`, etc., +/// so our encoder/decoder need to set the rules. +/// +/// Solution adapted from https://github.com/launchbadge/sqlx/discussions/1502 +/// The 0.6.2 series solution adapted from https://docs.rs/sqlx-core/0.6.2/src/sqlx_core/mysql/types/uuid.rs.html#38-66 +/// +macro_rules! impl_mysql_enum_coders { + ($t:ident) => { + + impl sqlx::Type for $t { + fn type_info() -> sqlx_mysql::MySqlTypeInfo { + >::type_info() + } + } + + impl<'q> sqlx::Encode<'q, sqlx::MySql> for $t { + fn encode_by_ref( + &self, + buf: &mut >::ArgumentBuffer + ) -> sqlx_core::encode::IsNull { + let value = self.to_str(); + <&str as sqlx::Encode>::encode(&*value, buf) + } + } + + impl<'r> sqlx::Decode<'r, sqlx::MySql> for $t { + fn decode( + value: sqlx_mysql::MySqlValueRef<'r>, + ) -> Result { + let text = <&str as sqlx::Decode>::decode(value)?; + let value = $t::from_str(&text)?; + Ok(value) + } + } + + } +} diff --git a/crates/schema/public/enums_db/src/macros/impl_mysql_from_row.rs b/crates/schema/public/enums_db/src/macros/impl_mysql_from_row.rs new file mode 100644 index 0000000000..67159f5889 --- /dev/null +++ b/crates/schema/public/enums_db/src/macros/impl_mysql_from_row.rs @@ -0,0 +1,47 @@ +/// Implement `MySqlFromRow` on a type. +macro_rules! impl_mysql_from_row { + ($t:ident) => { + + // Try to convert a MySQL row and named field into the value type (for non-nullable fields). + impl crate::traits::mysql_from_row::MySqlFromRow<$t> for $t { + fn try_from_mysql_row(row: &sqlx_mysql::MySqlRow, field_name: &str) -> Result<$t, sqlx::Error> { + use sqlx::{Error, Row}; + + let value : String = row.try_get(field_name)?; + + let output_type = Self::from_str(&value) + .map_err(|err| { + Error::ColumnDecode { + index: format!("mysql_from_row failure on field {}: {:?}", field_name, err), + source: format!("mysql_from_row failure on field {}: {:?}", field_name, err).into(), + } + })?; + + Ok(output_type) + } + + // Try to convert a MySQL row and named field into the value type (for nullable fields). + fn try_from_mysql_row_nullable(row: &sqlx_mysql::MySqlRow, field_name: &str) -> Result, sqlx::Error> { + use sqlx::{Error, Row}; + + let maybe_value : Option = row.try_get(field_name)?; + + let value = match maybe_value { + Some(value) => value, + None => return Ok(None), + }; + + let output_type = Self::from_str(&value) + .map_err(|err| { + Error::ColumnDecode { + index: format!("mysql_from_row failure on field {}: {:?}", field_name, err), + source: format!("mysql_from_row failure on field {}: {:?}", field_name, err).into(), + } + })?; + + Ok(Some(output_type)) + } + } + + } +} diff --git a/crates/schema/public/enums_db/src/macros/impl_sqlite_enum_coders.rs b/crates/schema/public/enums_db/src/macros/impl_sqlite_enum_coders.rs new file mode 100644 index 0000000000..1ec4d0e8ec --- /dev/null +++ b/crates/schema/public/enums_db/src/macros/impl_sqlite_enum_coders.rs @@ -0,0 +1,6 @@ +/// SQLite enum coders (currently unused — all SQLite code is commented out). +macro_rules! impl_sqlite_enum_coders { + ($t:ident) => { + // Intentionally empty — SQLite is no longer used. + } +} diff --git a/crates/schema/public/enums_db/src/macros/mod.rs b/crates/schema/public/enums_db/src/macros/mod.rs new file mode 100644 index 0000000000..93cba5b4dc --- /dev/null +++ b/crates/schema/public/enums_db/src/macros/mod.rs @@ -0,0 +1,4 @@ +#[macro_use] pub mod impl_enum_display_and_debug_using_to_str; +#[macro_use] pub mod impl_mysql_enum_coders; +#[macro_use] pub mod impl_mysql_from_row; +#[macro_use] pub mod impl_sqlite_enum_coders; diff --git a/crates/schema/public/enums_db/src/no_table/mod.rs b/crates/schema/public/enums_db/src/no_table/mod.rs new file mode 100644 index 0000000000..df89af707b --- /dev/null +++ b/crates/schema/public/enums_db/src/no_table/mod.rs @@ -0,0 +1,2 @@ +pub mod premium_product; +pub mod style_transfer; diff --git a/crates/schema/public/enums_db/src/no_table/premium_product/mod.rs b/crates/schema/public/enums_db/src/no_table/premium_product/mod.rs new file mode 100644 index 0000000000..09a42c40ff --- /dev/null +++ b/crates/schema/public/enums_db/src/no_table/premium_product/mod.rs @@ -0,0 +1 @@ +pub mod premium_product_name; diff --git a/crates/schema/public/enums_db/src/no_table/premium_product/premium_product_name.rs b/crates/schema/public/enums_db/src/no_table/premium_product/premium_product_name.rs new file mode 100644 index 0000000000..a06f43e7c8 --- /dev/null +++ b/crates/schema/public/enums_db/src/no_table/premium_product/premium_product_name.rs @@ -0,0 +1,76 @@ +use strum::EnumCount; +use strum::EnumIter; + +/// This enum is not backed by a particular database table. +/// This is used to count premium product uses for free and paid users. +#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash, Deserialize, Serialize, EnumIter, EnumCount)] +#[serde(rename_all = "snake_case")] +pub enum PremiumProductName { + #[serde(rename = "fa")] + FaceAnimator, + #[serde(rename = "fm")] + FaceMirror, + #[serde(rename = "lip")] + Lipsync, + #[serde(rename = "vst")] + VideoStyleTransfer, +} + +impl_enum_display_and_debug_using_to_str!(PremiumProductName); + +impl PremiumProductName { + pub fn to_str(&self) -> &'static str { + match self { + Self::FaceAnimator => "fa", + Self::FaceMirror => "fm", + Self::Lipsync => "lip", + Self::VideoStyleTransfer => "vst", + } + } + + pub fn from_str(value: &str) -> Result { + match value { + "fa" => Ok(Self::FaceAnimator), + "fm" => Ok(Self::FaceMirror), + "lip" => Ok(Self::Lipsync), + "vst" => Ok(Self::VideoStyleTransfer), + _ => Err(format!("Unknown PremiumProductName: {}", value)), + } + } +} + +#[cfg(test)] +mod tests { + use super::PremiumProductName; + use enums_shared::test_helpers::assert_serialization; + + #[test] + fn test_serialization() { + assert_serialization(PremiumProductName::FaceAnimator, "fa"); + assert_serialization(PremiumProductName::FaceMirror, "fm"); + assert_serialization(PremiumProductName::Lipsync, "lip"); + assert_serialization(PremiumProductName::VideoStyleTransfer, "vst"); + } + + mod mechanical_checks { + use super::*; + use strum::IntoEnumIterator; + + #[test] + fn round_trip() { + for variant in PremiumProductName::iter() { + assert_eq!(variant, PremiumProductName::from_str(variant.to_str()).unwrap()); + } + } + + #[test] + fn serialized_length_ok_for_database() { + const MAX_LENGTH: usize = 32; // TODO(bt): Confirm database column width, then remove this comment. + for variant in PremiumProductName::iter() { + let serialized = variant.to_str(); + assert!(!serialized.is_empty(), "variant {:?} is too short", variant); + assert!(serialized.len() <= MAX_LENGTH, "variant {:?} is too long", variant); + } + } + } +} diff --git a/crates/schema/public/enums_db/src/no_table/style_transfer/mod.rs b/crates/schema/public/enums_db/src/no_table/style_transfer/mod.rs new file mode 100644 index 0000000000..f7f0351a17 --- /dev/null +++ b/crates/schema/public/enums_db/src/no_table/style_transfer/mod.rs @@ -0,0 +1 @@ +pub mod style_transfer_name; diff --git a/crates/schema/public/enums_db/src/no_table/style_transfer/style_transfer_name.rs b/crates/schema/public/enums_db/src/no_table/style_transfer/style_transfer_name.rs new file mode 100644 index 0000000000..3a000e20bd --- /dev/null +++ b/crates/schema/public/enums_db/src/no_table/style_transfer/style_transfer_name.rs @@ -0,0 +1,237 @@ +use strum::EnumCount; +use strum::EnumIter; + +/// This enum is not backed by a particular database table. +/// It's used in Jobs and DB payloads to agree upon ComfyUI style transfer style configurations. +/// +/// DO NOT CHANGE VALUES WITHOUT A MIGRATION STRATEGY. +#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash, Deserialize, Serialize, EnumIter, EnumCount)] +#[serde(rename_all = "snake_case")] +pub enum StyleTransferName { + #[serde(rename = "anime_2_5d")] + Anime2_5D, + #[serde(rename = "anime_2d_flat")] + Anime2DFlat, + #[serde(rename = "cartoon_3d")] + Cartoon3D, + #[serde(rename = "comic_book")] + ComicBook, + #[serde(rename = "anime_ghibli")] + AnimeGhibli, + #[serde(rename = "ink_punk")] + InkPunk, + #[serde(rename = "ink_splash")] + InkSplash, + #[serde(rename = "ink_bw_style")] + InkBWStyle, + #[serde(rename = "jojo_style")] + JojoStyle, + #[serde(rename = "paper_origami")] + PaperOrigami, + #[serde(rename = "pixel_art")] + PixelArt, + #[serde(rename = "pop_art")] + PopArt, + #[serde(rename = "realistic_1")] + Realistic1, + #[serde(rename = "realistic_2")] + Realistic2, + #[serde(rename = "anime_retro_neon")] + AnimeRetroNeon, + #[serde(rename = "anime_standard")] + AnimeStandard, + #[serde(rename = "hr_giger")] + HrGiger, + #[serde(rename = "simpsons")] + Simpsons, + #[serde(rename = "carnage")] + Carnage, + #[serde(rename = "pastel_cute_anime")] + AnimePastelCute, + #[serde(rename = "bloom_lighting")] + BloomLighting, + #[serde(rename = "25d_horror")] + Horror2_5D, + #[serde(rename = "creepy")] + Creepy, + #[serde(rename = "creepy_vhs")] + CreepyVhs, + #[serde(rename = "trail_cam_footage")] + TrailCamFootage, + #[serde(rename = "old_black_white_movie")] + OldBlackWhiteMovie, + #[serde(rename = "horror_noir_black_white")] + HorrorNoirBlackWhite, + #[serde(rename = "techno_noir_black_white")] + TechnoNoirBlackWhite, + #[serde(rename = "black_white_20s")] + BlackWhite20s, + #[serde(rename = "cyberpunk_anime")] + CyberpunkAnime, + #[serde(rename = "dragonball")] + Dragonball, + #[serde(rename = "realistic_matrix")] + RealisticMatrix, + #[serde(rename = "realistic_cyberpunk")] + RealisticCyberpunk, + #[serde(rename = "dreamer")] + Dreamer, +} + +impl_enum_display_and_debug_using_to_str!(StyleTransferName); + +impl StyleTransferName { + pub fn to_str(&self) -> &'static str { + match self { + Self::Anime2_5D => "anime_2_5d", + Self::Anime2DFlat => "anime_2d_flat", + Self::Cartoon3D => "cartoon_3d", + Self::ComicBook => "comic_book", + Self::AnimeGhibli => "anime_ghibli", + Self::InkPunk => "ink_punk", + Self::InkSplash => "ink_splash", + Self::InkBWStyle => "ink_bw_style", + Self::JojoStyle => "jojo_style", + Self::PaperOrigami => "paper_origami", + Self::PixelArt => "pixel_art", + Self::PopArt => "pop_art", + Self::Realistic1 => "realistic_1", + Self::Realistic2 => "realistic_2", + Self::AnimeRetroNeon => "anime_retro_neon", + Self::AnimeStandard => "anime_standard", + Self::HrGiger => "hr_giger", + Self::Simpsons => "simpsons", + Self::Carnage => "carnage", + Self::AnimePastelCute => "pastel_cute_anime", + Self::BloomLighting => "bloom_lighting", + Self::Horror2_5D => "25d_horror", + Self::Creepy => "creepy", + Self::CreepyVhs => "creepy_vhs", + Self::TrailCamFootage => "trail_cam_footage", + Self::OldBlackWhiteMovie => "old_black_white_movie", + Self::HorrorNoirBlackWhite => "horror_noir_black_white", + Self::TechnoNoirBlackWhite => "techno_noir_black_white", + Self::BlackWhite20s => "black_white_20s", + Self::CyberpunkAnime => "cyberpunk_anime", + Self::Dragonball => "dragonball", + Self::RealisticMatrix => "realistic_matrix", + Self::RealisticCyberpunk => "realistic_cyberpunk", + Self::Dreamer => "dreamer", + } + } + + pub fn from_str(value: &str) -> Result { + match value { + "anime_2_5d" => Ok(Self::Anime2_5D), + "anime_2d_flat" => Ok(Self::Anime2DFlat), + "cartoon_3d" => Ok(Self::Cartoon3D), + "comic_book" => Ok(Self::ComicBook), + "anime_ghibli" => Ok(Self::AnimeGhibli), + "ink_punk" => Ok(Self::InkPunk), + "ink_splash" => Ok(Self::InkSplash), + "ink_bw_style" => Ok(Self::InkBWStyle), + "jojo_style" => Ok(Self::JojoStyle), + "paper_origami" => Ok(Self::PaperOrigami), + "pixel_art" => Ok(Self::PixelArt), + "pop_art" => Ok(Self::PopArt), + "realistic_1" => Ok(Self::Realistic1), + "realistic_2" => Ok(Self::Realistic2), + "anime_retro_neon" => Ok(Self::AnimeRetroNeon), + "anime_standard" => Ok(Self::AnimeStandard), + "hr_giger" => Ok(Self::HrGiger), + "simpsons" => Ok(Self::Simpsons), + "carnage" => Ok(Self::Carnage), + "pastel_cute_anime" => Ok(Self::AnimePastelCute), + "bloom_lighting" => Ok(Self::BloomLighting), + "25d_horror" => Ok(Self::Horror2_5D), + "creepy" => Ok(Self::Creepy), + "creepy_vhs" => Ok(Self::CreepyVhs), + "trail_cam_footage" => Ok(Self::TrailCamFootage), + "old_black_white_movie" => Ok(Self::OldBlackWhiteMovie), + "horror_noir_black_white" => Ok(Self::HorrorNoirBlackWhite), + "techno_noir_black_white" => Ok(Self::TechnoNoirBlackWhite), + "black_white_20s" => Ok(Self::BlackWhite20s), + "cyberpunk_anime" => Ok(Self::CyberpunkAnime), + "dragonball" => Ok(Self::Dragonball), + "realistic_matrix" => Ok(Self::RealisticMatrix), + "realistic_cyberpunk" => Ok(Self::RealisticCyberpunk), + "dreamer" => Ok(Self::Dreamer), + _ => Err(format!("Unknown StyleTransferName: {}", value)), + } + } + + pub fn to_filename(&self) -> &'static str { + match self { + Self::Anime2_5D => "1_2.5d_anime_model.json", + Self::Anime2DFlat => "2_2d_flat_anime_model.json", + Self::Cartoon3D => "3_3d_cartoon_style.json", + Self::ComicBook => "4_comic_book_model.json", + Self::AnimeGhibli => "5_ghibli_anime_model.json", + Self::InkPunk => "6_ink_punk.json", + Self::InkSplash => "7_ink_splash.json", + Self::InkBWStyle => "8_ink_w_and_b_style.json", + Self::JojoStyle => "9_jojo_style.json", + Self::PaperOrigami => "10_paper_origami.json", + Self::PixelArt => "11_pixel_art.json", + Self::PopArt => "12_pop_art.json", + Self::Realistic1 => "13_realistic_1.json", + Self::Realistic2 => "14_realistic_2.json", + Self::AnimeRetroNeon => "15_retro_neon_anime_90.json", + Self::AnimeStandard => "16_standard_anime_model.json", + Self::HrGiger => "17_hr_giger.json", + Self::Simpsons => "18_simpsons.json", + Self::Carnage => "19_carnage.json", + Self::AnimePastelCute => "20_pastel_cute_anime.json", + Self::BloomLighting => "21_bloom_lighting.json", + Self::Horror2_5D => "22_25D_Horror.json", + Self::Creepy => "23_creepy.json", + Self::CreepyVhs => "24_creepy_vhs.json", + Self::TrailCamFootage => "25_trail_cam_footage.json", + Self::OldBlackWhiteMovie => "26_old_black_white_movie.json", + Self::HorrorNoirBlackWhite => "27_horror_noir_black_white.json", + Self::TechnoNoirBlackWhite => "28_techno_noir_black_white.json", + Self::BlackWhite20s => "29_black_white_20s.json", + Self::CyberpunkAnime => "30_cyberpunk_anime.json", + Self::Dragonball => "31_dragonball.json", + Self::RealisticMatrix => "32_realistic_matrix.json", + Self::RealisticCyberpunk => "33_realistic_cyberpunk.json", + Self::Dreamer => "34_dreamer.json", + } + } +} + +#[cfg(test)] +mod tests { + use super::StyleTransferName; + use enums_shared::test_helpers::assert_serialization; + + #[test] + fn test_serialization() { + assert_serialization(StyleTransferName::Anime2_5D, "anime_2_5d"); + assert_serialization(StyleTransferName::Dreamer, "dreamer"); + } + + mod mechanical_checks { + use super::*; + use strum::IntoEnumIterator; + + #[test] + fn round_trip() { + for variant in StyleTransferName::iter() { + assert_eq!(variant, StyleTransferName::from_str(variant.to_str()).unwrap()); + assert_eq!(variant, StyleTransferName::from_str(&format!("{}", variant)).unwrap()); + assert_eq!(variant, StyleTransferName::from_str(&format!("{:?}", variant)).unwrap()); + } + } + + #[test] + fn serialized_length_ok_for_database() { + const MAX_LENGTH: usize = 32; // TODO(bt): Confirm database column width, then remove this comment. + for variant in StyleTransferName::iter() { + let serialized = variant.to_str(); + assert!(!serialized.is_empty(), "variant {:?} is too short", variant); + assert!(serialized.len() <= MAX_LENGTH, "variant {:?} is too long", variant); + } + } + } +} diff --git a/crates/schema/public/enums_db/src/tauri/mod.rs b/crates/schema/public/enums_db/src/tauri/mod.rs new file mode 100644 index 0000000000..c687f0ee1b --- /dev/null +++ b/crates/schema/public/enums_db/src/tauri/mod.rs @@ -0,0 +1,2 @@ +pub mod tasks; +pub mod ux; diff --git a/crates/schema/public/enums_db/src/tauri/tasks/mod.rs b/crates/schema/public/enums_db/src/tauri/tasks/mod.rs new file mode 100644 index 0000000000..ef469ecb21 --- /dev/null +++ b/crates/schema/public/enums_db/src/tauri/tasks/mod.rs @@ -0,0 +1,5 @@ +pub mod task_failure_type; +pub mod task_media_file_class; +pub mod task_model_type; +pub mod task_status; +pub mod task_type; diff --git a/crates/schema/public/enums_db/src/tauri/tasks/task_failure_type.rs b/crates/schema/public/enums_db/src/tauri/tasks/task_failure_type.rs new file mode 100644 index 0000000000..9f137231da --- /dev/null +++ b/crates/schema/public/enums_db/src/tauri/tasks/task_failure_type.rs @@ -0,0 +1,206 @@ +use crate::by_table::generic_inference_jobs::frontend_failure_category::FrontendFailureCategory; +use enums_shared::error::enums_error::EnumsError; +use strum::EnumCount; +use strum::EnumIter; + +/// Failure type for tasks in the Tauri desktop app. +/// +/// Mirrors the relevant variants from `FrontendFailureCategory` so the desktop +/// client can display localized failure information without depending / breaking on the +/// server-side enum directly. +#[derive(Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd, Serialize, Deserialize, EnumIter, EnumCount)] +#[serde(rename_all = "snake_case")] +pub enum TaskFailureType { + /// Catch-all for unknown failures. + Unknown, + + RuleBansUserImage, + RuleBansUserImageWithFaces, + RuleBansUserTextPrompt, + RuleBansUserContent, + + RuleBansGeneratedVideo, + RuleBansGeneratedAudio, + RuleBansGeneratedContent, + + /// No reason given for generation failure, but this matches what we were told. + GenerationFailed, +} + +impl_enum_display_and_debug_using_to_str!(TaskFailureType); + +impl TaskFailureType { + + /// Convert the web API's `FrontendFailureCategory` to a Tauri-facing type, if there is a matching variant. + /// If there isn't a matching variant, return `Unknown`. + pub fn from_frontend_failure_category(category: FrontendFailureCategory) -> Self { + match category { + FrontendFailureCategory::ModelRulesViolation => Self::RuleBansUserContent, // NB: This is a legacy enum value. + FrontendFailureCategory::RuleBansUserImage => Self::RuleBansUserImage, + FrontendFailureCategory::RuleBansUserImageWithFaces => Self::RuleBansUserImageWithFaces, + FrontendFailureCategory::RuleBansUserTextPrompt => Self::RuleBansUserTextPrompt, + FrontendFailureCategory::RuleBansUserContent => Self::RuleBansUserContent, + FrontendFailureCategory::RuleBansGeneratedVideo => Self::RuleBansGeneratedVideo, + FrontendFailureCategory::RuleBansGeneratedAudio => Self::RuleBansGeneratedAudio, + FrontendFailureCategory::RuleBansGeneratedContent => Self::RuleBansGeneratedContent, + FrontendFailureCategory::GenerationFailed => Self::GenerationFailed, + _ => Self::Unknown, + } + } + + pub const fn to_str(&self) -> &'static str { + match self { + Self::Unknown => "unknown", + Self::RuleBansUserImage => "rule_bans_user_image", + Self::RuleBansUserImageWithFaces => "rule_bans_user_image_with_faces", + Self::RuleBansUserTextPrompt => "rule_bans_user_text_prompt", + Self::RuleBansUserContent => "rule_bans_user_content", + Self::RuleBansGeneratedVideo => "rule_bans_generated_video", + Self::RuleBansGeneratedAudio => "rule_bans_generated_audio", + Self::RuleBansGeneratedContent => "rule_bans_generated_content", + Self::GenerationFailed => "generation_failed", + } + } + + pub fn from_str(value: &str) -> Result { + match value { + "unknown" => Ok(Self::Unknown), + "rule_bans_user_image" => Ok(Self::RuleBansUserImage), + "rule_bans_user_image_with_faces" => Ok(Self::RuleBansUserImageWithFaces), + "rule_bans_user_text_prompt" => Ok(Self::RuleBansUserTextPrompt), + "rule_bans_user_content" => Ok(Self::RuleBansUserContent), + "rule_bans_generated_video" => Ok(Self::RuleBansGeneratedVideo), + "rule_bans_generated_audio" => Ok(Self::RuleBansGeneratedAudio), + "rule_bans_generated_content" => Ok(Self::RuleBansGeneratedContent), + "generation_failed" => Ok(Self::GenerationFailed), + _ => Err(EnumsError::CouldNotConvertFromString(value.to_string())), + } + } + +} + +#[cfg(test)] +mod tests { + use super::TaskFailureType; + use enums_shared::test_helpers::assert_serialization; + + mod explicit_checks { + use super::*; + use enums_shared::error::enums_error::EnumsError; + + #[test] + fn test_serialization() { + assert_serialization(TaskFailureType::Unknown, "unknown"); + assert_serialization(TaskFailureType::RuleBansUserImage, "rule_bans_user_image"); + assert_serialization(TaskFailureType::RuleBansUserImageWithFaces, "rule_bans_user_image_with_faces"); + assert_serialization(TaskFailureType::RuleBansUserTextPrompt, "rule_bans_user_text_prompt"); + assert_serialization(TaskFailureType::RuleBansUserContent, "rule_bans_user_content"); + assert_serialization(TaskFailureType::RuleBansGeneratedVideo, "rule_bans_generated_video"); + assert_serialization(TaskFailureType::RuleBansGeneratedAudio, "rule_bans_generated_audio"); + assert_serialization(TaskFailureType::RuleBansGeneratedContent, "rule_bans_generated_content"); + assert_serialization(TaskFailureType::GenerationFailed, "generation_failed"); + } + + #[test] + fn to_str() { + assert_eq!(TaskFailureType::Unknown.to_str(), "unknown"); + assert_eq!(TaskFailureType::RuleBansUserImage.to_str(), "rule_bans_user_image"); + assert_eq!(TaskFailureType::RuleBansUserImageWithFaces.to_str(), "rule_bans_user_image_with_faces"); + assert_eq!(TaskFailureType::RuleBansUserTextPrompt.to_str(), "rule_bans_user_text_prompt"); + assert_eq!(TaskFailureType::RuleBansUserContent.to_str(), "rule_bans_user_content"); + assert_eq!(TaskFailureType::RuleBansGeneratedVideo.to_str(), "rule_bans_generated_video"); + assert_eq!(TaskFailureType::RuleBansGeneratedAudio.to_str(), "rule_bans_generated_audio"); + assert_eq!(TaskFailureType::RuleBansGeneratedContent.to_str(), "rule_bans_generated_content"); + assert_eq!(TaskFailureType::GenerationFailed.to_str(), "generation_failed"); + } + + #[test] + fn from_str() { + assert_eq!(TaskFailureType::from_str("unknown").unwrap(), TaskFailureType::Unknown); + assert_eq!(TaskFailureType::from_str("rule_bans_user_image").unwrap(), TaskFailureType::RuleBansUserImage); + assert_eq!(TaskFailureType::from_str("rule_bans_user_image_with_faces").unwrap(), TaskFailureType::RuleBansUserImageWithFaces); + assert_eq!(TaskFailureType::from_str("rule_bans_user_text_prompt").unwrap(), TaskFailureType::RuleBansUserTextPrompt); + assert_eq!(TaskFailureType::from_str("rule_bans_user_content").unwrap(), TaskFailureType::RuleBansUserContent); + assert_eq!(TaskFailureType::from_str("rule_bans_generated_video").unwrap(), TaskFailureType::RuleBansGeneratedVideo); + assert_eq!(TaskFailureType::from_str("rule_bans_generated_audio").unwrap(), TaskFailureType::RuleBansGeneratedAudio); + assert_eq!(TaskFailureType::from_str("rule_bans_generated_content").unwrap(), TaskFailureType::RuleBansGeneratedContent); + assert_eq!(TaskFailureType::from_str("generation_failed").unwrap(), TaskFailureType::GenerationFailed); + } + + #[test] + fn from_str_err() { + let result = TaskFailureType::from_str("asdf"); + assert!(result.is_err()); + if let Err(EnumsError::CouldNotConvertFromString(value)) = result { + assert_eq!(value, "asdf"); + } else { + panic!("Expected EnumsError::CouldNotConvertFromString"); + } + } + + } + + mod from_frontend_failure_category { + use super::*; + use crate::by_table::generic_inference_jobs::frontend_failure_category::FrontendFailureCategory; + + #[test] + fn direct_mappings() { + assert_eq!(TaskFailureType::from_frontend_failure_category(FrontendFailureCategory::RuleBansUserImage), TaskFailureType::RuleBansUserImage); + assert_eq!(TaskFailureType::from_frontend_failure_category(FrontendFailureCategory::RuleBansUserImageWithFaces), TaskFailureType::RuleBansUserImageWithFaces); + assert_eq!(TaskFailureType::from_frontend_failure_category(FrontendFailureCategory::RuleBansUserTextPrompt), TaskFailureType::RuleBansUserTextPrompt); + assert_eq!(TaskFailureType::from_frontend_failure_category(FrontendFailureCategory::RuleBansUserContent), TaskFailureType::RuleBansUserContent); + assert_eq!(TaskFailureType::from_frontend_failure_category(FrontendFailureCategory::RuleBansGeneratedVideo), TaskFailureType::RuleBansGeneratedVideo); + assert_eq!(TaskFailureType::from_frontend_failure_category(FrontendFailureCategory::RuleBansGeneratedAudio), TaskFailureType::RuleBansGeneratedAudio); + assert_eq!(TaskFailureType::from_frontend_failure_category(FrontendFailureCategory::RuleBansGeneratedContent), TaskFailureType::RuleBansGeneratedContent); + assert_eq!(TaskFailureType::from_frontend_failure_category(FrontendFailureCategory::GenerationFailed), TaskFailureType::GenerationFailed); + } + + #[test] + fn legacy_model_rules_violation_maps_to_rule_bans_user_content() { + assert_eq!(TaskFailureType::from_frontend_failure_category(FrontendFailureCategory::ModelRulesViolation), TaskFailureType::RuleBansUserContent); + } + + #[test] + fn unmapped_variants_become_unknown() { + assert_eq!(TaskFailureType::from_frontend_failure_category(FrontendFailureCategory::FaceNotDetected), TaskFailureType::Unknown); + assert_eq!(TaskFailureType::from_frontend_failure_category(FrontendFailureCategory::KeepAliveElapsed), TaskFailureType::Unknown); + assert_eq!(TaskFailureType::from_frontend_failure_category(FrontendFailureCategory::NotYetImplemented), TaskFailureType::Unknown); + assert_eq!(TaskFailureType::from_frontend_failure_category(FrontendFailureCategory::RetryableWorkerError), TaskFailureType::Unknown); + } + + #[test] + fn all_frontend_variants_are_handled() { + use strum::IntoEnumIterator; + for variant in FrontendFailureCategory::iter() { + // Should not panic — every variant produces a valid TaskFailureType. + let _ = TaskFailureType::from_frontend_failure_category(variant); + } + } + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip() { + use strum::IntoEnumIterator; + for variant in TaskFailureType::iter() { + assert_eq!(variant, TaskFailureType::from_str(variant.to_str()).unwrap()); + assert_eq!(variant, TaskFailureType::from_str(&format!("{}", variant)).unwrap()); + assert_eq!(variant, TaskFailureType::from_str(&format!("{:?}", variant)).unwrap()); + } + } + + #[test] + fn serialized_length_ok_for_database() { + const MAX_LENGTH: usize = 32; // TODO(bt): Confirm database column width, then remove this comment. + use strum::IntoEnumIterator; + for variant in TaskFailureType::iter() { + let serialized = variant.to_str(); + assert!(!serialized.is_empty(), "variant {:?} is too short", variant); + assert!(serialized.len() <= MAX_LENGTH, "variant {:?} is too long", variant); + } + } + } +} diff --git a/crates/schema/public/enums_db/src/tauri/tasks/task_media_file_class.rs b/crates/schema/public/enums_db/src/tauri/tasks/task_media_file_class.rs new file mode 100644 index 0000000000..47baa6261e --- /dev/null +++ b/crates/schema/public/enums_db/src/tauri/tasks/task_media_file_class.rs @@ -0,0 +1,120 @@ +use enums_shared::error::enums_error::EnumsError; +use strum::EnumCount; +use strum::EnumIter; + +#[derive(Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd, Serialize, Deserialize, EnumIter, EnumCount)] +#[serde(rename_all = "snake_case")] +pub enum TaskMediaFileClass { + /// Audio files: wav, mp3, etc. + Audio, + + /// Image files: png, jpeg, etc. + Image, + + /// Video files: mp4, etc. + Video, + + /// 3D engine data: glb, gltf, etc. + Dimensional, +} + +impl_enum_display_and_debug_using_to_str!(TaskMediaFileClass); +//impl_mysql_enum_coders!(TaskMediaFileType); +//impl_mysql_from_row!(TaskMediaFileType); + +// NB: We can derive `sqlx::Type` instead of using `impl_mysql_enum_coders` + +impl TaskMediaFileClass { + pub fn to_str(&self) -> &'static str { + match self { + Self::Audio => "audio", + Self::Image => "image", + Self::Video => "video", + Self::Dimensional => "dimensional", + } + } + + pub fn from_str(value: &str) -> Result { + match value { + "audio" => Ok(Self::Audio), + "image" => Ok(Self::Image), + "video" => Ok(Self::Video), + "dimensional" => Ok(Self::Dimensional), + _ => Err(EnumsError::CouldNotConvertFromString(value.to_string())), + } + } + +} + +#[cfg(test)] +mod tests { + use super::TaskMediaFileClass; + use enums_shared::test_helpers::assert_serialization; + + mod explicit_checks { + use super::*; + use enums_shared::error::enums_error::EnumsError; + + #[test] + fn test_serialization() { + assert_serialization(TaskMediaFileClass::Audio, "audio"); + assert_serialization(TaskMediaFileClass::Image, "image"); + assert_serialization(TaskMediaFileClass::Video, "video"); + assert_serialization(TaskMediaFileClass::Dimensional, "dimensional"); + } + + #[test] + fn to_str() { + assert_eq!(TaskMediaFileClass::Audio.to_str(), "audio"); + assert_eq!(TaskMediaFileClass::Image.to_str(), "image"); + assert_eq!(TaskMediaFileClass::Video.to_str(), "video"); + assert_eq!(TaskMediaFileClass::Dimensional.to_str(), "dimensional"); + } + + #[test] + fn from_str() { + assert_eq!(TaskMediaFileClass::from_str("audio").unwrap(), TaskMediaFileClass::Audio); + assert_eq!(TaskMediaFileClass::from_str("image").unwrap(), TaskMediaFileClass::Image); + assert_eq!(TaskMediaFileClass::from_str("video").unwrap(), TaskMediaFileClass::Video); + assert_eq!(TaskMediaFileClass::from_str("dimensional").unwrap(), TaskMediaFileClass::Dimensional); + } + + #[test] + fn from_str_err() { + let result = TaskMediaFileClass::from_str("asdf"); + assert!(result.is_err()); + if let Err(EnumsError::CouldNotConvertFromString(value)) = result { + assert_eq!(value, "asdf"); + } else { + panic!("Expected EnumsError::CouldNotConvertFromString"); + } + } + + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip() { + use strum::IntoEnumIterator; + for variant in TaskMediaFileClass::iter() { + // Test to_str(), from_str(), Display, and Debug. + assert_eq!(variant, TaskMediaFileClass::from_str(variant.to_str()).unwrap()); + assert_eq!(variant, TaskMediaFileClass::from_str(&format!("{}", variant)).unwrap()); + assert_eq!(variant, TaskMediaFileClass::from_str(&format!("{:?}", variant)).unwrap()); + } + } + + #[test] + fn serialized_length_ok_for_database() { + const MAX_LENGTH: usize = 32; // TODO(bt): Confirm database column width, then remove this comment. + use strum::IntoEnumIterator; + for variant in TaskMediaFileClass::iter() { + let serialized = variant.to_str(); + assert!(!serialized.is_empty(), "variant {:?} is too short", variant); + assert!(serialized.len() <= MAX_LENGTH, "variant {:?} is too long", variant); + } + } + } +} diff --git a/crates/schema/public/enums_db/src/tauri/tasks/task_model_type.rs b/crates/schema/public/enums_db/src/tauri/tasks/task_model_type.rs new file mode 100644 index 0000000000..bf83ca30a5 --- /dev/null +++ b/crates/schema/public/enums_db/src/tauri/tasks/task_model_type.rs @@ -0,0 +1,427 @@ +use enums_shared::error::enums_error::EnumsError; +use strum::EnumCount; +use strum::EnumIter; + +#[derive(Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd, Serialize, Deserialize, EnumIter, EnumCount)] +#[serde(rename_all = "snake_case")] +pub enum TaskModelType { + // Image models + #[serde(rename = "flux_1_dev")] + Flux1Dev, + #[serde(rename = "flux_1_schnell")] + Flux1Schnell, + #[serde(rename = "flux_dev_juggernaut")] + FluxDevJuggernaut, + // NB: For inpainting for now + #[serde(rename = "flux_pro_1")] + FluxPro1, + #[serde(rename = "flux_pro_1.1")] + FluxPro11, + #[serde(rename = "flux_pro_1.1_ultra")] + FluxPro11Ultra, + #[serde(rename = "flux_pro_kontext_max")] + FluxProKontextMax, + #[serde(rename = "gemini_25_flash")] + Gemini25Flash, + #[serde(rename = "nano_banana")] + NanoBanana, + #[serde(rename = "nano_banana_2")] + NanoBanana2, + #[serde(rename = "nano_banana_pro")] + NanoBananaPro, + #[serde(rename = "gpt_image_1")] + GptImage1, + #[serde(rename = "gpt_image_1p5")] + GptImage1p5, + #[serde(rename = "seedream_4")] + Seedream4, + #[serde(rename = "seedream_4p5")] + Seedream4p5, + #[serde(rename = "seedream_5_lite")] + Seedream5Lite, + #[serde(rename = "qwen_edit_2511_angles")] + QwenEdit2511Angles, + #[serde(rename = "flux_2_lora_angles")] + Flux2LoraAngles, + #[serde(rename = "grok_image")] + GrokImage, + #[serde(rename = "recraft_3")] + Recraft3, + + // Generic Midjourney model, version unknown. + #[serde(rename = "midjourney")] + Midjourney, + + // Video models + #[serde(rename = "grok_video")] + GrokVideo, // Video version unspecified/unknown + #[serde(rename = "kling_1.6_pro")] + Kling16Pro, + #[serde(rename = "kling_2.1_pro")] + Kling21Pro, + #[serde(rename = "kling_2.1_master")] + Kling21Master, + #[serde(rename = "kling_2p5_turbo_pro")] + Kling2p5TurboPro, + #[serde(rename = "kling_2p6_pro")] + Kling2p6Pro, + #[serde(rename = "kling_3p0_standard")] + Kling3p0Standard, + #[serde(rename = "kling_3p0_pro")] + Kling3p0Pro, + #[serde(rename = "seedance_1.0_lite")] + Seedance10Lite, + #[serde(rename = "seedance_1p5_pro")] + Seedance1p5Pro, + #[serde(rename = "seedance_2p0")] + Seedance2p0, + #[serde(rename = "sora_2")] + Sora2, + #[serde(rename = "sora_2_pro")] + Sora2Pro, + #[serde(rename = "veo_2")] + Veo2, + #[serde(rename = "veo_3")] + Veo3, + #[serde(rename = "veo_3_fast")] + Veo3Fast, + #[serde(rename = "veo_3p1")] + Veo3p1, + #[serde(rename = "veo_3p1_fast")] + Veo3p1Fast, + + // 3D Object generation models + #[serde(rename = "hunyuan_3d_2.0")] + Hunyuan3d2_0, + #[serde(rename = "hunyuan_3d_2.1")] + Hunyuan3d2_1, + #[serde(rename = "hunyuan_3d_3")] + Hunyuan3d3, + #[serde(rename = "worldlabs_marble")] + WorldlabsMarble, + #[serde(rename = "marble_0p1_mini")] + WorldlabsMarble0p1Mini, + #[serde(rename = "marble_0p1_plus")] + WorldlabsMarble0p1Plus, +} + +impl_enum_display_and_debug_using_to_str!(TaskModelType); +//impl_mysql_enum_coders!(TaskModelType); +//impl_mysql_from_row!(TaskModelType); + +// NB: We can derive `sqlx::Type` instead of using `impl_mysql_enum_coders` + +impl TaskModelType { + pub fn to_str(&self) -> &'static str { + match self { + // Image models + Self::Flux1Dev => "flux_1_dev", + Self::Flux1Schnell => "flux_1_schnell", + Self::FluxDevJuggernaut => "flux_dev_juggernaut", + Self::FluxPro1 => "flux_pro_1", + Self::FluxPro11 => "flux_pro_1.1", + Self::FluxPro11Ultra => "flux_pro_1.1_ultra", + Self::FluxProKontextMax => "flux_pro_kontext_max", + Self::Gemini25Flash => "gemini_25_flash", + Self::NanoBanana => "nano_banana", + Self::NanoBanana2 => "nano_banana_2", + Self::NanoBananaPro => "nano_banana_pro", + Self::GptImage1 => "gpt_image_1", + Self::GptImage1p5 => "gpt_image_1p5", + Self::Seedream4 => "seedream_4", + Self::Seedream4p5 => "seedream_4p5", + Self::Seedream5Lite => "seedream_5_lite", + Self::QwenEdit2511Angles => "qwen_edit_2511_angles", + Self::Flux2LoraAngles => "flux_2_lora_angles", + Self::GrokImage => "grok_image", + Self::Recraft3 => "recraft_3", + Self::Midjourney => "midjourney", + // Video models + Self::GrokVideo => "grok_video", + Self::Kling16Pro => "kling_1.6_pro", + Self::Kling21Pro => "kling_2.1_pro", + Self::Kling21Master => "kling_2.1_master", + Self::Kling2p5TurboPro => "kling_2p5_turbo_pro", + Self::Kling2p6Pro => "kling_2p6_pro", + Self::Kling3p0Standard => "kling_3p0_standard", + Self::Kling3p0Pro => "kling_3p0_pro", + Self::Seedance10Lite => "seedance_1.0_lite", + Self::Seedance1p5Pro => "seedance_1p5_pro", + Self::Seedance2p0 => "seedance_2p0", + Self::Sora2 => "sora_2", + Self::Sora2Pro => "sora_2_pro", + Self::Veo2 => "veo_2", + Self::Veo3 => "veo_3", + Self::Veo3Fast => "veo_3_fast", + Self::Veo3p1 => "veo_3p1", + Self::Veo3p1Fast => "veo_3p1_fast", + // 3D Object generation models + Self::Hunyuan3d2_0 => "hunyuan_3d_2.0", + Self::Hunyuan3d2_1 => "hunyuan_3d_2.1", + Self::Hunyuan3d3 => "hunyuan_3d_3", + Self::WorldlabsMarble => "worldlabs_marble", + Self::WorldlabsMarble0p1Mini => "marble_0p1_mini", + Self::WorldlabsMarble0p1Plus => "marble_0p1_plus", + } + } + + pub fn from_str(value: &str) -> Result { + match value { + // Image models + "flux_1_dev" => Ok(Self::Flux1Dev), + "flux_1_schnell" => Ok(Self::Flux1Schnell), + "flux_dev_juggernaut" => Ok(Self::FluxDevJuggernaut), + "flux_pro_1" => Ok(Self::FluxPro1), + "flux_pro_1.1" => Ok(Self::FluxPro11), + "flux_pro_1.1_ultra" => Ok(Self::FluxPro11Ultra), + "flux_pro_kontext_max" => Ok(Self::FluxProKontextMax), + "gemini_25_flash" => Ok(Self::Gemini25Flash), + "nano_banana" => Ok(Self::NanoBanana), + "nano_banana_2" => Ok(Self::NanoBanana2), + "nano_banana_pro" => Ok(Self::NanoBananaPro), + "gpt_image_1" => Ok(Self::GptImage1), + "gpt_image_1p5" => Ok(Self::GptImage1p5), + "seedream_4" => Ok(Self::Seedream4), + "seedream_4p5" => Ok(Self::Seedream4p5), + "seedream_5_lite" => Ok(Self::Seedream5Lite), + "qwen_edit_2511_angles" => Ok(Self::QwenEdit2511Angles), + "flux_2_lora_angles" => Ok(Self::Flux2LoraAngles), + "grok_image" => Ok(Self::GrokImage), + "recraft_3" => Ok(Self::Recraft3), + "midjourney" => Ok(Self::Midjourney), + // Video models + "grok_video" => Ok(Self::GrokVideo), + "kling_1.6_pro" => Ok(Self::Kling16Pro), + "kling_2.1_pro" => Ok(Self::Kling21Pro), + "kling_2.1_master" => Ok(Self::Kling21Master), + "kling_2p5_turbo_pro" => Ok(Self::Kling2p5TurboPro), + "kling_2p6_pro" => Ok(Self::Kling2p6Pro), + "kling_3p0_standard" => Ok(Self::Kling3p0Standard), + "kling_3p0_pro" => Ok(Self::Kling3p0Pro), + "seedance_1.0_lite" => Ok(Self::Seedance10Lite), + "seedance_1p5_pro" => Ok(Self::Seedance1p5Pro), + "seedance_2p0" => Ok(Self::Seedance2p0), + "sora_2" => Ok(Self::Sora2), + "sora_2_pro" => Ok(Self::Sora2Pro), + "veo_2" => Ok(Self::Veo2), + "veo_3" => Ok(Self::Veo3), + "veo_3_fast" => Ok(Self::Veo3Fast), + "veo_3p1" => Ok(Self::Veo3p1), + "veo_3p1_fast" => Ok(Self::Veo3p1Fast), + // 3D Object generation models + "hunyuan_3d_2.0" => Ok(Self::Hunyuan3d2_0), + "hunyuan_3d_2.1" => Ok(Self::Hunyuan3d2_1), + "hunyuan_3d_3" => Ok(Self::Hunyuan3d3), + "worldlabs_marble" => Ok(Self::WorldlabsMarble), + "marble_0p1_mini" => Ok(Self::WorldlabsMarble0p1Mini), + "marble_0p1_plus" => Ok(Self::WorldlabsMarble0p1Plus), + _ => Err(EnumsError::CouldNotConvertFromString(value.to_string())), + } + } + +} + +#[cfg(test)] +mod tests { + use super::TaskModelType; + use enums_shared::test_helpers::assert_serialization; + use enums_shared::error::enums_error::EnumsError; + + mod explicit_checks { + use super::*; + + #[test] + fn test_serialization() { + // Image models + assert_serialization(TaskModelType::Flux1Dev, "flux_1_dev"); + assert_serialization(TaskModelType::Flux1Schnell, "flux_1_schnell"); + assert_serialization(TaskModelType::FluxDevJuggernaut, "flux_dev_juggernaut"); + assert_serialization(TaskModelType::FluxPro1, "flux_pro_1"); + assert_serialization(TaskModelType::FluxPro11, "flux_pro_1.1"); + assert_serialization(TaskModelType::FluxPro11Ultra, "flux_pro_1.1_ultra"); + assert_serialization(TaskModelType::FluxProKontextMax, "flux_pro_kontext_max"); + assert_serialization(TaskModelType::Gemini25Flash, "gemini_25_flash"); + assert_serialization(TaskModelType::NanoBanana, "nano_banana"); + assert_serialization(TaskModelType::NanoBanana2, "nano_banana_2"); + assert_serialization(TaskModelType::NanoBananaPro, "nano_banana_pro"); + assert_serialization(TaskModelType::GptImage1, "gpt_image_1"); + assert_serialization(TaskModelType::GptImage1p5, "gpt_image_1p5"); + assert_serialization(TaskModelType::Seedream4, "seedream_4"); + assert_serialization(TaskModelType::Seedream4p5, "seedream_4p5"); + assert_serialization(TaskModelType::Seedream5Lite, "seedream_5_lite"); + assert_serialization(TaskModelType::QwenEdit2511Angles, "qwen_edit_2511_angles"); + assert_serialization(TaskModelType::Flux2LoraAngles, "flux_2_lora_angles"); + assert_serialization(TaskModelType::GrokImage, "grok_image"); + assert_serialization(TaskModelType::Recraft3, "recraft_3"); + assert_serialization(TaskModelType::Midjourney, "midjourney"); + // Video models + assert_serialization(TaskModelType::GrokVideo, "grok_video"); + assert_serialization(TaskModelType::Kling16Pro, "kling_1.6_pro"); + assert_serialization(TaskModelType::Kling21Pro, "kling_2.1_pro"); + assert_serialization(TaskModelType::Kling21Master, "kling_2.1_master"); + assert_serialization(TaskModelType::Kling2p5TurboPro, "kling_2p5_turbo_pro"); + assert_serialization(TaskModelType::Kling2p6Pro, "kling_2p6_pro"); + assert_serialization(TaskModelType::Kling3p0Standard, "kling_3p0_standard"); + assert_serialization(TaskModelType::Kling3p0Pro, "kling_3p0_pro"); + assert_serialization(TaskModelType::Seedance10Lite, "seedance_1.0_lite"); + assert_serialization(TaskModelType::Seedance1p5Pro, "seedance_1p5_pro"); + assert_serialization(TaskModelType::Seedance2p0, "seedance_2p0"); + assert_serialization(TaskModelType::Sora2, "sora_2"); + assert_serialization(TaskModelType::Sora2Pro, "sora_2_pro"); + assert_serialization(TaskModelType::Veo2, "veo_2"); + assert_serialization(TaskModelType::Veo3, "veo_3"); + assert_serialization(TaskModelType::Veo3Fast, "veo_3_fast"); + assert_serialization(TaskModelType::Veo3p1, "veo_3p1"); + assert_serialization(TaskModelType::Veo3p1Fast, "veo_3p1_fast"); + // 3D Object generation models + assert_serialization(TaskModelType::Hunyuan3d2_0, "hunyuan_3d_2.0"); + assert_serialization(TaskModelType::Hunyuan3d2_1, "hunyuan_3d_2.1"); + assert_serialization(TaskModelType::Hunyuan3d3, "hunyuan_3d_3"); + assert_serialization(TaskModelType::WorldlabsMarble, "worldlabs_marble"); + assert_serialization(TaskModelType::WorldlabsMarble0p1Mini, "marble_0p1_mini"); + assert_serialization(TaskModelType::WorldlabsMarble0p1Plus, "marble_0p1_plus"); + } + + #[test] + fn to_str() { + // Image models + assert_eq!(TaskModelType::Flux1Dev.to_str(), "flux_1_dev"); + assert_eq!(TaskModelType::Flux1Schnell.to_str(), "flux_1_schnell"); + assert_eq!(TaskModelType::FluxDevJuggernaut.to_str(), "flux_dev_juggernaut"); + assert_eq!(TaskModelType::FluxPro1.to_str(), "flux_pro_1"); + assert_eq!(TaskModelType::FluxPro11.to_str(), "flux_pro_1.1"); + assert_eq!(TaskModelType::FluxPro11Ultra.to_str(), "flux_pro_1.1_ultra"); + assert_eq!(TaskModelType::FluxProKontextMax.to_str(), "flux_pro_kontext_max"); + assert_eq!(TaskModelType::Gemini25Flash.to_str(), "gemini_25_flash"); + assert_eq!(TaskModelType::NanoBanana.to_str(), "nano_banana"); + assert_eq!(TaskModelType::NanoBanana2.to_str(), "nano_banana_2"); + assert_eq!(TaskModelType::NanoBananaPro.to_str(), "nano_banana_pro"); + assert_eq!(TaskModelType::GptImage1.to_str(), "gpt_image_1"); + assert_eq!(TaskModelType::GptImage1p5.to_str(), "gpt_image_1p5"); + assert_eq!(TaskModelType::Seedream4.to_str(), "seedream_4"); + assert_eq!(TaskModelType::Seedream4p5.to_str(), "seedream_4p5"); + assert_eq!(TaskModelType::Seedream5Lite.to_str(), "seedream_5_lite"); + assert_eq!(TaskModelType::QwenEdit2511Angles.to_str(), "qwen_edit_2511_angles"); + assert_eq!(TaskModelType::Flux2LoraAngles.to_str(), "flux_2_lora_angles"); + assert_eq!(TaskModelType::GrokImage.to_str(), "grok_image"); + assert_eq!(TaskModelType::Recraft3.to_str(), "recraft_3"); + assert_eq!(TaskModelType::Midjourney.to_str(), "midjourney"); + // Video models + assert_eq!(TaskModelType::GrokVideo.to_str(), "grok_video"); + assert_eq!(TaskModelType::Kling16Pro.to_str(), "kling_1.6_pro"); + assert_eq!(TaskModelType::Kling21Pro.to_str(), "kling_2.1_pro"); + assert_eq!(TaskModelType::Kling21Master.to_str(), "kling_2.1_master"); + assert_eq!(TaskModelType::Kling2p5TurboPro.to_str(), "kling_2p5_turbo_pro"); + assert_eq!(TaskModelType::Kling2p6Pro.to_str(), "kling_2p6_pro"); + assert_eq!(TaskModelType::Kling3p0Standard.to_str(), "kling_3p0_standard"); + assert_eq!(TaskModelType::Kling3p0Pro.to_str(), "kling_3p0_pro"); + assert_eq!(TaskModelType::Seedance10Lite.to_str(), "seedance_1.0_lite"); + assert_eq!(TaskModelType::Seedance1p5Pro.to_str(), "seedance_1p5_pro"); + assert_eq!(TaskModelType::Seedance2p0.to_str(), "seedance_2p0"); + assert_eq!(TaskModelType::Sora2.to_str(), "sora_2"); + assert_eq!(TaskModelType::Sora2Pro.to_str(), "sora_2_pro"); + assert_eq!(TaskModelType::Veo2.to_str(), "veo_2"); + assert_eq!(TaskModelType::Veo3.to_str(), "veo_3"); + assert_eq!(TaskModelType::Veo3Fast.to_str(), "veo_3_fast"); + assert_eq!(TaskModelType::Veo3p1.to_str(), "veo_3p1"); + assert_eq!(TaskModelType::Veo3p1Fast.to_str(), "veo_3p1_fast"); + // 3D Object generation models + assert_eq!(TaskModelType::Hunyuan3d2_0.to_str(), "hunyuan_3d_2.0"); + assert_eq!(TaskModelType::Hunyuan3d2_1.to_str(), "hunyuan_3d_2.1"); + assert_eq!(TaskModelType::Hunyuan3d3.to_str(), "hunyuan_3d_3"); + assert_eq!(TaskModelType::WorldlabsMarble.to_str(), "worldlabs_marble"); + assert_eq!(TaskModelType::WorldlabsMarble0p1Mini.to_str(), "marble_0p1_mini"); + assert_eq!(TaskModelType::WorldlabsMarble0p1Plus.to_str(), "marble_0p1_plus"); + } + + #[test] + fn from_str() { + // Image models + assert_eq!(TaskModelType::from_str("flux_1_dev").unwrap(), TaskModelType::Flux1Dev); + assert_eq!(TaskModelType::from_str("flux_1_schnell").unwrap(), TaskModelType::Flux1Schnell); + assert_eq!(TaskModelType::from_str("flux_dev_juggernaut").unwrap(), TaskModelType::FluxDevJuggernaut); + assert_eq!(TaskModelType::from_str("flux_pro_1").unwrap(), TaskModelType::FluxPro1); + assert_eq!(TaskModelType::from_str("flux_pro_1.1").unwrap(), TaskModelType::FluxPro11); + assert_eq!(TaskModelType::from_str("flux_pro_1.1_ultra").unwrap(), TaskModelType::FluxPro11Ultra); + assert_eq!(TaskModelType::from_str("flux_pro_kontext_max").unwrap(), TaskModelType::FluxProKontextMax); + assert_eq!(TaskModelType::from_str("gemini_25_flash").unwrap(), TaskModelType::Gemini25Flash); + assert_eq!(TaskModelType::from_str("nano_banana").unwrap(), TaskModelType::NanoBanana); + assert_eq!(TaskModelType::from_str("nano_banana_2").unwrap(), TaskModelType::NanoBanana2); + assert_eq!(TaskModelType::from_str("nano_banana_pro").unwrap(), TaskModelType::NanoBananaPro); + assert_eq!(TaskModelType::from_str("gpt_image_1").unwrap(), TaskModelType::GptImage1); + assert_eq!(TaskModelType::from_str("gpt_image_1p5").unwrap(), TaskModelType::GptImage1p5); + assert_eq!(TaskModelType::from_str("seedream_4").unwrap(), TaskModelType::Seedream4); + assert_eq!(TaskModelType::from_str("seedream_4p5").unwrap(), TaskModelType::Seedream4p5); + assert_eq!(TaskModelType::from_str("seedream_5_lite").unwrap(), TaskModelType::Seedream5Lite); + assert_eq!(TaskModelType::from_str("qwen_edit_2511_angles").unwrap(), TaskModelType::QwenEdit2511Angles); + assert_eq!(TaskModelType::from_str("flux_2_lora_angles").unwrap(), TaskModelType::Flux2LoraAngles); + assert_eq!(TaskModelType::from_str("grok_image").unwrap(), TaskModelType::GrokImage); + assert_eq!(TaskModelType::from_str("recraft_3").unwrap(), TaskModelType::Recraft3); + assert_eq!(TaskModelType::from_str("midjourney").unwrap(), TaskModelType::Midjourney); + // Video models + assert_eq!(TaskModelType::from_str("grok_video").unwrap(), TaskModelType::GrokVideo); + assert_eq!(TaskModelType::from_str("kling_1.6_pro").unwrap(), TaskModelType::Kling16Pro); + assert_eq!(TaskModelType::from_str("kling_2.1_pro").unwrap(), TaskModelType::Kling21Pro); + assert_eq!(TaskModelType::from_str("kling_2.1_master").unwrap(), TaskModelType::Kling21Master); + assert_eq!(TaskModelType::from_str("kling_2p5_turbo_pro").unwrap(), TaskModelType::Kling2p5TurboPro); + assert_eq!(TaskModelType::from_str("kling_2p6_pro").unwrap(), TaskModelType::Kling2p6Pro); + assert_eq!(TaskModelType::from_str("kling_3p0_standard").unwrap(), TaskModelType::Kling3p0Standard); + assert_eq!(TaskModelType::from_str("kling_3p0_pro").unwrap(), TaskModelType::Kling3p0Pro); + assert_eq!(TaskModelType::from_str("seedance_1.0_lite").unwrap(), TaskModelType::Seedance10Lite); + assert_eq!(TaskModelType::from_str("seedance_1p5_pro").unwrap(), TaskModelType::Seedance1p5Pro); + assert_eq!(TaskModelType::from_str("seedance_2p0").unwrap(), TaskModelType::Seedance2p0); + assert_eq!(TaskModelType::from_str("sora_2").unwrap(), TaskModelType::Sora2); + assert_eq!(TaskModelType::from_str("sora_2_pro").unwrap(), TaskModelType::Sora2Pro); + assert_eq!(TaskModelType::from_str("veo_2").unwrap(), TaskModelType::Veo2); + assert_eq!(TaskModelType::from_str("veo_3").unwrap(), TaskModelType::Veo3); + assert_eq!(TaskModelType::from_str("veo_3_fast").unwrap(), TaskModelType::Veo3Fast); + assert_eq!(TaskModelType::from_str("veo_3p1").unwrap(), TaskModelType::Veo3p1); + assert_eq!(TaskModelType::from_str("veo_3p1_fast").unwrap(), TaskModelType::Veo3p1Fast); + // 3D Object generation models + assert_eq!(TaskModelType::from_str("hunyuan_3d_2.0").unwrap(), TaskModelType::Hunyuan3d2_0); + assert_eq!(TaskModelType::from_str("hunyuan_3d_2.1").unwrap(), TaskModelType::Hunyuan3d2_1); + assert_eq!(TaskModelType::from_str("hunyuan_3d_3").unwrap(), TaskModelType::Hunyuan3d3); + assert_eq!(TaskModelType::from_str("worldlabs_marble").unwrap(), TaskModelType::WorldlabsMarble); + assert_eq!(TaskModelType::from_str("marble_0p1_mini").unwrap(), TaskModelType::WorldlabsMarble0p1Mini); + assert_eq!(TaskModelType::from_str("marble_0p1_plus").unwrap(), TaskModelType::WorldlabsMarble0p1Plus); + } + + #[test] + fn from_str_err() { + let result = TaskModelType::from_str("asdf"); + assert!(result.is_err()); + if let Err(EnumsError::CouldNotConvertFromString(value)) = result { + assert_eq!(value, "asdf"); + } else { + panic!("Expected EnumsError::CouldNotConvertFromString"); + } + } + + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip() { + use strum::IntoEnumIterator; + for variant in TaskModelType::iter() { + // Test to_str(), from_str(), Display, and Debug. + assert_eq!(variant, TaskModelType::from_str(variant.to_str()).unwrap()); + assert_eq!(variant, TaskModelType::from_str(&format!("{}", variant)).unwrap()); + assert_eq!(variant, TaskModelType::from_str(&format!("{:?}", variant)).unwrap()); + } + } + + #[test] + fn serialized_length_ok_for_database() { + use strum::IntoEnumIterator; + const MAX_LENGTH : usize = 24; + for variant in TaskModelType::iter() { + let serialized = variant.to_str(); + assert!(serialized.len() > 0, "variant {:?} is too short", variant); + assert!(serialized.len() <= MAX_LENGTH, "variant {:?} is too long", variant); + } + } + } +} diff --git a/crates/schema/public/enums_db/src/tauri/tasks/task_status.rs b/crates/schema/public/enums_db/src/tauri/tasks/task_status.rs new file mode 100644 index 0000000000..7bfb77666f --- /dev/null +++ b/crates/schema/public/enums_db/src/tauri/tasks/task_status.rs @@ -0,0 +1,154 @@ +use enums_shared::error::enums_error::EnumsError; +use strum::EnumCount; +use strum::EnumIter; + +#[derive(Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd, Serialize, Deserialize, EnumIter, EnumCount)] +#[serde(rename_all = "snake_case")] +pub enum TaskStatus { + Pending, + Started, + CompleteSuccess, + CompleteFailure, + AttemptFailed, + Dead, + CancelledByUser, + CancelledByProvider, + CancelledByUs, +} + +impl_enum_display_and_debug_using_to_str!(TaskStatus); +//impl_mysql_enum_coders!(TaskStatus); +//impl_mysql_from_row!(TaskStatus); + +// NB: We can derive `sqlx::Type` instead of using `impl_mysql_enum_coders` + +impl Default for TaskStatus { + fn default() -> Self { + Self::Pending + } +} + +impl TaskStatus { + pub const fn to_str(&self) -> &'static str { + match self { + Self::Pending => "pending", + Self::Started => "started", + Self::CompleteSuccess => "complete_success", + Self::CompleteFailure => "complete_failure", + Self::AttemptFailed => "attempt_failed", + Self::Dead => "dead", + Self::CancelledByUser => "cancelled_by_user", + Self::CancelledByProvider => "cancelled_by_provider", + Self::CancelledByUs => "cancelled_by_us", + } + } + + pub fn from_str(value: &str) -> Result { + match value { + "pending" => Ok(Self::Pending), + "started" => Ok(Self::Started), + "complete_success" => Ok(Self::CompleteSuccess), + "complete_failure" => Ok(Self::CompleteFailure), + "attempt_failed" => Ok(Self::AttemptFailed), + "dead" => Ok(Self::Dead), + "cancelled_by_user" => Ok(Self::CancelledByUser), + "cancelled_by_provider" => Ok(Self::CancelledByProvider), + "cancelled_by_us" => Ok(Self::CancelledByUs), + _ => Err(EnumsError::CouldNotConvertFromString(value.to_string())), + } + } + +} + +#[cfg(test)] +mod tests { + use super::TaskStatus; + use enums_shared::test_helpers::assert_serialization; + + mod explicit_checks { + use super::*; + use enums_shared::error::enums_error::EnumsError; + + #[test] + fn test_default() { + assert_eq!(TaskStatus::default(), TaskStatus::Pending); + } + + #[test] + fn test_serialization() { + assert_serialization(TaskStatus::Pending, "pending"); + assert_serialization(TaskStatus::Started, "started"); + assert_serialization(TaskStatus::CompleteSuccess, "complete_success"); + assert_serialization(TaskStatus::CompleteFailure, "complete_failure"); + assert_serialization(TaskStatus::AttemptFailed, "attempt_failed"); + assert_serialization(TaskStatus::Dead, "dead"); + assert_serialization(TaskStatus::CancelledByUser, "cancelled_by_user"); + assert_serialization(TaskStatus::CancelledByProvider, "cancelled_by_provider"); + assert_serialization(TaskStatus::CancelledByUs, "cancelled_by_us"); + } + + #[test] + fn to_str() { + assert_eq!(TaskStatus::Pending.to_str(), "pending"); + assert_eq!(TaskStatus::Started.to_str(), "started"); + assert_eq!(TaskStatus::CompleteSuccess.to_str(), "complete_success"); + assert_eq!(TaskStatus::CompleteFailure.to_str(), "complete_failure"); + assert_eq!(TaskStatus::AttemptFailed.to_str(), "attempt_failed"); + assert_eq!(TaskStatus::Dead.to_str(), "dead"); + assert_eq!(TaskStatus::CancelledByUser.to_str(), "cancelled_by_user"); + assert_eq!(TaskStatus::CancelledByProvider.to_str(), "cancelled_by_provider"); + assert_eq!(TaskStatus::CancelledByUs.to_str(), "cancelled_by_us"); + } + + #[test] + fn from_str() { + assert_eq!(TaskStatus::from_str("pending").unwrap(), TaskStatus::Pending); + assert_eq!(TaskStatus::from_str("started").unwrap(), TaskStatus::Started); + assert_eq!(TaskStatus::from_str("complete_success").unwrap(), TaskStatus::CompleteSuccess); + assert_eq!(TaskStatus::from_str("complete_failure").unwrap(), TaskStatus::CompleteFailure); + assert_eq!(TaskStatus::from_str("attempt_failed").unwrap(), TaskStatus::AttemptFailed); + assert_eq!(TaskStatus::from_str("dead").unwrap(), TaskStatus::Dead); + assert_eq!(TaskStatus::from_str("cancelled_by_user").unwrap(), TaskStatus::CancelledByUser); + assert_eq!(TaskStatus::from_str("cancelled_by_provider").unwrap(), TaskStatus::CancelledByProvider); + assert_eq!(TaskStatus::from_str("cancelled_by_us").unwrap(), TaskStatus::CancelledByUs); + } + + #[test] + fn from_str_err() { + let result = TaskStatus::from_str("asdf"); + assert!(result.is_err()); + if let Err(EnumsError::CouldNotConvertFromString(value)) = result { + assert_eq!(value, "asdf"); + } else { + panic!("Expected EnumsError::CouldNotConvertFromString"); + } + } + + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip() { + use strum::IntoEnumIterator; + for variant in TaskStatus::iter() { + // Test to_str(), from_str(), Display, and Debug. + assert_eq!(variant, TaskStatus::from_str(variant.to_str()).unwrap()); + assert_eq!(variant, TaskStatus::from_str(&format!("{}", variant)).unwrap()); + assert_eq!(variant, TaskStatus::from_str(&format!("{:?}", variant)).unwrap()); + } + } + + #[test] + fn serialized_length_ok_for_database() { + const MAX_LENGTH: usize = 32; // TODO(bt): Confirm database column width, then remove this comment. + use strum::IntoEnumIterator; + for variant in TaskStatus::iter() { + let serialized = variant.to_str(); + assert!(!serialized.is_empty(), "variant {:?} is too short", variant); + assert!(serialized.len() <= MAX_LENGTH, "variant {:?} is too long", variant); + } + } + } +} diff --git a/crates/schema/public/enums_db/src/tauri/tasks/task_type.rs b/crates/schema/public/enums_db/src/tauri/tasks/task_type.rs new file mode 100644 index 0000000000..fc1247f5fb --- /dev/null +++ b/crates/schema/public/enums_db/src/tauri/tasks/task_type.rs @@ -0,0 +1,125 @@ +use enums_shared::error::enums_error::EnumsError; +use strum::EnumCount; +use strum::EnumIter; + +#[derive(Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd, Serialize, Deserialize, EnumIter, EnumCount)] +#[serde(rename_all = "snake_case")] +pub enum TaskType { + ImageGeneration, + ImageInpaintEdit, + VideoGeneration, + ObjectGeneration, + GaussianGeneration, + BackgroundRemoval, +} + +impl_enum_display_and_debug_using_to_str!(TaskType); +//impl_mysql_enum_coders!(TaskType); +//impl_mysql_from_row!(TaskType); + +// NB: We can derive `sqlx::Type` instead of using `impl_mysql_enum_coders` + +impl TaskType { + pub fn to_str(&self) -> &'static str { + match self { + Self::ImageGeneration => "image_generation", + Self::ImageInpaintEdit => "image_inpaint_edit", + Self::VideoGeneration => "video_generation", + Self::ObjectGeneration => "object_generation", + Self::GaussianGeneration => "gaussian_generation", + Self::BackgroundRemoval => "background_removal", + } + } + + pub fn from_str(value: &str) -> Result { + match value { + "image_generation" => Ok(Self::ImageGeneration), + "image_inpaint_edit" => Ok(Self::ImageInpaintEdit), + "video_generation" => Ok(Self::VideoGeneration), + "object_generation" => Ok(Self::ObjectGeneration), + "gaussian_generation" => Ok(Self::GaussianGeneration), + "background_removal" => Ok(Self::BackgroundRemoval), + _ => Err(EnumsError::CouldNotConvertFromString(value.to_string())), + } + } + +} + +#[cfg(test)] +mod tests { + use super::TaskType; + use enums_shared::test_helpers::assert_serialization; + + mod explicit_checks { + use super::*; + use enums_shared::error::enums_error::EnumsError; + + #[test] + fn test_serialization() { + assert_serialization(TaskType::ImageGeneration, "image_generation"); + assert_serialization(TaskType::ImageInpaintEdit, "image_inpaint_edit"); + assert_serialization(TaskType::VideoGeneration, "video_generation"); + assert_serialization(TaskType::ObjectGeneration, "object_generation"); + assert_serialization(TaskType::GaussianGeneration, "gaussian_generation"); + assert_serialization(TaskType::BackgroundRemoval, "background_removal"); + } + + #[test] + fn to_str() { + assert_eq!(TaskType::ImageGeneration.to_str(), "image_generation"); + assert_eq!(TaskType::ImageInpaintEdit.to_str(), "image_inpaint_edit"); + assert_eq!(TaskType::VideoGeneration.to_str(), "video_generation"); + assert_eq!(TaskType::ObjectGeneration.to_str(), "object_generation"); + assert_eq!(TaskType::GaussianGeneration.to_str(), "gaussian_generation"); + assert_eq!(TaskType::BackgroundRemoval.to_str(), "background_removal"); + } + + #[test] + fn from_str() { + assert_eq!(TaskType::from_str("image_generation").unwrap(), TaskType::ImageGeneration); + assert_eq!(TaskType::from_str("image_inpaint_edit").unwrap(), TaskType::ImageInpaintEdit); + assert_eq!(TaskType::from_str("video_generation").unwrap(), TaskType::VideoGeneration); + assert_eq!(TaskType::from_str("object_generation").unwrap(), TaskType::ObjectGeneration); + assert_eq!(TaskType::from_str("gaussian_generation").unwrap(), TaskType::GaussianGeneration); + assert_eq!(TaskType::from_str("background_removal").unwrap(), TaskType::BackgroundRemoval); + } + + #[test] + fn from_str_err() { + let result = TaskType::from_str("asdf"); + assert!(result.is_err()); + if let Err(EnumsError::CouldNotConvertFromString(value)) = result { + assert_eq!(value, "asdf"); + } else { + panic!("Expected EnumsError::CouldNotConvertFromString"); + } + } + + } + + mod mechanical_checks { + use super::*; + + #[test] + fn round_trip() { + use strum::IntoEnumIterator; + for variant in TaskType::iter() { + // Test to_str(), from_str(), Display, and Debug. + assert_eq!(variant, TaskType::from_str(variant.to_str()).unwrap()); + assert_eq!(variant, TaskType::from_str(&format!("{}", variant)).unwrap()); + assert_eq!(variant, TaskType::from_str(&format!("{:?}", variant)).unwrap()); + } + } + + #[test] + fn serialized_length_ok_for_database() { + const MAX_LENGTH: usize = 32; // TODO(bt): Confirm database column width, then remove this comment. + use strum::IntoEnumIterator; + for variant in TaskType::iter() { + let serialized = variant.to_str(); + assert!(!serialized.is_empty(), "variant {:?} is too short", variant); + assert!(serialized.len() <= MAX_LENGTH, "variant {:?} is too long", variant); + } + } + } +} diff --git a/crates/schema/public/enums_db/src/tauri/ux/mod.rs b/crates/schema/public/enums_db/src/tauri/ux/mod.rs new file mode 100644 index 0000000000..40215426d6 --- /dev/null +++ b/crates/schema/public/enums_db/src/tauri/ux/mod.rs @@ -0,0 +1,2 @@ +pub mod tauri_command_caller; +pub mod tauri_event_name; diff --git a/crates/schema/public/enums_db/src/tauri/ux/tauri_command_caller.rs b/crates/schema/public/enums_db/src/tauri/ux/tauri_command_caller.rs new file mode 100644 index 0000000000..cebc72e6f5 --- /dev/null +++ b/crates/schema/public/enums_db/src/tauri/ux/tauri_command_caller.rs @@ -0,0 +1,115 @@ +use enums_shared::error::enums_error::EnumsError; +use strum::EnumCount; +use strum::EnumIter; + +/// Defines the names of the Tauri-sent events that the frontend subscribes to. +/// These event names are also stored in the database, so keep them short-ish. +#[derive(Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd, Serialize, Deserialize, EnumIter, EnumCount)] +#[serde(rename_all = "snake_case")] +pub enum TauriCommandCaller { + /// The 2D canvas + Canvas, + /// The inpainting editor + ImageEditor, + /// The text-to-image page + TextToImage, + /// The image-to-video page + ImageToVideo, + /// A mini-app (doesn't specify which one) + MiniApp, +} + +impl_enum_display_and_debug_using_to_str!(TauriCommandCaller); +impl_mysql_enum_coders!(TauriCommandCaller); +impl_mysql_from_row!(TauriCommandCaller); + +// NB: We can derive `sqlx::Type` instead of using `impl_mysql_enum_coders` + +impl TauriCommandCaller { + pub fn to_str(&self) -> &'static str { + match self { + Self::Canvas => "canvas", + Self::ImageEditor => "image_editor", + Self::TextToImage => "text_to_image", + Self::ImageToVideo => "image_to_video", + Self::MiniApp => "mini_app", + } + } + + pub fn from_str(value: &str) -> Result { + match value { + "canvas" => Ok(Self::Canvas), + "image_editor" => Ok(Self::ImageEditor), + "text_to_image" => Ok(Self::TextToImage), + "image_to_video" => Ok(Self::ImageToVideo), + "mini_app" => Ok(Self::MiniApp), + _ => Err(EnumsError::CouldNotConvertFromString(value.to_string())), + } + } + +} + +#[cfg(test)] +mod tests { + use enums_shared::error::enums_error::EnumsError; + use super::TauriCommandCaller; + use enums_shared::test_helpers::assert_serialization; + + mod explicit_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(TauriCommandCaller::Canvas, "canvas"); + assert_serialization(TauriCommandCaller::ImageEditor, "image_editor"); + assert_serialization(TauriCommandCaller::TextToImage, "text_to_image"); + assert_serialization(TauriCommandCaller::ImageToVideo, "image_to_video"); + assert_serialization(TauriCommandCaller::MiniApp, "mini_app"); + } + + #[test] + fn to_str() { + assert_eq!(TauriCommandCaller::Canvas.to_str(), "canvas"); + assert_eq!(TauriCommandCaller::ImageEditor.to_str(), "image_editor"); + assert_eq!(TauriCommandCaller::TextToImage.to_str(), "text_to_image"); + assert_eq!(TauriCommandCaller::ImageToVideo.to_str(), "image_to_video"); + assert_eq!(TauriCommandCaller::MiniApp.to_str(), "mini_app"); + } + + #[test] + fn from_str() { + assert_eq!(TauriCommandCaller::from_str("canvas").unwrap(), TauriCommandCaller::Canvas); + assert_eq!(TauriCommandCaller::from_str("image_editor").unwrap(), TauriCommandCaller::ImageEditor); + assert_eq!(TauriCommandCaller::from_str("text_to_image").unwrap(), TauriCommandCaller::TextToImage); + assert_eq!(TauriCommandCaller::from_str("image_to_video").unwrap(), TauriCommandCaller::ImageToVideo); + assert_eq!(TauriCommandCaller::from_str("mini_app").unwrap(), TauriCommandCaller::MiniApp); + } + + #[test] + fn from_str_err() { + let result = TauriCommandCaller::from_str("asdf"); + assert!(result.is_err()); + if let Err(EnumsError::CouldNotConvertFromString(value)) = result { + assert_eq!(value, "asdf"); + } else { + panic!("Expected EnumsError::CouldNotConvertFromString"); + } + } + + } + + mod mechanical_checks { + use super::*; + use strum::IntoEnumIterator; + + #[test] + fn round_trip() { + for variant in TauriCommandCaller::iter() { + // Test to_str(), from_str(), Display, and Debug. + assert_eq!(variant, TauriCommandCaller::from_str(variant.to_str()).unwrap()); + assert_eq!(variant, TauriCommandCaller::from_str(&format!("{}", variant)).unwrap()); + assert_eq!(variant, TauriCommandCaller::from_str(&format!("{:?}", variant)).unwrap()); + } + } + } +} diff --git a/crates/schema/public/enums_db/src/tauri/ux/tauri_event_name.rs b/crates/schema/public/enums_db/src/tauri/ux/tauri_event_name.rs new file mode 100644 index 0000000000..fbfddd21c9 --- /dev/null +++ b/crates/schema/public/enums_db/src/tauri/ux/tauri_event_name.rs @@ -0,0 +1,251 @@ +use strum::EnumCount; +use strum::EnumIter; + +/// Defines the names of the Tauri-sent events that the frontend subscribes to. +/// These event names are also stored in the database, so keep them short-ish. +/// +/// NB: Events should end in "_event" so they're easy to grep for in Javascript. +#[derive(Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd, Serialize, Deserialize, EnumIter, EnumCount)] +#[serde(rename_all = "snake_case")] +pub enum TauriEventName { + // TODO: Get rid of kebab case. + /// General purpose event: + /// Generation enqueued + #[serde(rename = "generation-enqueue-success-event")] + GenerationEnqueueSuccessEvent, + + // TODO: Get rid of kebab case. + /// General purpose event: + /// Generation failed to enqueue + #[serde(rename = "generation-enqueue-failure-event")] + GenerationEnqueueFailureEvent, + + // TODO: Get rid of kebab case. + /// General purpose event: + /// Generation completed successfully + #[serde(rename = "generation-complete-event")] + GenerationCompleteEvent, + + // TODO: Get rid of kebab case. + /// General purpose event: + /// Generation failed + #[serde(rename = "generation-failed-event")] + GenerationFailedEvent, + + /// Informational event: + /// Credits were purchased or spent (but we don't know how much) + #[serde(rename = "credits_balance_changed_event")] + CreditsBalanceChangedEvent, + + /// Informational event: + /// Subscription was changed (but we don't know the details - upgrade, cancel, etc.) + #[serde(rename = "subscription_plan_changed_event")] + SubscriptionPlanChangedEvent, + + /// Informational event: + /// A media file was deleted (and we'll send the token) + #[serde(rename = "media_file_deleted_event")] + MediaFileDeletedEvent, + + /// Special event: + /// Background removal is complete + #[serde(rename = "canvas_bg_removed_event")] + CanvasBgRemovedEvent, + + /// Special event: + /// Image generation is complete + #[serde(rename = "text_to_image_generation_complete_event")] + TextToImageGenerationCompleteEvent, + + /// Special event: + /// Image edit is complete + #[serde(rename = "image_edit_complete_event")] + ImageEditCompleteEvent, + + /// Special event: + /// Object (3D mesh) generation is complete + #[serde(rename = "object_generation_complete_event")] + ObjectGenerationCompleteEvent, + + /// Special event: + /// Gaussian generation is complete + #[serde(rename = "gaussian_generation_complete_event")] + GaussianGenerationCompleteEvent, + + /// Special event: + /// Video generation is complete + #[serde(rename = "video_generation_complete_event")] + VideoGenerationCompleteEvent, + + /// Special event: + /// Refresh account states + #[serde(rename = "refresh_account_state_event")] + RefreshAccountStateEvent, + + /// Special event: + /// Show a billing modal (a suggestion to pay, etc. for a specific provider) + #[serde(rename = "show_provider_billing_modal_event")] + ShowProviderBillingModalEvent, + + /// Special event: + /// Show a login modal (or a suggestion to login) + #[serde(rename = "show_provider_login_modal_event")] + ShowProviderLoginModalEvent, + + /// Warning event: + /// Flash a user input error message + #[serde(rename = "flash_user_input_error_event")] + FlashUserInputErrorEvent, + + /// Warning event: + /// File with that name was already downloaded + #[serde(rename = "flash_file_download_error_event")] + FlashFileDownloadErrorEvent, +} + +impl_enum_display_and_debug_using_to_str!(TauriEventName); +impl_mysql_enum_coders!(TauriEventName); +impl_mysql_from_row!(TauriEventName); + +// NB: We can derive `sqlx::Type` instead of using `impl_mysql_enum_coders` + +impl TauriEventName { + pub fn to_str(&self) -> &'static str { + match self { + Self::GenerationEnqueueSuccessEvent => "generation-enqueue-success-event", + Self::GenerationEnqueueFailureEvent => "generation-enqueue-failure-event", + Self::GenerationCompleteEvent => "generation-complete-event", + Self::GenerationFailedEvent => "generation-failed-event", + Self::CreditsBalanceChangedEvent => "credits_balance_changed_event", + Self::SubscriptionPlanChangedEvent => "subscription_plan_changed_event", + Self::MediaFileDeletedEvent => "media_file_deleted_event", + Self::CanvasBgRemovedEvent => "canvas_bg_removed_event", + Self::TextToImageGenerationCompleteEvent => "text_to_image_generation_complete_event", + Self::ImageEditCompleteEvent => "image_edit_complete_event", + Self::ObjectGenerationCompleteEvent => "object_generation_complete_event", + Self::GaussianGenerationCompleteEvent => "gaussian_generation_complete_event", + Self::VideoGenerationCompleteEvent => "video_generation_complete_event", + Self::RefreshAccountStateEvent => "refresh_account_state_event", + Self::ShowProviderBillingModalEvent => "show_provider_billing_modal_event", + Self::ShowProviderLoginModalEvent => "show_provider_login_modal_event", + Self::FlashUserInputErrorEvent => "flash_user_input_error_event", + Self::FlashFileDownloadErrorEvent => "flash_file_download_error_event", + } + } + + pub fn from_str(job_status: &str) -> Result { + match job_status { + "generation-enqueue-success-event" => Ok(Self::GenerationEnqueueSuccessEvent), + "generation-enqueue-failure-event" => Ok(Self::GenerationEnqueueFailureEvent), + "generation-complete-event" => Ok(Self::GenerationCompleteEvent), + "generation-failed-event" => Ok(Self::GenerationFailedEvent), + "credits_balance_changed_event" => Ok(Self::CreditsBalanceChangedEvent), + "subscription_plan_changed_event" => Ok(Self::SubscriptionPlanChangedEvent), + "media_file_deleted_event" => Ok(Self::MediaFileDeletedEvent), + "canvas_bg_removed_event" => Ok(Self::CanvasBgRemovedEvent), + "text_to_image_generation_complete_event" => Ok(Self::TextToImageGenerationCompleteEvent), + "image_edit_complete_event" => Ok(Self::ImageEditCompleteEvent), + "object_generation_complete_event" => Ok(Self::ObjectGenerationCompleteEvent), + "gaussian_generation_complete_event" => Ok(Self::GaussianGenerationCompleteEvent), + "video_generation_complete_event" => Ok(Self::VideoGenerationCompleteEvent), + "refresh_account_state_event" => Ok(Self::RefreshAccountStateEvent), + "show_provider_billing_modal_event" => Ok(Self::ShowProviderBillingModalEvent), + "show_provider_login_modal_event" => Ok(Self::ShowProviderLoginModalEvent), + "flash_user_input_error_event" => Ok(Self::FlashUserInputErrorEvent), + "flash_file_download_error_event" => Ok(Self::FlashFileDownloadErrorEvent), + _ => Err(format!("invalid tauri_event_name: {:?}", job_status)), + } + } +} + +#[cfg(test)] +mod tests { + use super::TauriEventName; + use enums_shared::test_helpers::assert_serialization; + + mod explicit_checks { + use super::*; + + #[test] + fn test_serialization() { + assert_serialization(TauriEventName::GenerationEnqueueSuccessEvent, "generation-enqueue-success-event"); + assert_serialization(TauriEventName::GenerationEnqueueFailureEvent, "generation-enqueue-failure-event"); + assert_serialization(TauriEventName::GenerationCompleteEvent, "generation-complete-event"); + assert_serialization(TauriEventName::GenerationFailedEvent, "generation-failed-event"); + assert_serialization(TauriEventName::CreditsBalanceChangedEvent, "credits_balance_changed_event"); + assert_serialization(TauriEventName::SubscriptionPlanChangedEvent, "subscription_plan_changed_event"); + assert_serialization(TauriEventName::MediaFileDeletedEvent, "media_file_deleted_event"); + assert_serialization(TauriEventName::CanvasBgRemovedEvent, "canvas_bg_removed_event"); + assert_serialization(TauriEventName::TextToImageGenerationCompleteEvent, "text_to_image_generation_complete_event"); + assert_serialization(TauriEventName::ImageEditCompleteEvent, "image_edit_complete_event"); + assert_serialization(TauriEventName::ObjectGenerationCompleteEvent, "object_generation_complete_event"); + assert_serialization(TauriEventName::GaussianGenerationCompleteEvent, "gaussian_generation_complete_event"); + assert_serialization(TauriEventName::VideoGenerationCompleteEvent, "video_generation_complete_event"); + assert_serialization(TauriEventName::RefreshAccountStateEvent, "refresh_account_state_event"); + assert_serialization(TauriEventName::ShowProviderBillingModalEvent, "show_provider_billing_modal_event"); + assert_serialization(TauriEventName::ShowProviderLoginModalEvent, "show_provider_login_modal_event"); + assert_serialization(TauriEventName::FlashUserInputErrorEvent, "flash_user_input_error_event"); + assert_serialization(TauriEventName::FlashFileDownloadErrorEvent, "flash_file_download_error_event"); + } + + #[test] + fn to_str() { + assert_eq!(TauriEventName::GenerationEnqueueSuccessEvent.to_str(), "generation-enqueue-success-event"); + assert_eq!(TauriEventName::GenerationEnqueueFailureEvent.to_str(), "generation-enqueue-failure-event"); + assert_eq!(TauriEventName::GenerationCompleteEvent.to_str(), "generation-complete-event"); + assert_eq!(TauriEventName::GenerationFailedEvent.to_str(), "generation-failed-event"); + assert_eq!(TauriEventName::CreditsBalanceChangedEvent.to_str(), "credits_balance_changed_event"); + assert_eq!(TauriEventName::SubscriptionPlanChangedEvent.to_str(), "subscription_plan_changed_event"); + assert_eq!(TauriEventName::MediaFileDeletedEvent.to_str(), "media_file_deleted_event"); + assert_eq!(TauriEventName::CanvasBgRemovedEvent.to_str(), "canvas_bg_removed_event"); + assert_eq!(TauriEventName::TextToImageGenerationCompleteEvent.to_str(), "text_to_image_generation_complete_event"); + assert_eq!(TauriEventName::ImageEditCompleteEvent.to_str(), "image_edit_complete_event"); + assert_eq!(TauriEventName::ObjectGenerationCompleteEvent.to_str(), "object_generation_complete_event"); + assert_eq!(TauriEventName::GaussianGenerationCompleteEvent.to_str(), "gaussian_generation_complete_event"); + assert_eq!(TauriEventName::VideoGenerationCompleteEvent.to_str(), "video_generation_complete_event"); + assert_eq!(TauriEventName::RefreshAccountStateEvent.to_str(), "refresh_account_state_event"); + assert_eq!(TauriEventName::ShowProviderBillingModalEvent.to_str(), "show_provider_billing_modal_event"); + assert_eq!(TauriEventName::ShowProviderLoginModalEvent.to_str(), "show_provider_login_modal_event"); + assert_eq!(TauriEventName::FlashUserInputErrorEvent.to_str(), "flash_user_input_error_event"); + assert_eq!(TauriEventName::FlashFileDownloadErrorEvent.to_str(), "flash_file_download_error_event"); + } + + #[test] + fn from_str() { + assert_eq!(TauriEventName::from_str("generation-enqueue-success-event").unwrap(), TauriEventName::GenerationEnqueueSuccessEvent); + assert_eq!(TauriEventName::from_str("generation-enqueue-failure-event").unwrap(), TauriEventName::GenerationEnqueueFailureEvent); + assert_eq!(TauriEventName::from_str("generation-complete-event").unwrap(), TauriEventName::GenerationCompleteEvent); + assert_eq!(TauriEventName::from_str("generation-failed-event").unwrap(), TauriEventName::GenerationFailedEvent); + assert_eq!(TauriEventName::from_str("credits_balance_changed_event").unwrap(), TauriEventName::CreditsBalanceChangedEvent); + assert_eq!(TauriEventName::from_str("subscription_plan_changed_event").unwrap(), TauriEventName::SubscriptionPlanChangedEvent); + assert_eq!(TauriEventName::from_str("media_file_deleted_event").unwrap(), TauriEventName::MediaFileDeletedEvent); + assert_eq!(TauriEventName::from_str("canvas_bg_removed_event").unwrap(), TauriEventName::CanvasBgRemovedEvent); + assert_eq!(TauriEventName::from_str("text_to_image_generation_complete_event").unwrap(), TauriEventName::TextToImageGenerationCompleteEvent); + assert_eq!(TauriEventName::from_str("image_edit_complete_event").unwrap(), TauriEventName::ImageEditCompleteEvent); + assert_eq!(TauriEventName::from_str("object_generation_complete_event").unwrap(), TauriEventName::ObjectGenerationCompleteEvent); + assert_eq!(TauriEventName::from_str("gaussian_generation_complete_event").unwrap(), TauriEventName::GaussianGenerationCompleteEvent); + assert_eq!(TauriEventName::from_str("video_generation_complete_event").unwrap(), TauriEventName::VideoGenerationCompleteEvent); + assert_eq!(TauriEventName::from_str("refresh_account_state_event").unwrap(), TauriEventName::RefreshAccountStateEvent); + assert_eq!(TauriEventName::from_str("show_provider_billing_modal_event").unwrap(), TauriEventName::ShowProviderBillingModalEvent); + assert_eq!(TauriEventName::from_str("show_provider_login_modal_event").unwrap(), TauriEventName::ShowProviderLoginModalEvent); + assert_eq!(TauriEventName::from_str("flash_user_input_error_event").unwrap(), TauriEventName::FlashUserInputErrorEvent); + assert_eq!(TauriEventName::from_str("flash_file_download_error_event").unwrap(), TauriEventName::FlashFileDownloadErrorEvent); + } + + } + + mod mechanical_checks { + use super::*; + use strum::IntoEnumIterator; + + #[test] + fn round_trip() { + for variant in TauriEventName::iter() { + // Test to_str(), from_str(), Display, and Debug. + assert_eq!(variant, TauriEventName::from_str(variant.to_str()).unwrap()); + assert_eq!(variant, TauriEventName::from_str(&format!("{}", variant)).unwrap()); + assert_eq!(variant, TauriEventName::from_str(&format!("{:?}", variant)).unwrap()); + } + } + } +} diff --git a/crates/schema/public/enums_db/src/traits/mod.rs b/crates/schema/public/enums_db/src/traits/mod.rs new file mode 100644 index 0000000000..287cadb28c --- /dev/null +++ b/crates/schema/public/enums_db/src/traits/mod.rs @@ -0,0 +1 @@ +pub mod mysql_from_row; diff --git a/crates/schema/public/enums_db/src/traits/mysql_from_row.rs b/crates/schema/public/enums_db/src/traits/mysql_from_row.rs new file mode 100644 index 0000000000..7d3c3cbb67 --- /dev/null +++ b/crates/schema/public/enums_db/src/traits/mysql_from_row.rs @@ -0,0 +1,11 @@ +use sqlx_mysql::MySqlRow; + +/// This is a trait (in conjunction with the macro implementation) that makes up for sqlx's +/// QueryBuilder not playing well with FromRow implementation or derivation of named types. +pub trait MySqlFromRow { + + /// Attempt to parse a named column from a MySqlRow into the type. + fn try_from_mysql_row(row: &MySqlRow, field_name: &str) -> Result; + + fn try_from_mysql_row_nullable(row: &MySqlRow, field_name: &str) -> Result, sqlx::Error>; +} diff --git a/crates/schema/public/enums_shared/Cargo.toml b/crates/schema/public/enums_shared/Cargo.toml new file mode 100644 index 0000000000..f4b8adaedd --- /dev/null +++ b/crates/schema/public/enums_shared/Cargo.toml @@ -0,0 +1,34 @@ +[package] +name = "enums_shared" +edition = "2021" +version = "0.0.1" +authors = [ + "Brandon Thomas ", + "Brandon Thomas ", +] +publish = false + +[package.metadata.cargo-udeps.ignore] +normal = ["workspace-build-acceleration"] + +[lib] +name = "enums_shared" +path = "src/lib.rs" + +[dependencies] +# Workspace hack (faster compile times) +workspace-build-acceleration.workspace = true + +# Serialization +serde.workspace = true +serde_derive.workspace = true +serde_json.workspace = true + +log.workspace = true + +[dev-dependencies] +# Enum utilities +strum.workspace = true + +# Test serialization +toml.workspace = true diff --git a/crates/schema/public/enums_shared/src/error/enums_error.rs b/crates/schema/public/enums_shared/src/error/enums_error.rs new file mode 100644 index 0000000000..d4ad783183 --- /dev/null +++ b/crates/schema/public/enums_shared/src/error/enums_error.rs @@ -0,0 +1,18 @@ +use std::error::Error; + +#[derive(Debug)] +pub enum EnumsError { + CouldNotConvertFromString(String), +} + +impl Error for EnumsError {} + +impl std::fmt::Display for EnumsError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + EnumsError::CouldNotConvertFromString(value) => { + write!(f, "Could not convert from string: {}", value) + } + } + } +} diff --git a/crates/schema/public/enums_shared/src/error/mod.rs b/crates/schema/public/enums_shared/src/error/mod.rs new file mode 100644 index 0000000000..123182374d --- /dev/null +++ b/crates/schema/public/enums_shared/src/error/mod.rs @@ -0,0 +1 @@ +pub mod enums_error; diff --git a/crates/schema/public/enums_shared/src/lib.rs b/crates/schema/public/enums_shared/src/lib.rs new file mode 100644 index 0000000000..d93795852e --- /dev/null +++ b/crates/schema/public/enums_shared/src/lib.rs @@ -0,0 +1,21 @@ +// Never allow these +#![forbid(private_bounds)] +#![forbid(private_interfaces)] +#![forbid(unused_must_use)] // NB: It's unsafe to not close/check some things + +// Okay to toggle +#![forbid(unreachable_patterns)] +#![deny(unused_imports)] +#![forbid(unused_mut)] +#![forbid(unused_variables)] + +// Always allow +#![allow(dead_code)] +#![allow(non_snake_case)] + +#[allow(unused_imports)] +#[macro_use] extern crate serde_derive; + +pub mod error; +#[macro_use] pub mod macros; +pub mod test_helpers; diff --git a/crates/schema/public/enums_shared/src/macros/mod.rs b/crates/schema/public/enums_shared/src/macros/mod.rs new file mode 100644 index 0000000000..0f6a711358 --- /dev/null +++ b/crates/schema/public/enums_shared/src/macros/mod.rs @@ -0,0 +1 @@ +// (empty — macros moved to enums_db) diff --git a/crates/schema/public/enums_shared/src/test_helpers.rs b/crates/schema/public/enums_shared/src/test_helpers.rs new file mode 100644 index 0000000000..b8a6b62911 --- /dev/null +++ b/crates/schema/public/enums_shared/src/test_helpers.rs @@ -0,0 +1,24 @@ +//! Only imported in tests + +use serde::{Serialize, de::DeserializeOwned}; + +pub fn to_json(t: &T) -> String { + serde_json::to_string(t) + .expect("serialization error") + .replace("\"", "") // JSON values are quoted, so we remove quotes +} + +/// Assert that the Serialize is represented by the expected string value. +/// This is useful for ensuring stability of serialization. +pub fn assert_serialization(t: T, expected: &str) { + assert_eq!(&to_json(&t), expected); +} + +/// Assert that a JSON string deserializes to the expected value. +/// This is useful for ensuring stability of deserialization. +pub fn assert_deserialization(json_str: &str, expected: T) { + let quoted = format!("\"{}\"", json_str); + let actual: T = serde_json::from_str("ed) + .unwrap_or_else(|e| panic!("failed to deserialize {:?}: {}", json_str, e)); + assert_eq!(actual, expected); +}