use serde::{Deserialize, Serialize};
use super::ToolCallFunction;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
pub struct ToolCall {
#[serde(skip_serializing_if = "Option::is_none")]
pub function: Option<ToolCallFunction>,
}
impl ToolCall {
pub fn new(function: ToolCallFunction) -> Self {
Self {
function: Some(function),
}
}
pub fn function_name(&self) -> Option<&str> {
self.function.as_ref().map(|f| f.name.as_str())
}
pub fn arguments(&self) -> Option<&serde_json::Value> {
self.function.as_ref().and_then(|f| f.arguments.as_ref())
}
pub fn arguments_as<T>(&self) -> Option<T>
where
T: for<'de> Deserialize<'de>,
{
self.function.as_ref().and_then(|f| f.arguments_as())
}
pub fn is_valid(&self) -> bool {
self.function.is_some()
}
}
#[cfg(test)]
mod tests {
use super::*;
use serde_json::json;
#[test]
fn test_tool_call_new() {
let func = ToolCallFunction::new("test");
let call = ToolCall::new(func);
assert!(call.function.is_some());
assert_eq!(call.function_name(), Some("test"));
}
#[test]
fn test_tool_call_default() {
let call = ToolCall::default();
assert!(call.function.is_none());
assert_eq!(call.function_name(), None);
}
#[test]
fn test_tool_call_function_name() {
let call = ToolCall::new(ToolCallFunction::new("my_func"));
assert_eq!(call.function_name(), Some("my_func"));
}
#[test]
fn test_tool_call_arguments() {
let func = ToolCallFunction::with_arguments("test", json!({"a": 1, "b": "two"}));
let call = ToolCall::new(func);
let args = call.arguments().unwrap();
assert_eq!(args["a"], 1);
assert_eq!(args["b"], "two");
}
#[test]
fn test_tool_call_arguments_none() {
let call = ToolCall::new(ToolCallFunction::new("no_args"));
assert!(call.arguments().is_none());
}
#[test]
fn test_tool_call_arguments_as() {
#[derive(Deserialize, Debug, PartialEq)]
struct Args {
x: i32,
}
let func = ToolCallFunction::with_arguments("test", json!({"x": 42}));
let call = ToolCall::new(func);
let args: Option<Args> = call.arguments_as();
assert_eq!(args, Some(Args { x: 42 }));
}
#[test]
fn test_tool_call_is_valid() {
let valid = ToolCall::new(ToolCallFunction::new("test"));
assert!(valid.is_valid());
let invalid = ToolCall::default();
assert!(!invalid.is_valid());
}
#[test]
fn test_tool_call_serialize() {
let func = ToolCallFunction::with_arguments("weather", json!({"city": "NYC"}));
let call = ToolCall::new(func);
let json = serde_json::to_value(&call).unwrap();
assert_eq!(json["function"]["name"], "weather");
assert_eq!(json["function"]["arguments"]["city"], "NYC");
}
#[test]
fn test_tool_call_serialize_empty() {
let call = ToolCall::default();
let json = serde_json::to_string(&call).unwrap();
assert_eq!(json, "{}"); }
#[test]
fn test_tool_call_deserialize() {
let json = r#"{
"function": {
"name": "calculate",
"arguments": {"expression": "1 + 1"}
}
}"#;
let call: ToolCall = serde_json::from_str(json).unwrap();
assert_eq!(call.function_name(), Some("calculate"));
assert_eq!(call.arguments().unwrap()["expression"], "1 + 1");
}
#[test]
fn test_tool_call_deserialize_empty() {
let json = "{}";
let call: ToolCall = serde_json::from_str(json).unwrap();
assert!(call.function.is_none());
}
#[test]
fn test_tool_call_deserialize_null_function() {
let json = r#"{"function": null}"#;
let call: ToolCall = serde_json::from_str(json).unwrap();
assert!(call.function.is_none());
}
#[test]
fn test_tool_call_clone() {
let call = ToolCall::new(ToolCallFunction::with_arguments("test", json!({"x": 1})));
let cloned = call.clone();
assert_eq!(call, cloned);
}
#[test]
fn test_tool_call_equality() {
let call1 = ToolCall::new(ToolCallFunction::new("a"));
let call2 = ToolCall::new(ToolCallFunction::new("a"));
let call3 = ToolCall::new(ToolCallFunction::new("b"));
assert_eq!(call1, call2);
assert_ne!(call1, call3);
}
}