sip2-ruby 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.
Files changed (45) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +21 -0
  3. data/README.md +136 -0
  4. data/Rakefile +10 -0
  5. data/bin/json-to-sip2 +109 -0
  6. data/bin/sip2-to-json +81 -0
  7. data/lib/sip2/checksum_encoder.rb +11 -0
  8. data/lib/sip2/field_parser_rules.rb +490 -0
  9. data/lib/sip2/fields.rb +742 -0
  10. data/lib/sip2/message/base_message.rb +135 -0
  11. data/lib/sip2/message/unknown_message.rb +26 -0
  12. data/lib/sip2/message.rb +95 -0
  13. data/lib/sip2/message_parser_rules.rb +122 -0
  14. data/lib/sip2/messages.rb +628 -0
  15. data/lib/sip2/parser.rb +14 -0
  16. data/lib/sip2/parser_atoms.rb +53 -0
  17. data/lib/sip2/transformer.rb +94 -0
  18. data/lib/sip2/types.rb +6 -0
  19. data/lib/sip2/version.rb +3 -0
  20. data/lib/sip2.rb +18 -0
  21. data/sip2-ruby.gemspec +39 -0
  22. data/test/fixture_helper.rb +31 -0
  23. data/test/fixtures/09.sip2 +1 -0
  24. data/test/fixtures/10.sip2 +1 -0
  25. data/test/fixtures/17.sip2 +1 -0
  26. data/test/fixtures/18.sip2 +1 -0
  27. data/test/fixtures/98-with-unexpected.sip2 +1 -0
  28. data/test/fixtures/98.sip2 +1 -0
  29. data/test/fixtures/99-with-unexpected.sip2 +1 -0
  30. data/test/fixtures/99.sip2 +1 -0
  31. data/test/fixtures/XX.sip2 +1 -0
  32. data/test/fixtures/alma/09.sip2 +1 -0
  33. data/test/fixtures/alma/10.sip2 +1 -0
  34. data/test/fixtures/alma/17.sip2 +1 -0
  35. data/test/fixtures/alma/18.sip2 +1 -0
  36. data/test/fixtures/alma/98.sip2 +1 -0
  37. data/test/fixtures/alma/99.sip2 +1 -0
  38. data/test/round_trip_spec.rb +82 -0
  39. data/test/sip2/message_parser_rules_spec.rb +50 -0
  40. data/test/sip2/parser_atoms_spec.rb +354 -0
  41. data/test/sip2/parser_test.rb +11 -0
  42. data/test/sip2_spec.rb +145 -0
  43. data/test/spec_helper.rb +4 -0
  44. data/test/test_helper.rb +4 -0
  45. metadata +190 -0
@@ -0,0 +1,354 @@
1
+ require_relative '../spec_helper'
2
+ require 'sip2/parser_atoms'
3
+
4
+ include Sip2
5
+
6
+ describe ParserAtoms do
7
+
8
+ include ParserAtoms
9
+
10
+ describe :digit do
11
+ it "matches a single digit" do
12
+ assert_equal "1", digit.parse("1")
13
+ end
14
+
15
+ it "doesn't match multiple digits" do
16
+ assert_raises(Parslet::ParseFailed) { digit.parse("12") }
17
+ end
18
+
19
+ it "doesn't match other chars" do
20
+ %w[a . _].each do |c|
21
+ assert_raises(Parslet::ParseFailed) { digit.parse(c) }
22
+ end
23
+ end
24
+ end
25
+
26
+ describe :year do
27
+ subject { year }
28
+
29
+ it "matches a normal four digit year" do
30
+ assert_equal "2023", subject.parse("2023")
31
+ end
32
+
33
+ it "doesn't match non-four-digit values" do
34
+ %w[123 202E 12345].each do |c|
35
+ assert_raises(Parslet::ParseFailed) { subject.parse(c) }
36
+ end
37
+ end
38
+ end
39
+
40
+ describe :month do
41
+ subject { month }
42
+
43
+ it "matches all normal two digit months" do
44
+ ("01".."12").each do |str|
45
+ assert_equal str, subject.parse(str)
46
+ end
47
+ end
48
+
49
+ it "doesn't match months outside the 01-12 range" do
50
+ %w[00 13].each do |c|
51
+ assert_raises(Parslet::ParseFailed) { subject.parse(c) }
52
+ end
53
+ end
54
+
55
+ it "doesn't match non-two-digit values" do
56
+ %w[0 1 ab 123].each do |c|
57
+ assert_raises(Parslet::ParseFailed) { subject.parse(c) }
58
+ end
59
+ end
60
+ end
61
+
62
+ describe :day do
63
+ subject { day }
64
+
65
+ it "matches normal two digit days" do
66
+ %w[01 15 23 31].each do |str|
67
+ assert_equal str, subject.parse(str)
68
+ end
69
+ end
70
+
71
+ it "doesn't match days outside the 01-31 range" do
72
+ %w[00 32 60].each do |c|
73
+ assert_raises(Parslet::ParseFailed) { subject.parse(c) }
74
+ end
75
+ end
76
+
77
+ it "doesn't match non-two-digit values" do
78
+ %w[0 1 ab 123].each do |c|
79
+ assert_raises(Parslet::ParseFailed) { subject.parse(c) }
80
+ end
81
+ end
82
+ end
83
+
84
+ describe :hour do
85
+ subject { hour }
86
+
87
+ it "matches normal two digit hours" do
88
+ %w[00 08 15 23].each do |str|
89
+ assert_equal str, subject.parse(str)
90
+ end
91
+ end
92
+
93
+ it "doesn't match hours outside the 00-23 range" do
94
+ %w[24 42].each do |c|
95
+ assert_raises(Parslet::ParseFailed) { subject.parse(c) }
96
+ end
97
+ end
98
+
99
+ it "doesn't match non-two-digit values" do
100
+ %w[0 1 ab 123].each do |c|
101
+ assert_raises(Parslet::ParseFailed) { subject.parse(c) }
102
+ end
103
+ end
104
+ end
105
+
106
+ [:second, :minute].each do |unit|
107
+ describe unit do
108
+ subject { self.send(unit) }
109
+
110
+ it "matches normal two digit #{unit}s" do
111
+ %w[00 08 32 59].each do |str|
112
+ assert_equal str, subject.parse(str)
113
+ end
114
+ end
115
+
116
+ it "doesn't match #{unit}s outside the 00-59 range" do
117
+ %w[60 99].each do |c|
118
+ assert_raises(Parslet::ParseFailed) { subject.parse(c) }
119
+ end
120
+ end
121
+
122
+ it "doesn't match non-two-digit values" do
123
+ %w[0 1 ab 123].each do |c|
124
+ assert_raises(Parslet::ParseFailed) { subject.parse(c) }
125
+ end
126
+ end
127
+ end
128
+ end
129
+
130
+ describe :zzzz do
131
+ subject { zzzz }
132
+
133
+ let(:allowed) { [" ", "ZZZZ", "EST "] }
134
+ let(:disallowed) { ["zzzz", "1234", "...."] }
135
+
136
+ it "matches all allowed values" do
137
+ allowed.each do |v|
138
+ assert_equal v, subject.parse(v)
139
+ end
140
+ end
141
+
142
+ it "doesn't match disallowed values" do
143
+ disallowed.each do |v|
144
+ assert_raises(Parslet::ParseFailed) { subject.parse(v) }
145
+ end
146
+ end
147
+
148
+ it "only matches a 4 char values" do
149
+ allowed.each do |v|
150
+ assert_raises(Parslet::ParseFailed) { subject.parse(v + v) }
151
+ end
152
+ end
153
+
154
+ end
155
+
156
+ describe :bool do
157
+ subject { bool }
158
+
159
+ it "matches Y" do
160
+ assert_equal subject.parse("Y"), { bool: "Y" }
161
+ end
162
+
163
+ it "matches N" do
164
+ assert_equal subject.parse("N"), { bool: "N" }
165
+ end
166
+
167
+ it "doesn't match alternative bool patterns" do
168
+ [" ", "U", "1", "0"].each do |c|
169
+ assert_raises(Parslet::ParseFailed) { subject.parse(c) }
170
+ end
171
+ end
172
+
173
+ it "only matches a single char" do
174
+ %w[YY NN YN NY].each do |c|
175
+ assert_raises(Parslet::ParseFailed) { subject.parse(c) }
176
+ end
177
+ end
178
+ end
179
+
180
+ describe :bool do
181
+ subject { bool }
182
+
183
+ let(:allowed) { ["Y", "N"] }
184
+ let(:disallowed) { [" ", "U", "0", "1"] }
185
+
186
+ it "matches all allowed values" do
187
+ allowed.each do |v|
188
+ assert_equal subject.parse(v), { bool: v }
189
+ end
190
+ end
191
+
192
+ it "doesn't match disallowed values" do
193
+ disallowed.each do |v|
194
+ assert_raises(Parslet::ParseFailed) { subject.parse(v) }
195
+ end
196
+ end
197
+
198
+ it "only matches a single char" do
199
+ allowed.each do |v|
200
+ assert_raises(Parslet::ParseFailed) { subject.parse(v + v) }
201
+ end
202
+ end
203
+
204
+ end
205
+
206
+ describe :bool_with_space do
207
+ subject { bool_with_space }
208
+
209
+ let(:allowed) { ["Y", " "] }
210
+ let(:disallowed) { ["N", "U", "0", "1"] }
211
+
212
+ it "matches all allowed values" do
213
+ allowed.each do |v|
214
+ assert_equal subject.parse(v), { bool: v }
215
+ end
216
+ end
217
+
218
+ it "doesn't match disallowed values" do
219
+ disallowed.each do |v|
220
+ assert_raises(Parslet::ParseFailed) { subject.parse(v) }
221
+ end
222
+ end
223
+
224
+ it "only matches a single char" do
225
+ allowed.each do |v|
226
+ assert_raises(Parslet::ParseFailed) { subject.parse(v + v) }
227
+ end
228
+ end
229
+
230
+ end
231
+
232
+ describe :nillable_bool do
233
+ subject { nillable_bool }
234
+
235
+ let(:allowed) { ["Y", "N", "U"] }
236
+ let(:disallowed) { [" ", "0", "1"] }
237
+
238
+ it "matches all allowed values" do
239
+ allowed.each do |v|
240
+ assert_equal subject.parse(v), { bool: v }
241
+ end
242
+ end
243
+
244
+ it "doesn't match disallowed values" do
245
+ disallowed.each do |v|
246
+ assert_raises(Parslet::ParseFailed) { subject.parse(v) }
247
+ end
248
+ end
249
+
250
+ it "only matches a single char" do
251
+ allowed.each do |v|
252
+ assert_raises(Parslet::ParseFailed) { subject.parse(v + v) }
253
+ end
254
+ end
255
+
256
+ end
257
+
258
+ describe :numerical_bool do
259
+ subject { numerical_bool }
260
+
261
+ let(:allowed) { ["0", "1"] }
262
+ let(:disallowed) { ["Y", "N", "U", " "] }
263
+
264
+ it "matches all allowed values" do
265
+ allowed.each do |v|
266
+ assert_equal subject.parse(v), { bool: v }
267
+ end
268
+ end
269
+
270
+ it "doesn't match disallowed values" do
271
+ disallowed.each do |v|
272
+ assert_raises(Parslet::ParseFailed) { subject.parse(v) }
273
+ end
274
+ end
275
+
276
+ it "only matches a single char" do
277
+ allowed.each do |v|
278
+ assert_raises(Parslet::ParseFailed) { subject.parse(v + v) }
279
+ end
280
+ end
281
+
282
+ end
283
+
284
+
285
+ describe :timestamp do
286
+ subject { timestamp }
287
+
288
+ it "matches timestamps with valid dates and times" do
289
+ [
290
+ "19700101ZZZZ000000",
291
+ "20230823ZZZZ102930",
292
+ "20991231 235959",
293
+ ].each do |str|
294
+ assert_equal subject.parse(str).keys, [:year, :month, :day, :zone, :hour, :minute, :second]
295
+ end
296
+ end
297
+
298
+ it "doesn't match timestamp with *clearly* invalid dates or times" do
299
+ [
300
+ "AB010203 040506",
301
+ "20019903 040506",
302
+ "20010299 040506",
303
+ "20010203 990506",
304
+ "20010203 049906",
305
+ "20010203 040599",
306
+ ].each do |str|
307
+ assert_raises(Parslet::ParseFailed) { subject.parse(str) }
308
+ end
309
+ end
310
+
311
+ it "doesn't match non-18-char values" do
312
+ [
313
+ "19700101ZZZ000000",
314
+ "20230823ZZZZZ102930",
315
+ "20991231235959",
316
+ ].each do |str|
317
+ assert_raises(Parslet::ParseFailed) { subject.parse(str) }
318
+ end
319
+ end
320
+ end
321
+
322
+ describe :variable_length_value do
323
+ subject { variable_length_value }
324
+
325
+ it "requires a trailing pipe char" do
326
+ assert_raises(Parslet::ParseFailed) { subject.parse("foo") }
327
+ end
328
+
329
+ it "captures the value without the trailing pipe char" do
330
+ assert_equal({str: "foo"}, subject.parse("foo|"))
331
+ end
332
+
333
+ it "matches any kind of str in lengths from 1 to 255" do
334
+ ["a", "A", "Å", "1", ".", " "].product([1, 20, 255]).each do |chr, length|
335
+ value = (chr * length)
336
+ assert_equal({str: value}, subject.parse(value + "|"))
337
+ end
338
+ end
339
+
340
+ it "matches a single pipe (empty value)" do
341
+ assert_equal({str: []}, subject.parse("|"))
342
+ end
343
+
344
+ it "doesn't match strings longer than 255" do
345
+ assert_raises(Parslet::ParseFailed) { subject.parse("A" * 256 + "|") }
346
+ end
347
+
348
+ it "doesn't allow a pipe char in the data" do
349
+ assert_raises(Parslet::ParseFailed) { subject.parse("||") }
350
+ end
351
+
352
+ end
353
+
354
+ end
@@ -0,0 +1,11 @@
1
+ require "test_helper"
2
+
3
+ class Sip2::ParserTest < Minitest::Test
4
+ def test_that_it_has_a_version_number
5
+ refute_nil ::Sip2::Parser::VERSION
6
+ end
7
+
8
+ def test_it_does_something_useful
9
+ assert false
10
+ end
11
+ end
data/test/sip2_spec.rb ADDED
@@ -0,0 +1,145 @@
1
+ require_relative 'spec_helper'
2
+ require_relative 'fixture_helper'
3
+
4
+ include FixtureHelper
5
+
6
+ require 'sip2'
7
+
8
+ describe Sip2 do
9
+
10
+ describe "::parse" do
11
+ describe "Known messages" do
12
+ KNOWN_MESSAGES_FIXTURE_CODES.each do |code|
13
+
14
+ describe code do
15
+
16
+ msg = sip2_fixture(code)
17
+
18
+ it "accepts the message" do
19
+ assert_kind_of Array, Sip2.parse(msg)
20
+ assert_kind_of Hash, Sip2.parse(msg).first
21
+ end
22
+
23
+ it "sets :message_code to the message code" do
24
+ assert_equal code, Sip2.parse(msg).first[:message_code]
25
+ end
26
+
27
+ it "set :message_name" do
28
+ assert_kind_of String, Sip2.parse(msg).first[:message_name]
29
+ end
30
+ end
31
+ end
32
+ end
33
+
34
+ describe "Unknown message" do
35
+ UNKNOWN_MESSAGES_FIXTURE_CODES.each do |code|
36
+
37
+ describe code do
38
+
39
+ msg = sip2_fixture(code)
40
+
41
+ it "accepts the message" do
42
+ assert_kind_of Array, Sip2.parse(msg)
43
+ assert_kind_of Hash, Sip2.parse(msg).first
44
+ end
45
+
46
+ it "sets :message_code to the message code" do
47
+ assert_equal code, Sip2.parse(msg).first[:message_code]
48
+ end
49
+
50
+ it "sets :message_name to 'Unknown Message'" do
51
+ assert_equal "Unknown Message", Sip2.parse(msg).first[:message_name]
52
+ end
53
+
54
+ it "sets :message_data to what's between the code and the terminator" do
55
+ expected = msg.sub(/^#{Regexp.escape(code)}/, "").chomp
56
+ assert_equal(expected, Sip2.parse(msg).first[:message_data])
57
+ end
58
+ end
59
+ end
60
+ end
61
+
62
+ describe "Invalid message" do
63
+ it "does not accept invalid message identifiers" do
64
+ ["", "X", "!Y", "!Yfoo"].each do |msg|
65
+ assert_raises(Parslet::ParseFailed) {
66
+ Sip2.parse(sprintf("%s\r", msg))
67
+ }
68
+ end
69
+ end
70
+
71
+ it "does not acceptg valid message identifiers with invalid data" do
72
+ ["98", "99abc"].each do |msg|
73
+ assert_raises(Parslet::ParseFailed) {
74
+ Sip2.parse(sprintf("%s\r", msg))
75
+ }
76
+ end
77
+ end
78
+
79
+ it "requires the message terminator for both known and unknown messages" do
80
+ ["XXfoo", "9900302.00"].each do |msg|
81
+ assert_kind_of Array, Sip2.parse(sprintf("%s\r", msg))
82
+ assert_raises(Parslet::ParseFailed) {
83
+ Sip2.parse(sprintf("%s", msg))
84
+ }
85
+ end
86
+ end
87
+ end
88
+
89
+ describe "multiple messages" do
90
+ let(:messages) {
91
+ [
92
+ "9900302.00\r",
93
+ "XXfoo\r",
94
+ ]
95
+ }
96
+
97
+ it "reads multiple messages into an array of hashes" do
98
+ result = Sip2.parse(messages.join)
99
+
100
+ assert_kind_of Array, result
101
+ assert_kind_of Hash, result.first
102
+ assert_kind_of Hash, result.last
103
+ end
104
+
105
+ it "allows for an extra newline character (lf) between messages" do
106
+ result = Sip2.parse(messages.join("\n"))
107
+
108
+ assert_kind_of Array, result
109
+ assert_kind_of Hash, result.first
110
+ assert_kind_of Hash, result.last
111
+ end
112
+ end
113
+
114
+ describe "Messages with unexpected fields" do
115
+ let(:messages) {
116
+ [
117
+ "9900302.00XXSomeExtraValue|\r",
118
+ ]
119
+ }
120
+
121
+ it "reads a single unexpected field into an array" do
122
+ result = Sip2.parse("9900302.00XXSome Unexpected Value|\r")
123
+
124
+ assert_equal(
125
+ [{ code: "XX", value: "Some Unexpected Value" }],
126
+ result.first[:unexpected_fields]
127
+ )
128
+ end
129
+
130
+ it "reads multiple unexpected fields into an array" do
131
+ result = Sip2.parse("9900302.00XXSome Unexpected Value|ZZAnother Unexpected Value|\r")
132
+
133
+ assert_equal(
134
+ [
135
+ { code: "XX", value: "Some Unexpected Value" },
136
+ { code: "ZZ", value: "Another Unexpected Value" },
137
+ ],
138
+ result.first[:unexpected_fields]
139
+ )
140
+ end
141
+
142
+ end
143
+ end
144
+
145
+ end
@@ -0,0 +1,4 @@
1
+ require_relative '../environment'
2
+ require 'minitest/autorun'
3
+ require 'minitest/reporters'
4
+ Minitest::Reporters.use!
@@ -0,0 +1,4 @@
1
+ $LOAD_PATH.unshift File.expand_path("../lib", __dir__)
2
+ require "sip2/parser"
3
+
4
+ require "minitest/autorun"
metadata ADDED
@@ -0,0 +1,190 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sip2-ruby
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Daniel Sandbecker
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 1980-01-01 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: dry-struct
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.4'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.4'
27
+ - !ruby/object:Gem::Dependency
28
+ name: parslet
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '2.0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '2.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: yajl-ruby
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.4'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.4'
55
+ - !ruby/object:Gem::Dependency
56
+ name: minitest
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '5.19'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '5.19'
69
+ - !ruby/object:Gem::Dependency
70
+ name: minitest-reporters
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '1.6'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '1.6'
83
+ - !ruby/object:Gem::Dependency
84
+ name: pry
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rake
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ description: |2
112
+ A library and executables for parsing and encoding SIP2 messages (a standard
113
+ for data exchange between Library Automation Systems and Library Systems).
114
+ email:
115
+ - daniel.sandbecker@hb.se
116
+ executables:
117
+ - sip2-to-json
118
+ - json-to-sip2
119
+ extensions: []
120
+ extra_rdoc_files: []
121
+ files:
122
+ - LICENSE.txt
123
+ - README.md
124
+ - Rakefile
125
+ - bin/json-to-sip2
126
+ - bin/sip2-to-json
127
+ - lib/sip2.rb
128
+ - lib/sip2/checksum_encoder.rb
129
+ - lib/sip2/field_parser_rules.rb
130
+ - lib/sip2/fields.rb
131
+ - lib/sip2/message.rb
132
+ - lib/sip2/message/base_message.rb
133
+ - lib/sip2/message/unknown_message.rb
134
+ - lib/sip2/message_parser_rules.rb
135
+ - lib/sip2/messages.rb
136
+ - lib/sip2/parser.rb
137
+ - lib/sip2/parser_atoms.rb
138
+ - lib/sip2/transformer.rb
139
+ - lib/sip2/types.rb
140
+ - lib/sip2/version.rb
141
+ - sip2-ruby.gemspec
142
+ - test/fixture_helper.rb
143
+ - test/fixtures/09.sip2
144
+ - test/fixtures/10.sip2
145
+ - test/fixtures/17.sip2
146
+ - test/fixtures/18.sip2
147
+ - test/fixtures/98-with-unexpected.sip2
148
+ - test/fixtures/98.sip2
149
+ - test/fixtures/99-with-unexpected.sip2
150
+ - test/fixtures/99.sip2
151
+ - test/fixtures/XX.sip2
152
+ - test/fixtures/alma/09.sip2
153
+ - test/fixtures/alma/10.sip2
154
+ - test/fixtures/alma/17.sip2
155
+ - test/fixtures/alma/18.sip2
156
+ - test/fixtures/alma/98.sip2
157
+ - test/fixtures/alma/99.sip2
158
+ - test/round_trip_spec.rb
159
+ - test/sip2/message_parser_rules_spec.rb
160
+ - test/sip2/parser_atoms_spec.rb
161
+ - test/sip2/parser_test.rb
162
+ - test/sip2_spec.rb
163
+ - test/spec_helper.rb
164
+ - test/test_helper.rb
165
+ homepage: https://github.com/ub-library/sip2-ruby
166
+ licenses:
167
+ - MIT
168
+ metadata:
169
+ homepage_uri: https://github.com/ub-library/sip2-ruby
170
+ source_code_uri: https://github.com/ub-library/sip2-ruby
171
+ post_install_message:
172
+ rdoc_options: []
173
+ require_paths:
174
+ - lib
175
+ required_ruby_version: !ruby/object:Gem::Requirement
176
+ requirements:
177
+ - - ">="
178
+ - !ruby/object:Gem::Version
179
+ version: 2.3.0
180
+ required_rubygems_version: !ruby/object:Gem::Requirement
181
+ requirements:
182
+ - - ">="
183
+ - !ruby/object:Gem::Version
184
+ version: '0'
185
+ requirements: []
186
+ rubygems_version: 3.4.22
187
+ signing_key:
188
+ specification_version: 4
189
+ summary: Parse and encode SIP2 messages
190
+ test_files: []