use std::collections::HashMap;
use serde::{Deserialize, Serialize};
use serde_json::Value;
use ts_rs::TS;
pub use crate::abort_signal::AbortSignal;
pub use crate::types::Warning;
pub type SharedHeaders = HashMap<String, String>;
pub type SharedProviderOptions = HashMap<String, Value>;
pub type SharedProviderMetadata = HashMap<String, Value>;
pub type SharedProviderReference = HashMap<String, String>;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, TS)]
#[ts(export)]
pub enum FileBytes {
Binary(Vec<u8>),
Base64(String),
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, TS)]
#[ts(export)]
pub enum FileData {
Data { data: FileBytes },
Url { url: String },
Reference { reference: SharedProviderReference },
Text { text: String },
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, TS)]
#[ts(export)]
pub struct Size {
width: u32,
height: u32,
}
impl Size {
#[must_use]
pub const fn new(width: u32, height: u32) -> Self {
Self { width, height }
}
pub fn parse(s: &str) -> Result<Self, String> {
let (w, h) = parse_pair(s, 'x').ok_or_else(|| {
format!("invalid size `{s}`: expected format `{{width}}x{{height}}` (e.g. `1024x1024`)")
})?;
if w == 0 || h == 0 {
return Err(format!("invalid size `{s}`: width and height must be > 0"));
}
Ok(Self::new(w, h))
}
#[must_use]
pub const fn width(&self) -> u32 {
self.width
}
#[must_use]
pub const fn height(&self) -> u32 {
self.height
}
}
impl std::fmt::Display for Size {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}x{}", self.width, self.height)
}
}
impl std::str::FromStr for Size {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Self::parse(s)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, TS)]
#[ts(export)]
pub struct AspectRatio {
width: u32,
height: u32,
}
impl AspectRatio {
#[must_use]
pub const fn new(width: u32, height: u32) -> Self {
Self { width, height }
}
pub fn parse(s: &str) -> Result<Self, String> {
let (w, h) = parse_pair(s, ':').ok_or_else(|| {
format!(
"invalid aspect ratio `{s}`: expected format `{{width}}:{{height}}` (e.g. `16:9`)"
)
})?;
if w == 0 || h == 0 {
return Err(format!(
"invalid aspect ratio `{s}`: width and height must be > 0"
));
}
Ok(Self::new(w, h))
}
#[must_use]
pub const fn width(&self) -> u32 {
self.width
}
#[must_use]
pub const fn height(&self) -> u32 {
self.height
}
}
impl std::fmt::Display for AspectRatio {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}:{}", self.width, self.height)
}
}
impl std::str::FromStr for AspectRatio {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Self::parse(s)
}
}
fn parse_pair(s: &str, sep: char) -> Option<(u32, u32)> {
let (a, b) = s.split_once(sep)?;
let a: u32 = a.trim().parse().ok()?;
let b: u32 = b.trim().parse().ok()?;
Some((a, b))
}
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
#[ts(export)]
pub struct ResponseInfo {
pub timestamp: Option<String>,
pub model_id: Option<String>,
pub headers: Option<SharedHeaders>,
pub body: Option<Value>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
#[ts(export)]
pub struct RequestInfo {
pub body: Option<Value>,
}