toon-parser 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,137 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ToonParser
4
+ # Serializer for converting Ruby objects to TOON format
5
+ class Serializer
6
+ def initialize(indent: 2)
7
+ @indent_size = indent
8
+ end
9
+
10
+ # Serialize Ruby objects into TOON format
11
+ #
12
+ # @param data [Hash, Array] Ruby object to serialize
13
+ # @return [String] TOON formatted string
14
+ def serialize(data)
15
+ serialize_value(data, 0)
16
+ end
17
+
18
+ private
19
+
20
+ def serialize_value(value, level)
21
+ case value
22
+ when Hash
23
+ serialize_hash(value, level)
24
+ when Array
25
+ serialize_array(value, level)
26
+ else
27
+ serialize_primitive(value)
28
+ end
29
+ end
30
+
31
+ def serialize_hash(hash, level)
32
+ result = []
33
+ indent = " " * (level * @indent_size)
34
+
35
+ hash.each do |key, value|
36
+ key_str = key.to_s
37
+
38
+ case value
39
+ when Array
40
+ if array_of_objects?(value)
41
+ # Array of objects with schema
42
+ schema = detect_schema(value)
43
+ result << "#{indent}#{key_str}[#{value.size}]{#{schema.join(',')}}:"
44
+ value.each do |item|
45
+ row = serialize_object_row(item, schema)
46
+ result << "#{indent} #{row}"
47
+ end
48
+ else
49
+ # Simple array
50
+ result << "#{indent}#{key_str}[#{value.size}]:"
51
+ value.each do |item|
52
+ item_str = serialize_primitive(item)
53
+ result << "#{indent} #{item_str}"
54
+ end
55
+ end
56
+ when Hash
57
+ result << "#{indent}#{key_str}:"
58
+ result << serialize_hash(value, level + 1)
59
+ else
60
+ value_str = serialize_primitive(value)
61
+ result << "#{indent}#{key_str}: #{value_str}"
62
+ end
63
+ end
64
+
65
+ result.join("\n")
66
+ end
67
+
68
+ def serialize_array(array, level)
69
+ result = []
70
+ indent = " " * (level * @indent_size)
71
+
72
+ if array_of_objects?(array)
73
+ # Array of objects with schema
74
+ schema = detect_schema(array)
75
+ result << "#{indent}[#{array.size}]{#{schema.join(',')}}:"
76
+ array.each do |item|
77
+ row = serialize_object_row(item, schema)
78
+ result << "#{indent} #{row}"
79
+ end
80
+ else
81
+ # Simple array
82
+ result << "#{indent}[#{array.size}]:"
83
+ array.each do |item|
84
+ item_str = serialize_primitive(item)
85
+ result << "#{indent} #{item_str}"
86
+ end
87
+ end
88
+
89
+ result.join("\n")
90
+ end
91
+
92
+ def array_of_objects?(array)
93
+ return false unless array.is_a?(Array) && !array.empty?
94
+
95
+ array.all? { |item| item.is_a?(Hash) }
96
+ end
97
+
98
+ def detect_schema(array)
99
+ return [] if array.empty?
100
+
101
+ # Get all unique keys from all objects
102
+ all_keys = array.flat_map(&:keys).uniq.map(&:to_s)
103
+ all_keys.sort
104
+ end
105
+
106
+ def serialize_object_row(obj, schema)
107
+ values = schema.map do |key|
108
+ value = obj[key.to_sym] || obj[key]
109
+ serialize_primitive(value)
110
+ end
111
+ values.join(",")
112
+ end
113
+
114
+ def serialize_primitive(value)
115
+ case value
116
+ when nil
117
+ "null"
118
+ when true
119
+ "true"
120
+ when false
121
+ "false"
122
+ when Integer, Float
123
+ value.to_s
124
+ when String
125
+ # Quote if contains special characters or spaces
126
+ if value.match?(/[,\s:\[\]{}]/) || value.empty?
127
+ "\"#{value.gsub('"', '\\"')}\""
128
+ else
129
+ value
130
+ end
131
+ else
132
+ value.to_s
133
+ end
134
+ end
135
+ end
136
+ end
137
+
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ToonParser
4
+ VERSION = "0.1.0"
5
+ end
6
+
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "toon-parser/version"
4
+
5
+ module ToonParser
6
+ class Error < StandardError; end
7
+ end
8
+
9
+ require_relative "toon-parser/parser"
10
+ require_relative "toon-parser/serializer"
11
+ require_relative "toon-parser/api"
12
+
13
+ # Load Rails integration if Rails is available
14
+ begin
15
+ require "rails"
16
+ require_relative "toon-parser/railtie"
17
+ require_relative "toon-parser/controller_helpers"
18
+ rescue LoadError
19
+ # Rails is not available, skip Rails integration
20
+ end
21
+
22
+ module ToonParser
23
+
24
+ # Parse a TOON string into Ruby objects
25
+ #
26
+ # @param toon_string [String] The TOON formatted string
27
+ # @return [Hash, Array] Parsed Ruby object
28
+ #
29
+ # @example
30
+ # ToonParser.parse("users[2]{id,name}:\n 1,Alice\n 2,Bob")
31
+ # # => {"users" => [{"id" => 1, "name" => "Alice"}, {"id" => 2, "name" => "Bob"}]}
32
+ def self.parse(toon_string)
33
+ Parser.new.parse(toon_string)
34
+ end
35
+
36
+ # Serialize Ruby objects into TOON format
37
+ #
38
+ # @param data [Hash, Array] Ruby object to serialize
39
+ # @return [String] TOON formatted string
40
+ #
41
+ # @example
42
+ # ToonParser.serialize({"users" => [{"id" => 1, "name" => "Alice"}]})
43
+ # # => "users[1]{id,name}:\n 1,Alice"
44
+ def self.serialize(data)
45
+ Serializer.new.serialize(data)
46
+ end
47
+
48
+ # Parse a TOON file
49
+ #
50
+ # @param file_path [String] Path to the TOON file
51
+ # @return [Hash, Array] Parsed Ruby object
52
+ def self.parse_file(file_path)
53
+ content = File.read(file_path)
54
+ parse(content)
55
+ end
56
+
57
+ # Serialize Ruby objects to a TOON file
58
+ #
59
+ # @param data [Hash, Array] Ruby object to serialize
60
+ # @param file_path [String] Path where to save the TOON file
61
+ def self.serialize_to_file(data, file_path)
62
+ content = serialize(data)
63
+ File.write(file_path, content)
64
+ end
65
+ end
66
+
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "lib/toon-parser/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "toon-parser"
7
+ spec.version = ToonParser::VERSION
8
+ spec.authors = ["afshmini"]
9
+ spec.email = [""]
10
+
11
+ spec.summary = "A Ruby gem for parsing and serializing TOON (Token-Oriented Object Notation) format"
12
+ spec.description = "Parse TOON files and handle TOON-formatted API requests/responses. TOON is a compact, human-readable data format designed to reduce token usage in LLM applications."
13
+ spec.homepage = "https://github.com/afshmini/toon-parser"
14
+ spec.license = "MIT"
15
+ spec.required_ruby_version = ">= 2.7.0"
16
+
17
+ spec.metadata["homepage_uri"] = spec.homepage
18
+ spec.metadata["source_code_uri"] = spec.homepage
19
+ spec.metadata["changelog_uri"] = "#{spec.homepage}/blob/main/CHANGELOG.md"
20
+
21
+ # Specify which files should be added to the gem when it is released.
22
+ spec.files = Dir.chdir(__dir__) do
23
+ `git ls-files -z`.split("\x0").reject do |f|
24
+ (File.expand_path(f) == __FILE__) ||
25
+ f.start_with?(*%w[bin/ test/ spec/ features/ .git .github appveyor Gemfile])
26
+ end
27
+ end
28
+ spec.bindir = "exe"
29
+ spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
30
+ spec.require_paths = ["lib"]
31
+
32
+ # Dependencies
33
+ spec.add_development_dependency "rake", "~> 13.0"
34
+ spec.add_development_dependency "rspec", "~> 3.0"
35
+ spec.add_development_dependency "rubocop", "~> 1.21"
36
+ end
37
+
metadata ADDED
@@ -0,0 +1,105 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: toon-parser
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - afshmini
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2025-11-20 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rake
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '13.0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '13.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '3.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '3.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rubocop
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.21'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.21'
55
+ description: Parse TOON files and handle TOON-formatted API requests/responses. TOON
56
+ is a compact, human-readable data format designed to reduce token usage in LLM applications.
57
+ email:
58
+ - ''
59
+ executables: []
60
+ extensions: []
61
+ extra_rdoc_files: []
62
+ files:
63
+ - ".rspec"
64
+ - CHANGELOG.md
65
+ - CONTRIBUTING.md
66
+ - LICENSE.txt
67
+ - README.md
68
+ - Rakefile
69
+ - examples/rails_controller_example.rb
70
+ - lib/toon-parser.rb
71
+ - lib/toon-parser/api.rb
72
+ - lib/toon-parser/controller_helpers.rb
73
+ - lib/toon-parser/parser.rb
74
+ - lib/toon-parser/railtie.rb
75
+ - lib/toon-parser/serializer.rb
76
+ - lib/toon-parser/version.rb
77
+ - toon-parser.gemspec
78
+ homepage: https://github.com/afshmini/toon-parser
79
+ licenses:
80
+ - MIT
81
+ metadata:
82
+ homepage_uri: https://github.com/afshmini/toon-parser
83
+ source_code_uri: https://github.com/afshmini/toon-parser
84
+ changelog_uri: https://github.com/afshmini/toon-parser/blob/main/CHANGELOG.md
85
+ post_install_message:
86
+ rdoc_options: []
87
+ require_paths:
88
+ - lib
89
+ required_ruby_version: !ruby/object:Gem::Requirement
90
+ requirements:
91
+ - - ">="
92
+ - !ruby/object:Gem::Version
93
+ version: 2.7.0
94
+ required_rubygems_version: !ruby/object:Gem::Requirement
95
+ requirements:
96
+ - - ">="
97
+ - !ruby/object:Gem::Version
98
+ version: '0'
99
+ requirements: []
100
+ rubygems_version: 3.5.20
101
+ signing_key:
102
+ specification_version: 4
103
+ summary: A Ruby gem for parsing and serializing TOON (Token-Oriented Object Notation)
104
+ format
105
+ test_files: []