1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
//! Procedural macros for SimpleAgents.
//!
//! This crate provides derive macros for automatic schema generation and partial type
//! support for streaming responses.
//!
//! # Macros
//!
//! - [`PartialType`] - Generates a partial version of a type with all fields as `Option<T>`
//!
//! # Example
//!
//! ```rust
//! use simple_agents_macros::PartialType;
//! use serde::{Deserialize, Serialize};
//!
//! #[derive(Debug, Clone, PartialType, Serialize, Deserialize)]
//! pub struct User {
//! pub id: u64,
//! pub name: String,
//! pub email: String,
//! pub age: u32,
//! }
//!
//! let partial = PartialUser {
//! id: Some(1),
//! name: Some("Ada".to_string()),
//! email: Some("ada@example.com".to_string()),
//! age: Some(42),
//! };
//! let user = User::from_partial(partial).unwrap();
//! assert_eq!(user.name, "Ada");
//! ```
use TokenStream;
/// Derives a partial type for streaming support.
///
/// Generates a `Partial{TypeName}` struct with all fields wrapped in `Option<T>`.
/// The partial type is useful for progressive emission during streaming responses,
/// where not all fields may be available yet.
///
/// # Generated Code
///
/// For each struct annotated with `#[derive(PartialType)]`, this macro generates:
///
/// 1. **Partial Struct**: `Partial{TypeName}` with all fields as `Option<T>`
/// - Derives: `Debug`, `Clone`, `Default`, `Serialize`, `Deserialize`
///
/// 2. **Conversion Method**: `from_partial()` on the original type
/// - Converts `PartialType` → `Type`
/// - Returns `Result<Type, String>` (error if required fields missing)
///
/// 3. **Merge Method**: `merge()` on the partial type
/// - Merges two partial values (newer values take precedence)
///
/// # Field Attributes
///
/// - `#[partial(skip)]` - Exclude field from partial type (always uses default)
/// - `#[partial(default)]` - Use default value if missing in partial
///
/// # Example
///
/// ```rust
/// use simple_agents_macros::PartialType;
/// use std::time::Duration;
///
/// #[derive(PartialType)]
/// pub struct Resume {
/// pub name: String,
/// pub email: String,
/// #[partial(default)]
/// pub skills: Vec<String>,
/// #[partial(skip)]
/// pub created_at: Duration,
/// }
///
/// let mut partial = PartialResume::default();
/// partial.name = Some("Alice".to_string());
/// assert_eq!(partial.email, None);
///
/// partial.merge(PartialResume {
/// email: Some("alice@example.com".to_string()),
/// skills: Some(vec!["Rust".to_string()]),
/// ..Default::default()
/// });
///
/// let resume = Resume::from_partial(partial).unwrap();
/// assert_eq!(resume.name, "Alice");
/// assert_eq!(resume.skills, vec!["Rust".to_string()]);
/// ```
///
/// # Streaming Annotations
///
/// Future versions will support streaming annotations:
/// - `#[partial(stream_not_null)]` - Don't emit until non-null
/// - `#[partial(stream_done)]` - Only emit when complete