influxdb-lineprotocol-parser 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e8e81800340bcf80271e56f5c19d03ea4cd8b9535e8d0fd5bd86e605f3dae124
4
- data.tar.gz: 1baa9ee265fc57e8b7bf987b8314c9305c8ab3f0240066ea9db2d901b425a35d
3
+ metadata.gz: a8e433f4f34e310f1886a551df2e5673f8f3ca4831f786cb22bb490b31740dc5
4
+ data.tar.gz: 5fd20ecf8b09f2fa682fff68dad78fdecd6c47c87f9cbe0d887ba57d4978565b
5
5
  SHA512:
6
- metadata.gz: 3655611e6edbfce8c960707bf72f1f3972a7d8ced12488280a088646145551e5668329766143df26f4258acc17ffa17233e7ea9f802240d4a579d01b99e4b55f
7
- data.tar.gz: ba6b7f5b37fcdc32f4e46a51d4fb7ed92b34921cb0c173ba80664a838dafef33008423745b21193592f483161edb66e916116dd353d7234f53d4db4932e05f2d
6
+ metadata.gz: e0273635beaf425e9d284219ac2e513bb3bc467fd10f65e6e9600e368743bfa26ac5e22edba50a50778e20313355dd3a1c79b9ecc6e89b8157626c3db3efe627
7
+ data.tar.gz: c8e24fde968761c85a6eecaa6d6a51bde1976a950b167bed45b53636e70644d5a18f9394bf857473d813df9bfa7915bd2f62a00d8e4f8257ec1173ce32b453cf
@@ -17,7 +17,7 @@ require 'logger'
17
17
  ##
18
18
  # Extension to InfluxDB module.
19
19
  #
20
- module InfluxDBExt
20
+ module InfluxDB
21
21
  ##
22
22
  # Line Protocol module.
23
23
  #
@@ -27,9 +27,15 @@ module InfluxDBExt
27
27
  # Line Protocol parser.
28
28
  #
29
29
  class Parser
30
- def initialize(logger: nil, log_level: :warn)
30
+ def initialize(logger: nil, log_level: :warn, escapes: nil)
31
31
  @log = logger || ::Logger.new(STDERR)
32
32
  @log.level = log_level
33
+ case escapes
34
+ when :compat
35
+ @unescapes = InfluxDB::LineProtocol::CompatUnescapes.new
36
+ else
37
+ @unescapes = InfluxDB::LineProtocol::Unescapes.new
38
+ end
33
39
  enter_initial
34
40
  end
35
41
 
@@ -40,9 +46,11 @@ module InfluxDBExt
40
46
  #
41
47
  # If block is not given, returns a list of points in data.
42
48
  #
49
+ # The data can be a String, or a single Integer or an Array of Integers.
50
+ # The Integers are assumed to be UTF-8 bytes.
51
+ #
43
52
  def each_point(data)
44
- # TODO: support byte arrays (client does not have to ensure that only complete UTF-8 characters are passed)
45
- buf = data.to_s.encode(UTF_8).bytes.freeze
53
+ buf = bytes(data)
46
54
  i = 0
47
55
  len = buf.size
48
56
 
@@ -82,14 +90,14 @@ module InfluxDBExt
82
90
  BACKSLASH = 92
83
91
  COMMA = 44
84
92
  EQUALS = 61
85
- HASH = 23
93
+ HASH = 35
86
94
  NEWLINE = 10
87
95
  NULL = 0
88
96
  SPACE = 32
89
97
  TAB = 9
90
98
 
91
99
  # Start (and end) marker of a string field value (not special anywhere else)
92
- QUOTATION_MARK = 22
100
+ QUOTATION_MARK = 34
93
101
 
94
102
  # Start markers of a numeric field value (not special anywhere else)
95
103
  PLUS_SIGN = 43
@@ -117,7 +125,7 @@ module InfluxDBExt
117
125
  when COMMA
118
126
  @log.error "initial: missing measurement"
119
127
  @state = :invalid
120
- invalid(buf, i, len)
128
+ i + 1
121
129
  when HASH # comment
122
130
  @state = :comment
123
131
  i + 1
@@ -139,21 +147,21 @@ module InfluxDBExt
139
147
  i += 1
140
148
  else
141
149
  c = buf[i]
150
+ raise "unsupported input type" unless c.is_a? Integer
142
151
  case c
143
152
  when BACKSLASH
144
153
  @escaped = true
145
154
  i += 1
146
155
  when COMMA # start of tag set.
147
- @point = {series: decode(buf[start..i-1]), tags: {}}
156
+ @point = {series: decode(buf, start, i-1), tags: {}, values: {}}
148
157
  @state = :tag_key
149
158
  return i+1
150
159
  when NEWLINE
151
160
  @log.error("measurement: missing fields")
152
- # no need to go via :invalid; already at newline
153
- enter_initial
154
- return i+1
161
+ @state = :invalid
162
+ return i
155
163
  when SPACE # start of field set
156
- @point = {series: decode(buf[start..i-1]), values: {}}
164
+ @point = {series: decode(buf, start, i-1), values: {}}
157
165
  @state = :field_key
158
166
  i, _ = whitespace(buf, i + 1, len)
159
167
  return i
@@ -176,23 +184,24 @@ module InfluxDBExt
176
184
  i += 1
177
185
  else
178
186
  c = buf[i]
187
+ raise "unsupported input type" unless c.is_a? Integer
179
188
  case c
180
189
  when BACKSLASH
181
190
  @escaped = true
182
191
  i += 1
183
192
  when EQUALS
184
- @key = decode(buf[start..i-1])
193
+ @key = decode(buf, start, i-1)
185
194
  if @key == ""
186
195
  @log.error("tag_key: empty key")
187
196
  @state = :invalid
188
- return invalid(buf, i, len)
197
+ return i
189
198
  end
190
199
  @state = :tag_value
191
200
  return i+1
192
201
  when NEWLINE
193
202
  @log.error("tag key: newline")
194
- enter_initial
195
- return i+1
203
+ @state = :invalid
204
+ return i
196
205
  else
197
206
  i += 1
198
207
  end
@@ -212,21 +221,22 @@ module InfluxDBExt
212
221
  i += 1
213
222
  else
214
223
  c = buf[i]
224
+ raise "unsupported input type" unless c.is_a? Integer
215
225
  case c
216
226
  when BACKSLASH
217
227
  @escaped = true
218
228
  i += 1
219
229
  when COMMA
220
- @point[:tags][@key] = decode(buf[start..i-1])
230
+ @point[:tags][@key] = decode(buf, start, i-1)
221
231
  @key = nil
222
232
  @state = :tag_key
223
233
  return i+1
224
234
  when NEWLINE
225
235
  @log.error("tag value: newline")
226
- enter_initial
227
- return i+1
236
+ @state = :invalid
237
+ return i
228
238
  when SPACE
229
- @point[:tags][@key] = decode(buf[start..i-1])
239
+ @point[:tags][@key] = decode(buf, start, i-1)
230
240
  @key = nil
231
241
  @state = :field_key
232
242
  i, _ = whitespace(buf, i + 1, len)
@@ -250,23 +260,24 @@ module InfluxDBExt
250
260
  i += 1
251
261
  else
252
262
  c = buf[i]
263
+ raise "unsupported input type" unless c.is_a? Integer
253
264
  case c
254
265
  when BACKSLASH
255
266
  @escaped = true
256
267
  i += 1
257
268
  when EQUALS
258
- @key = decode(buf[start..i-1])
269
+ @key = decode(buf, start, i-1)
259
270
  if @key == ""
260
271
  @log.error("field key: empty key")
261
272
  @state = :invalid
262
- return invalid(buf, i + 1, len)
273
+ return i
263
274
  end
264
275
  @state = :field_value
265
276
  return i+1
266
277
  when NEWLINE
267
278
  @log.error("field key: newline")
268
- enter_initial
269
- return i+1
279
+ @state = :invalid
280
+ return i
270
281
  else
271
282
  i += 1
272
283
  end
@@ -283,6 +294,7 @@ module InfluxDBExt
283
294
  return len
284
295
  end
285
296
  c = buf[i]
297
+ raise "unsupported input type" unless c.is_a? Integer
286
298
  case c
287
299
  when LATIN_CAPITAL_LETTER_F, LATIN_CAPITAL_LETTER_T, LATIN_SMALL_LETTER_F, LATIN_SMALL_LETTER_T
288
300
  @state = :field_value_boolean
@@ -296,7 +308,7 @@ module InfluxDBExt
296
308
  else
297
309
  @log.error("field value: invalid")
298
310
  @state = :invalid
299
- invalid(buf, i, len)
311
+ i
300
312
  end
301
313
  end
302
314
 
@@ -308,23 +320,24 @@ module InfluxDBExt
308
320
  i += 1
309
321
  else
310
322
  c = buf[i]
323
+ raise "unsupported input type" unless c.is_a? Integer
311
324
  case c
312
325
  when BACKSLASH
313
326
  @escaped = true
314
327
  i += 1
315
328
  when COMMA
316
- value = decode(buf[start..i-1])
329
+ value = decode(buf, start, i-1)
317
330
  if value.nil?
318
331
  @log.error("field value boolean: invalid boolean")
319
332
  @state = :invalid
320
- return invalid(buf, i, len)
333
+ return i
321
334
  end
322
335
  @point[:values][@key] = value
323
336
  @key = nil
324
337
  @state = :field_key
325
338
  return i+1
326
339
  when NEWLINE
327
- value = decode(buf[start..i-1])
340
+ value = decode(buf, start, i-1)
328
341
  if value.nil?
329
342
  @log.error("field value boolean: invalid boolean")
330
343
  enter_initial
@@ -335,11 +348,11 @@ module InfluxDBExt
335
348
  @state = :complete
336
349
  return i+1
337
350
  when SPACE
338
- value = decode(buf[start..i-1])
351
+ value = decode(buf, start, i-1)
339
352
  if value.nil?
340
353
  @log.error("field value boolean: invalid boolean")
341
354
  @state = :invalid
342
- return invalid(buf, i, len)
355
+ return i
343
356
  end
344
357
  @point[:values][@key] = value
345
358
  @key = nil
@@ -365,34 +378,35 @@ module InfluxDBExt
365
378
  i += 1
366
379
  else
367
380
  c = buf[i]
381
+ raise "unsupported input type" unless c.is_a? Integer
368
382
  case c
369
383
  when BACKSLASH
370
384
  @escaped = true
371
385
  i += 1
372
386
  when COMMA
373
- value = decode(buf[start..i-1])
387
+ value = decode(buf, start, i-1)
374
388
  if value.nil?
375
389
  @log.error("field value numeric: invalid number")
376
390
  @state = :invalid
377
- return invalid(buf, i, len)
391
+ return i
378
392
  end
379
393
  @point[:values][@key] = value
380
394
  @key = nil
381
395
  @state = :field_key
382
396
  return i+1
383
397
  when NEWLINE
384
- value = decode(buf[start..i-1])
398
+ value = decode(buf, start, i-1)
385
399
  if value.nil?
386
400
  @log.error("field value numeric: invalid number")
387
401
  @state = :invalid
388
- return invalid(buf, i, len)
402
+ return i
389
403
  end
390
404
  @point[:values][@key] = value
391
405
  @key = nil
392
406
  @state = :complete
393
407
  return i+1
394
408
  when SPACE
395
- value = decode(buf[start..i-1])
409
+ value = decode(buf, start, i-1)
396
410
  if value.nil?
397
411
  @log.error("field value numeric: invalid number")
398
412
  @state = :invalid
@@ -422,16 +436,17 @@ module InfluxDBExt
422
436
  i += 1
423
437
  else
424
438
  c = buf[i]
439
+ raise "unsupported input type" unless c.is_a? Integer
425
440
  case c
426
441
  when BACKSLASH
427
442
  @escaped = true
428
443
  i += 1
429
444
  when QUOTATION_MARK
430
- value = decode(buf[start..i-1])
445
+ value = decode(buf, start, i-1)
431
446
  if value.nil?
432
447
  @log.error("field value string: invalid string")
433
448
  @state = :invalid
434
- return invalid(buf, i, len)
449
+ return i
435
450
  end
436
451
  @point[:values][@key] = value
437
452
  @key = nil
@@ -450,7 +465,9 @@ module InfluxDBExt
450
465
 
451
466
  def field_value_string_end(buf, i, len)
452
467
  if i < len
453
- case buf[i]
468
+ c = buf[i]
469
+ raise "unsupported input type" unless c.is_a? Integer
470
+ case c
454
471
  when COMMA
455
472
  @state = :field_key
456
473
  i + 1
@@ -463,7 +480,7 @@ module InfluxDBExt
463
480
  i
464
481
  else
465
482
  @state = :invalid
466
- invalid(buf, i, len)
483
+ i
467
484
  end
468
485
  else
469
486
  len
@@ -478,16 +495,17 @@ module InfluxDBExt
478
495
  i += 1
479
496
  else
480
497
  c = buf[i]
498
+ raise "unsupported input type" unless c.is_a? Integer
481
499
  case c
482
500
  when BACKSLASH
483
501
  @escaped = true
484
502
  i += 1
485
503
  when NEWLINE
486
- value = decode(buf[start..i-1])
504
+ value = decode(buf, start, i-1)
487
505
  if value.nil?
488
506
  @log.error("timestamp: invalid timestamp")
489
507
  @state = :invalid
490
- return invalid(buf, i, len)
508
+ return i
491
509
  end
492
510
  @point[:timestamp] = value
493
511
  @key = nil
@@ -508,6 +526,7 @@ module InfluxDBExt
508
526
  i = line_end(buf, i, len)
509
527
  if i < len
510
528
  enter_initial
529
+ i += 1
511
530
  end
512
531
  i
513
532
  end
@@ -516,18 +535,19 @@ module InfluxDBExt
516
535
  i = line_end(buf, i, len)
517
536
  if i < len
518
537
  enter_initial
538
+ i += 1
519
539
  end
520
540
  i
521
541
  end
522
542
 
523
543
  # Starting from position i,
524
- # returns the index of the byte that follows next newline.
525
- # Returns len if no such byte is found or it is at the end of buf.
544
+ # returns the index of the newline.
545
+ # Returns len if no such byte is found.
526
546
  def line_end(buf, i, len)
527
547
  while i < len
528
548
  c = buf[i]
549
+ raise "unsupported input type" unless c.is_a? Integer
529
550
  if c == NEWLINE
530
- i += 1
531
551
  return i
532
552
  end
533
553
  i += 1
@@ -541,6 +561,7 @@ module InfluxDBExt
541
561
  def whitespace(buf, i, len)
542
562
  while i < len
543
563
  c = buf[i]
564
+ raise "unsupported input type" unless c.is_a? Integer
544
565
  if c != SPACE && c != TAB && c != NULL
545
566
  return [i, c]
546
567
  end
@@ -549,12 +570,16 @@ module InfluxDBExt
549
570
  [len, nil]
550
571
  end
551
572
 
552
- def decode(buf)
553
- str = @buf.nil? ? string(buf) : string(@buf + buf)
573
+ def decode(buf, start, i)
574
+ str = if @buf.nil?
575
+ (start <= i) ? string(buf[start..i]) : ""
576
+ else
577
+ (start <= i) ? string(@buf + buf[start..i]) : string(@buf)
578
+ end
554
579
  @buf = nil
555
580
  case @state
556
581
  when :measurement
557
- str
582
+ @unescapes.unescape(:measurement, str)
558
583
  when :tag_key
559
584
  str
560
585
  when :tag_value
@@ -595,9 +620,48 @@ module InfluxDBExt
595
620
  end
596
621
  end
597
622
 
623
+ def bytes(data)
624
+ case data
625
+ when nil
626
+ [].freeze
627
+ when Integer
628
+ [data].freeze
629
+ when String
630
+ data.encode(UTF_8).bytes.freeze
631
+ when Array
632
+ data
633
+ end
634
+ end
635
+
598
636
  def string(buf)
599
637
  buf.pack(UTF_8_PACK_FORMAT).force_encoding(UTF_8)
600
638
  end
639
+ end # Parser
640
+
641
+ class CompatUnescapes
642
+ def unescape(field, value)
643
+ case field
644
+ when :measurement
645
+ value.gsub(/\\([, ])/, '\\1')
646
+ # escaped comma anywhere
647
+ # escaped space anywhere
648
+ end
649
+ end
650
+ end
651
+
652
+ class Unescapes
653
+ def unescape(field, value)
654
+ case field
655
+ when :measurement
656
+ # 1. escaped hash, null, or tab at the beginning
657
+ # 2. escaped comma, space, or newline anywhere
658
+ # 3. escaped backslash at the end
659
+ value
660
+ .sub(/^\\([#\0\t])/, '\\1')
661
+ .gsub(/\\([, \n])/, '\\1')
662
+ .sub(/\\\\$/, '\\')
663
+ end
664
+ end
601
665
  end
602
666
  end
603
667
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: influxdb-lineprotocol-parser
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mikko Värri
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-05-15 00:00:00.000000000 Z
11
+ date: 2019-05-16 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: 'Streaming parser for InfluxDB line protocol.
14
14