Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prototype Literal::Array #133

Merged
merged 4 commits into from
Nov 9, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions lib/literal.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ module Literal
autoload :Flags16, "literal/flags"
autoload :Flags32, "literal/flags"
autoload :Flags64, "literal/flags"
autoload :Array, "literal/array"
autoload :ArrayGeneric, "literal/array"

# Errors
autoload :Error, "literal/errors/error"
Expand All @@ -30,6 +32,10 @@ def self.Enum(type)
end
end

def self.Array(type)
Literal::ArrayGeneric.new(type)
end

def self.check(actual:, expected:)
if expected === actual
true
Expand Down
51 changes: 51 additions & 0 deletions lib/literal/array.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# frozen_string_literal: true

class Literal::ArrayGeneric
def initialize(type)
@type = type
end

def new(*value)
Literal::Array.new(@type, value)
end
Comment on lines +8 to +10
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This importantly makes a copy of the array since it picks up the splat. This is essential to maintain the integrity of the array, since otherwise it could be mutated elsewhere. This value should never be exposed. Even to_a should only expose a duplicate.


alias_method :[], :new

def ===(value)
Literal::Array === value && @type == value.__type__
end
end

class Literal::Array
def initialize(type, value)
unless Array === value && value.all?(type)
raise
end

@__type__ = type
@__value__ = value
end
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should probably allocate and call another method because this shouldn’t be called directly by a user.


attr_reader :__type__

def each(...)
@__value__.each(...)
end

def map(type, &)
Literal::Array.new(type, @__value__.map(&))
end

def [](index)
@__value__[index]
end

def <<(value)
unless @__type__ === value
raise
end

@__value__ << value
self
end
end
14 changes: 14 additions & 0 deletions test/array.test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# frozen_string_literal: true

test "Array" do
array = Literal::Array(Integer).new(1, 2, 3)

expect(array[0]) == 1
expect(array.map(String, &:to_s)[0]) == "1"

expect { array << "1" }.to_raise
expect { array << 1 }.not_to_raise

assert Literal::Array(Integer) === array
refute Literal::Array(String) === array
end
Loading