lm_studio_api/chat/
image.rs

1use crate::prelude::*;
2use base64::{ engine::general_purpose, Engine as _ };
3use std::fs;
4
5/// The image base64 URL
6#[derive(Debug, Clone, From, Serialize, Deserialize, Eq, PartialEq)]
7pub struct Image {
8    pub url: String,
9}
10
11impl Image {
12    /// Validates a base64 URL
13    pub fn validate_base64(base64_url: &str) -> bool {
14        general_purpose::STANDARD.decode(base64_url).is_ok()
15    }
16    
17    /// Creates a new image from base64 url (example: "data:image/png;base64,iVBORw0KGgoA...")
18    pub fn from_base64<S: Into<String>>(base64_url: S) -> Result<Self> {
19        let base64_url = base64_url.into();
20        
21        if Self::validate_base64(
22            &base64_url.split_once(",").ok_or(Error::InvalidBase64Url)?.1
23        ) {
24            Ok(Self {
25                url: base64_url,
26            })
27        } else {
28            Err(Error::InvalidBase64Url.into())
29        }
30    }
31    
32    /// Creates a new image from file path
33    pub fn from_file<P: Into<PathBuf>>(file_path: P) -> Result<Self> {
34        // reading file:
35        let file_path = file_path.into();
36        let file_content = fs::read(&file_path)?;
37
38        // reading mime-type:
39        let mime_type = match file_path.extension().and_then(|e| e.to_str()) {
40            Some("png") => "image/png",
41            Some("jpg") | Some("jpeg") => "image/jpeg",
42            Some("gif") => "image/gif",
43            _ => "application/octet-stream",
44        };
45
46        // encoding into base64:
47        let encoded = general_purpose::STANDARD.encode(&file_content);
48        let base64_url = format!("data:{};base64,{}", mime_type, encoded);
49
50        Ok(Self { url: base64_url })
51    }
52}