async_openai/
util.rs

1use reqwest::Body;
2use tokio::fs::File;
3use tokio_util::codec::{BytesCodec, FramedRead};
4
5use crate::error::OpenAIError;
6use crate::types::InputSource;
7
8pub(crate) async fn file_stream_body(source: InputSource) -> Result<Body, OpenAIError> {
9    let body = match source {
10        InputSource::Path { path } => {
11            let file = File::open(path)
12                .await
13                .map_err(|e| OpenAIError::FileReadError(e.to_string()))?;
14            let stream = FramedRead::new(file, BytesCodec::new());
15            Body::wrap_stream(stream)
16        }
17        _ => {
18            return Err(OpenAIError::FileReadError(
19                "Cannot create stream from non-file source".to_string(),
20            ))
21        }
22    };
23    Ok(body)
24}
25
26/// Creates the part for the given file for multipart upload.
27pub(crate) async fn create_file_part(
28    source: InputSource,
29) -> Result<reqwest::multipart::Part, OpenAIError> {
30    let (stream, file_name) = match source {
31        InputSource::Path { path } => {
32            let file_name = path
33                .file_name()
34                .ok_or_else(|| {
35                    OpenAIError::FileReadError(format!(
36                        "cannot extract file name from {}",
37                        path.display()
38                    ))
39                })?
40                .to_str()
41                .unwrap()
42                .to_string();
43
44            (
45                file_stream_body(InputSource::Path { path }).await?,
46                file_name,
47            )
48        }
49        InputSource::Bytes { filename, bytes } => (Body::from(bytes), filename),
50        InputSource::VecU8 { filename, vec } => (Body::from(vec), filename),
51    };
52
53    let file_part = reqwest::multipart::Part::stream(stream).file_name(file_name);
54
55    Ok(file_part)
56}
57
58#[cfg(any(feature = "image", feature = "audio"))]
59pub(crate) fn create_all_dir<P: AsRef<std::path::Path>>(dir: P) -> Result<(), OpenAIError> {
60    let exists = match std::path::Path::try_exists(dir.as_ref()) {
61        Ok(exists) => exists,
62        Err(e) => return Err(OpenAIError::FileSaveError(e.to_string())),
63    };
64
65    if !exists {
66        std::fs::create_dir_all(dir.as_ref())
67            .map_err(|e| OpenAIError::FileSaveError(e.to_string()))?;
68    }
69
70    Ok(())
71}