1use crate::TOON_CONTENT_TYPE;
7
8pub const TOON_FORMAT_DESCRIPTION: &str = r#"
10**TOON (Token-Oriented Object Notation)**
11
12A compact, human-readable format designed for passing structured data to Large Language Models (LLMs) with significantly reduced token usage (typically 40-60% savings).
13
14### Format Example
15
16**JSON (561 bytes, ~141 tokens):**
17```json
18[
19 {"id": 1, "name": "Alice", "role": "admin", "active": true},
20 {"id": 2, "name": "Bob", "role": "user", "active": false}
21]
22```
23
24**TOON (259 bytes, ~65 tokens) - 54% savings:**
25```
26[2]{id,name,role,active}:
27 1,Alice,admin,true
28 2,Bob,user,false
29```
30
31### Usage
32
33Set `Accept: application/toon` header to receive TOON formatted responses.
34
35### When to Use TOON
36
37- Sending data to LLM APIs (reduces token costs)
38- Bandwidth-constrained environments
39- Caching large datasets
40- Any scenario where token efficiency matters
41"#;
42
43pub fn toon_schema() -> serde_json::Value {
45 serde_json::json!({
46 "type": "string",
47 "format": "toon",
48 "description": "TOON (Token-Oriented Object Notation) formatted data",
49 "externalDocs": {
50 "description": "TOON Format Specification",
51 "url": "https://toonformat.dev/"
52 }
53 })
54}
55
56pub fn toon_extension() -> serde_json::Value {
58 serde_json::json!({
59 "x-toon-support": {
60 "enabled": true,
61 "contentTypes": [TOON_CONTENT_TYPE, "text/toon"],
62 "tokenSavings": "40-60%",
63 "documentation": "https://toonformat.dev/"
64 }
65 })
66}
67
68pub fn token_headers_schema() -> serde_json::Value {
70 serde_json::json!({
71 "X-Token-Count-JSON": {
72 "description": "Estimated token count for JSON format (~4 chars/token)",
73 "schema": {
74 "type": "integer",
75 "example": 141
76 }
77 },
78 "X-Token-Count-TOON": {
79 "description": "Estimated token count for TOON format (~4 chars/token)",
80 "schema": {
81 "type": "integer",
82 "example": 65
83 }
84 },
85 "X-Token-Savings": {
86 "description": "Percentage of tokens saved by using TOON format",
87 "schema": {
88 "type": "string",
89 "example": "53.90%"
90 }
91 },
92 "X-Format-Used": {
93 "description": "The format used in the response (json or toon)",
94 "schema": {
95 "type": "string",
96 "enum": ["json", "toon"]
97 }
98 }
99 })
100}
101
102pub fn format_comparison_example<T: serde::Serialize>(data: &T) -> serde_json::Value {
104 let json_str = serde_json::to_string_pretty(data).unwrap_or_default();
105 let toon_str = toon_format::encode_default(data).unwrap_or_default();
106
107 let json_bytes = json_str.len();
108 let toon_bytes = toon_str.len();
109 let json_tokens = json_bytes / 4;
110 let toon_tokens = toon_bytes / 4;
111 let savings = if json_tokens > 0 {
112 ((json_tokens - toon_tokens) as f64 / json_tokens as f64) * 100.0
113 } else {
114 0.0
115 };
116
117 serde_json::json!({
118 "json": {
119 "content": json_str,
120 "bytes": json_bytes,
121 "estimatedTokens": json_tokens
122 },
123 "toon": {
124 "content": toon_str,
125 "bytes": toon_bytes,
126 "estimatedTokens": toon_tokens
127 },
128 "savings": {
129 "bytes": format!("{:.1}%", ((json_bytes - toon_bytes) as f64 / json_bytes as f64) * 100.0),
130 "tokens": format!("{:.1}%", savings)
131 }
132 })
133}
134
135pub fn api_description_with_toon(base_description: &str) -> String {
137 format!(
138 "{}\n\n---\n\n### 🚀 TOON Format Support\n\nThis API supports **TOON (Token-Oriented Object Notation)** \
139 for reduced token usage when sending data to LLMs.\n\n\
140 Set `Accept: application/toon` header to receive TOON formatted responses.\n\n\
141 **Benefits:**\n\
142 - 40-60% token savings\n\
143 - Human-readable format\n\
144 - Reduced API costs\n\n\
145 [Learn more about TOON](https://toonformat.dev/)",
146 base_description
147 )
148}
149
150#[cfg(test)]
151mod tests {
152 use super::*;
153 use serde::Serialize;
154
155 #[derive(Serialize)]
156 struct TestUser {
157 id: u64,
158 name: String,
159 }
160
161 #[test]
162 fn test_toon_schema() {
163 let schema = toon_schema();
164 assert_eq!(schema["type"], "string");
165 assert_eq!(schema["format"], "toon");
166 }
167
168 #[test]
169 fn test_toon_extension() {
170 let ext = toon_extension();
171 assert!(ext["x-toon-support"]["enabled"].as_bool().unwrap());
172 }
173
174 #[test]
175 fn test_token_headers_schema() {
176 let headers = token_headers_schema();
177 assert!(headers["X-Token-Count-JSON"].is_object());
178 assert!(headers["X-Token-Count-TOON"].is_object());
179 assert!(headers["X-Token-Savings"].is_object());
180 assert!(headers["X-Format-Used"].is_object());
181 }
182
183 #[test]
184 fn test_format_comparison_example() {
185 let users = vec![
186 TestUser {
187 id: 1,
188 name: "Alice".to_string(),
189 },
190 TestUser {
191 id: 2,
192 name: "Bob".to_string(),
193 },
194 ];
195 let comparison = format_comparison_example(&users);
196
197 assert!(comparison["json"]["bytes"].as_u64().unwrap() > 0);
198 assert!(comparison["toon"]["bytes"].as_u64().unwrap() > 0);
199 assert!(
201 comparison["toon"]["bytes"].as_u64().unwrap()
202 < comparison["json"]["bytes"].as_u64().unwrap()
203 );
204 }
205
206 #[test]
207 fn test_api_description_with_toon() {
208 let desc = api_description_with_toon("My API");
209 assert!(desc.contains("TOON Format Support"));
210 assert!(desc.contains("40-60% token savings"));
211 }
212}