Skip to content

Commit

Permalink
Improve Box of reference types by reusing the same pointer. Box of `n…
Browse files Browse the repository at this point in the history
…il` returns a null pointer. (#8016)
  • Loading branch information
waj authored and Brian J. Cardiff committed Jul 31, 2019
1 parent de48f32 commit 9dc7daf
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 1 deletion.
15 changes: 15 additions & 0 deletions spec/std/box_spec.cr
Expand Up @@ -6,4 +6,19 @@ describe "Box" do
box = Box.box(a)
Box(Int32).unbox(box).should eq(1)
end

it "boxing a reference returns the same pointer" do
a = "foo"
box = Box.box(a)
box.address.should eq(a.object_id)

Box(String).unbox(box).should be(a)
end

it "boxing nil returns a null pointer" do
box = Box.box(nil)
box.address.should eq(0)

Box(Nil).unbox(box).should be_nil
end
end
14 changes: 13 additions & 1 deletion src/box.cr
Expand Up @@ -14,6 +14,11 @@ class Box(T)
def initialize(@object : T)
end

# Creates a Box for a reference type (or `nil`) and returns the same pointer (or `NULL`)
def self.box(r : Reference?) : Void*
r.as(Void*)
end

# Creates a Box for an object and returns it as a `Void*`.
def self.box(object) : Void*
new(object).as(Void*)
Expand All @@ -22,6 +27,13 @@ class Box(T)
# Unboxes a `Void*` into an object of type `T`. Note that for this you must
# specify T: `Box(T).unbox(data)`.
def self.unbox(pointer : Void*) : T
pointer.as(self).object
{% if T <= Reference %}
pointer.as(T)
{% elsif T == Nil %}
# FIXME: This branch could be merged with the previous one once the issue #8015 is fixed
nil
{% else %}
pointer.as(self).object
{% end %}
end
end

0 comments on commit 9dc7daf

Please sign in to comment.