edn2023 1.1.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (142) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +19 -0
  3. data/.travis.yml +7 -0
  4. data/CHANGELOG.md +29 -0
  5. data/Gemfile +6 -0
  6. data/LICENSE +22 -0
  7. data/README.md +268 -0
  8. data/Rakefile +12 -0
  9. data/edn2023.gemspec +22 -0
  10. data/lib/edn/char_stream.rb +84 -0
  11. data/lib/edn/core_ext.rb +112 -0
  12. data/lib/edn/metadata.rb +27 -0
  13. data/lib/edn/parser.rb +92 -0
  14. data/lib/edn/reader.rb +23 -0
  15. data/lib/edn/ruby_edn_parser.rb +266 -0
  16. data/lib/edn/type/list.rb +13 -0
  17. data/lib/edn/type/symbol.rb +39 -0
  18. data/lib/edn/type/unknown.rb +9 -0
  19. data/lib/edn/type/uuid.rb +9 -0
  20. data/lib/edn/types.rb +3 -0
  21. data/lib/edn/version.rb +3 -0
  22. data/lib/edn.rb +80 -0
  23. data/spec/edn/char_stream_spec.rb +111 -0
  24. data/spec/edn/metadata_spec.rb +38 -0
  25. data/spec/edn/parser_spec.rb +162 -0
  26. data/spec/edn/reader_spec.rb +23 -0
  27. data/spec/edn_spec.rb +114 -0
  28. data/spec/exemplars/big_decimal.edn +1 -0
  29. data/spec/exemplars/big_decimal.rb +1 -0
  30. data/spec/exemplars/big_int.edn +1 -0
  31. data/spec/exemplars/big_int.rb +1 -0
  32. data/spec/exemplars/char.edn +1 -0
  33. data/spec/exemplars/char.rb +1 -0
  34. data/spec/exemplars/empty_string.edn +1 -0
  35. data/spec/exemplars/empty_string.rb +1 -0
  36. data/spec/exemplars/false.edn +1 -0
  37. data/spec/exemplars/false.rb +1 -0
  38. data/spec/exemplars/float.edn +1 -0
  39. data/spec/exemplars/float.rb +1 -0
  40. data/spec/exemplars/float_neg_exp.edn +1 -0
  41. data/spec/exemplars/float_neg_exp.rb +1 -0
  42. data/spec/exemplars/float_point_dec_neg_exp.edn +1 -0
  43. data/spec/exemplars/float_point_dec_neg_exp.rb +1 -0
  44. data/spec/exemplars/float_point_plus_exp.edn +1 -0
  45. data/spec/exemplars/float_point_plus_exp.rb +1 -0
  46. data/spec/exemplars/float_pointneg_exp.edn +1 -0
  47. data/spec/exemplars/float_pointneg_exp.rb +1 -0
  48. data/spec/exemplars/float_pos_exp.edn +1 -0
  49. data/spec/exemplars/float_pos_exp.rb +1 -0
  50. data/spec/exemplars/float_sign_exp.edn +1 -0
  51. data/spec/exemplars/float_sign_exp.rb +1 -0
  52. data/spec/exemplars/float_with_exp.edn +1 -0
  53. data/spec/exemplars/float_with_exp.rb +1 -0
  54. data/spec/exemplars/float_with_exp_no_dec.edn +1 -0
  55. data/spec/exemplars/float_with_exp_no_dec.rb +1 -0
  56. data/spec/exemplars/gt_symbol.edn +1 -0
  57. data/spec/exemplars/gt_symbol.rb +1 -0
  58. data/spec/exemplars/integer.edn +1 -0
  59. data/spec/exemplars/integer.rb +1 -0
  60. data/spec/exemplars/keyword.edn +1 -0
  61. data/spec/exemplars/keyword.rb +1 -0
  62. data/spec/exemplars/keyword_with_namespace.edn +1 -0
  63. data/spec/exemplars/keyword_with_namespace.rb +1 -0
  64. data/spec/exemplars/list_empty.edn +1 -0
  65. data/spec/exemplars/list_empty.rb +1 -0
  66. data/spec/exemplars/list_mixed.edn +1 -0
  67. data/spec/exemplars/list_mixed.rb +1 -0
  68. data/spec/exemplars/list_nested.edn +1 -0
  69. data/spec/exemplars/list_nested.rb +1 -0
  70. data/spec/exemplars/list_one_element.edn +1 -0
  71. data/spec/exemplars/list_one_element.rb +1 -0
  72. data/spec/exemplars/long_string.edn +1 -0
  73. data/spec/exemplars/long_string.rb +1 -0
  74. data/spec/exemplars/map_empty.edn +1 -0
  75. data/spec/exemplars/map_empty.rb +1 -0
  76. data/spec/exemplars/map_nested.edn +1 -0
  77. data/spec/exemplars/map_nested.rb +1 -0
  78. data/spec/exemplars/map_one_element.edn +1 -0
  79. data/spec/exemplars/map_one_element.rb +1 -0
  80. data/spec/exemplars/map_two_entry.edn +1 -0
  81. data/spec/exemplars/map_two_entry.rb +1 -0
  82. data/spec/exemplars/mmv +4 -0
  83. data/spec/exemplars/nil.edn +1 -0
  84. data/spec/exemplars/nil.rb +1 -0
  85. data/spec/exemplars/set_empty.edn +1 -0
  86. data/spec/exemplars/set_empty.rb +1 -0
  87. data/spec/exemplars/set_nested.edn +1 -0
  88. data/spec/exemplars/set_nested.rb +1 -0
  89. data/spec/exemplars/set_one_element.edn +1 -0
  90. data/spec/exemplars/set_one_element.rb +1 -0
  91. data/spec/exemplars/set_two_elements.edn +1 -0
  92. data/spec/exemplars/set_two_elements.rb +1 -0
  93. data/spec/exemplars/simple_skip.edn +1 -0
  94. data/spec/exemplars/simple_skip.rb +1 -0
  95. data/spec/exemplars/skip_more_space.edn +1 -0
  96. data/spec/exemplars/skip_more_space.rb +1 -0
  97. data/spec/exemplars/skip_more_vector_elements.edn +1 -0
  98. data/spec/exemplars/skip_more_vector_elements.rb +1 -0
  99. data/spec/exemplars/skip_some_vector_elements.edn +1 -0
  100. data/spec/exemplars/skip_some_vector_elements.rb +1 -0
  101. data/spec/exemplars/skip_two_vector_elements.edn +1 -0
  102. data/spec/exemplars/skip_two_vector_elements.rb +1 -0
  103. data/spec/exemplars/skip_vector_element.edn +1 -0
  104. data/spec/exemplars/skip_vector_element.rb +1 -0
  105. data/spec/exemplars/skip_with_spaces.edn +1 -0
  106. data/spec/exemplars/skip_with_spaces.rb +1 -0
  107. data/spec/exemplars/skip_yet_more_space.edn +1 -0
  108. data/spec/exemplars/skip_yet_more_space.rb +1 -0
  109. data/spec/exemplars/special_symbol.edn +1 -0
  110. data/spec/exemplars/special_symbol.rb +1 -0
  111. data/spec/exemplars/string_with_newline.edn +1 -0
  112. data/spec/exemplars/string_with_newline.rb +1 -0
  113. data/spec/exemplars/symbol.edn +1 -0
  114. data/spec/exemplars/symbol.rb +1 -0
  115. data/spec/exemplars/symbol_begins_with_false.edn +1 -0
  116. data/spec/exemplars/symbol_begins_with_false.rb +1 -0
  117. data/spec/exemplars/symbol_begins_with_nil.edn +1 -0
  118. data/spec/exemplars/symbol_begins_with_nil.rb +1 -0
  119. data/spec/exemplars/symbol_with_dash.edn +1 -0
  120. data/spec/exemplars/symbol_with_dash.rb +1 -0
  121. data/spec/exemplars/symbol_with_namespace.edn +1 -0
  122. data/spec/exemplars/symbol_with_namespace.rb +1 -0
  123. data/spec/exemplars/tagged_instant.edn +1 -0
  124. data/spec/exemplars/tagged_instant.rb +1 -0
  125. data/spec/exemplars/tagged_uuid.edn +1 -0
  126. data/spec/exemplars/tagged_uuid.rb +1 -0
  127. data/spec/exemplars/true.edn +1 -0
  128. data/spec/exemplars/true.rb +1 -0
  129. data/spec/exemplars/utf8.edn +1 -0
  130. data/spec/exemplars/utf8.rb +1 -0
  131. data/spec/exemplars/vector_empty.edn +1 -0
  132. data/spec/exemplars/vector_empty.rb +1 -0
  133. data/spec/exemplars/vector_mixed.edn +1 -0
  134. data/spec/exemplars/vector_mixed.rb +1 -0
  135. data/spec/exemplars/vector_nested.edn +1 -0
  136. data/spec/exemplars/vector_nested.rb +1 -0
  137. data/spec/exemplars/vector_one_element.edn +1 -0
  138. data/spec/exemplars/vector_one_element.rb +1 -0
  139. data/spec/exemplars/whole_number_with_exp.edn +1 -0
  140. data/spec/exemplars/whole_number_with_exp.rb +1 -0
  141. data/spec/spec_helper.rb +164 -0
  142. metadata +357 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: b6536c5d243ceaf4962408fcdf528d7bf983b13223284562de5377ab692a7f2e
4
+ data.tar.gz: 8b186c8112be6fbf2194562b20a538780cfc118bb819ec0098a4a89a77b856fa
5
+ SHA512:
6
+ metadata.gz: 7ae3d3d1b5ee8449e977644c11fc0f6aa546d13556bbc687a6526658e162f7190608ff68f42763f79fbe8d34a85353d741d716ded46f1017fe2fb0e881b8c9f0
7
+ data.tar.gz: aae587f32dca3595f9a3a4526175ed6af9488e9c3a1be5c706bab3ec6d3ccb8568cf70638e63ffc3e6fc426c4b21c2379b4672f688e9b0abcee795b150c20b9a
data/.gitignore ADDED
@@ -0,0 +1,19 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ .rspec
7
+ README.html
8
+ Gemfile.lock
9
+ InstalledFiles
10
+ _yardoc
11
+ coverage
12
+ doc/
13
+ lib/bundler/man
14
+ pkg
15
+ rdoc
16
+ spec/reports
17
+ test/tmp
18
+ test/version_tmp
19
+ tmp
data/.travis.yml ADDED
@@ -0,0 +1,7 @@
1
+ language: ruby
2
+ rvm:
3
+ - "1.9.2"
4
+ - "2.1.0"
5
+ - "3.2.0"
6
+ - jruby-head
7
+ script: bundle exec rspec spec
data/CHANGELOG.md ADDED
@@ -0,0 +1,29 @@
1
+ # 1.1.4 (March 9, 2023)
2
+
3
+ * Forked to support Ruby 3.2. <https://github.com/edn2023/edn2023> New RubyGem `edn2023`. (@edn2023)
4
+
5
+
6
+ # 1.1.2 (January 13, 2020)
7
+
8
+ * BigDecimal.new() -> BigDecimal() for Ruby 2.7 (BigDecimal 2). (@caleb)
9
+
10
+
11
+ # 1.0.2
12
+ * Handle numbers with M precision
13
+
14
+ # 1.0.1
15
+ * EDN.register defaults to the identity function when no handler is given
16
+
17
+ # 0.9.4 (18 Sep 2012)
18
+
19
+ * Require `set`
20
+
21
+ # 0.9.3 (17 Sep 2012)
22
+
23
+ * Updated to latest EDN spec
24
+ ** Added new symbol characters
25
+ ** Added ability to have a + before a number
26
+
27
+ # 0.9.2 (13 Sep 2012)
28
+
29
+ * EDN spec fully implemented
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in edn.gemspec
4
+ gemspec
5
+
6
+
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Relevance Inc & Clinton N. Dreisbach
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,268 @@
1
+ # edn2023
2
+
3
+ &copy; 2012 Relevance Inc
4
+
5
+ **edn2023** is a Ruby library to read and write EDN (extensible data notation), a subset of Clojure used for transferring data between applications, much like JSON, YAML, or XML.
6
+
7
+ ## Installation
8
+
9
+ If the `edn` gem is installed it should be uninstalled:
10
+
11
+ $ gem uninstall edn
12
+
13
+ Add this line to your application's Gemfile:
14
+
15
+ gem 'edn2023'
16
+
17
+ And then execute:
18
+
19
+ $ bundle
20
+
21
+ Or install it yourself as:
22
+
23
+ $ gem install edn2023
24
+
25
+
26
+ Note that you might also want to look at [edn_turbo](https://github.com/edporras/edn_turbo)
27
+ which provides a much faster EDN parser (It's written in C) with an interface that is largely compatible
28
+ with ths gem.
29
+
30
+ ## Usage
31
+
32
+ To read a string of EDN:
33
+
34
+ ```ruby
35
+ require 'edn'
36
+ EDN.read('[1 2 {:foo "bar"}]')
37
+ ```
38
+
39
+ Alternatively you can pass in an IO instance, for
40
+ example an open file:
41
+
42
+ ```ruby
43
+ File.open("data.edn") do |f|
44
+ data = EDN.read(f)
45
+ # Do something with data
46
+ end
47
+ ```
48
+
49
+ By default EDN.read will throw an execption
50
+ if you try to read past the end of the data:
51
+
52
+ ```ruby
53
+ EDN.read("") # Boom!
54
+ ```
55
+
56
+ Alternatively, the `EDN.read` method takes an optional
57
+ parameter, which is the value to return
58
+ when it hits the end of data:
59
+
60
+ ```ruby
61
+ EDN.read("", :nomore)
62
+
63
+ #=> :nomore
64
+ ```
65
+
66
+ There is no problem using `nil` as an eof value.
67
+
68
+ ### EDN::Reader
69
+
70
+ You can also do things in a more object oriented way by
71
+ creating instances of `EDN::Reader`:
72
+
73
+ ```ruby
74
+ r = EDN::Reader.new('[1 2 3] {:a 1 :b 2}')
75
+
76
+ r.read #=> [1, 2, 3]
77
+ r.read #=> {:a => 1, :b => 2}
78
+ r.read #=> RuntimeError: Unexpected end of file
79
+ ```
80
+
81
+ `EDN:Reader` will also take an IO instance:
82
+
83
+ ```ruby
84
+ r = EDN::Reader.new(open("data.edn"))
85
+
86
+ r.read # Read the first form from the file.
87
+ r.read # Read the second form from the file.
88
+ r.read # Read the third from from the file.
89
+ ```
90
+
91
+ You can also iterate through the forms with `each`:
92
+
93
+ ```ruby
94
+ r = EDN::Reader.new('[1 2 3] {:a 1 :b 2}')
95
+
96
+ r.each do |form|
97
+ p form
98
+ end
99
+
100
+ #=> [1, 2, 3]
101
+ #=> {:a => 1, :b => 2}
102
+ ```
103
+
104
+ Note that in contrast to earlier versions of this gem,
105
+ EDN::Reader is no longer `Enumerable`.
106
+
107
+ Like `EDN.read`, `Reader.read` also takes an optional
108
+ parameter, which is returned when there is no more data:
109
+
110
+ ```ruby
111
+ r = EDN::Reader.new('1 2 3')
112
+ r.read(:eof) # returns 1
113
+ r.read(:eof) # returns 2
114
+ r.read(:eof) # returns 3
115
+ r.read(:eof) # returns :eof
116
+ ```
117
+
118
+ ### Converting Ruby data to EDN
119
+
120
+ To convert a data structure to an EDN string:
121
+
122
+ ```ruby
123
+ data.to_edn
124
+ ```
125
+
126
+ By default, this will work for strings, symbols, numbers, arrays, hashes, sets, nil, Time, and boolean values.
127
+
128
+ ### Value Translations
129
+
130
+ Note that EDN uses its own terminology for the types of objects it represents
131
+ and in some cases those types not map cleanly to Ruby.
132
+
133
+ In EDN, you have _keywords_, which look like Ruby symbols and have the same meaning and
134
+ purpose. These are converted to Ruby symbols.
135
+
136
+ You also have EDN _symbols_, which generally reflect variable names, but have
137
+ several purposes. We parse these and return `EDN::Type::Symbol` values for them,
138
+ as they don't map to anything built into Ruby. To create an EDN symbol in Ruby,
139
+ call `EDN::Type::Symbol.new` or `EDN.symbol` with a string argument, or use the
140
+ convenience unary operator `~` like so: `~"elf/rings"`.
141
+
142
+ EDN also has _vectors_, which map to Ruby arrays, and _lists_, which are linked lists
143
+ in Clojure. We map EDN lists to `EDN::Type::List` values, which are type-compatible with
144
+ arrays. To create an EDN list in Ruby, call `EDN::Type::List.new` or `EDN.list`
145
+ with all arguments to go in the list. If you have an array, you will use the splat
146
+ operator, like so: `EDN.list(*[1, 2, 3])`. You can also use the `~` unary
147
+ operator like so: `~[1, 2, 3]`.
148
+
149
+ EDN also has character types, but Ruby does not. These are converted into one-character strings.
150
+
151
+ ### Tagged Values
152
+
153
+ The interesting part of EDN is the _extensible_ part.
154
+ Data can be be _tagged_ to coerce interpretation of
155
+ it to a particular data type. An example of a tagged data element:
156
+
157
+ ```
158
+ #wolf/pack {:alpha "Greybeard" :betas ["Frostpaw" "Blackwind" "Bloodjaw"]}
159
+ ```
160
+
161
+ The tag (`#wolf/pack`) will tell any consumers of this data
162
+ to use a data type registered to handle `wolf/pack` to represent this data.
163
+
164
+ The rules for tags from the [EDN README][README] should be followed. In short, custom tags should have a prefix (the part before the `/`) designating the user that created them or context they are used in. Non-prefixed tags are reserved for built-in tags.
165
+
166
+ There are two tags built in by default: `#uuid`, used for UUIDs, and `#inst`, used for an instant in time. In `edn-ruby`, `#inst` is converted to a Time, and Time values are tagged as `#inst`. There is not a UUID data type built into Ruby, so `#uuid` is converted to an instance of `EDN::Type::UUID`.
167
+
168
+ Tags that are not registered generate a struct of the type `EDN::Type::Unknown` with the methods `tag` and `value`.
169
+
170
+ ### Registering a New Tag For Reading
171
+
172
+ To register a tag for reading, call the method `EDN.register` with a tag and one of the following:
173
+
174
+ - A block that accepts data and returns a value.
175
+ - A lambda that accepts data and returns a value.
176
+ - A class that has an `initialize` method that accepts data.
177
+
178
+ Examples:
179
+
180
+ ```ruby
181
+ EDN.register("clinton/uri") do |uri|
182
+ URI(uri)
183
+ end
184
+
185
+ EDN.register("clinton/date", lambda { |date_array| Date.new(*date_array) })
186
+
187
+ class Dog
188
+ def initialize(name)
189
+ @name = name
190
+ end
191
+ end
192
+
193
+ EDN.register("clinton/dog", Dog)
194
+ ```
195
+
196
+ ### Writing Tags
197
+
198
+ Writing tags should be done as part of the class's `.to_edn` method, like so:
199
+
200
+ ```ruby
201
+ class Dog
202
+ def to_edn
203
+ ["#clinton/dog", @name.to_edn].join(" ")
204
+ end
205
+ end
206
+ ```
207
+
208
+ `EDN` provides a helper method, `EDN.tagout`:
209
+
210
+ ```ruby
211
+ class Dog
212
+ def to_edn
213
+ EDN.tagout("clinton/dog", @name)
214
+ end
215
+ end
216
+ ```
217
+
218
+ This method calls `.to_edn` on the second argument and joins the arguments appropriately.
219
+
220
+ Other examples are:
221
+ ```
222
+ EDN.tagout("wolf/pack", {:alpha=>"Greybeard", :betas=>["Frostpaw", "Blackwind", "Bloodjaw"]})
223
+ => "#wolf/pack {:alpha \"Greybeard\", :betas [\"Frostpaw\" \"Blackwind\" \"Bloodjaw\"]}"
224
+
225
+ class Range
226
+ def to_edn
227
+ EDN.tagout("ruby/range", [self.begin, self.end, self.exclude_end?])
228
+ end
229
+ end
230
+
231
+ (0..9).to_edn
232
+ => "#ruby/range [0 9 false]"
233
+ ```
234
+
235
+
236
+ ## Metadata
237
+
238
+ Certain elements of EDN can have *metadata*. Metadata is a map of values about the element, which must follow specific rules.
239
+
240
+ * Only symbols, lists, vectors, maps, and sets can have metadata. Tagged elements *cannot* have metadata.
241
+ * Metadata keys must be symbols, keywords, or strings.
242
+
243
+ Metadata can be expressed in one of the following three ways:
244
+
245
+ * Via a map. The element is prefixed with a map which has a caret (`^`) prefixed to it, like so: `^{:doc "This is my vector" :rel :temps} [98.6 99.7]`.
246
+ * Via a keyword. The element is prefixed with a keyword, also prefixed by a caret: `^:awesome #{1 2 \c}`. This results in the key `:awesome` being set to `true`, as if the metadata was: `^{:awesome true} #{1 2 \c}`.
247
+ * Via a symbol. The element is prefixed with a symbol, also prefixed by a caret: `^Boolean "true"`. This results in the key `:tag` being set to the symbol, as if the metadata was: `^{:tag Boolean} "true"`. This is used in Clojure to indicate the Java type of the element. In other EDN implementations, it may be ignored or used differently.
248
+
249
+ More than one piece of metadata can be applied to an element. Metadata is applied to the next element appearing after it, so in the case of `^:foo ^{:bar false} [1 2]`, the metadata would be, in total, `^{:foo true, :bar false}`. Note that `^:foo` is applied to the element `[1 2]` with the metadata `^{:bar false}` applied to it. Because of this, key collisions are resolved *right-to-left*.
250
+
251
+ ## Contributors
252
+
253
+ * Clinton N. Dreisbach (@crnixon)
254
+ * Michael Ficarra (@michaelficarra)
255
+ * Andrew Forward (@aforward)
256
+ * Gabriel Horner (@cldwalker)
257
+ * Russ Olsen (@russolsen)
258
+
259
+ ## Contributing
260
+
261
+ 1. Fork it
262
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
263
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
264
+ 4. Push to the branch (`git push origin my-new-feature`)
265
+ 5. Create new Pull Request
266
+
267
+ [edn]: https://github.com/edn-format/edn
268
+ [README]: https://github.com/edn-format/edn/blob/master/README.md
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+ require 'rspec/core/rake_task'
4
+
5
+ RSpec::Core::RakeTask.new(:spec)
6
+
7
+ task :default => :spec
8
+
9
+ task :irb do
10
+ sh "irb -I lib -r edn"
11
+ sh "reset"
12
+ end
data/edn2023.gemspec ADDED
@@ -0,0 +1,22 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/edn/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Clinton N. Dreisbach & Russ Olsen"]
6
+ gem.description = %q{edn implements a reader for Extensible Data Notation by Rich Hickey.}
7
+ gem.summary = gem.description
8
+ gem.homepage = "https://github.com/edn2023/edn2023"
9
+ gem.license = "MIT"
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = "edn2023"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = EDN::VERSION
17
+
18
+ gem.add_development_dependency 'pry'
19
+ gem.add_development_dependency 'rspec'
20
+ gem.add_development_dependency 'rantly'
21
+ gem.add_development_dependency 'rake'
22
+ end
@@ -0,0 +1,84 @@
1
+ require 'stringio'
2
+ require 'set'
3
+
4
+ module EDN
5
+ class CharStream
6
+ def initialize(io=$stdin)
7
+ @io = io
8
+ @current = nil
9
+ end
10
+
11
+ def current
12
+ return @current if @current
13
+ advance
14
+ end
15
+
16
+ def advance
17
+ return @current if @current == :eof
18
+ @current = @io.getc || :eof
19
+ end
20
+
21
+ def digit?(c=current)
22
+ /[0-9]/ =~ c
23
+ end
24
+
25
+ def alpha?(c=current)
26
+ /[a-zA-Z]/ =~ c
27
+ end
28
+
29
+ def eof?(c=current)
30
+ c == :eof
31
+ end
32
+
33
+ def ws?(c=current)
34
+ /[ \t\r\n,]/ =~ c
35
+ end
36
+
37
+ def newline?(c=current)
38
+ /[\n\r]/ =~ c
39
+ end
40
+
41
+ def repeat(pattern, &block)
42
+ result = nil
43
+ while current =~ pattern
44
+ result ||= ''
45
+ result = block.call(result, current)
46
+ end
47
+ result
48
+ end
49
+
50
+ def gather(pattern)
51
+ repeat(pattern) do |result, ch|
52
+ result << ch
53
+ end
54
+ end
55
+
56
+ def skip_past(expected, error_message=nil)
57
+ if current == expected
58
+ advance
59
+ return expected
60
+ elsif error_message
61
+ raise error_message
62
+ end
63
+ nil
64
+ end
65
+
66
+ def skip_to_eol
67
+ until current == :eof || newline?
68
+ advance
69
+ end
70
+ end
71
+
72
+ def skip_ws
73
+ while current != :eof
74
+ if ws?(current)
75
+ advance
76
+ elsif current == ';'
77
+ skip_to_eol
78
+ else
79
+ break
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,112 @@
1
+ require 'time'
2
+ require 'bigdecimal'
3
+ require 'set'
4
+
5
+ module EDN
6
+ module CoreExt
7
+ module Unquoted
8
+ def to_edn
9
+ self.to_s
10
+ end
11
+ end
12
+
13
+ module AllowsMetadata
14
+ def allows_metadata?
15
+ true
16
+ end
17
+ end
18
+
19
+ module Integer
20
+ def to_edn
21
+ self.to_s + 'N'
22
+ end
23
+ end
24
+
25
+ module BigDecimal
26
+ def to_edn
27
+ self.to_s('F') + 'M'
28
+ end
29
+ end
30
+
31
+ module String
32
+ def ~@
33
+ EDN::Type::Symbol.new(self)
34
+ end
35
+
36
+ def to_edn
37
+ array = chars.map do |ch|
38
+ if %w{" \\}.include?(ch)
39
+ '\\' + ch
40
+ else
41
+ ch
42
+ end
43
+ end
44
+ '"' + array.join + '"'
45
+ end
46
+ end
47
+
48
+ module Symbol
49
+ def to_edn
50
+ ":#{self.to_s}"
51
+ end
52
+ end
53
+
54
+ module Array
55
+ def ~@
56
+ EDN::Type::List.new(*self)
57
+ end
58
+
59
+ def to_edn
60
+ '[' + self.map(&:to_edn).join(" ") + ']'
61
+ end
62
+ end
63
+
64
+ module Hash
65
+ def to_edn
66
+ '{' + self.map { |k, v| [k, v].map(&:to_edn).join(" ") }.join(", ") + '}'
67
+ end
68
+ end
69
+
70
+ module Set
71
+ def to_edn
72
+ '#{' + self.to_a.map(&:to_edn).join(" ") + '}'
73
+ end
74
+ end
75
+
76
+ module NilClass
77
+ def to_edn
78
+ "nil"
79
+ end
80
+ end
81
+
82
+ module DateTime
83
+ def to_edn
84
+ EDN.tagout("inst", self.rfc3339)
85
+ end
86
+ end
87
+
88
+ module Time
89
+ def to_edn
90
+ EDN.tagout("inst", self.xmlschema)
91
+ end
92
+ end
93
+ end
94
+ end
95
+
96
+ Numeric.send(:include, EDN::CoreExt::Unquoted)
97
+ Integer.send(:include, EDN::CoreExt::Integer)
98
+ BigDecimal.send(:include, EDN::CoreExt::BigDecimal)
99
+ TrueClass.send(:include, EDN::CoreExt::Unquoted)
100
+ FalseClass.send(:include, EDN::CoreExt::Unquoted)
101
+ NilClass.send(:include, EDN::CoreExt::NilClass)
102
+ String.send(:include, EDN::CoreExt::String)
103
+ Symbol.send(:include, EDN::CoreExt::Symbol)
104
+ Array.send(:include, EDN::CoreExt::Array)
105
+ Hash.send(:include, EDN::CoreExt::Hash)
106
+ Set.send(:include, EDN::CoreExt::Set)
107
+ DateTime.send(:include, EDN::CoreExt::DateTime)
108
+ Time.send(:include, EDN::CoreExt::Time)
109
+
110
+ [Array, Hash, Set].each do |klass|
111
+ klass.send(:include, EDN::CoreExt::AllowsMetadata)
112
+ end
@@ -0,0 +1,27 @@
1
+ module EDN
2
+ module Metadata
3
+ def self.extended(base)
4
+ base.instance_eval do
5
+ alias :to_edn_without_metadata :to_edn
6
+ alias :to_edn :to_edn_with_metadata
7
+ end
8
+ end
9
+
10
+ attr_accessor :metadata
11
+
12
+ def has_metadata?
13
+ respond_to?(:allows_metadata?) and
14
+ allows_metadata? and
15
+ !metadata.nil? and
16
+ !metadata.empty?
17
+ end
18
+
19
+ def to_edn_with_metadata
20
+ if has_metadata?
21
+ '^' + metadata.to_edn + ' ' + to_edn_without_metadata
22
+ else
23
+ to_edn_without_metadata
24
+ end
25
+ end
26
+ end
27
+ end