1mod batch;
70mod client;
71mod error;
72mod provider;
73mod schema;
74mod usage;
75mod validate;
76
77pub use batch::BatchBuilder;
78pub use client::{Client, ExtractBuilder, ExtractResult};
79pub use error::{Error, Result};
80pub use provider::Message;
81pub use usage::Usage;
82pub use validate::{Validate, ValidationError};
83
84pub use schemars::JsonSchema;
86pub use serde;
87
88pub mod prelude {
94 pub use crate::{
95 BatchBuilder, Client, ExtractResult, Message, Usage, Validate, ValidationError,
96 };
97 pub use schemars::JsonSchema;
98 pub use serde::Deserialize;
99}
100
101#[cfg(test)]
102mod tests {
103 use super::*;
104 use schemars::JsonSchema;
105 use serde::Deserialize;
106
107 #[derive(Debug, Deserialize, JsonSchema)]
108 struct TestStruct {
109 name: String,
110 age: u32,
111 }
112
113 #[derive(Debug, Deserialize, JsonSchema)]
114 struct WithOptional {
115 title: String,
116 subtitle: Option<String>,
117 }
118
119 #[derive(Debug, Deserialize, JsonSchema)]
120 enum Category {
121 Bug,
122 Feature,
123 Question,
124 }
125
126 #[test]
127 fn deserialize_from_json() {
128 let json = r#"{"name": "Alice", "age": 30}"#;
129 let result: TestStruct = serde_json::from_str(json).unwrap();
130 assert_eq!(result.name, "Alice");
131 assert_eq!(result.age, 30);
132 }
133
134 #[test]
135 fn optional_field_present() {
136 let json = r#"{"title": "Hello", "subtitle": "World"}"#;
137 let result: WithOptional = serde_json::from_str(json).unwrap();
138 assert_eq!(result.subtitle, Some("World".into()));
139 }
140
141 #[test]
142 fn optional_field_null() {
143 let json = r#"{"title": "Hello", "subtitle": null}"#;
144 let result: WithOptional = serde_json::from_str(json).unwrap();
145 assert_eq!(result.subtitle, None);
146 }
147
148 #[test]
149 fn optional_field_missing() {
150 let json = r#"{"title": "Hello"}"#;
151 let result: WithOptional = serde_json::from_str(json).unwrap();
152 assert_eq!(result.subtitle, None);
153 }
154
155 #[test]
156 fn enum_deserialize() {
157 let json = r#""Bug""#;
158 let result: Category = serde_json::from_str(json).unwrap();
159 assert!(matches!(result, Category::Bug));
160
161 let json = r#""Feature""#;
162 let result: Category = serde_json::from_str(json).unwrap();
163 assert!(matches!(result, Category::Feature));
164
165 let json = r#""Question""#;
166 let result: Category = serde_json::from_str(json).unwrap();
167 assert!(matches!(result, Category::Question));
168 }
169
170 #[test]
171 fn schema_generation() {
172 let schema = schemars::schema_for!(TestStruct);
173 let value = serde_json::to_value(&schema).unwrap();
174 assert_eq!(value["type"], "object");
175 assert!(value["properties"]["name"].is_object());
176 assert!(value["properties"]["age"].is_object());
177 }
178
179 #[test]
180 fn usage_accumulate() {
181 let mut usage = Usage::default();
182 usage.accumulate(100, 50);
183 assert_eq!(usage.input_tokens, 100);
184 assert_eq!(usage.output_tokens, 50);
185 assert_eq!(usage.total_tokens, 150);
186
187 usage.accumulate(200, 100);
188 assert_eq!(usage.input_tokens, 300);
189 assert_eq!(usage.output_tokens, 150);
190 assert_eq!(usage.total_tokens, 450);
191 }
192
193 #[test]
194 fn prelude_re_exports() {
195 fn _check() {
197 use crate::prelude::*;
198 let _: fn() -> std::result::Result<(), ValidationError> = || Ok(());
199 fn _accepts_client(_: &Client) {}
200 fn _accepts_usage(_: &Usage) {}
201 }
202 }
203
204 #[test]
205 fn re_exports_available() {
206 let _: fn() -> Result<()> = || Ok(());
208 fn _check_json_schema<T: JsonSchema>() {}
209 _check_json_schema::<TestStruct>();
210 }
211}