Skip to main content

systemprompt_files/models/
image_metadata.rs

1//! Image metadata and generation-info models.
2//!
3//! Copyright (c) systemprompt.io — Business Source License 1.1.
4//! See <https://systemprompt.io> for licensing details.
5
6use serde::{Deserialize, Serialize};
7use systemprompt_identifiers::AiRequestId;
8
9#[derive(Debug, Clone, Default, Serialize, Deserialize)]
10pub struct ImageMetadata {
11    #[serde(default, skip_serializing_if = "Option::is_none")]
12    pub width: Option<u32>,
13
14    #[serde(default, skip_serializing_if = "Option::is_none")]
15    pub height: Option<u32>,
16
17    #[serde(default, skip_serializing_if = "Option::is_none")]
18    pub alt_text: Option<String>,
19
20    #[serde(default, skip_serializing_if = "Option::is_none")]
21    pub description: Option<String>,
22
23    #[serde(default, skip_serializing_if = "Option::is_none")]
24    pub generation: Option<ImageGenerationInfo>,
25}
26
27#[derive(Debug, Clone, Serialize, Deserialize)]
28pub struct ImageGenerationInfo {
29    pub prompt: String,
30    pub model: String,
31    pub provider: String,
32
33    #[serde(default, skip_serializing_if = "Option::is_none")]
34    pub resolution: Option<String>,
35
36    #[serde(default, skip_serializing_if = "Option::is_none")]
37    pub aspect_ratio: Option<String>,
38
39    #[serde(default, skip_serializing_if = "Option::is_none")]
40    pub generation_time_ms: Option<i32>,
41
42    #[serde(default, skip_serializing_if = "Option::is_none")]
43    pub cost_estimate: Option<f32>,
44
45    #[serde(default, skip_serializing_if = "Option::is_none")]
46    pub request_id: Option<String>,
47}
48
49impl ImageMetadata {
50    pub const fn new() -> Self {
51        Self {
52            width: None,
53            height: None,
54            alt_text: None,
55            description: None,
56            generation: None,
57        }
58    }
59
60    pub const fn with_dimensions(mut self, width: u32, height: u32) -> Self {
61        self.width = Some(width);
62        self.height = Some(height);
63        self
64    }
65
66    pub fn with_alt_text(mut self, alt: impl Into<String>) -> Self {
67        self.alt_text = Some(alt.into());
68        self
69    }
70
71    pub fn with_description(mut self, desc: impl Into<String>) -> Self {
72        self.description = Some(desc.into());
73        self
74    }
75
76    pub fn with_generation(mut self, generation: ImageGenerationInfo) -> Self {
77        self.generation = Some(generation);
78        self
79    }
80}
81
82impl ImageGenerationInfo {
83    pub fn new(
84        prompt: impl Into<String>,
85        model: impl Into<String>,
86        provider: impl Into<String>,
87    ) -> Self {
88        Self {
89            prompt: prompt.into(),
90            model: model.into(),
91            provider: provider.into(),
92            resolution: None,
93            aspect_ratio: None,
94            generation_time_ms: None,
95            cost_estimate: None,
96            request_id: None,
97        }
98    }
99
100    pub fn with_resolution(mut self, resolution: impl Into<String>) -> Self {
101        self.resolution = Some(resolution.into());
102        self
103    }
104
105    pub fn with_aspect_ratio(mut self, aspect_ratio: impl Into<String>) -> Self {
106        self.aspect_ratio = Some(aspect_ratio.into());
107        self
108    }
109
110    pub const fn with_generation_time(mut self, time_ms: i32) -> Self {
111        self.generation_time_ms = Some(time_ms);
112        self
113    }
114
115    pub const fn with_cost_estimate(mut self, cost: f32) -> Self {
116        self.cost_estimate = Some(cost);
117        self
118    }
119
120    pub fn with_request_id(mut self, request_id: &AiRequestId) -> Self {
121        self.request_id = Some(request_id.as_str().to_owned());
122        self
123    }
124}