#[cfg(feature = "derive")]
use std::collections::HashMap;
#[cfg(feature = "derive")]
use tryparse::{parse_llm, parse_llm_with_candidates};
#[cfg(feature = "derive")]
use tryparse_derive::LlmDeserialize;
#[cfg(feature = "derive")]
#[derive(Debug, Clone, serde::Deserialize, LlmDeserialize, PartialEq)]
enum Role {
Admin,
User,
Guest,
}
#[cfg(feature = "derive")]
#[derive(Debug, Clone, serde::Deserialize, LlmDeserialize, PartialEq)]
struct Address {
street: String,
city: String,
zip_code: String,
}
#[cfg(feature = "derive")]
#[derive(Debug, Clone, serde::Deserialize, LlmDeserialize, PartialEq)]
struct Profile {
bio: Option<String>,
avatar_url: Option<String>,
}
#[cfg(feature = "derive")]
#[derive(Debug, Clone, serde::Deserialize, LlmDeserialize, PartialEq)]
struct User {
name: String,
age: i64,
email: String,
role: Role,
address: Address,
profile: Option<Profile>,
tags: Vec<String>,
metadata: HashMap<String, String>,
}
#[cfg(feature = "derive")]
#[test]
fn test_complex_nested_structure() {
let response = r#"{
"name": "Alice Johnson",
"age": "30",
"email": "alice@example.com",
"role": "admin",
"address": {
"street": "123 Main St",
"city": "Springfield",
"zipCode": "12345"
},
"profile": {
"bio": "Software engineer",
"avatarUrl": "https://example.com/avatar.jpg"
},
"tags": ["developer", "rust", "ai"],
"metadata": {
"joinDate": "2024-01-01",
"status": "active"
}
}"#;
let user: User = parse_llm(response).unwrap();
assert_eq!(user.name, "Alice Johnson");
assert_eq!(user.age, 30);
assert_eq!(user.email, "alice@example.com");
assert_eq!(user.role, Role::Admin);
assert_eq!(user.address.street, "123 Main St");
assert_eq!(user.address.city, "Springfield");
assert_eq!(user.address.zip_code, "12345");
let profile = user.profile.unwrap();
assert_eq!(profile.bio, Some("Software engineer".to_string()));
assert_eq!(
profile.avatar_url,
Some("https://example.com/avatar.jpg".to_string())
);
assert_eq!(user.tags, vec!["developer", "rust", "ai"]);
assert_eq!(user.metadata.len(), 2);
assert_eq!(
user.metadata.get("joinDate"),
Some(&"2024-01-01".to_string())
);
assert_eq!(user.metadata.get("status"), Some(&"active".to_string()));
}
#[cfg(feature = "derive")]
#[test]
fn test_fuzzy_field_matching_throughout() {
let response = r#"{
"userName": "Bob",
"userAge": "25",
"userEmail": "bob@example.com",
"userRole": "user",
"userAddress": {
"streetName": "456 Oak Ave",
"cityName": "Boston",
"zipCode": "54321"
},
"userTags": ["backend", "python"],
"userMetadata": {
"createdAt": "2024-02-01"
}
}"#;
let result: Result<User, _> = parse_llm(response);
match result {
Ok(user) => {
assert!(!user.name.is_empty());
}
Err(_) => {
}
}
}
#[cfg(feature = "derive")]
#[test]
fn test_messy_llm_output_with_markdown() {
let response = r#"
Sure! Here's the user data you requested:
```json
{
"name": "Charlie Brown",
"age": "35",
"email": "charlie@example.com",
"role": "guest",
"address": {
"street": "789 Pine Rd",
"city": "Seattle",
"zipCode": "98101"
},
"tags": ["tester"],
"metadata": {}
}
```
Let me know if you need anything else!
"#;
let user: User = parse_llm(response).unwrap();
assert_eq!(user.name, "Charlie Brown");
assert_eq!(user.age, 35);
assert_eq!(user.role, Role::Guest);
assert_eq!(user.address.city, "Seattle");
}
#[cfg(feature = "derive")]
#[derive(Debug, Clone, serde::Deserialize, LlmDeserialize, PartialEq)]
#[llm(union)]
enum IntOrString {
Int(i64),
String(String),
}
#[cfg(feature = "derive")]
#[derive(Debug, Clone, serde::Deserialize, LlmDeserialize, PartialEq)]
struct FlexibleData {
value: IntOrString,
count: i64,
}
#[cfg(feature = "derive")]
#[test]
fn test_union_in_struct() {
let response1 = r#"{"value": 42, "count": 1}"#;
let data1: FlexibleData = parse_llm(response1).unwrap();
assert!(matches!(data1.value, IntOrString::Int(42)));
assert_eq!(data1.count, 1);
let response2 = r#"{"value": "hello", "count": 2}"#;
let data2: FlexibleData = parse_llm(response2).unwrap();
assert!(matches!(data2.value, IntOrString::String(_)));
assert_eq!(data2.count, 2);
}
#[cfg(feature = "derive")]
#[derive(Debug, Clone, serde::Deserialize, LlmDeserialize, PartialEq)]
struct Task {
title: String,
completed: bool,
priority: i64,
}
#[cfg(feature = "derive")]
#[test]
fn test_array_of_structs() {
let response = r#"[
{"title": "Task 1", "completed": true, "priority": 1},
{"title": "Task 2", "completed": false, "priority": "2"},
{"title": "Task 3", "completed": "true", "priority": 3}
]"#;
let tasks: Vec<Task> = parse_llm(response).unwrap();
assert_eq!(tasks.len(), 3);
assert_eq!(tasks[0].title, "Task 1");
assert!(tasks[0].completed);
assert_eq!(tasks[1].priority, 2);
assert!(tasks[2].completed); }
#[cfg(feature = "derive")]
#[test]
fn test_missing_required_field() {
let response = r#"{"name": "Test"}"#;
let result: Result<User, _> = parse_llm(response);
assert!(result.is_err());
}
#[cfg(feature = "derive")]
#[test]
fn test_invalid_json() {
let response = "This is not JSON at all!";
let result: Result<User, _> = parse_llm(response);
assert!(result.is_err());
}
#[cfg(feature = "derive")]
#[test]
fn test_parse_with_candidates() {
let response = r#"{"name": "Test", "age": "25", "email": "test@example.com", "role": "user", "address": {"street": "St", "city": "City", "zipCode": "12345"}, "tags": [], "metadata": {}}"#;
let (user, candidates) = parse_llm_with_candidates::<User>(response).unwrap();
assert_eq!(user.name, "Test");
assert!(!candidates.is_empty());
for candidate in &candidates {
let _ = candidate.transformations();
}
}
#[cfg(feature = "derive")]
#[test]
fn test_hashmap_preserves_keys() {
let response = r#"{"joinDate": "2024-01-01", "createdAt": "2024-02-01"}"#;
let map: HashMap<String, String> = parse_llm(response).unwrap();
assert_eq!(map.get("joinDate"), Some(&"2024-01-01".to_string()));
assert_eq!(map.get("createdAt"), Some(&"2024-02-01".to_string()));
}
#[cfg(feature = "derive")]
#[derive(Debug, Clone, serde::Deserialize, LlmDeserialize, PartialEq)]
struct EmptyStruct {
data: HashMap<String, String>,
items: Vec<String>,
}
#[cfg(feature = "derive")]
#[test]
fn test_empty_collections() {
let response = r#"{"data": {}, "items": []}"#;
let result: EmptyStruct = parse_llm(response).unwrap();
assert_eq!(result.data.len(), 0);
assert_eq!(result.items.len(), 0);
}
#[cfg(feature = "derive")]
#[derive(Debug, Clone, serde::Deserialize, LlmDeserialize, PartialEq)]
struct WithOptionals {
required: String,
optional1: Option<String>,
optional2: Option<i64>,
}
#[cfg(feature = "derive")]
#[test]
fn test_optional_fields() {
let response = r#"{"required": "value"}"#;
let result: WithOptionals = parse_llm(response).unwrap();
assert_eq!(result.required, "value");
assert_eq!(result.optional1, None);
assert_eq!(result.optional2, None);
}
#[cfg(feature = "derive")]
#[test]
fn test_partial_optionals() {
let response = r#"{"required": "value", "optional1": "present"}"#;
let result: WithOptionals = parse_llm(response).unwrap();
assert_eq!(result.required, "value");
assert_eq!(result.optional1, Some("present".to_string()));
assert_eq!(result.optional2, None);
}
#[cfg(feature = "derive")]
#[derive(Debug, Clone, serde::Deserialize, LlmDeserialize, PartialEq)]
struct CoercionTest {
int_from_string: i64,
bool_from_string: bool,
string_from_number: String,
}
#[cfg(feature = "derive")]
#[test]
fn test_all_coercion_types() {
let response = r#"{
"int_from_string": "42",
"bool_from_string": "true",
"string_from_number": 123
}"#;
let result: CoercionTest = parse_llm(response).unwrap();
assert_eq!(result.int_from_string, 42);
assert!(result.bool_from_string);
assert_eq!(result.string_from_number, "123");
}
#[cfg(feature = "derive")]
#[derive(Debug, Clone, serde::Deserialize, LlmDeserialize, PartialEq)]
enum Status {
InProgress,
Completed,
Cancelled,
}
#[cfg(feature = "derive")]
#[derive(Debug, Clone, serde::Deserialize, LlmDeserialize, PartialEq)]
struct Project {
name: String,
status: Status,
}
#[cfg(feature = "derive")]
#[test]
fn test_enum_fuzzy_matching_scenarios() {
let r1 = r#"{"name": "P1", "status": "Completed"}"#;
let p1: Project = parse_llm(r1).unwrap();
assert_eq!(p1.status, Status::Completed);
let r2 = r#"{"name": "P2", "status": "completed"}"#;
let p2: Project = parse_llm(r2).unwrap();
assert_eq!(p2.status, Status::Completed);
let r3 = r#"{"name": "P3", "status": "cancel"}"#;
let p3: Project = parse_llm(r3).unwrap();
assert_eq!(p3.status, Status::Cancelled);
}
#[cfg(feature = "derive")]
#[derive(Debug, Clone, serde::Deserialize, LlmDeserialize, PartialEq)]
struct ApiResponse {
success: bool,
data: Option<User>,
error: Option<String>,
metadata: HashMap<String, String>,
}
#[cfg(feature = "derive")]
#[test]
fn test_real_world_api_response() {
let response = r#"
Here's the API response:
```json
{
"success": true,
"data": {
"name": "Real User",
"age": "28",
"email": "real@example.com",
"role": "user",
"address": {
"street": "Real Street",
"city": "Real City",
"zipCode": "99999"
},
"tags": ["real"],
"metadata": {"source": "api"}
},
"metadata": {
"requestId": "12345",
"timestamp": "2024-01-01T00:00:00Z"
}
}
```
"#;
let api_response: ApiResponse = parse_llm(response).unwrap();
assert!(api_response.success);
assert!(api_response.data.is_some());
assert_eq!(api_response.error, None);
let user = api_response.data.unwrap();
assert_eq!(user.name, "Real User");
assert_eq!(user.age, 28);
}