ruvector_scipix/api/
requests.rs1use serde::{Deserialize, Serialize};
2use validator::Validate;
3
4#[derive(Debug, Clone, Serialize, Deserialize, Validate)]
6pub struct TextRequest {
7 #[serde(skip_serializing_if = "Option::is_none")]
9 pub src: Option<String>,
10
11 #[serde(skip_serializing_if = "Option::is_none")]
13 pub base64: Option<String>,
14
15 #[serde(skip_serializing_if = "Option::is_none")]
17 #[validate(url)]
18 pub url: Option<String>,
19
20 #[serde(default)]
22 pub metadata: RequestMetadata,
23}
24
25impl TextRequest {
26 pub async fn get_image_data(&self) -> anyhow::Result<Vec<u8>> {
28 if let Some(base64_data) = &self.base64 {
29 use base64::Engine;
31 let decoded = base64::engine::general_purpose::STANDARD.decode(base64_data)?;
32 Ok(decoded)
33 } else if let Some(url) = &self.url {
34 let response = reqwest::get(url).await?;
36 let bytes = response.bytes().await?;
37 Ok(bytes.to_vec())
38 } else {
39 anyhow::bail!("No image data provided")
40 }
41 }
42}
43
44#[derive(Debug, Clone, Serialize, Deserialize, Validate)]
46pub struct StrokesRequest {
47 #[validate(length(min = 1))]
49 pub strokes: Vec<Stroke>,
50
51 #[serde(default)]
53 pub metadata: RequestMetadata,
54}
55
56#[derive(Debug, Clone, Serialize, Deserialize)]
58pub struct Stroke {
59 pub x: Vec<f64>,
61
62 pub y: Vec<f64>,
64
65 #[serde(skip_serializing_if = "Option::is_none")]
67 pub t: Option<Vec<f64>>,
68}
69
70#[derive(Debug, Clone, Serialize, Deserialize, Validate)]
72pub struct LatexRequest {
73 #[serde(skip_serializing_if = "Option::is_none")]
75 pub src: Option<String>,
76
77 #[serde(skip_serializing_if = "Option::is_none")]
79 pub base64: Option<String>,
80
81 #[serde(skip_serializing_if = "Option::is_none")]
83 #[validate(url)]
84 pub url: Option<String>,
85
86 #[serde(default)]
88 pub metadata: RequestMetadata,
89}
90
91#[derive(Debug, Clone, Serialize, Deserialize, Validate)]
93pub struct PdfRequest {
94 #[validate(url)]
96 pub url: String,
97
98 #[serde(default)]
100 pub options: PdfOptions,
101
102 #[serde(skip_serializing_if = "Option::is_none")]
104 #[validate(url)]
105 pub webhook_url: Option<String>,
106
107 #[serde(default)]
109 pub metadata: RequestMetadata,
110}
111
112#[derive(Debug, Clone, Serialize, Deserialize, Default)]
114pub struct PdfOptions {
115 #[serde(default = "default_format")]
117 pub format: String,
118
119 #[serde(default)]
121 pub enable_ocr: bool,
122
123 #[serde(default = "default_true")]
125 pub include_images: bool,
126
127 #[serde(skip_serializing_if = "Option::is_none")]
129 pub page_range: Option<String>,
130}
131
132fn default_format() -> String {
133 "mmd".to_string()
134}
135
136fn default_true() -> bool {
137 true
138}
139
140#[derive(Debug, Clone, Serialize, Deserialize, Default)]
142pub struct RequestMetadata {
143 #[serde(default = "default_formats")]
145 pub formats: Vec<String>,
146
147 #[serde(default)]
149 pub include_confidence: bool,
150
151 #[serde(default = "default_true")]
153 pub enable_math: bool,
154
155 #[serde(skip_serializing_if = "Option::is_none")]
157 pub language: Option<String>,
158}
159
160fn default_formats() -> Vec<String> {
161 vec!["text".to_string()]
162}
163
164#[cfg(test)]
165mod tests {
166 use super::*;
167
168 #[test]
169 fn test_text_request_validation() {
170 let request = TextRequest {
171 src: None,
172 base64: Some("SGVsbG8gV29ybGQ=".to_string()),
173 url: None,
174 metadata: RequestMetadata::default(),
175 };
176
177 assert!(request.validate().is_ok());
178 }
179
180 #[test]
181 fn test_strokes_request_validation() {
182 let request = StrokesRequest {
183 strokes: vec![Stroke {
184 x: vec![0.0, 1.0, 2.0],
185 y: vec![0.0, 1.0, 0.0],
186 t: None,
187 }],
188 metadata: RequestMetadata::default(),
189 };
190
191 assert!(request.validate().is_ok());
192 }
193
194 #[test]
195 fn test_empty_strokes_validation() {
196 let request = StrokesRequest {
197 strokes: vec![],
198 metadata: RequestMetadata::default(),
199 };
200
201 assert!(request.validate().is_err());
202 }
203
204 #[test]
205 fn test_pdf_request_validation() {
206 let request = PdfRequest {
207 url: "https://example.com/document.pdf".to_string(),
208 options: PdfOptions::default(),
209 webhook_url: None,
210 metadata: RequestMetadata::default(),
211 };
212
213 assert!(request.validate().is_ok());
214 }
215
216 #[test]
217 fn test_invalid_url() {
218 let request = PdfRequest {
219 url: "not-a-url".to_string(),
220 options: PdfOptions::default(),
221 webhook_url: None,
222 metadata: RequestMetadata::default(),
223 };
224
225 assert!(request.validate().is_err());
226 }
227}