Skip to content

Commit

Permalink
Update Marshal
Browse files Browse the repository at this point in the history
  • Loading branch information
sampersand committed Sep 19, 2023
1 parent 1c9b959 commit 6c5c342
Show file tree
Hide file tree
Showing 3 changed files with 123 additions and 47 deletions.
38 changes: 24 additions & 14 deletions core/marshal.rbs
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,16 @@
# which is Marshal.loaded in _load for complex objects.
#
module Marshal
# <!-- rdoc-file=marshal.c -->
# major version
#
MAJOR_VERSION: Integer

# <!-- rdoc-file=marshal.c -->
# minor version
#
MINOR_VERSION: Integer

# <!--
# rdoc-file=marshal.c
# - dump( obj [, anIO] , limit=-1 ) -> anIO
Expand Down Expand Up @@ -141,8 +151,8 @@ module Marshal
# ThreadGroup, Continuation
# * objects which define singleton methods
#
def self.dump: (untyped obj, untyped port, ?Integer limit) -> untyped
| (untyped obj, ?Integer limit) -> String
def self?.dump: [W < _Writer] (untyped obj, W port, ?int? limit) -> W
| (untyped obj, ?Integer limit) -> String

# <!--
# rdoc-file=marshal.rb
Expand Down Expand Up @@ -175,8 +185,18 @@ module Marshal
# deserialized.map(&:object_id)
# # => [1039360, 1039380, 1039360, 1039380] -- only 2 different objects, object_ids repeating
#
def self.load: (String | untyped port, ?freeze: boolish) -> untyped
| [A] (String | untyped port, ^(untyped) -> A, ?freeze: boolish) -> A
def self.load: (string | _Source source, ?freeze: boolish) -> untyped
| [A] (string | _Source source, _Proc[A] proc, ?freeze: boolish) -> A

interface _Proc[T]
def call: (untyped loaded) -> T
end

interface _Source
def getbyte: () -> (String | int)

def read: (Integer) -> string
end

# <!--
# rdoc-file=marshal.rb
Expand All @@ -185,13 +205,3 @@ module Marshal
#
alias self.restore self.load
end

# <!-- rdoc-file=marshal.c -->
# major version
#
Marshal::MAJOR_VERSION: Integer

# <!-- rdoc-file=marshal.c -->
# minor version
#
Marshal::MINOR_VERSION: Integer
120 changes: 87 additions & 33 deletions test/stdlib/Marshal_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,51 +6,105 @@ class MarshalSingletonTest < Test::Unit::TestCase
include TypeAssertions
testing "singleton(::Marshal)"

def test_MAJOR_VERSION
assert_const_type 'Integer', 'Marshal::MAJOR_VERSION'
end

def test_MINOR_VERSION
assert_const_type 'Integer', 'Marshal::MINOR_VERSION'
end

def test_dump
assert_send_type "(::String) -> ::String",
Marshal, :dump, ""
obj = Object.new

assert_send_type "(::String, ::Integer) -> ::String",
Marshal, :dump, "", 3
assert_send_type '(untyped) -> String',
Marshal, :dump, obj
assert_send_type '(untyped, Integer) -> String',
Marshal, :dump, obj, 123

io = (Pathname(Dir.mktmpdir) + "foo").open("w")
writer = Writer.new
assert_send_type '(untyped, Writer) -> Writer',
Marshal, :dump, obj, writer

assert_send_type "(::String, ::File) -> ::File",
Marshal, :dump, "", io
with_int.chain([nil]).each do |limit|
assert_send_type '(untyped, Writer, int?) -> Writer',
Marshal, :dump, obj, writer, limit
end
end

def test_load
dump = Marshal.dump([1,2,3])
def with_source(src = Marshal.dump(Object.new))
with_string src do |string|
def string.reset!; end
yield string
end

src = src.chars
source = Struct.new(:source).new(src.dup)
source.define_singleton_method(:reset!) do
self.source = src.dup
end

# String, String
def source.getbyte = source.shift
def source.read(x) = source.shift(x).join
yield source

# int, string
source.reset!
def source.getbyte = ToInt.new(source.shift.ord)
def source.read(x) = ToStr.new(source.shift(x).join)
yield source
end

assert_send_type(
"(::String) -> ::Array[::Integer]",
Marshal, :load, dump
)
def test_load(meth = :load)
result_proc = Object.new
def result_proc.call(loaded) 1r end

assert_send_type(
"(::String, freeze: bool) -> ::Array[::Integer]",
Marshal, :load, dump, freeze: true
)
assert_send_type(
"(::String, freeze: Symbol) -> ::Array[::Integer]",
Marshal, :load, dump, freeze: :true
)
with_source do |source|
assert_send_type '(string | Marshal::_Source) -> untyped',
Marshal, meth, source
source.reset!

assert_send_type(
"(::String, ^(untyped) -> void) -> ::Integer",
Marshal, :load, dump, -> (_x) { 123 }
)
assert_send_type '(string | Marshal::_Source, Marshal::_Proc[Rational]) -> Rational',
Marshal, meth, source, result_proc
source.reset!

name = Pathname(Dir.mktmpdir) + "foo"
[nil, :yep, true, "hello"].each do |freeze|
assert_send_type '(string | Marshal::_Source, freeze: boolish) -> untyped',
Marshal, meth, source, freeze: freeze
source.reset!

File.open(name, "w") do |io|
Marshal.dump([1,2,3], io)
assert_send_type '(string | Marshal::_Source, Marshal::_Proc[Rational], freeze: boolish) -> Rational',
Marshal, meth, source, result_proc, freeze: freeze
source.reset!
end
end
File.open(name) do |io|
assert_send_type(
"(IO) -> ::Array[::Integer]",
Marshal, :load, io
)
end

def test_restore
test_load :restore
end
end

class MarshalIncludeTest < Test::Unit::TestCase
include TypeAssertions
testing "::Marshal"

def test_dump
obj = Object.new

assert_send_type '(untyped) -> String',
Marshal, :dump, obj
assert_send_type '(untyped, Integer) -> String',
Marshal, :dump, obj, 123

writer = Writer.new
assert_send_type '(untyped, Writer) -> Writer',
Marshal, :dump, obj, writer

with_int.chain([nil]).each do |limit|
assert_send_type '(untyped, Writer, int?) -> Writer',
Marshal, :dump, obj, writer, limit
end
end
end
12 changes: 12 additions & 0 deletions test/stdlib/test_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -625,6 +625,18 @@ def each(&block)
end
end

class Writer
attr_reader :buffer

def initialize
@buffer = ""
end

def write(*vals)
@buffer.concat vals.join
end
end

class ToJson
end

Expand Down

0 comments on commit 6c5c342

Please sign in to comment.