firm 0.9.3 → 0.9.7

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: 5c1c7b999e2db422d608d8aaf8e28a9bace6824640f50a8e5dabb30e2ca89a36
4
- data.tar.gz: a16d62247a09cc2e1d8b3c4d2a990ffefb7b48c18f6f1d8f27e12c770ff103eb
3
+ metadata.gz: 8a4a4e31a319e92f4e5efb708562832f1072602084f5c0b4907c88d1e28d2c1b
4
+ data.tar.gz: 0e9e64b8fb301c3f895fe0b76978d6794389d0ca651339fd132396866d05eefa
5
5
  SHA512:
6
- metadata.gz: 6c45a0bc530a143ad8b37de7e00f6fdd4a2af91ffb52b18ce86f91ffac390ea05825d58b042e29361a96fd762be58d210d141bdb88d9748c3232e7c30232b8cc
7
- data.tar.gz: 939fe265f4f55f1255851e5f246b73ca416c6649af2ffcdad6aa8fb63341289ef64c71678bc02a7372c66acd6a91a26111ebc049d2a571b5f3f189f7010d3fb2
6
+ metadata.gz: 6144308bc7ba7bba7cac24c173a8fbabcac75e3074d29205593c64173696c7b9c41b47c5747b1265ad680f437d87abbce400e9ea0f311b8417403be4faeb55a8
7
+ data.tar.gz: 32353706f381e81dcacb705bbe144464fef1233df920dcb45d21e3386fca873bbd6ae52b7a1825cff84fec88d43a68935c89ad7577e9fa8f31f1e618c6cba8c4
data/README.md CHANGED
@@ -43,6 +43,10 @@ FIRM supports (de-)serializing many core Ruby objects out of the box including:
43
43
  - `Date`
44
44
  - `DateTime`
45
45
 
46
+ For security reasons FIRM does **not** support direct (de-)serializing of `Class` objects but will rather
47
+ serialize (and deserialize) these as their scoped string names. Customized property setters can be used to
48
+ resolve Class objects from these names if really needed.
49
+
46
50
  FIRM also supports a simple scheme to provide (de-)serialization support for user defined classes.
47
51
 
48
52
  FIRM provides object aliasing support for JSON and XML in a similar fashion as the standard support provided
@@ -143,6 +143,12 @@ module FIRM
143
143
 
144
144
  class << self
145
145
 
146
+ TLS_VARS_KEY = :firm_tls_vars.freeze
147
+
148
+ def tls_vars
149
+ Thread.current[TLS_VARS_KEY] ||= {}
150
+ end
151
+
146
152
  def serializables
147
153
  @serializables ||= ::Set.new
148
154
  end
@@ -198,7 +204,7 @@ module FIRM
198
204
  private_constant :TLS_ALIAS_STACK_KEY
199
205
 
200
206
  def anchor_object_registry_stack
201
- ::Thread.current[TLS_ANCHOR_OBJECTS_KEY] ||= []
207
+ Serializable.tls_vars[TLS_ANCHOR_OBJECTS_KEY] ||= []
202
208
  end
203
209
  private :anchor_object_registry_stack
204
210
 
@@ -252,7 +258,7 @@ module FIRM
252
258
  end
253
259
 
254
260
  def anchor_references_stack
255
- ::Thread.current[TLS_ALIAS_STACK_KEY] ||= []
261
+ Serializable.tls_vars[TLS_ALIAS_STACK_KEY] ||= []
256
262
  end
257
263
  private :anchor_references_stack
258
264
 
@@ -658,9 +664,8 @@ module FIRM
658
664
  derived.class_eval <<~__CODE
659
665
  module SerializerMethods
660
666
  def for_serialize(hash, excludes = ::Set.new)
661
- hash = super(hash, excludes | #{derived.name}.excluded_serializer_properties)
662
667
  #{derived.name}.serializer_properties.each { |prop| prop.serialize(self, hash, excludes) }
663
- hash
668
+ super(hash, excludes | #{derived.name}.excluded_serializer_properties)
664
669
  end
665
670
  protected :for_serialize
666
671
 
@@ -70,7 +70,7 @@ module FIRM
70
70
  private_constant :TLS_PARSE_STACK_KEY
71
71
 
72
72
  def safe_deserialize
73
- ::Thread.current[TLS_SAFE_DESERIALIZE_KEY] ||= []
73
+ Serializable.tls_vars[TLS_SAFE_DESERIALIZE_KEY] ||= []
74
74
  end
75
75
  private :safe_deserialize
76
76
 
@@ -83,7 +83,7 @@ module FIRM
83
83
  end
84
84
 
85
85
  def parse_stack
86
- ::Thread.current[TLS_PARSE_STACK_KEY] ||= []
86
+ Serializable.tls_vars[TLS_PARSE_STACK_KEY] ||= []
87
87
  end
88
88
  private :parse_stack
89
89
 
@@ -20,7 +20,7 @@ module FIRM
20
20
  private_constant :TLS_STATE_KEY
21
21
 
22
22
  def xml_state
23
- ::Thread.current[TLS_STATE_KEY] ||= []
23
+ Serializable.tls_vars[TLS_STATE_KEY] ||= []
24
24
  end
25
25
  private :xml_state
26
26
 
@@ -133,6 +133,22 @@ module FIRM
133
133
  end
134
134
  end
135
135
 
136
+ # registered as tag 'Class' but that is never actually used
137
+ define_xml_handler(::Class, 'Class') do
138
+ # overload to emit 'String' tags
139
+ def create_type_node(xml)
140
+ xml.add_child(Nokogiri::XML::Node.new('String', xml.document))
141
+ end
142
+ def to_xml(xml, value)
143
+ create_type_node(xml).add_child(Nokogiri::XML::CDATA.new(xml.document, value.name))
144
+ xml
145
+ end
146
+ def from_xml(xml)
147
+ # should never be called
148
+ raise Serializable::Exception, 'Unsupported Class deserialization'
149
+ end
150
+ end
151
+
136
152
  define_xml_handler(::NilClass, :nil) do
137
153
  def to_xml(xml, _value)
138
154
  create_type_node(xml)
@@ -68,8 +68,26 @@ module FIRM
68
68
  end
69
69
  end
70
70
 
71
+ # Derived Psych YAMLTree class to emit simple strings for
72
+ # Class instances
73
+ class NoClassYAMLTree < ::Psych::Visitors::YAMLTree
74
+
75
+ def visit_Class(o)
76
+ raise TypeError, "can't dump anonymous module: #{o}" unless o.name
77
+ visit_String(o.name)
78
+ end
79
+
80
+ def visit_Module(o)
81
+ raise TypeError, "can't dump anonymous class: #{o}" unless o.name
82
+ visit_String(o.name)
83
+ end
84
+
85
+ end
86
+
71
87
  def self.dump(obj, io=nil, **)
72
- ::YAML.dump(obj, io)
88
+ visitor = YAML::NoClassYAMLTree.create
89
+ visitor << obj
90
+ visitor.tree.yaml io
73
91
  end
74
92
 
75
93
  def self.load(source)
data/lib/firm/version.rb CHANGED
@@ -4,6 +4,6 @@
4
4
  module FIRM
5
5
 
6
6
  # FIRM version
7
- VERSION = "0.9.3"
7
+ VERSION = "0.9.7"
8
8
 
9
9
  end
@@ -292,6 +292,17 @@ module SerializerTestMixin
292
292
 
293
293
  end
294
294
 
295
+ def test_class
296
+
297
+ obj_serial = [Point, Colour].serialize
298
+ obj_new = assert_nothing_raised { FIRM.deserialize(obj_serial) }
299
+ assert_instance_of(::Array, obj_new)
300
+ assert_true(obj_new.all? { |e| String === e })
301
+ assert_equal(Point.name, obj_new[0])
302
+ assert_equal(Colour.name, obj_new[1])
303
+
304
+ end
305
+
295
306
  class PointsOwner
296
307
  include FIRM::Serializable
297
308
 
@@ -596,6 +607,90 @@ module SerializerTestMixin
596
607
  assert_equal(obj_new.map[:five].object_id, obj_new.map[:six].object_id)
597
608
  end
598
609
 
610
+ class Shape
611
+ include FIRM::Serializable
612
+ property :kind
613
+
614
+ def initialize(kind = :circle)
615
+ @kind = kind
616
+ end
617
+
618
+ attr_accessor :kind
619
+ end
620
+
621
+ class ShapeOwner
622
+ include FIRM::Serializable
623
+ property :shapes
624
+ def initialize
625
+ @shapes = []
626
+ end
627
+
628
+ attr_accessor :shapes
629
+ end
630
+
631
+ class Grid < ShapeOwner
632
+ property :dimensions
633
+ property :cells
634
+
635
+ DIMENSIONS = Struct.new(:rows, :columns)
636
+
637
+ def initialize(rows=nil, columns=nil)
638
+ super()
639
+ @dimensions = DIMENSIONS.new(rows || 3, columns || 3)
640
+ @cells = ::Array.new(@dimensions.rows*@dimensions.columns)
641
+ end
642
+
643
+ attr_reader :dimensions
644
+
645
+ def place_shape_at(row, col, shape)
646
+ shapes << shape
647
+ @cells[(row*dimensions.columns)+col] = shape
648
+ self
649
+ end
650
+
651
+ def get_shape_at(row, col)
652
+ @cells.at((row*dimensions.columns)+col)
653
+ end
654
+
655
+
656
+ private
657
+
658
+ def set_dimensions(dimensions)
659
+ @dimensions = dimensions
660
+ end
661
+
662
+ def get_cells
663
+ @cells
664
+ end
665
+
666
+ def set_cells(cells)
667
+ @cells = cells
668
+ end
669
+ end
670
+
671
+ def test_inherited_aliases
672
+
673
+ grid = Grid.new(2,2)
674
+ .place_shape_at(0, 0, Shape.new(:circle))
675
+ .place_shape_at(0, 1, Shape.new(:rect))
676
+ .place_shape_at(1,0, Shape.new(:cross))
677
+ .place_shape_at(1,1, Shape.new(:diamond))
678
+ obj_serial = grid.serialize
679
+ grid_new = assert_nothing_raised { FIRM.deserialize(obj_serial) }
680
+ assert_instance_of(Grid, grid_new)
681
+ assert_equal(4, grid_new.shapes.size)
682
+ assert_equal(:circle, grid_new.get_shape_at(0, 0).kind)
683
+ assert_equal(:rect, grid_new.get_shape_at(0, 1).kind)
684
+ assert_equal(:cross, grid_new.get_shape_at(1, 0).kind)
685
+ assert_equal(:diamond, grid_new.get_shape_at(1, 1).kind)
686
+ 2.times do |r|
687
+ 2.times do |c|
688
+ assert_true(grid_new.shapes.include?(grid_new.get_shape_at(r, c)))
689
+ end
690
+ end
691
+
692
+ end
693
+
599
694
  class House
600
695
 
601
696
  include FIRM::Serializable
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: firm
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.3
4
+ version: 0.9.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Martin Corino
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-09-14 00:00:00.000000000 Z
11
+ date: 2024-09-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake