1use serde::{Deserialize, Deserializer, Serialize};
2
3use crate::util::deserialize_obj_or_vec;
4
5pub mod request;
6pub mod response;
7pub use request::*;
8pub use response::*;
9
10#[derive(Debug, Serialize, Deserialize, Default, Clone, PartialEq)]
11pub struct Content {
12 #[serde(deserialize_with = "deserialize_role")]
14 pub role: Role,
15 #[serde(deserialize_with = "deserialize_obj_or_vec")]
16 pub parts: Vec<Part>,
17}
18
19#[derive(Debug, Serialize, Deserialize, Clone, Default, Copy, PartialEq, Eq)]
23#[serde(rename_all = "lowercase")]
24pub enum Role {
25 #[default]
26 User,
27 Model,
28}
29
30fn deserialize_role<'de, D>(deserializer: D) -> Result<Role, D::Error>
31where
32 D: Deserializer<'de>,
33{
34 let s = String::deserialize(deserializer)?;
35 let ss = s.to_lowercase();
36 match ss.as_str() {
37 "user" => Ok(Role::User),
38 "model" => Ok(Role::Model),
39 _ => Err(serde::de::Error::custom("Invalid value for Role")),
40 }
41}
42
43#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
47pub enum Part {
48 #[serde(rename = "text")]
50 Text(String),
51 #[serde(rename = "inlineData")]
53 Inline(InlineData),
54 #[serde(rename = "functionCall")]
55 FunctionCall(FunctionCall),
56 #[serde(rename = "functionResponse")]
57 FunctionResponse(FunctionResponse),
58 #[serde(rename = "fileData")]
59 File(FileData),
60}
61
62impl Part {
63 pub fn is_empty(&self) -> bool {
64 match self {
65 Part::Text(s) => s.trim().is_empty(),
66 Part::Inline(data) => data.data.trim().is_empty(),
67 Part::FunctionCall(call) => call.name.trim().is_empty(),
68 Part::FunctionResponse(response) => {
69 response.name.trim().is_empty() || response.response.is_null()
70 }
71 Part::File(file) => file.file_uri.trim().is_empty() || file.mime_type.trim().is_empty(),
72 }
73 }
74}
75
76#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
77#[serde(rename_all = "camelCase")]
78pub struct InlineData {
79 pub mime_type: String,
97 pub data: String,
100 pub video_metadata: Option<VideoMetadata>,
101}
102
103#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
105pub struct FunctionCall {
106 pub name: String,
108 pub args: Option<serde_json::Value>,
110}
111
112#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
114pub struct FunctionResponse {
115 name: String,
116 response: serde_json::Value,
117}
118
119#[derive(Debug, Serialize, Deserialize, Default, Clone, PartialEq)]
120#[serde(rename_all = "camelCase")]
121pub struct FileData {
122 pub mime_type: String,
123 pub file_uri: String,
126 pub video_metadata: Option<VideoMetadata>,
127}
128
129#[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq)]
131pub struct VideoMetadata {
132 pub start_offset: VideoOffset,
133 pub end_offset: VideoOffset,
134}
135
136#[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq)]
137pub struct VideoOffset {
138 pub seconds: i64,
139 pub nanos: i32,
140}
141
142#[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq)]
145pub enum HarmCategory {
146 #[serde(rename = "HARM_CATEGORY_SEXUALLY_EXPLICIT")]
148 SexuallyExplicit,
149
150 #[serde(rename = "HARM_CATEGORY_HATE_SPEECH")]
152 HateSpeech,
153
154 #[serde(rename = "HARM_CATEGORY_HARASSMENT")]
156 Harassment,
157
158 #[serde(rename = "HARM_CATEGORY_DANGEROUS_CONTENT")]
160 DangerousContent,
161}