Skip to content

Commit

Permalink
Support Data in Marshal.load/Marshal.restore
Browse files Browse the repository at this point in the history
  • Loading branch information
herwinw committed Dec 13, 2024
1 parent 42290f7 commit b8cdb40
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 15 deletions.
22 changes: 7 additions & 15 deletions spec/core/marshal/shared/load.rb
Original file line number Diff line number Diff line change
Expand Up @@ -830,20 +830,18 @@ def io.binmode; raise "binmode"; end
it "loads a struct having ivar" do
obj = Struct.new("Thick").new
obj.instance_variable_set(:@foo, 5)
NATFIXME 'loads a struct having ivar', exception: ArgumentError, message: 'dump format error' do
NATFIXME 'ivar names', exception: NameError, message: "`@@foo' is not allowed as an instance variable name" do
reloaded = Marshal.send(@method, "\004\bIS:\022Struct::Thick\000\006:\t@fooi\n")
reloaded.should == obj
reloaded.instance_variable_get(:@foo).should == 5
Struct.send(:remove_const, :Thick)
end
Struct.send(:remove_const, :Thick)
end

it "loads a struct having fields" do
obj = Struct.new("Ure1", :a, :b).new
NATFIXME 'loads a struct having fields', exception: ArgumentError, message: 'dump format error' do
Marshal.send(@method, "\004\bS:\021Struct::Ure1\a:\006a0:\006b0").should == obj
Struct.send(:remove_const, :Ure1)
end
Marshal.send(@method, "\004\bS:\021Struct::Ure1\a:\006a0:\006b0").should == obj
Struct.send(:remove_const, :Ure1)
end

it "does not call initialize on the unmarshaled struct" do
Expand All @@ -870,29 +868,23 @@ def io.binmode; raise "binmode"; end
dumped = "\x04\bS:#MarshalSpec::DataSpec::Measure\a:\vamountii:\tunit\"\akm"
Marshal.dump(obj).should == dumped

NATFIXME 'load Data', exception: ArgumentError, message: 'dump format error' do
Marshal.send(@method, dumped).should == obj
end
Marshal.send(@method, dumped).should == obj
end

it "loads an extended Data" do
obj = MarshalSpec::DataSpec::MeasureExtended.new(100, "km")
dumped = "\x04\bS:+MarshalSpec::DataSpec::MeasureExtended\a:\vamountii:\tunit\"\akm"
Marshal.dump(obj).should == dumped

NATFIXME 'load Data', exception: ArgumentError, message: 'dump format error' do
Marshal.send(@method, dumped).should == obj
end
Marshal.send(@method, dumped).should == obj
end

it "returns a frozen object" do
obj = MarshalSpec::DataSpec::Measure.new(100, 'km')
dumped = "\x04\bS:#MarshalSpec::DataSpec::Measure\a:\vamountii:\tunit\"\akm"
Marshal.dump(obj).should == dumped

NATFIXME 'load Data', exception: ArgumentError, message: 'dump format error' do
Marshal.send(@method, dumped).should.frozen?
end
Marshal.send(@method, dumped).should.frozen?
end
end
end
Expand Down
20 changes: 20 additions & 0 deletions src/marshal.rb
Original file line number Diff line number Diff line change
Expand Up @@ -529,6 +529,24 @@ def read_user_marshaled_object_without_allocate
object_class._load(data)
end

def read_struct
name = read_value
object_class = find_constant(name)
size = read_integer
values = size.times.each_with_object({}) do |_, tmp|
name = read_value
value = read_value
tmp[name] = value
end
if object_class.ancestors.include?(Data)
object_class.new(**values)
else
object = object_class.allocate
values.each { |k, v| object.send(:"#{k}=", v) }
object
end
end

def read_object
name = read_value
object_class = find_constant(name)
Expand Down Expand Up @@ -595,6 +613,8 @@ def read_value
read_user_marshaled_object_with_allocate
when 'u'
read_user_marshaled_object_without_allocate
when 'S'
read_struct
when 'o'
read_object
when 'I'
Expand Down

0 comments on commit b8cdb40

Please sign in to comment.