psych 3.0.3.pre4-java → 3.3.0-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +6 -0
  3. data/LICENSE +21 -0
  4. data/README.md +3 -6
  5. data/Rakefile +2 -16
  6. data/ext/java/{PsychEmitter.java → org/jruby/ext/psych/PsychEmitter.java} +9 -3
  7. data/ext/java/{PsychLibrary.java → org/jruby/ext/psych/PsychLibrary.java} +25 -1
  8. data/ext/java/{PsychParser.java → org/jruby/ext/psych/PsychParser.java} +0 -0
  9. data/ext/java/{PsychToRuby.java → org/jruby/ext/psych/PsychToRuby.java} +0 -0
  10. data/ext/java/{PsychYamlTree.java → org/jruby/ext/psych/PsychYamlTree.java} +0 -8
  11. data/ext/psych/depend +2 -0
  12. data/ext/psych/extconf.rb +6 -2
  13. data/ext/psych/psych.c +6 -3
  14. data/ext/psych/psych_parser.c +20 -33
  15. data/ext/psych/psych_yaml_tree.c +0 -12
  16. data/ext/psych/yaml/api.c +48 -47
  17. data/ext/psych/yaml/config.h +77 -7
  18. data/ext/psych/yaml/dumper.c +3 -3
  19. data/ext/psych/yaml/emitter.c +48 -19
  20. data/ext/psych/yaml/loader.c +210 -110
  21. data/ext/psych/yaml/parser.c +11 -6
  22. data/ext/psych/yaml/reader.c +3 -3
  23. data/ext/psych/yaml/scanner.c +52 -28
  24. data/ext/psych/yaml/yaml.h +41 -27
  25. data/ext/psych/yaml/yaml_private.h +46 -20
  26. data/lib/psych.rb +171 -77
  27. data/lib/psych/class_loader.rb +6 -4
  28. data/lib/psych/handler.rb +1 -1
  29. data/lib/psych/nodes/node.rb +2 -2
  30. data/lib/psych/scalar_scanner.rb +23 -36
  31. data/lib/psych/versions.rb +4 -3
  32. data/lib/psych/visitors/to_ruby.rb +42 -11
  33. data/lib/psych/visitors/visitor.rb +17 -3
  34. data/lib/psych/visitors/yaml_tree.rb +30 -42
  35. data/psych.gemspec +18 -14
  36. metadata +13 -58
  37. data/.travis.yml +0 -20
  38. data/CHANGELOG.rdoc +0 -576
@@ -3,7 +3,7 @@
3
3
  #endif
4
4
 
5
5
  #if HAVE_CONFIG_H
6
- #include <config.h>
6
+ #include "config.h"
7
7
  #endif
8
8
 
9
9
  #include <yaml.h>
@@ -12,16 +12,6 @@
12
12
  #include <limits.h>
13
13
  #include <stddef.h>
14
14
 
15
- #ifndef _MSC_VER
16
- #include <stdint.h>
17
- #else
18
- #ifdef _WIN64
19
- #define PTRDIFF_MAX _I64_MAX
20
- #else
21
- #define PTRDIFF_MAX INT_MAX
22
- #endif
23
- #endif
24
-
25
15
  /*
26
16
  * Memory management.
27
17
  */
@@ -80,6 +70,17 @@ yaml_parser_fetch_more_tokens(yaml_parser_t *parser);
80
70
 
81
71
  #define OUTPUT_RAW_BUFFER_SIZE (OUTPUT_BUFFER_SIZE*2+2)
82
72
 
73
+ /*
74
+ * The maximum size of a YAML input file.
75
+ * This used to be PTRDIFF_MAX, but that's not entirely portable
76
+ * because stdint.h isn't available on all platforms.
77
+ * It is not entirely clear why this isn't the maximum value
78
+ * that can fit into the parser->offset field.
79
+ */
80
+
81
+ #define MAX_FILE_SIZE (~(size_t)0 / 2)
82
+
83
+
83
84
  /*
84
85
  * The size of other stacks and queues.
85
86
  */
@@ -93,7 +94,7 @@ yaml_parser_fetch_more_tokens(yaml_parser_t *parser);
93
94
  */
94
95
 
95
96
  #define BUFFER_INIT(context,buffer,size) \
96
- (((buffer).start = yaml_malloc(size)) ? \
97
+ (((buffer).start = (yaml_char_t *)yaml_malloc(size)) ? \
97
98
  ((buffer).last = (buffer).pointer = (buffer).start, \
98
99
  (buffer).end = (buffer).start+(size), \
99
100
  1) : \
@@ -133,7 +134,7 @@ yaml_string_join(
133
134
  (value).pointer = (string))
134
135
 
135
136
  #define STRING_INIT(context,string,size) \
136
- (((string).start = yaml_malloc(size)) ? \
137
+ (((string).start = YAML_MALLOC(size)) ? \
137
138
  ((string).pointer = (string).start, \
138
139
  (string).end = (string).start+(size), \
139
140
  memset((string).start, 0, (size)), \
@@ -174,14 +175,14 @@ yaml_string_join(
174
175
  * Check the octet at the specified position.
175
176
  */
176
177
 
177
- #define CHECK_AT(string,octet,offset) \
178
+ #define CHECK_AT(string,octet,offset) \
178
179
  ((string).pointer[offset] == (yaml_char_t)(octet))
179
180
 
180
181
  /*
181
182
  * Check the current octet in the buffer.
182
183
  */
183
184
 
184
- #define CHECK(string,octet) CHECK_AT((string),(octet),0)
185
+ #define CHECK(string,octet) (CHECK_AT((string),(octet),0))
185
186
 
186
187
  /*
187
188
  * Check if the character at the specified position is an alphabetical
@@ -423,10 +424,10 @@ yaml_stack_extend(void **start, void **top, void **end);
423
424
  YAML_DECLARE(int)
424
425
  yaml_queue_extend(void **start, void **head, void **tail, void **end);
425
426
 
426
- #define STACK_INIT(context,stack,size) \
427
- (((stack).start = yaml_malloc((size)*sizeof(*(stack).start))) ? \
427
+ #define STACK_INIT(context,stack,type) \
428
+ (((stack).start = (type)yaml_malloc(INITIAL_STACK_SIZE*sizeof(*(stack).start))) ? \
428
429
  ((stack).top = (stack).start, \
429
- (stack).end = (stack).start+(size), \
430
+ (stack).end = (stack).start+INITIAL_STACK_SIZE, \
430
431
  1) : \
431
432
  ((context)->error = YAML_MEMORY_ERROR, \
432
433
  0))
@@ -456,8 +457,8 @@ yaml_queue_extend(void **start, void **head, void **tail, void **end);
456
457
  #define POP(context,stack) \
457
458
  (*(--(stack).top))
458
459
 
459
- #define QUEUE_INIT(context,queue,size) \
460
- (((queue).start = yaml_malloc((size)*sizeof(*(queue).start))) ? \
460
+ #define QUEUE_INIT(context,queue,size,type) \
461
+ (((queue).start = (type)yaml_malloc((size)*sizeof(*(queue).start))) ? \
461
462
  ((queue).head = (queue).tail = (queue).start, \
462
463
  (queue).end = (queue).start+(size), \
463
464
  1) : \
@@ -660,3 +661,28 @@ yaml_queue_extend(void **start, void **head, void **tail, void **end);
660
661
  (node).data.mapping.pairs.end = (node_pairs_end), \
661
662
  (node).data.mapping.pairs.top = (node_pairs_start), \
662
663
  (node).data.mapping.style = (node_style))
664
+
665
+ /* Strict C compiler warning helpers */
666
+
667
+ #if defined(__clang__) || defined(__GNUC__)
668
+ # define HASATTRIBUTE_UNUSED
669
+ #endif
670
+ #ifdef HASATTRIBUTE_UNUSED
671
+ # define __attribute__unused__ __attribute__((__unused__))
672
+ #else
673
+ # define __attribute__unused__
674
+ #endif
675
+
676
+ /* Shim arguments are arguments that must be included in your function,
677
+ * but serve no purpose inside. Silence compiler warnings. */
678
+ #define SHIM(a) /*@unused@*/ a __attribute__unused__
679
+
680
+ /* UNUSED_PARAM() marks a shim argument in the body to silence compiler warnings */
681
+ #ifdef __clang__
682
+ # define UNUSED_PARAM(a) (void)(a);
683
+ #else
684
+ # define UNUSED_PARAM(a) /*@-noeffect*/if (0) (void)(a)/*@=noeffect*/;
685
+ #endif
686
+
687
+ #define YAML_MALLOC_STATIC(type) (type*)yaml_malloc(sizeof(type))
688
+ #define YAML_MALLOC(size) (yaml_char_t *)yaml_malloc(size)
@@ -10,11 +10,7 @@ when 'jruby'
10
10
  org.jruby.ext.psych.PsychLibrary.new.load(JRuby.runtime, false)
11
11
  end
12
12
  else
13
- begin
14
- require "#{RUBY_VERSION[/\d+\.\d+/]}/psych.so"
15
- rescue LoadError
16
- require 'psych.so'
17
- end
13
+ require 'psych.so'
18
14
  end
19
15
  require 'psych/nodes'
20
16
  require 'psych/streaming'
@@ -36,7 +32,7 @@ require 'psych/class_loader'
36
32
  # = Overview
37
33
  #
38
34
  # Psych is a YAML parser and emitter.
39
- # Psych leverages libyaml [Home page: http://pyyaml.org/wiki/LibYAML]
35
+ # Psych leverages libyaml [Home page: https://pyyaml.org/wiki/LibYAML]
40
36
  # or [HG repo: https://bitbucket.org/xi/libyaml] for its YAML parsing
41
37
  # and emitting capabilities. In addition to wrapping libyaml, Psych also
42
38
  # knows how to serialize and de-serialize most Ruby objects to and from
@@ -78,12 +74,15 @@ require 'psych/class_loader'
78
74
  #
79
75
  # ==== Reading from a string
80
76
  #
81
- # Psych.load("--- a") # => 'a'
82
- # Psych.load("---\n - a\n - b") # => ['a', 'b']
77
+ # Psych.safe_load("--- a") # => 'a'
78
+ # Psych.safe_load("---\n - a\n - b") # => ['a', 'b']
79
+ # # From a trusted string:
80
+ # Psych.load("--- !ruby/range\nbegin: 0\nend: 42\nexcl: false\n") # => 0..42
83
81
  #
84
82
  # ==== Reading from a file
85
83
  #
86
- # Psych.load_file("database.yml")
84
+ # Psych.safe_load_file("data.yml", permitted_classes: [Date])
85
+ # Psych.load_file("trusted_database.yml")
87
86
  #
88
87
  # ==== Exception handling
89
88
  #
@@ -234,15 +233,17 @@ require 'psych/class_loader'
234
233
 
235
234
  module Psych
236
235
  # The version of libyaml Psych is using
237
- LIBYAML_VERSION = Psych.libyaml_version.join '.'
238
-
239
- FALLBACK = Struct.new :to_ruby # :nodoc:
236
+ LIBYAML_VERSION = Psych.libyaml_version.join('.').freeze
237
+ # Deprecation guard
238
+ NOT_GIVEN = Object.new.freeze
239
+ private_constant :NOT_GIVEN
240
240
 
241
241
  ###
242
242
  # Load +yaml+ in to a Ruby data structure. If multiple documents are
243
243
  # provided, the object contained in the first document will be returned.
244
- # +filename+ will be used in the exception message if any exception is raised
245
- # while parsing.
244
+ # +filename+ will be used in the exception message if any exception
245
+ # is raised while parsing. If +yaml+ is empty, it returns
246
+ # the specified +fallback+ return value, which defaults to +false+.
246
247
  #
247
248
  # Raises a Psych::SyntaxError when a YAML syntax error is detected.
248
249
  #
@@ -252,7 +253,7 @@ module Psych
252
253
  # Psych.load("---\n - a\n - b") # => ['a', 'b']
253
254
  #
254
255
  # begin
255
- # Psych.load("--- `", "file.txt")
256
+ # Psych.load("--- `", filename: "file.txt")
256
257
  # rescue Psych::SyntaxError => ex
257
258
  # ex.file # => 'file.txt'
258
259
  # ex.message # => "(file.txt): found character that cannot start any token"
@@ -264,11 +265,21 @@ module Psych
264
265
  # Psych.load("---\n foo: bar") # => {"foo"=>"bar"}
265
266
  # Psych.load("---\n foo: bar", symbolize_names: true) # => {:foo=>"bar"}
266
267
  #
267
- def self.load yaml, filename = nil, fallback: false, symbolize_names: false
268
- result = parse(yaml, filename, fallback: fallback)
269
- result = result.to_ruby if result
270
- symbolize_names!(result) if symbolize_names
271
- result
268
+ # Raises a TypeError when `yaml` parameter is NilClass
269
+ #
270
+ # NOTE: This method *should not* be used to parse untrusted documents, such as
271
+ # YAML documents that are supplied via user input. Instead, please use the
272
+ # safe_load method.
273
+ #
274
+ def self.load yaml, legacy_filename = NOT_GIVEN, filename: nil, fallback: false, symbolize_names: false, freeze: false
275
+ if legacy_filename != NOT_GIVEN
276
+ warn_with_uplevel 'Passing filename with the 2nd argument of Psych.load is deprecated. Use keyword argument like Psych.load(yaml, filename: ...) instead.', uplevel: 1 if $VERBOSE
277
+ filename = legacy_filename
278
+ end
279
+
280
+ result = parse(yaml, filename: filename)
281
+ return fallback unless result
282
+ result.to_ruby(symbolize_names: symbolize_names, freeze: freeze)
272
283
  end
273
284
 
274
285
  ###
@@ -284,27 +295,27 @@ module Psych
284
295
  # * Hash
285
296
  #
286
297
  # Recursive data structures are not allowed by default. Arbitrary classes
287
- # can be allowed by adding those classes to the +whitelist+. They are
298
+ # can be allowed by adding those classes to the +permitted_classes+ keyword argument. They are
288
299
  # additive. For example, to allow Date deserialization:
289
300
  #
290
- # Psych.safe_load(yaml, [Date])
301
+ # Psych.safe_load(yaml, permitted_classes: [Date])
291
302
  #
292
303
  # Now the Date class can be loaded in addition to the classes listed above.
293
304
  #
294
- # Aliases can be explicitly allowed by changing the +aliases+ parameter.
305
+ # Aliases can be explicitly allowed by changing the +aliases+ keyword argument.
295
306
  # For example:
296
307
  #
297
308
  # x = []
298
309
  # x << x
299
310
  # yaml = Psych.dump x
300
311
  # Psych.safe_load yaml # => raises an exception
301
- # Psych.safe_load yaml, [], [], true # => loads the aliases
312
+ # Psych.safe_load yaml, aliases: true # => loads the aliases
302
313
  #
303
314
  # A Psych::DisallowedClass exception will be raised if the yaml contains a
304
- # class that isn't in the whitelist.
315
+ # class that isn't in the +permitted_classes+ list.
305
316
  #
306
317
  # A Psych::BadAlias exception will be raised if the yaml contains aliases
307
- # but the +aliases+ parameter is set to false.
318
+ # but the +aliases+ keyword argument is set to false.
308
319
  #
309
320
  # +filename+ will be used in the exception message if any exception is raised
310
321
  # while parsing.
@@ -315,20 +326,39 @@ module Psych
315
326
  # Psych.safe_load("---\n foo: bar") # => {"foo"=>"bar"}
316
327
  # Psych.safe_load("---\n foo: bar", symbolize_names: true) # => {:foo=>"bar"}
317
328
  #
318
- def self.safe_load yaml, whitelist_classes = [], whitelist_symbols = [], aliases = false, filename = nil, symbolize_names: false
319
- result = parse(yaml, filename)
320
- return unless result
329
+ def self.safe_load yaml, legacy_permitted_classes = NOT_GIVEN, legacy_permitted_symbols = NOT_GIVEN, legacy_aliases = NOT_GIVEN, legacy_filename = NOT_GIVEN, permitted_classes: [], permitted_symbols: [], aliases: false, filename: nil, fallback: nil, symbolize_names: false, freeze: false
330
+ if legacy_permitted_classes != NOT_GIVEN
331
+ warn_with_uplevel 'Passing permitted_classes with the 2nd argument of Psych.safe_load is deprecated. Use keyword argument like Psych.safe_load(yaml, permitted_classes: ...) instead.', uplevel: 1 if $VERBOSE
332
+ permitted_classes = legacy_permitted_classes
333
+ end
321
334
 
322
- class_loader = ClassLoader::Restricted.new(whitelist_classes.map(&:to_s),
323
- whitelist_symbols.map(&:to_s))
324
- scanner = ScalarScanner.new class_loader
325
- if aliases
326
- visitor = Visitors::ToRuby.new scanner, class_loader
327
- else
328
- visitor = Visitors::NoAliasRuby.new scanner, class_loader
335
+ if legacy_permitted_symbols != NOT_GIVEN
336
+ warn_with_uplevel 'Passing permitted_symbols with the 3rd argument of Psych.safe_load is deprecated. Use keyword argument like Psych.safe_load(yaml, permitted_symbols: ...) instead.', uplevel: 1 if $VERBOSE
337
+ permitted_symbols = legacy_permitted_symbols
329
338
  end
339
+
340
+ if legacy_aliases != NOT_GIVEN
341
+ warn_with_uplevel 'Passing aliases with the 4th argument of Psych.safe_load is deprecated. Use keyword argument like Psych.safe_load(yaml, aliases: ...) instead.', uplevel: 1 if $VERBOSE
342
+ aliases = legacy_aliases
343
+ end
344
+
345
+ if legacy_filename != NOT_GIVEN
346
+ warn_with_uplevel 'Passing filename with the 5th argument of Psych.safe_load is deprecated. Use keyword argument like Psych.safe_load(yaml, filename: ...) instead.', uplevel: 1 if $VERBOSE
347
+ filename = legacy_filename
348
+ end
349
+
350
+ result = parse(yaml, filename: filename)
351
+ return fallback unless result
352
+
353
+ class_loader = ClassLoader::Restricted.new(permitted_classes.map(&:to_s),
354
+ permitted_symbols.map(&:to_s))
355
+ scanner = ScalarScanner.new class_loader
356
+ visitor = if aliases
357
+ Visitors::ToRuby.new scanner, class_loader, symbolize_names: symbolize_names, freeze: freeze
358
+ else
359
+ Visitors::NoAliasRuby.new scanner, class_loader, symbolize_names: symbolize_names, freeze: freeze
360
+ end
330
361
  result = visitor.accept result
331
- symbolize_names!(result) if symbolize_names
332
362
  result
333
363
  end
334
364
 
@@ -344,28 +374,40 @@ module Psych
344
374
  # Psych.parse("---\n - a\n - b") # => #<Psych::Nodes::Document:0x00>
345
375
  #
346
376
  # begin
347
- # Psych.parse("--- `", "file.txt")
377
+ # Psych.parse("--- `", filename: "file.txt")
348
378
  # rescue Psych::SyntaxError => ex
349
379
  # ex.file # => 'file.txt'
350
380
  # ex.message # => "(file.txt): found character that cannot start any token"
351
381
  # end
352
382
  #
353
383
  # See Psych::Nodes for more information about YAML AST.
354
- def self.parse yaml, filename = nil, fallback: false
355
- parse_stream(yaml, filename) do |node|
384
+ def self.parse yaml, legacy_filename = NOT_GIVEN, filename: nil, fallback: NOT_GIVEN
385
+ if legacy_filename != NOT_GIVEN
386
+ warn_with_uplevel 'Passing filename with the 2nd argument of Psych.parse is deprecated. Use keyword argument like Psych.parse(yaml, filename: ...) instead.', uplevel: 1 if $VERBOSE
387
+ filename = legacy_filename
388
+ end
389
+
390
+ parse_stream(yaml, filename: filename) do |node|
356
391
  return node
357
392
  end
358
- fallback
393
+
394
+ if fallback != NOT_GIVEN
395
+ warn_with_uplevel 'Passing the `fallback` keyword argument of Psych.parse is deprecated.', uplevel: 1 if $VERBOSE
396
+ fallback
397
+ else
398
+ false
399
+ end
359
400
  end
360
401
 
361
402
  ###
362
403
  # Parse a file at +filename+. Returns the Psych::Nodes::Document.
363
404
  #
364
405
  # Raises a Psych::SyntaxError when a YAML syntax error is detected.
365
- def self.parse_file filename
366
- File.open filename, 'r:bom|utf-8' do |f|
367
- parse f, filename
406
+ def self.parse_file filename, fallback: false
407
+ result = File.open filename, 'r:bom|utf-8' do |f|
408
+ parse f, filename: filename
368
409
  end
410
+ result || fallback
369
411
  end
370
412
 
371
413
  ###
@@ -394,14 +436,21 @@ module Psych
394
436
  # end
395
437
  #
396
438
  # begin
397
- # Psych.parse_stream("--- `", "file.txt")
439
+ # Psych.parse_stream("--- `", filename: "file.txt")
398
440
  # rescue Psych::SyntaxError => ex
399
441
  # ex.file # => 'file.txt'
400
442
  # ex.message # => "(file.txt): found character that cannot start any token"
401
443
  # end
402
444
  #
445
+ # Raises a TypeError when NilClass is passed.
446
+ #
403
447
  # See Psych::Nodes for more information about YAML AST.
404
- def self.parse_stream yaml, filename = nil, &block
448
+ def self.parse_stream yaml, legacy_filename = NOT_GIVEN, filename: nil, &block
449
+ if legacy_filename != NOT_GIVEN
450
+ warn_with_uplevel 'Passing filename with the 2nd argument of Psych.parse_stream is deprecated. Use keyword argument like Psych.parse_stream(yaml, filename: ...) instead.', uplevel: 1 if $VERBOSE
451
+ filename = legacy_filename
452
+ end
453
+
405
454
  if block_given?
406
455
  parser = Psych::Parser.new(Handlers::DocumentStream.new(&block))
407
456
  parser.parse yaml, filename
@@ -502,68 +551,113 @@ module Psych
502
551
  # end
503
552
  # list # => ['foo', 'bar']
504
553
  #
505
- def self.load_stream yaml, filename = nil
506
- if block_given?
507
- parse_stream(yaml, filename) do |node|
508
- yield node.to_ruby
509
- end
510
- else
511
- parse_stream(yaml, filename).children.map { |child| child.to_ruby }
554
+ def self.load_stream yaml, legacy_filename = NOT_GIVEN, filename: nil, fallback: [], **kwargs
555
+ if legacy_filename != NOT_GIVEN
556
+ warn_with_uplevel 'Passing filename with the 2nd argument of Psych.load_stream is deprecated. Use keyword argument like Psych.load_stream(yaml, filename: ...) instead.', uplevel: 1 if $VERBOSE
557
+ filename = legacy_filename
512
558
  end
559
+
560
+ result = if block_given?
561
+ parse_stream(yaml, filename: filename) do |node|
562
+ yield node.to_ruby(**kwargs)
563
+ end
564
+ else
565
+ parse_stream(yaml, filename: filename).children.map { |node| node.to_ruby(**kwargs) }
566
+ end
567
+
568
+ return fallback if result.is_a?(Array) && result.empty?
569
+ result
513
570
  end
514
571
 
515
572
  ###
516
573
  # Load the document contained in +filename+. Returns the yaml contained in
517
574
  # +filename+ as a Ruby object, or if the file is empty, it returns
518
575
  # the specified +fallback+ return value, which defaults to +false+.
519
- def self.load_file filename, fallback: false
576
+ #
577
+ # NOTE: This method *should not* be used to parse untrusted documents, such as
578
+ # YAML documents that are supplied via user input. Instead, please use the
579
+ # safe_load_file method.
580
+ def self.load_file filename, **kwargs
581
+ File.open(filename, 'r:bom|utf-8') { |f|
582
+ self.load f, filename: filename, **kwargs
583
+ }
584
+ end
585
+
586
+ ###
587
+ # Safely loads the document contained in +filename+. Returns the yaml contained in
588
+ # +filename+ as a Ruby object, or if the file is empty, it returns
589
+ # the specified +fallback+ return value, which defaults to +false+.
590
+ # See safe_load for options.
591
+ def self.safe_load_file filename, **kwargs
520
592
  File.open(filename, 'r:bom|utf-8') { |f|
521
- self.load f, filename, fallback: FALLBACK.new(fallback)
593
+ self.safe_load f, filename: filename, **kwargs
522
594
  }
523
595
  end
524
596
 
525
597
  # :stopdoc:
526
- @domain_types = {}
527
598
  def self.add_domain_type domain, type_tag, &block
528
599
  key = ['tag', domain, type_tag].join ':'
529
- @domain_types[key] = [key, block]
530
- @domain_types["tag:#{type_tag}"] = [key, block]
600
+ domain_types[key] = [key, block]
601
+ domain_types["tag:#{type_tag}"] = [key, block]
531
602
  end
532
603
 
533
604
  def self.add_builtin_type type_tag, &block
534
605
  domain = 'yaml.org,2002'
535
606
  key = ['tag', domain, type_tag].join ':'
536
- @domain_types[key] = [key, block]
607
+ domain_types[key] = [key, block]
537
608
  end
538
609
 
539
610
  def self.remove_type type_tag
540
- @domain_types.delete type_tag
611
+ domain_types.delete type_tag
541
612
  end
542
613
 
543
- @load_tags = {}
544
- @dump_tags = {}
545
614
  def self.add_tag tag, klass
546
- @load_tags[tag] = klass.name
547
- @dump_tags[klass] = tag
615
+ load_tags[tag] = klass.name
616
+ dump_tags[klass] = tag
548
617
  end
549
618
 
550
- def self.symbolize_names!(result)
551
- case result
552
- when Hash
553
- result.keys.each do |key|
554
- result[key.to_sym] = symbolize_names!(result.delete(key))
555
- end
556
- when Array
557
- result.map! { |r| symbolize_names!(r) }
619
+ # Workaround for emulating `warn '...', uplevel: 1` in Ruby 2.4 or lower.
620
+ def self.warn_with_uplevel(message, uplevel: 1)
621
+ at = parse_caller(caller[uplevel]).join(':')
622
+ warn "#{at}: #{message}"
623
+ end
624
+
625
+ def self.parse_caller(at)
626
+ if /^(.+?):(\d+)(?::in `.*')?/ =~ at
627
+ file = $1
628
+ line = $2.to_i
629
+ [file, line]
558
630
  end
559
- result
560
631
  end
561
- private_class_method :symbolize_names!
632
+ private_class_method :warn_with_uplevel, :parse_caller
562
633
 
563
634
  class << self
564
- attr_accessor :load_tags
565
- attr_accessor :dump_tags
566
- attr_accessor :domain_types
635
+ if defined?(Ractor)
636
+ require 'forwardable'
637
+ extend Forwardable
638
+
639
+ class Config
640
+ attr_accessor :load_tags, :dump_tags, :domain_types
641
+ def initialize
642
+ @load_tags = {}
643
+ @dump_tags = {}
644
+ @domain_types = {}
645
+ end
646
+ end
647
+
648
+ def config
649
+ Ractor.current[:PsychConfig] ||= Config.new
650
+ end
651
+
652
+ def_delegators :config, :load_tags, :dump_tags, :domain_types, :load_tags=, :dump_tags=, :domain_types=
653
+ else
654
+ attr_accessor :load_tags
655
+ attr_accessor :dump_tags
656
+ attr_accessor :domain_types
657
+ end
567
658
  end
659
+ self.load_tags = {}
660
+ self.dump_tags = {}
661
+ self.domain_types = {}
568
662
  # :startdoc:
569
663
  end