170 lines
5.0 KiB
Rust
170 lines
5.0 KiB
Rust
use serde::{Deserialize, Serialize};
|
|
use serde_json::Value;
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
|
|
#[serde(rename_all = "kebab-case")]
|
|
pub enum Hyper3dGenerationMode {
|
|
TextToModel,
|
|
ImageToModel,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct Hyper3dTextToModelRequest {
|
|
pub prompt: String,
|
|
#[serde(default)]
|
|
pub negative_prompt: Option<String>,
|
|
#[serde(default)]
|
|
pub seed: Option<u32>,
|
|
#[serde(default)]
|
|
pub geometry_file_format: Option<String>,
|
|
#[serde(default)]
|
|
pub material: Option<String>,
|
|
#[serde(default)]
|
|
pub quality: Option<String>,
|
|
#[serde(default)]
|
|
pub mesh_mode: Option<String>,
|
|
#[serde(default)]
|
|
pub addons: Vec<String>,
|
|
#[serde(default)]
|
|
pub bbox_condition: Option<Vec<f32>>,
|
|
#[serde(default)]
|
|
pub preview_render: Option<bool>,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct Hyper3dImageToModelRequest {
|
|
#[serde(default)]
|
|
pub image_data_urls: Vec<String>,
|
|
#[serde(default)]
|
|
pub image_urls: Vec<String>,
|
|
#[serde(default)]
|
|
pub prompt: Option<String>,
|
|
#[serde(default)]
|
|
pub condition_mode: Option<String>,
|
|
#[serde(default)]
|
|
pub seed: Option<u32>,
|
|
#[serde(default)]
|
|
pub geometry_file_format: Option<String>,
|
|
#[serde(default)]
|
|
pub material: Option<String>,
|
|
#[serde(default)]
|
|
pub quality: Option<String>,
|
|
#[serde(default)]
|
|
pub mesh_mode: Option<String>,
|
|
#[serde(default)]
|
|
pub addons: Vec<String>,
|
|
#[serde(default)]
|
|
pub bbox_condition: Option<Vec<f32>>,
|
|
#[serde(default)]
|
|
pub preview_render: Option<bool>,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct Hyper3dTaskSubmitResponse {
|
|
pub ok: bool,
|
|
pub provider: String,
|
|
pub mode: Hyper3dGenerationMode,
|
|
pub task_uuid: String,
|
|
pub subscription_key: String,
|
|
pub job_uuids: Vec<String>,
|
|
pub message: Option<String>,
|
|
pub tier: String,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct Hyper3dTaskStatusRequest {
|
|
pub subscription_key: String,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct Hyper3dTaskStatusResponse {
|
|
pub ok: bool,
|
|
pub provider: String,
|
|
pub status: String,
|
|
#[serde(default)]
|
|
pub jobs: Vec<Hyper3dJobStatusPayload>,
|
|
pub raw: Value,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct Hyper3dJobStatusPayload {
|
|
pub uuid: Option<String>,
|
|
pub status: String,
|
|
pub progress: Option<f32>,
|
|
pub message: Option<String>,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct Hyper3dDownloadRequest {
|
|
pub task_uuid: String,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct Hyper3dDownloadResponse {
|
|
pub ok: bool,
|
|
pub provider: String,
|
|
#[serde(default)]
|
|
pub files: Vec<Hyper3dDownloadFilePayload>,
|
|
pub raw: Value,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct Hyper3dDownloadFilePayload {
|
|
pub name: String,
|
|
pub url: String,
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
use serde_json::json;
|
|
|
|
#[test]
|
|
fn text_to_model_request_uses_camel_case_fields() {
|
|
let payload = serde_json::to_value(Hyper3dTextToModelRequest {
|
|
prompt: "低多边形宝箱".to_string(),
|
|
negative_prompt: Some("文字".to_string()),
|
|
seed: Some(42),
|
|
geometry_file_format: Some("glb".to_string()),
|
|
material: Some("PBR".to_string()),
|
|
quality: Some("medium".to_string()),
|
|
mesh_mode: Some("Quad".to_string()),
|
|
addons: vec!["HighPack".to_string()],
|
|
bbox_condition: Some(vec![1.0, 1.0, 1.0]),
|
|
preview_render: Some(true),
|
|
})
|
|
.expect("request should serialize");
|
|
|
|
assert_eq!(payload["geometryFileFormat"], json!("glb"));
|
|
assert_eq!(payload["meshMode"], json!("Quad"));
|
|
assert_eq!(payload["bboxCondition"], json!([1.0, 1.0, 1.0]));
|
|
}
|
|
|
|
#[test]
|
|
fn submit_response_keeps_mode_as_kebab_case() {
|
|
let payload = serde_json::to_value(Hyper3dTaskSubmitResponse {
|
|
ok: true,
|
|
provider: "hyper3d-rodin".to_string(),
|
|
mode: Hyper3dGenerationMode::ImageToModel,
|
|
task_uuid: "task-1".to_string(),
|
|
subscription_key: "sub-1".to_string(),
|
|
job_uuids: vec!["job-1".to_string()],
|
|
message: Some("submitted".to_string()),
|
|
tier: "Gen-2".to_string(),
|
|
})
|
|
.expect("response should serialize");
|
|
|
|
assert_eq!(payload["mode"], json!("image-to-model"));
|
|
assert_eq!(payload["subscriptionKey"], json!("sub-1"));
|
|
}
|
|
}
|