Skip to main content

novel_openai/spec/
impls.rs

1#[cfg(any(
2    feature = "audio-types",
3    feature = "file-types",
4    feature = "image-types",
5    feature = "video-types"
6))]
7use std::path::Path;
8
9#[cfg(any(
10    feature = "audio-types",
11    feature = "file-types",
12    feature = "image-types",
13    feature = "video-types"
14))]
15use bytes::Bytes;
16
17#[cfg(feature = "response-types")]
18use super::CreateMessageRequestContent;
19#[cfg(feature = "embedding-types")]
20use super::EmbeddingInput;
21#[cfg(feature = "moderation-types")]
22use super::ModerationInput;
23#[cfg(any(feature = "chat-completion-types", feature = "completion-types"))]
24use super::chat::Prompt;
25#[cfg(any(
26    feature = "audio-types",
27    feature = "file-types",
28    feature = "image-types",
29    feature = "video-types"
30))]
31use super::{AudioInput, FileInput, ImageInput};
32#[cfg(any(feature = "chat-completion-types", feature = "completion-types"))]
33use super::{ChatCompletionToolChoiceOption, StopConfiguration};
34#[cfg(any(
35    feature = "audio-types",
36    feature = "file-types",
37    feature = "image-types",
38    feature = "video-types"
39))]
40use crate::spec::InputSource;
41
42/// for `impl_from!(T, Enum)`, implements
43/// - `From<T>`
44/// - `From<Vec<T>>`
45/// - `From<&Vec<T>>`
46/// - `From<[T; N]>`
47/// - `From<&[T; N]>`
48///
49/// for `T: Into<String>` and `Enum` having variants `String(String)` and `StringArray(Vec<String>)`
50#[cfg(any(
51    feature = "chat-completion-types",
52    feature = "completion-types",
53    feature = "embedding-types",
54    feature = "moderation-types"
55))]
56macro_rules! impl_from {
57    ($from_typ:ty, $to_typ:ty) => {
58        // From<T> -> String variant
59        impl From<$from_typ> for $to_typ {
60            fn from(value: $from_typ) -> Self {
61                <$to_typ>::String(value.into())
62            }
63        }
64
65        // From<Vec<T>> -> StringArray variant
66        impl From<Vec<$from_typ>> for $to_typ {
67            fn from(value: Vec<$from_typ>) -> Self {
68                <$to_typ>::StringArray(value.iter().map(|v| v.to_string()).collect())
69            }
70        }
71
72        // From<&Vec<T>> -> StringArray variant
73        impl From<&Vec<$from_typ>> for $to_typ {
74            fn from(value: &Vec<$from_typ>) -> Self {
75                <$to_typ>::StringArray(value.iter().map(|v| v.to_string()).collect())
76            }
77        }
78
79        // From<[T; N]> -> StringArray variant
80        impl<const N: usize> From<[$from_typ; N]> for $to_typ {
81            fn from(value: [$from_typ; N]) -> Self {
82                <$to_typ>::StringArray(value.into_iter().map(|v| v.to_string()).collect())
83            }
84        }
85
86        // From<&[T; N]> -> StringArray variatn
87        impl<const N: usize> From<&[$from_typ; N]> for $to_typ {
88            fn from(value: &[$from_typ; N]) -> Self {
89                <$to_typ>::StringArray(value.into_iter().map(|v| v.to_string()).collect())
90            }
91        }
92    };
93}
94
95// From String "family" to Prompt
96#[cfg(any(feature = "chat-completion-types", feature = "completion-types"))]
97impl_from!(&str, Prompt);
98#[cfg(any(feature = "chat-completion-types", feature = "completion-types"))]
99impl_from!(String, Prompt);
100#[cfg(any(feature = "chat-completion-types", feature = "completion-types"))]
101impl_from!(&String, Prompt);
102
103// From String "family" to StopConfiguration
104#[cfg(any(feature = "chat-completion-types", feature = "completion-types"))]
105impl_from!(&str, StopConfiguration);
106#[cfg(any(feature = "chat-completion-types", feature = "completion-types"))]
107impl_from!(String, StopConfiguration);
108#[cfg(any(feature = "chat-completion-types", feature = "completion-types"))]
109impl_from!(&String, StopConfiguration);
110
111// From String "family" to ModerationInput
112#[cfg(feature = "moderation-types")]
113impl_from!(&str, ModerationInput);
114#[cfg(feature = "moderation-types")]
115impl_from!(String, ModerationInput);
116#[cfg(feature = "moderation-types")]
117impl_from!(&String, ModerationInput);
118
119// From String "family" to EmbeddingInput
120#[cfg(feature = "embedding-types")]
121impl_from!(&str, EmbeddingInput);
122#[cfg(feature = "embedding-types")]
123impl_from!(String, EmbeddingInput);
124#[cfg(feature = "embedding-types")]
125impl_from!(&String, EmbeddingInput);
126
127/// for `impl_default!(Enum)`, implements `Default` for `Enum` as `Enum::String("")` where `Enum`
128/// has `String` variant
129#[cfg(any(
130    feature = "chat-completion-types",
131    feature = "completion-types",
132    feature = "embedding-types",
133    feature = "moderation-types"
134))]
135macro_rules! impl_default {
136    ($for_typ:ty) => {
137        impl Default for $for_typ {
138            fn default() -> Self {
139                Self::String("".into())
140            }
141        }
142    };
143}
144
145#[cfg(any(feature = "chat-completion-types", feature = "completion-types"))]
146impl_default!(Prompt);
147#[cfg(feature = "moderation-types")]
148impl_default!(ModerationInput);
149#[cfg(feature = "embedding-types")]
150impl_default!(EmbeddingInput);
151
152/// for `impl_input!(Struct)` where
153/// ```text
154/// Struct {
155///     source: InputSource
156/// }
157/// ```
158/// implements methods `from_bytes` and `from_vec_u8`,
159/// and `From<P>` for `P: AsRef<Path>`
160#[cfg(any(
161    feature = "audio-types",
162    feature = "file-types",
163    feature = "image-types",
164    feature = "video-types"
165))]
166macro_rules! impl_input {
167    ($for_typ:ty) => {
168        impl $for_typ {
169            pub fn from_bytes(filename: String, bytes: Bytes) -> Self {
170                Self {
171                    source: InputSource::Bytes { filename, bytes },
172                }
173            }
174
175            pub fn from_vec_u8(filename: String, vec: Vec<u8>) -> Self {
176                Self {
177                    source: InputSource::VecU8 { filename, vec },
178                }
179            }
180        }
181
182        #[cfg(not(target_family = "wasm"))]
183        impl<P: AsRef<Path>> From<P> for $for_typ {
184            fn from(path: P) -> Self {
185                let path_buf = path.as_ref().to_path_buf();
186                Self {
187                    source: InputSource::Path { path: path_buf },
188                }
189            }
190        }
191    };
192}
193
194#[cfg(feature = "audio-types")]
195impl_input!(AudioInput);
196#[cfg(feature = "file-types")]
197impl_input!(FileInput);
198#[cfg(any(feature = "image-types", feature = "video-types"))]
199impl_input!(ImageInput);
200
201// Note: Display impls for ImageSize, DallE2ImageSize, ImageModel, ImageResponseFormat
202// are in spec/images/impls.rs
203
204// Note: Display impls for AudioResponseFormat, TimestampGranularity
205// are in spec/audio/impls.rs
206
207// Note: Display impl for Role is in spec/chat/impls.rs
208
209// Note: Display impl for FilePurpose is in spec/files/impls.rs
210
211// Note: ImagesResponse::save and Image::save implementations are in spec/images/sdk.rs
212// Note: CreateSpeechResponse::save implementation is in spec/audio/sdk.rs
213
214macro_rules! impl_from_for_integer_array {
215    ($from_typ:ty, $to_typ:ty) => {
216        impl<const N: usize> From<[$from_typ; N]> for $to_typ {
217            fn from(value: [$from_typ; N]) -> Self {
218                Self::IntegerArray(value.to_vec())
219            }
220        }
221
222        impl<const N: usize> From<&[$from_typ; N]> for $to_typ {
223            fn from(value: &[$from_typ; N]) -> Self {
224                Self::IntegerArray(value.to_vec())
225            }
226        }
227
228        impl From<Vec<$from_typ>> for $to_typ {
229            fn from(value: Vec<$from_typ>) -> Self {
230                Self::IntegerArray(value)
231            }
232        }
233
234        impl From<&Vec<$from_typ>> for $to_typ {
235            fn from(value: &Vec<$from_typ>) -> Self {
236                Self::IntegerArray(value.clone())
237            }
238        }
239    };
240}
241
242#[cfg(feature = "embedding-types")]
243impl_from_for_integer_array!(u32, EmbeddingInput);
244#[cfg(any(feature = "chat-completion-types", feature = "completion-types"))]
245impl_from_for_integer_array!(u32, Prompt);
246#[cfg(any(
247    feature = "chat-completion-types",
248    feature = "completion-types",
249    feature = "embedding-types"
250))]
251macro_rules! impl_from_for_array_of_integer_array {
252    ($from_typ:ty, $to_typ:ty) => {
253        impl From<Vec<Vec<$from_typ>>> for $to_typ {
254            fn from(value: Vec<Vec<$from_typ>>) -> Self {
255                Self::ArrayOfIntegerArray(value)
256            }
257        }
258
259        impl From<&Vec<Vec<$from_typ>>> for $to_typ {
260            fn from(value: &Vec<Vec<$from_typ>>) -> Self {
261                Self::ArrayOfIntegerArray(value.clone())
262            }
263        }
264
265        impl<const M: usize, const N: usize> From<[[$from_typ; N]; M]> for $to_typ {
266            fn from(value: [[$from_typ; N]; M]) -> Self {
267                Self::ArrayOfIntegerArray(value.iter().map(|inner| inner.to_vec()).collect())
268            }
269        }
270
271        impl<const M: usize, const N: usize> From<[&[$from_typ; N]; M]> for $to_typ {
272            fn from(value: [&[$from_typ; N]; M]) -> Self {
273                Self::ArrayOfIntegerArray(value.iter().map(|inner| inner.to_vec()).collect())
274            }
275        }
276
277        impl<const M: usize, const N: usize> From<&[[$from_typ; N]; M]> for $to_typ {
278            fn from(value: &[[$from_typ; N]; M]) -> Self {
279                Self::ArrayOfIntegerArray(value.iter().map(|inner| inner.to_vec()).collect())
280            }
281        }
282
283        impl<const M: usize, const N: usize> From<&[&[$from_typ; N]; M]> for $to_typ {
284            fn from(value: &[&[$from_typ; N]; M]) -> Self {
285                Self::ArrayOfIntegerArray(value.iter().map(|inner| inner.to_vec()).collect())
286            }
287        }
288
289        impl<const N: usize> From<[Vec<$from_typ>; N]> for $to_typ {
290            fn from(value: [Vec<$from_typ>; N]) -> Self {
291                Self::ArrayOfIntegerArray(value.to_vec())
292            }
293        }
294
295        impl<const N: usize> From<&[Vec<$from_typ>; N]> for $to_typ {
296            fn from(value: &[Vec<$from_typ>; N]) -> Self {
297                Self::ArrayOfIntegerArray(value.to_vec())
298            }
299        }
300
301        impl<const N: usize> From<[&Vec<$from_typ>; N]> for $to_typ {
302            fn from(value: [&Vec<$from_typ>; N]) -> Self {
303                Self::ArrayOfIntegerArray(value.into_iter().map(|inner| inner.clone()).collect())
304            }
305        }
306
307        impl<const N: usize> From<&[&Vec<$from_typ>; N]> for $to_typ {
308            fn from(value: &[&Vec<$from_typ>; N]) -> Self {
309                Self::ArrayOfIntegerArray(
310                    value
311                        .to_vec()
312                        .into_iter()
313                        .map(|inner| inner.clone())
314                        .collect(),
315                )
316            }
317        }
318
319        impl<const N: usize> From<Vec<[$from_typ; N]>> for $to_typ {
320            fn from(value: Vec<[$from_typ; N]>) -> Self {
321                Self::ArrayOfIntegerArray(value.into_iter().map(|inner| inner.to_vec()).collect())
322            }
323        }
324
325        impl<const N: usize> From<&Vec<[$from_typ; N]>> for $to_typ {
326            fn from(value: &Vec<[$from_typ; N]>) -> Self {
327                Self::ArrayOfIntegerArray(value.into_iter().map(|inner| inner.to_vec()).collect())
328            }
329        }
330
331        impl<const N: usize> From<Vec<&[$from_typ; N]>> for $to_typ {
332            fn from(value: Vec<&[$from_typ; N]>) -> Self {
333                Self::ArrayOfIntegerArray(value.into_iter().map(|inner| inner.to_vec()).collect())
334            }
335        }
336
337        impl<const N: usize> From<&Vec<&[$from_typ; N]>> for $to_typ {
338            fn from(value: &Vec<&[$from_typ; N]>) -> Self {
339                Self::ArrayOfIntegerArray(value.into_iter().map(|inner| inner.to_vec()).collect())
340            }
341        }
342    };
343}
344
345#[cfg(feature = "embedding-types")]
346impl_from_for_array_of_integer_array!(u32, EmbeddingInput);
347#[cfg(any(feature = "chat-completion-types", feature = "completion-types"))]
348impl_from_for_array_of_integer_array!(u32, Prompt);
349
350// Note: From impls for ChatCompletionFunctionCall, FunctionName, ChatCompletionNamedToolChoice
351// are in spec/chat/impls.rs
352
353#[cfg(any(feature = "chat-completion-types", feature = "completion-types"))]
354impl From<&str> for ChatCompletionToolChoiceOption {
355    fn from(value: &str) -> Self {
356        match value {
357            "auto" => Self::Auto,
358            "none" => Self::None,
359            _ => Self::Named(value.into()),
360        }
361    }
362}
363
364#[cfg(any(feature = "chat-completion-types", feature = "completion-types"))]
365impl From<String> for ChatCompletionToolChoiceOption {
366    fn from(value: String) -> Self {
367        match value.as_str() {
368            "auto" => Self::Auto,
369            "none" => Self::None,
370            _ => Self::Named(value.into()),
371        }
372    }
373}
374
375// Note: From<PartibleTextContent> impls for messages removed due to type mismatch.
376// The content fields expect specific *MessageContent types, not PartibleTextContent.
377// Use the appropriate content type constructors instead.
378
379#[cfg(feature = "response-types")]
380impl Default for CreateMessageRequestContent {
381    fn default() -> Self {
382        Self::Content("".into())
383    }
384}