#[doc(hidden)]
#[macro_export]
macro_rules! __forward_provider_identity {
($($field:tt).+) => {
fn provider_name(&self) -> &str {
$crate::ProviderIdentity::provider_name(&self.$($field).+)
}
fn reads_namespace(&self, namespace: &str) -> bool {
$crate::ProviderIdentity::reads_namespace(&self.$($field).+, namespace)
}
fn downcast_any(
&self,
id: ::std::any::TypeId,
) -> ::std::option::Option<&(dyn ::std::any::Any + Send + Sync)> {
$crate::ProviderIdentity::downcast_any(&self.$($field).+, id)
}
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __forward_chat_questions {
($($field:tt).+) => {
fn chat_capability(
&self,
model: &str,
capability: $crate::ChatCapability,
) -> $crate::CapabilitySupport {
$crate::ChatProvider::chat_capability(&self.$($field).+, model, capability)
}
fn validate_chat_request(
&self,
request: &$crate::ChatRequest,
) -> $crate::Result<$crate::ChatValidation> {
$crate::ChatProvider::validate_chat_request(&self.$($field).+, request)
}
fn validate_chat_stream_request(
&self,
request: &$crate::ChatRequest,
) -> $crate::Result<$crate::ChatValidation> {
$crate::ChatProvider::validate_chat_stream_request(&self.$($field).+, request)
}
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __forward_embedding_questions {
($($field:tt).+) => {
fn embedding_capability(
&self,
model: &str,
capability: $crate::EmbeddingCapability,
) -> $crate::CapabilitySupport {
$crate::EmbeddingProvider::embedding_capability(&self.$($field).+, model, capability)
}
fn embedding_limits(&self, model: &str) -> $crate::EmbeddingLimits {
$crate::EmbeddingProvider::embedding_limits(&self.$($field).+, model)
}
fn validate_embedding_request(
&self,
request: &$crate::EmbeddingRequest,
) -> $crate::Result<$crate::EmbeddingValidation> {
$crate::EmbeddingProvider::validate_embedding_request(&self.$($field).+, request)
}
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __forward_decision_questions {
($($field:tt).+) => {
fn decision_capability(
&self,
model: &str,
capability: $crate::DecisionCapability,
) -> $crate::CapabilitySupport {
$crate::DecisionProvider::decision_capability(&self.$($field).+, model, capability)
}
fn decision_limits(&self, model: &str) -> $crate::DecisionLimits {
$crate::DecisionProvider::decision_limits(&self.$($field).+, model)
}
fn validate_decision_request(
&self,
request: &$crate::DecisionRequest,
) -> $crate::Result<$crate::DecisionValidation> {
$crate::DecisionProvider::validate_decision_request(&self.$($field).+, request)
}
};
}
#[cfg(test)]
mod tests {
use crate::mock::{MockEmbeddingProvider, MockProvider};
use crate::{
CapabilitySupport, ChatCapability, ChatProvider, ChatRequest, ChatResponse,
EmbeddingLimits, EmbeddingProvider, EmbeddingRequest, EmbeddingResponse, ProviderIdentity,
ProviderIdentityExt, Result,
};
struct Tuple<P>(P);
impl<P: ChatProvider> ChatProvider for Tuple<P> {
type Stream = P::Stream;
async fn chat(&self, request: &ChatRequest) -> Result<ChatResponse> {
self.0.chat(request).await
}
async fn chat_stream(&self, request: &ChatRequest) -> Result<Self::Stream> {
self.0.chat_stream(request).await
}
crate::wrappers::forward_chat_questions!(0);
}
impl<P: EmbeddingProvider> EmbeddingProvider for Tuple<P> {
async fn embed(&self, request: &EmbeddingRequest) -> Result<EmbeddingResponse> {
self.0.embed(request).await
}
crate::wrappers::forward_embedding_questions!(0);
}
impl<P: ProviderIdentity> ProviderIdentity for Tuple<P> {
crate::wrappers::forward_provider_identity!(0);
}
struct Nested<P> {
layer: Tuple<P>,
}
impl<P: ProviderIdentity> ProviderIdentity for Nested<P> {
crate::wrappers::forward_provider_identity!(layer.0);
}
#[test]
fn forwards_through_fields_and_paths() {
let chat = Tuple(
MockProvider::empty()
.with_chat_capability(ChatCapability::ToolCalls, CapabilitySupport::Supported),
);
assert_eq!(
chat.chat_capability("m", ChatCapability::ToolCalls),
CapabilitySupport::Supported
);
assert_eq!(chat.provider_name(), "mock");
assert!(chat.downcast_ref::<MockProvider>().is_some());
let embedding = Tuple(MockEmbeddingProvider::empty().with_max_inputs_per_call(7));
assert_eq!(
embedding.embedding_limits("m"),
EmbeddingLimits::new().max_inputs_per_call(7)
);
let nested = Nested {
layer: Tuple(MockProvider::empty()),
};
assert!(nested.reads_namespace("mock"));
assert!(nested.downcast_ref::<MockProvider>().is_some());
}
}