-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgotoon.go
More file actions
89 lines (77 loc) · 2.18 KB
/
Copy pathgotoon.go
File metadata and controls
89 lines (77 loc) · 2.18 KB
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
// Package gotoon provides a Token-Optimized Object Notation (TOON) encoder and decoder.
// TOON is designed to reduce token usage when sending data to LLMs while maintaining
// full round-trip fidelity.
package gotoon
import "encoding/json"
var (
defaultEncoder = NewEncoder(DefaultConfig())
defaultDecoder = NewDecoder(DefaultConfig())
)
// Encode converts data to TOON format using the default encoder.
func Encode(data any) (string, error) {
return defaultEncoder.Encode(data)
}
// Decode converts a TOON format string to Go data structures using the default decoder.
func Decode(toon string) (map[string]any, error) {
return defaultDecoder.Decode(toon)
}
// Diff estimates token savings between JSON and TOON formats.
// Returns a map with json_chars, toon_chars, saved_chars, and savings_percent.
func Diff(data any) map[string]any {
jsonBytes, err := json.Marshal(data)
if err != nil {
return map[string]any{
"json_chars": 0,
"toon_chars": 0,
"saved_chars": 0,
"savings_percent": 0.0,
}
}
toon, err := Encode(data)
if err != nil {
return map[string]any{
"json_chars": len(jsonBytes),
"toon_chars": 0,
"saved_chars": 0,
"savings_percent": 0.0,
}
}
jsonLen := len(jsonBytes)
toonLen := len(toon)
saved := jsonLen - toonLen
savingsPercent := 0.0
if jsonLen > 0 {
savingsPercent = float64(saved) / float64(jsonLen) * 100
}
return map[string]any{
"json_chars": jsonLen,
"toon_chars": toonLen,
"saved_chars": saved,
"savings_percent": savingsPercent,
}
}
// Only encodes only specific keys from the data.
func Only(data any, keys []string) (string, error) {
filtered := filterKeys(data, keys)
return Encode(filtered)
}
// filterKeys recursively filters data to only include specified keys.
func filterKeys(data any, keys []string) any {
if slice, ok := data.([]any); ok {
result := make([]any, len(slice))
for i, item := range slice {
result[i] = filterKeys(item, keys)
}
return result
}
if m, ok := data.(map[string]any); ok {
filtered := make(map[string]any)
for _, key := range keys {
if val, exists := m[key]; exists {
filtered[key] = val
}
}
return filtered
}
return data
}