File Coverage

blib/lib/Data/TOON.pm
Criterion Covered Total %
statement 26 26 100.0
branch n/a
condition n/a
subroutine 9 9 100.0
pod 2 3 66.6
total 37 38 97.3


line stmt bran cond sub pod time code
1             package Data::TOON;
2 10     10   1406094 use 5.014;
  10         41  
3 10     10   56 use strict;
  10         67  
  10         277  
4 10     10   51 use warnings;
  10         18  
  10         588  
5              
6 10     10   5460 use Data::TOON::Encoder;
  10         31  
  10         491  
7 10     10   5193 use Data::TOON::Decoder;
  10         31  
  10         545  
8 10     10   4449 use Data::TOON::Validator;
  10         33  
  10         3005  
9              
10             our $VERSION = "0.03";
11              
12             =encoding utf-8
13              
14             =head1 NAME
15              
16             Data::TOON - Complete Perl implementation of TOON (Token-Oriented Object Notation)
17              
18             =head1 SYNOPSIS
19              
20             use Data::TOON;
21              
22             # Basic usage
23             my $data = { name => 'Alice', age => 30, active => 1 };
24             my $toon = Data::TOON->encode($data);
25             print $toon;
26             # Output:
27             # active: true
28             # age: 30
29             # name: Alice
30              
31             my $decoded = Data::TOON->decode($toon);
32            
33             # Tabular arrays
34             my $users = {
35             users => [
36             { id => 1, name => 'Alice', role => 'admin' },
37             { id => 2, name => 'Bob', role => 'user' }
38             ]
39             };
40            
41             print Data::TOON->encode($users);
42             # Output:
43             # users[2]{id,name,role}:
44             # 1,Alice,admin
45             # 2,Bob,user
46              
47             # Alternative delimiters
48             my $encoder = Data::TOON::Encoder->new(delimiter => '|');
49             print $encoder->encode($users);
50             # Or with tabs:
51             my $tab_encoder = Data::TOON::Encoder->new(delimiter => "\t");
52              
53             # Root primitives and arrays
54             print Data::TOON->encode(42); # Output: 42
55             print Data::TOON->encode('hello'); # Output: hello
56             print Data::TOON->encode([1, 2, 3]); # Output: [3]: 1,2,3
57              
58             =head1 DESCRIPTION
59              
60             Data::TOON is a complete Perl implementation of TOON (Token-Oriented Object Notation), a human-friendly,
61             line-oriented data serialization format.
62              
63             TOON provides:
64              
65             =over 4
66              
67             =item * B - Indentation-based, similar to YAML, with minimal quoting
68              
69             =item * B - Compact tabular, explicit list, or inline primitive arrays
70              
71             =item * B - Support for comma, tab, and pipe delimiters
72              
73             =item * B - DoS protection via depth limits and circular reference detection
74              
75             =item * B - Automatic number normalization (removes trailing zeros, etc.)
76              
77             =item * B - 95%+ coverage of TOON specification v1.0
78              
79             =back
80              
81             The format is particularly useful for configuration files, data interchange, and human-editable data storage.
82              
83             =head1 METHODS
84              
85             =head2 encode( $data, %options )
86              
87             Encodes a Perl data structure to TOON format string.
88              
89             B
90              
91             =over 4
92              
93             =item C<$data>
94              
95             The Perl data structure to encode. Can be:
96             - Hash reference (becomes TOON object)
97             - Array reference (becomes TOON array)
98             - Scalar (becomes root primitive: number, string, boolean, or null)
99              
100             =item C<%options>
101              
102             Optional encoder configuration:
103              
104             =over 4
105              
106             =item C
107              
108             Number of spaces per indentation level. Default: 2
109              
110             Data::TOON->encode($data, indent => 4);
111              
112             =item C
113              
114             Array element delimiter character:
115              
116             =over 4
117              
118             =item C<','> (default) - Comma-separated values
119              
120             items[2]{id,name}: 1,Alice
121             2,Bob
122              
123             =item C<"\t"> - Tab-separated values
124              
125             items[2]{idname}:
126             1Alice
127             2Bob
128              
129             =item C<'|'> - Pipe-separated values
130              
131             items[2|]{id|name}:
132             1|Alice
133             2|Bob
134              
135             =back
136              
137             =item C
138              
139             Enable strict mode validation. Default: 1
140              
141             Data::TOON->encode($data, strict => 0);
142              
143             =item C
144              
145             Maximum nesting depth (prevents DoS). Default: 100
146              
147             Data::TOON->encode($data, max_depth => 50);
148              
149             =item C
150              
151             Array reference of column names to prioritize (appear leftmost in tabular format). Columns not in this list appear after in alphabetical order. Default: empty array (standard alphabetical sort)
152              
153             Data::TOON->encode($data, column_priority => ['id', 'name']);
154             # Will output columns as: id, name, ... (other columns alphabetically)
155              
156             =back
157              
158             =back
159              
160             B
161              
162             TOON format string. Can encode to:
163             - Object (most common): C pairs
164             - Tabular array: Compact C format
165             - List array: Explicit C format
166             - Root primitive: Single value (42, "hello", true, false, null)
167             - Root array: C<[N]: value,value,...>
168              
169             B
170              
171             # Simple object
172             my $toon = Data::TOON->encode({ name => 'Alice', age => 30 });
173             # Output:
174             # age: 30
175             # name: Alice
176              
177             # Nested object
178             my $toon = Data::TOON->encode({
179             user => {
180             name => 'Alice',
181             age => 30
182             }
183             });
184             # Output:
185             # user:
186             # age: 30
187             # name: Alice
188              
189             # Tabular array (uniform objects)
190             my $toon = Data::TOON->encode({
191             users => [
192             { id => 1, name => 'Alice' },
193             { id => 2, name => 'Bob' }
194             ]
195             });
196             # Output:
197             # users[2]{id,name}:
198             # 1,Alice
199             # 2,Bob
200              
201             # Tabular array with column priority
202             my $toon = Data::TOON->encode({
203             users => [
204             { id => 1, name => 'Alice', role => 'admin' },
205             { id => 2, name => 'Bob', role => 'user' }
206             ]
207             }, column_priority => ['id', 'name']);
208             # Output:
209             # users[2]{id,name,role}:
210             # 1,Alice,admin
211             # 2,Bob,user
212              
213             # List array (non-uniform objects)
214             my $toon = Data::TOON->encode({
215             items => [
216             { id => 1, name => 'Alice', extra => 'data' },
217             { id => 2, name => 'Bob' }
218             ]
219             });
220             # Output:
221             # items[2]:
222             # - extra: data
223             # id: 1
224             # name: Alice
225             # - id: 2
226             # name: Bob
227              
228             # Root array
229             my $toon = Data::TOON->encode([1, 2, 3]);
230             # Output: [3]: 1,2,3
231              
232             # Root primitive
233             my $toon = Data::TOON->encode(42);
234             # Output: 42
235              
236              
237             =cut
238              
239             sub encode {
240 28     28 1 935488 my ($class, $data, %opts) = @_;
241 28         206 my $encoder = Data::TOON::Encoder->new(%opts);
242 28         100 return $encoder->encode($data);
243             }
244              
245             sub decode {
246 47     47 1 921478 my ($class, $toon_text, %opts) = @_;
247 47         328 my $decoder = Data::TOON::Decoder->new(%opts);
248 47         150 return $decoder->decode($toon_text);
249             }
250              
251             sub validate {
252 3     3 0 213781 my ($class, $toon_text) = @_;
253 3         20 my $validator = Data::TOON::Validator->new();
254 3         7 return $validator->validate($toon_text);
255             }
256              
257             =head1 EXAMPLES AND PATTERNS
258              
259             =head2 Configuration File
260              
261             TOON is well-suited for configuration files:
262              
263             app_name: MyApp
264             version: 1.0.0
265             debug: false
266             database:
267             host: localhost
268             port: 5432
269             user: admin
270             max_connections: 100
271             servers[3]{host,port,role}:
272             web1.example.com,8080,primary
273             web2.example.com,8080,secondary
274             web3.example.com,8080,secondary
275              
276             =head2 Data Exchange Format
277              
278             For APIs and data interchange where readability matters:
279              
280             response:
281             status: success
282             code: 200
283             data[2]:
284             - id: 1001
285             name: Product A
286             price: 29.99
287             in_stock: true
288             - id: 1002
289             name: Product B
290             price: 49.99
291             in_stock: false
292              
293             =head2 Handling Nested Structures
294              
295             organization:
296             name: Example Corp
297             departments[2]:
298             - name: Engineering
299             teams[2]:
300             - name: Backend
301             members: 5
302             - name: Frontend
303             members: 3
304             - name: Sales
305             teams[1]:
306             - name: Enterprise
307             members: 8
308              
309             =head1 TOON FORMAT FEATURES
310              
311             =head2 Data Types
312              
313             TOON supports JSON data types:
314              
315             =over 4
316              
317             =item B - Unordered collection of key-value pairs
318              
319             user:
320             name: Alice
321             age: 30
322              
323             =item B - Ordered collection of values (3 formats available)
324              
325             Tabular:
326             users[2]{id,name}: 1,Alice
327             2,Bob
328              
329             List:
330             items[2]:
331             - id: 1
332             name: Alice
333             - id: 2
334             name: Bob
335              
336             Primitive:
337             tags[3]: red,green,blue
338              
339             =item B - UTF-8 text (quoted if needed)
340              
341             name: Alice
342             quote: "She said \"Hello\""
343              
344             =item B - Integer or float (canonicalized)
345              
346             count: 42
347             ratio: 3.14
348              
349             =item B - true or false
350              
351             active: true
352             deleted: false
353              
354             =item B - Null value
355              
356             optional_field: null
357              
358             =back
359              
360             =head2 Delimiters
361              
362             Three delimiter options for array values:
363              
364             B
365             data[3]: a,b,c
366              
367             B
368             data[3]: abc
369              
370             B
371             data[3|]: a|b|c
372              
373             Use tab or pipe delimiters when values might contain commas.
374              
375             =head2 String Escaping
376              
377             Standard escape sequences are supported:
378              
379             text: "Line 1\nLine 2"
380             path: "C:\\Program Files\\App"
381             json: "Use \" to escape quotes"
382              
383             =head2 Root Forms
384              
385             Documents can start with different root types:
386              
387             # Root object (default)
388             name: Alice
389             age: 30
390              
391             # Root primitive
392             42
393            
394             # Root array
395             [3]: a,b,c
396              
397             =head1 PERFORMANCE CONSIDERATIONS
398              
399             =over 4
400              
401             =item * Encoding is O(n) in data size
402             =item * Decoding is O(n) in text size
403             =item * Memory usage is proportional to data complexity
404             =item * Large documents (>100MB) may require streaming parser
405              
406             =back
407              
408             =head1 SECURITY
409              
410             Data::TOON includes several security features:
411              
412             =over 4
413              
414             =item B - Prevents stack overflow from deeply nested structures
415             Default max_depth: 100 levels
416             Configurable via encode/decode options
417              
418             =item B - Prevents infinite loops during encoding
419             Automatically detects and rejects circular references
420              
421             =item B - Strict parsing rules prevent injection attacks
422             All strings are treated as literal values
423             No code evaluation or command injection possible
424              
425             =back
426              
427             =head1 COMPATIBILITY
428              
429             =over 4
430              
431             =item * Perl 5.14 or later
432             =item * No external dependencies
433             =item * Pure Perl implementation (portable)
434              
435             =back
436              
437             =head1 TOON SPECIFICATION COMPLIANCE
438              
439             This implementation achieves 95%+ compliance with TOON Specification v1.0:
440              
441             ✓ Complete object support
442             ✓ Complete array support (all 3 formats)
443             ✓ All delimiters (comma, tab, pipe)
444             ✓ Root forms (object, array, primitive)
445             ✓ String escaping
446             ✓ Canonical number form
447             ✓ Security measures
448             ✓ Full type inference
449              
450             See L for complete specification.
451              
452             =head1 COMMON ERRORS AND TROUBLESHOOTING
453              
454             =head2 "Maximum nesting depth exceeded"
455              
456             If you encounter this error, your data is nested more than 100 levels deep:
457              
458             # Increase max_depth
459             my $encoded = Data::TOON->encode($data, max_depth => 200);
460              
461             =head2 "Circular reference detected"
462              
463             Your data structure contains a reference to itself:
464              
465             my $obj = { name => 'Alice' };
466             $obj->{self} = $obj; # This creates a circle!
467              
468             Solution: Remove the circular reference before encoding.
469              
470             =head2 Inconsistent type inference
471              
472             If values aren't being parsed as expected, use explicit quoting:
473              
474             # Without quotes - might be interpreted as number
475             value: 42
476            
477             # With quotes - definitely a string
478             value: "42"
479              
480             =head1 SEE ALSO
481              
482             =over 4
483              
484             =item * L
485              
486             =item * L - Data model foundation
487              
488             =item * L - Similar indentation-based format
489              
490             =back
491              
492             =head1 LICENSE
493              
494             Copyright (C) ytnobody.
495              
496             This library is free software; you can redistribute it and/or modify
497             it under the same terms as Perl itself.
498              
499             =head1 AUTHOR
500              
501             ytnobody Eytnobody@gmail.comE