firm 0.9.3 → 0.9.7
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.
- checksums.yaml +4 -4
- data/README.md +4 -0
- data/lib/firm/serializable.rb +9 -4
- data/lib/firm/serializer/json.rb +2 -2
- data/lib/firm/serializer/xml.rb +17 -1
- data/lib/firm/serializer/yaml.rb +19 -1
- data/lib/firm/version.rb +1 -1
- data/tests/serializer_tests.rb +95 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8a4a4e31a319e92f4e5efb708562832f1072602084f5c0b4907c88d1e28d2c1b
|
4
|
+
data.tar.gz: 0e9e64b8fb301c3f895fe0b76978d6794389d0ca651339fd132396866d05eefa
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
data/lib/firm/serializable.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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
|
|
data/lib/firm/serializer/json.rb
CHANGED
@@ -70,7 +70,7 @@ module FIRM
|
|
70
70
|
private_constant :TLS_PARSE_STACK_KEY
|
71
71
|
|
72
72
|
def safe_deserialize
|
73
|
-
|
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
|
-
|
86
|
+
Serializable.tls_vars[TLS_PARSE_STACK_KEY] ||= []
|
87
87
|
end
|
88
88
|
private :parse_stack
|
89
89
|
|
data/lib/firm/serializer/xml.rb
CHANGED
@@ -20,7 +20,7 @@ module FIRM
|
|
20
20
|
private_constant :TLS_STATE_KEY
|
21
21
|
|
22
22
|
def xml_state
|
23
|
-
|
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)
|
data/lib/firm/serializer/yaml.rb
CHANGED
@@ -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
|
-
::
|
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
data/tests/serializer_tests.rb
CHANGED
@@ -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.
|
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-
|
11
|
+
date: 2024-09-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|