use serde::{Deserialize, Deserializer, Serialize, Serializer};
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[non_exhaustive]
pub struct ElevenLabsSpeakProvider {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub version: Option<ElevenLabsVersion>,
pub model_id: ElevenLabsModelId,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub language: Option<String>,
#[deprecated(
since = "0.12.0",
note = "Use the `language` field instead. Mirrors deprecation in the AsyncAPI spec."
)]
#[serde(default, skip_serializing_if = "Option::is_none")]
pub language_code: Option<String>,
}
#[allow(deprecated)]
impl ElevenLabsSpeakProvider {
pub fn new(model_id: ElevenLabsModelId) -> Self {
Self {
version: None,
model_id,
language: None,
language_code: None,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[non_exhaustive]
pub enum ElevenLabsVersion {
#[serde(rename = "v1")]
V1,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum ElevenLabsModelId {
ElevenTurboV2_5,
ElevenMonolingualV1,
ElevenMultilingualV2,
Other(String),
}
impl ElevenLabsModelId {
pub fn as_str(&self) -> &str {
match self {
Self::ElevenTurboV2_5 => "eleven_turbo_v2_5",
Self::ElevenMonolingualV1 => "eleven_monolingual_v1",
Self::ElevenMultilingualV2 => "eleven_multilingual_v2",
Self::Other(s) => s,
}
}
}
impl From<String> for ElevenLabsModelId {
fn from(value: String) -> Self {
match value.as_str() {
"eleven_turbo_v2_5" => Self::ElevenTurboV2_5,
"eleven_monolingual_v1" => Self::ElevenMonolingualV1,
"eleven_multilingual_v2" => Self::ElevenMultilingualV2,
_ => Self::Other(value),
}
}
}
impl Serialize for ElevenLabsModelId {
fn serialize<S: Serializer>(&self, ser: S) -> Result<S::Ok, S::Error> {
ser.serialize_str(self.as_str())
}
}
impl<'de> Deserialize<'de> for ElevenLabsModelId {
fn deserialize<D: Deserializer<'de>>(de: D) -> Result<Self, D::Error> {
Ok(Self::from(String::deserialize(de)?))
}
}
#[cfg(test)]
mod tests {
use super::*;
use serde_json::json;
#[test]
fn round_trip_with_language() {
let raw = json!({
"version": "v1",
"model_id": "eleven_multilingual_v2",
"language": "en-US"
});
let p: ElevenLabsSpeakProvider = serde_json::from_value(raw.clone()).unwrap();
assert_eq!(p.model_id, ElevenLabsModelId::ElevenMultilingualV2);
assert_eq!(p.language.as_deref(), Some("en-US"));
assert_eq!(serde_json::to_value(&p).unwrap(), raw);
}
#[test]
fn round_trip_minimal() {
let raw = json!({ "model_id": "eleven_turbo_v2_5" });
let p: ElevenLabsSpeakProvider = serde_json::from_value(raw.clone()).unwrap();
assert_eq!(p.model_id, ElevenLabsModelId::ElevenTurboV2_5);
assert_eq!(serde_json::to_value(&p).unwrap(), raw);
}
#[test]
#[allow(deprecated)]
fn deprecated_language_code_still_round_trips() {
let raw = json!({
"model_id": "eleven_monolingual_v1",
"language_code": "fr-FR"
});
let p: ElevenLabsSpeakProvider = serde_json::from_value(raw.clone()).unwrap();
assert_eq!(p.language_code.as_deref(), Some("fr-FR"));
assert_eq!(serde_json::to_value(&p).unwrap(), raw);
}
}