typed-array 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.rspec +1 -0
- data/Gemfile +13 -0
- data/Gemfile.lock +28 -0
- data/LICENSE.txt +20 -0
- data/README.rdoc +19 -0
- data/Rakefile +71 -0
- data/VERSION +1 -0
- data/lib/typed-array.rb +115 -0
- data/lib/typed-array/.DS_Store +0 -0
- data/lib/typed-array/functions.rb +115 -0
- data/spec/spec_helper.rb +12 -0
- data/spec/typed-array_spec.rb +274 -0
- data/typed-array.gemspec +83 -0
- metadata +114 -0
data/.document
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/Gemfile
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
source "http://rubygems.org"
|
2
|
+
# Add dependencies required to use your gem here.
|
3
|
+
# Example:
|
4
|
+
# gem "activesupport", ">= 2.3.5"
|
5
|
+
|
6
|
+
# Add dependencies to develop your gem here.
|
7
|
+
# Include everything needed to run rake, tests, features, etc.
|
8
|
+
group :development do
|
9
|
+
gem "rspec", "~> 2.3.0"
|
10
|
+
gem "bundler", "~> 1.0.0"
|
11
|
+
gem "jeweler", "~> 1.6.4"
|
12
|
+
gem "rcov", ">= 0"
|
13
|
+
end
|
data/Gemfile.lock
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
GEM
|
2
|
+
remote: http://rubygems.org/
|
3
|
+
specs:
|
4
|
+
diff-lcs (1.1.2)
|
5
|
+
git (1.2.5)
|
6
|
+
jeweler (1.6.4)
|
7
|
+
bundler (~> 1.0)
|
8
|
+
git (>= 1.2.5)
|
9
|
+
rake
|
10
|
+
rake (0.9.2)
|
11
|
+
rcov (0.9.9)
|
12
|
+
rspec (2.3.0)
|
13
|
+
rspec-core (~> 2.3.0)
|
14
|
+
rspec-expectations (~> 2.3.0)
|
15
|
+
rspec-mocks (~> 2.3.0)
|
16
|
+
rspec-core (2.3.1)
|
17
|
+
rspec-expectations (2.3.0)
|
18
|
+
diff-lcs (~> 1.1.2)
|
19
|
+
rspec-mocks (2.3.0)
|
20
|
+
|
21
|
+
PLATFORMS
|
22
|
+
ruby
|
23
|
+
|
24
|
+
DEPENDENCIES
|
25
|
+
bundler (~> 1.0.0)
|
26
|
+
jeweler (~> 1.6.4)
|
27
|
+
rcov
|
28
|
+
rspec (~> 2.3.0)
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2011 Ryan Biesemeyer
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
= typed-array
|
2
|
+
|
3
|
+
Description goes here.
|
4
|
+
|
5
|
+
== Contributing to typed-array
|
6
|
+
|
7
|
+
* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
|
8
|
+
* Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
|
9
|
+
* Fork the project
|
10
|
+
* Start a feature/bugfix branch
|
11
|
+
* Commit and push until you are happy with your contribution
|
12
|
+
* Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
|
13
|
+
* Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
|
14
|
+
|
15
|
+
== Copyright
|
16
|
+
|
17
|
+
Copyright (c) 2011 Ryan Biesemeyer. See LICENSE.txt for
|
18
|
+
further details.
|
19
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'bundler'
|
5
|
+
begin
|
6
|
+
Bundler.setup(:default, :development)
|
7
|
+
rescue Bundler::BundlerError => e
|
8
|
+
$stderr.puts e.message
|
9
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
10
|
+
exit e.status_code
|
11
|
+
end
|
12
|
+
require 'rake'
|
13
|
+
|
14
|
+
require 'jeweler'
|
15
|
+
Jeweler::Tasks.new do |gem|
|
16
|
+
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
|
17
|
+
gem.name = "typed-array"
|
18
|
+
gem.homepage = "http://github.com/yaauie/typed-array"
|
19
|
+
gem.license = "MIT"
|
20
|
+
gem.summary = %Q{Provides methods for creating type-enforced Arrays}
|
21
|
+
gem.description =<<-DESCRIPTION
|
22
|
+
All methods that alter the contents of an array that implements this Gem are first checked to
|
23
|
+
ensure that the added items are of the types allowed. All methods behave exactly as their Array
|
24
|
+
counterparts, including additional forms, block processing, etc.
|
25
|
+
|
26
|
+
Defining a TypedArray Class:
|
27
|
+
|
28
|
+
```ruby
|
29
|
+
class ThingsArray < Array
|
30
|
+
extend TypedArray
|
31
|
+
restrict_types Thing1, Thing2
|
32
|
+
end
|
33
|
+
|
34
|
+
things = ThingsArray.new
|
35
|
+
```
|
36
|
+
|
37
|
+
Generating a single TypedArray
|
38
|
+
|
39
|
+
```ruby
|
40
|
+
things = TypedArray(Thing1,Thing2).new
|
41
|
+
|
42
|
+
These classes can be extended, and their accepted-types appended to after their initial definition.
|
43
|
+
DESCRIPTION
|
44
|
+
gem.email = "ruby-dev@yaauie.com"
|
45
|
+
gem.authors = ["Ryan Biesemeyer"]
|
46
|
+
# dependencies defined in Gemfile
|
47
|
+
end
|
48
|
+
Jeweler::RubygemsDotOrgTasks.new
|
49
|
+
|
50
|
+
require 'rspec/core'
|
51
|
+
require 'rspec/core/rake_task'
|
52
|
+
RSpec::Core::RakeTask.new(:spec) do |spec|
|
53
|
+
spec.pattern = FileList['spec/**/*_spec.rb']
|
54
|
+
end
|
55
|
+
|
56
|
+
RSpec::Core::RakeTask.new(:rcov) do |spec|
|
57
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
58
|
+
spec.rcov = true
|
59
|
+
end
|
60
|
+
|
61
|
+
task :default => :spec
|
62
|
+
|
63
|
+
require 'rake/rdoctask'
|
64
|
+
Rake::RDocTask.new do |rdoc|
|
65
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
66
|
+
|
67
|
+
rdoc.rdoc_dir = 'rdoc'
|
68
|
+
rdoc.title = "typed-array #{version}"
|
69
|
+
rdoc.rdoc_files.include('README*')
|
70
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
71
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.1
|
data/lib/typed-array.rb
ADDED
@@ -0,0 +1,115 @@
|
|
1
|
+
# = typed-array - Gemp provides enforced-type functionality to Arrays
|
2
|
+
#
|
3
|
+
# Copyright (c) 2011 Ryan Biesemeyer
|
4
|
+
# See LICENSE.txt for details
|
5
|
+
#
|
6
|
+
# Ryan Biesemeyer mailto:ruby-dev@yaauie.com
|
7
|
+
#
|
8
|
+
# == Example
|
9
|
+
#
|
10
|
+
# === Create Standard Class
|
11
|
+
#
|
12
|
+
# require 'typed-array'
|
13
|
+
# class Things < Array
|
14
|
+
# extend TypedArray
|
15
|
+
# restrict_types Thing1,Thing2
|
16
|
+
# end
|
17
|
+
#
|
18
|
+
# === Generate Class using Factory
|
19
|
+
#
|
20
|
+
# require 'typed-array'
|
21
|
+
# things = TypedArray(Thing1,Thing2)
|
22
|
+
#
|
23
|
+
# === Adding items to the Array
|
24
|
+
#
|
25
|
+
# # All standard Array interfaces are implemented, including block-processing
|
26
|
+
# # and variable-number of arguments. For methods that would usually return an
|
27
|
+
# # Array, they instead return an instance of the current class (except to_a).
|
28
|
+
# #
|
29
|
+
# # The difference is that if the method would generate an Array including the
|
30
|
+
# # wrong types, TypedArray::UnexpectedTypeException is raised and the call is
|
31
|
+
# # aborted before modifying the enforced TypedArray instance.
|
32
|
+
#
|
33
|
+
# require 'typed-array'
|
34
|
+
# symbols = TypedArray(Symbol).new([:foo,:bar,:baz,:bingo])
|
35
|
+
# begin
|
36
|
+
# integers = TypedArray(Integer).new([1,3,7,2,:symbol])
|
37
|
+
# rescue TypedArray::UnexpectedTypeException
|
38
|
+
# puts "An error occured: #{$!}"
|
39
|
+
# end
|
40
|
+
#
|
41
|
+
|
42
|
+
require "typed-array/functions"
|
43
|
+
|
44
|
+
# Provides TypedArray functionality to a subclass of Array
|
45
|
+
# when extended in the class's definiton
|
46
|
+
module TypedArray
|
47
|
+
|
48
|
+
# Hook the extension process in order to include the necessary functions
|
49
|
+
# and do some basic sanity checks.
|
50
|
+
def self.extended( mod )
|
51
|
+
unless mod <= Array
|
52
|
+
raise UnexpectedTypeException.new( [Array], mod.class )
|
53
|
+
end
|
54
|
+
mod.module_exec(self::Functions) do |functions_module|
|
55
|
+
include functions_module
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
# when a class inherits from this one, make sure that it also inherits
|
60
|
+
# the types that are being enforced
|
61
|
+
def inherited( subclass )
|
62
|
+
self._subclasses << subclass
|
63
|
+
subclass.restricted_types *restricted_types
|
64
|
+
end
|
65
|
+
|
66
|
+
# A getter/setter for types to add. If no arguments are passed, it simply
|
67
|
+
# returns the current array of accepted types.
|
68
|
+
def restricted_types(*types)
|
69
|
+
@_restricted_types ||= []
|
70
|
+
types.each do |type|
|
71
|
+
raise UnexpectedTypeException.new([Class],type.class) unless type.is_a? Class
|
72
|
+
@_restricted_types << type unless @_restricted_types.include? type
|
73
|
+
_subclasses.each do |subclass|
|
74
|
+
subclass.restricted_types type
|
75
|
+
end
|
76
|
+
end
|
77
|
+
@_restricted_types
|
78
|
+
end; alias :restricted_type :restricted_types
|
79
|
+
|
80
|
+
# The exception that is raised when an Unexpected Type is reached during validation
|
81
|
+
class UnexpectedTypeException < Exception
|
82
|
+
# Provide access to the types of objects expected and the class of the object received
|
83
|
+
attr_reader :expected, :received
|
84
|
+
|
85
|
+
def initialize expected_one_of, received
|
86
|
+
@expected = expected_one_of
|
87
|
+
@received = received
|
88
|
+
end
|
89
|
+
|
90
|
+
def to_s
|
91
|
+
%{Expected one of #{@expected.inspect} but received a(n) #{@received}}
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
protected
|
96
|
+
|
97
|
+
# a store of subclasses
|
98
|
+
def _subclasses
|
99
|
+
@_subclasses ||= []
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
103
|
+
|
104
|
+
# Provide a factory method. Takes any number of types to accept as arguments
|
105
|
+
# and returns a class that behaves as a type-enforced array.
|
106
|
+
def TypedArray *types_allowed
|
107
|
+
klass = Class.new( Array )
|
108
|
+
klass.class_exec(types_allowed) do |types_allowed|
|
109
|
+
extend TypedArray
|
110
|
+
restricted_types *types_allowed
|
111
|
+
restricted_types
|
112
|
+
end
|
113
|
+
klass.restricted_types
|
114
|
+
klass
|
115
|
+
end
|
Binary file
|
@@ -0,0 +1,115 @@
|
|
1
|
+
# Provides the validation functions that get included into a TypedArray
|
2
|
+
|
3
|
+
# Namespace TypedArray
|
4
|
+
module TypedArray
|
5
|
+
|
6
|
+
# The functions that get included into TypedArray
|
7
|
+
module Functions
|
8
|
+
# Validates outcome. See Array#initialize
|
9
|
+
def initialize *args, &block
|
10
|
+
ary = Array.new *args, &block
|
11
|
+
self.replace ary
|
12
|
+
end
|
13
|
+
|
14
|
+
# Validates outcome. See Array#replace
|
15
|
+
def replace other_ary
|
16
|
+
_ensure_all_items_in_array_are_allowed other_ary
|
17
|
+
super
|
18
|
+
end
|
19
|
+
|
20
|
+
# Validates outcome. See Array#&
|
21
|
+
def & ary
|
22
|
+
self.class.new super
|
23
|
+
end
|
24
|
+
|
25
|
+
# Validates outcome. See Array#*
|
26
|
+
def * int
|
27
|
+
self.class.new super
|
28
|
+
end
|
29
|
+
|
30
|
+
# Validates outcome. See Array#+
|
31
|
+
def + ary
|
32
|
+
self.class.new super
|
33
|
+
end
|
34
|
+
|
35
|
+
# Validates outcome. See Array#<<
|
36
|
+
def << item
|
37
|
+
_ensure_item_is_allowed item
|
38
|
+
super
|
39
|
+
end
|
40
|
+
|
41
|
+
# Validates outcome. See Array#[]
|
42
|
+
def [] idx
|
43
|
+
self.class.new super
|
44
|
+
end
|
45
|
+
|
46
|
+
# Validates outcome. See Array#slice
|
47
|
+
def slice *args
|
48
|
+
self.class.new super
|
49
|
+
end
|
50
|
+
|
51
|
+
# Validates outcome. See Array#[]=
|
52
|
+
def []= idx, item
|
53
|
+
_ensure_item_is_allowed item
|
54
|
+
super
|
55
|
+
end
|
56
|
+
|
57
|
+
# Validates outcome. See Array#concat
|
58
|
+
def concat other_ary
|
59
|
+
_ensure_all_items_in_array_are_allowed other_ary
|
60
|
+
super
|
61
|
+
end
|
62
|
+
|
63
|
+
# Validates outcome. See Array#eql?
|
64
|
+
def eql? other_ary
|
65
|
+
_ensure_all_items_in_array_are_allowed other_ary
|
66
|
+
super
|
67
|
+
end
|
68
|
+
|
69
|
+
# Validates outcome. See Array#fill
|
70
|
+
def fill *args, &block
|
71
|
+
ary = self.to_a
|
72
|
+
ary.fill *args, &block
|
73
|
+
self.replace ary
|
74
|
+
end
|
75
|
+
|
76
|
+
# Validates outcome. See Array#push
|
77
|
+
def push *items
|
78
|
+
_ensure_all_items_in_array_are_allowed items
|
79
|
+
super
|
80
|
+
end
|
81
|
+
|
82
|
+
# Validates outcome. See Array#unshift
|
83
|
+
def unshift *items
|
84
|
+
_ensure_all_items_in_array_are_allowed items
|
85
|
+
super
|
86
|
+
end
|
87
|
+
|
88
|
+
# Validates outcome. See Array#map!
|
89
|
+
def map! &block
|
90
|
+
self.replace( self.map &block )
|
91
|
+
end
|
92
|
+
|
93
|
+
protected
|
94
|
+
|
95
|
+
# Ensure that all items in the passed Array are allowed
|
96
|
+
def _ensure_all_items_in_array_are_allowed ary
|
97
|
+
# If we're getting an instance of self, accept
|
98
|
+
return true if ary.is_a? self.class
|
99
|
+
_ensure_item_is_allowed( ary, [Array] )
|
100
|
+
ary.each do |item|
|
101
|
+
_ensure_item_is_allowed(item)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
# Ensure that the specific item passed is allowed
|
106
|
+
def _ensure_item_is_allowed item, expected=nil
|
107
|
+
return true if item.nil? #allow nil entries
|
108
|
+
expected = self.class.restricted_types if expected.nil?
|
109
|
+
expected.each do |allowed|
|
110
|
+
return true if item.class <= allowed
|
111
|
+
end
|
112
|
+
raise TypedArray::UnexpectedTypeException.new expected, item.class
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
3
|
+
require 'rspec'
|
4
|
+
require 'typed-array'
|
5
|
+
|
6
|
+
# Requires supporting files with custom matchers and macros, etc,
|
7
|
+
# in ./support/ and its subdirectories.
|
8
|
+
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
|
9
|
+
|
10
|
+
RSpec.configure do |config|
|
11
|
+
|
12
|
+
end
|
@@ -0,0 +1,274 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
|
4
|
+
# We need to test in several different contexts, so provide the base info here.
|
5
|
+
inputs = {
|
6
|
+
[Symbol]=>{
|
7
|
+
:base => [:foo,:bar],
|
8
|
+
:match => [:baz,:bingo],
|
9
|
+
:fail => {
|
10
|
+
:one => [:zip,0],
|
11
|
+
:all => ['string',Class]
|
12
|
+
}
|
13
|
+
},
|
14
|
+
[Fixnum] => {
|
15
|
+
:base => [ 1,2,3 ],
|
16
|
+
:match => [ 17,18,19 ],
|
17
|
+
:fail => {
|
18
|
+
:one => [22,:symbol,43],
|
19
|
+
:all => ['string',:symbol]
|
20
|
+
}
|
21
|
+
},
|
22
|
+
[String,Symbol] => {
|
23
|
+
:base => ['Foo',:foo],
|
24
|
+
:match => [:bar,'Bar'],
|
25
|
+
:fail => {
|
26
|
+
:one => [:yippee,'a stirng',17],
|
27
|
+
:all => [12,Class,Array]
|
28
|
+
}
|
29
|
+
}
|
30
|
+
}
|
31
|
+
|
32
|
+
describe TypedArray do
|
33
|
+
describe '#new' do
|
34
|
+
inputs.each_pair do |accepted_types, config|
|
35
|
+
context "when only accepting <#{accepted_types.inspect}>" do
|
36
|
+
subject { TypedArray( *accepted_types ) }
|
37
|
+
context 'Form 1: typed_ary.new()' do
|
38
|
+
it "should have zero-length" do
|
39
|
+
subject.new().length.should == 0
|
40
|
+
end
|
41
|
+
it "should be empty" do
|
42
|
+
subject.new().to_a.should be_empty
|
43
|
+
end
|
44
|
+
end
|
45
|
+
context 'Form 1: typed_ary.new(size)' do
|
46
|
+
it "should have the proper length" do
|
47
|
+
subject.new(5).length.should == 5
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should conatin all nil values" do
|
51
|
+
subject.new(5).to_a.should == [nil,nil,nil,nil,nil]
|
52
|
+
end
|
53
|
+
end
|
54
|
+
context 'Form 2: typed_ary.new(size,object)' do
|
55
|
+
it "should have the proper length" do
|
56
|
+
subject.new(3,config[:match].first).length.should == 3
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should conatin the value specified" do
|
60
|
+
subject.new(3,config[:match].first).to_a.should == [config[:match].first]*3
|
61
|
+
end
|
62
|
+
|
63
|
+
it "should raise when obj is the wrong type" do
|
64
|
+
expect{ subject.new( 3, config[:fail][:all].first ) }.to raise_error TypedArray::UnexpectedTypeException
|
65
|
+
end
|
66
|
+
end
|
67
|
+
context 'Form 3: typed_ary.new( ary )' do
|
68
|
+
it "should accept when all items match" do
|
69
|
+
subject.new(config[:match]).to_a.should == config[:match]
|
70
|
+
end
|
71
|
+
it "should raise when one object is the wrong type" do
|
72
|
+
expect{ subject.new(config[:fail][:one])}.to raise_error TypedArray::UnexpectedTypeException
|
73
|
+
end
|
74
|
+
it "should raise when more than one object is the wrong type" do
|
75
|
+
expect{ subject.new(config[:fail][:all])}.to raise_error TypedArray::UnexpectedTypeException
|
76
|
+
end
|
77
|
+
end
|
78
|
+
context 'Form 4: typed_ary.new(size){|index|block}' do
|
79
|
+
it "should populate when block returns the right type" do
|
80
|
+
subject.new(config[:match].length){|i| config[:match][i]}.to_a.should == config[:match]
|
81
|
+
end
|
82
|
+
|
83
|
+
it "should raise when block returns wrong type once" do
|
84
|
+
expect{ subject.new(config[:fail][:one].length){|i| config[:fail][:one][i]} }.to raise_error TypedArray::UnexpectedTypeException
|
85
|
+
end
|
86
|
+
|
87
|
+
it "should raise when block returns wrong type more than once" do
|
88
|
+
expect{ subject.new(config[:fail][:all].length){|i| config[:fail][:all][i]} }.to raise_error TypedArray::UnexpectedTypeException
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
[:<<,:unshift,:push].each do |method|
|
96
|
+
context %Q{typed_ary#{('a'..'z').include?(method.to_s[0]) ? '.' : ' '}#{method.to_s} other_ary} do
|
97
|
+
inputs.each_pair do |accepted_types,config|
|
98
|
+
context "when only accepting <#{accepted_types.inspect}>" do
|
99
|
+
before :each do
|
100
|
+
@typed_ary = TypedArray( *accepted_types).new(config[:base])
|
101
|
+
@ary = config[:base].to_a
|
102
|
+
end
|
103
|
+
|
104
|
+
context "when the item being pushed matches (#{config[:match].first})" do
|
105
|
+
before :each do
|
106
|
+
@item = config[:match].first
|
107
|
+
end
|
108
|
+
|
109
|
+
it "should return as Array would return" do
|
110
|
+
@typed_ary.send(method,@item).to_a.should == @ary.send(method,@item)
|
111
|
+
end
|
112
|
+
|
113
|
+
it "should modify the TypedArray as Array would be modified" do
|
114
|
+
@typed_ary.send(method,@item)
|
115
|
+
@ary.send(method,@item)
|
116
|
+
@typed_ary.to_a.should == @ary
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
context "when the item being pushed does not match (#{config[:fail][:all].first})" do
|
121
|
+
before :each do
|
122
|
+
@item = config[:fail][:all].first
|
123
|
+
end
|
124
|
+
|
125
|
+
it "should raise an exception" do
|
126
|
+
|
127
|
+
expect{ @typed_ary.send(method,@item) }.to raise_error TypedArray::UnexpectedTypeException
|
128
|
+
end
|
129
|
+
|
130
|
+
it "should not modify typed_ary" do
|
131
|
+
begin
|
132
|
+
backup = @typed_ary.to_a
|
133
|
+
@typed_ary.send(method,@item)
|
134
|
+
rescue TypedArray::UnexpectedTypeException
|
135
|
+
ensure
|
136
|
+
@typed_ary.to_a.should == backup
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
[:[]=].each do |method|
|
147
|
+
context %Q{typed_ary[idx]= other_ary} do
|
148
|
+
inputs.each_pair do |accepted_types,config|
|
149
|
+
context "when only accepting <#{accepted_types.inspect}>" do
|
150
|
+
before :each do
|
151
|
+
@typed_ary = TypedArray( *accepted_types).new(config[:base])
|
152
|
+
@ary = config[:base].to_a
|
153
|
+
end
|
154
|
+
|
155
|
+
context "when the item being pushed matches (#{config[:match].first})" do
|
156
|
+
before :each do
|
157
|
+
@item = config[:match].first
|
158
|
+
end
|
159
|
+
|
160
|
+
it "should return as Array would return" do
|
161
|
+
@typed_ary.send(method,4,@item).should == @ary.send(method,4,@item)
|
162
|
+
end
|
163
|
+
|
164
|
+
it "should modify the TypedArray as Array would be modified" do
|
165
|
+
@typed_ary.send(method,4,@item)
|
166
|
+
@ary.send(method,4,@item)
|
167
|
+
@typed_ary.to_a.should == @ary
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
context "when the item being pushed does not match (#{config[:fail][:all].first})" do
|
172
|
+
before :each do
|
173
|
+
@item = config[:fail][:all].first
|
174
|
+
end
|
175
|
+
|
176
|
+
it "should raise an exception" do
|
177
|
+
|
178
|
+
expect{ @typed_ary.send(method,4,@item) }.to raise_error TypedArray::UnexpectedTypeException
|
179
|
+
end
|
180
|
+
|
181
|
+
it "should not modify typed_ary" do
|
182
|
+
begin
|
183
|
+
backup = @typed_ary.to_a
|
184
|
+
@typed_ary.send(method,4,@item)
|
185
|
+
rescue TypedArray::UnexpectedTypeException
|
186
|
+
ensure
|
187
|
+
@typed_ary.to_a.should == backup
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
|
198
|
+
[:+,:&,:concat,:replace].each do |method|
|
199
|
+
context %Q{typed_ary#{('a'..'z').include?(method.to_s[0]) ? '.' : ' '}#{method.to_s} other_ary} do
|
200
|
+
inputs.each_pair do |accepted_types,config|
|
201
|
+
context "when only accepting <#{accepted_types.inspect}>" do
|
202
|
+
before :each do
|
203
|
+
@typed_ary = TypedArray( *accepted_types).new(config[:base])
|
204
|
+
@ary = config[:base].to_a
|
205
|
+
end
|
206
|
+
|
207
|
+
context "when all items match (#{config[:match].inspect})" do
|
208
|
+
before :each do
|
209
|
+
@other_ary = config[:match].to_a
|
210
|
+
end
|
211
|
+
|
212
|
+
it "should return as Array would return" do
|
213
|
+
@typed_ary.send(method,@other_ary).to_a.should == @ary.send(method,@other_ary)
|
214
|
+
end
|
215
|
+
|
216
|
+
it "should modify the TypedArray as Array would be modified" do
|
217
|
+
@typed_ary.send(method,@other_ary)
|
218
|
+
@ary.send(method,@other_ary)
|
219
|
+
@typed_ary.to_a.should == @ary
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
config[:fail].each_key do |fail_type|
|
224
|
+
context "when #{fail_type} item fails to match (#{config[:fail][fail_type].inspect})" do
|
225
|
+
before :each do
|
226
|
+
@other_ary = config[:fail][fail_type].to_a
|
227
|
+
end
|
228
|
+
unless method == :& # `and` opperator cannot produce elements that are not in both arrays already; since one is assuredly filtered, we can skip this.
|
229
|
+
it "should raise an exception" do
|
230
|
+
expect{ @typed_ary.send(method,@other_ary) }.to raise_error TypedArray::UnexpectedTypeException
|
231
|
+
end
|
232
|
+
end
|
233
|
+
it "should not modify the TypedArray" do
|
234
|
+
begin
|
235
|
+
backup = @typed_ary.to_a
|
236
|
+
@typed_ary.send(method,@other_ary)
|
237
|
+
rescue TypedArray::UnexpectedTypeException
|
238
|
+
ensure
|
239
|
+
@typed_ary.to_a.should == backup
|
240
|
+
end
|
241
|
+
end
|
242
|
+
end
|
243
|
+
end
|
244
|
+
end
|
245
|
+
end
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
249
|
+
context 'when extending classes' do
|
250
|
+
before :each do
|
251
|
+
@base = TypedArray(Symbol)
|
252
|
+
@extension = Class.new( @base )
|
253
|
+
end
|
254
|
+
|
255
|
+
it 'should inherit default restrictions' do
|
256
|
+
@base.restricted_types.should == @extension.restricted_types
|
257
|
+
end
|
258
|
+
|
259
|
+
context 'when adding restricted_type to the parent' do
|
260
|
+
it 'should propogate to the child' do
|
261
|
+
@base.restricted_type Fixnum
|
262
|
+
@extension.restricted_types.should include(Fixnum)
|
263
|
+
end
|
264
|
+
end
|
265
|
+
context 'when adding restricted_type to the child' do
|
266
|
+
it 'should not propogate to the parent' do
|
267
|
+
@extension.restricted_type Fixnum
|
268
|
+
@base.restricted_types.should_not include(Fixnum)
|
269
|
+
end
|
270
|
+
end
|
271
|
+
|
272
|
+
|
273
|
+
end
|
274
|
+
end
|
data/typed-array.gemspec
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{typed-array}
|
8
|
+
s.version = "0.1.1"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = [%q{Ryan Biesemeyer}]
|
12
|
+
s.date = %q{2011-08-03}
|
13
|
+
s.description = %q{ All methods that alter the contents of an array that implements this Gem are first checked to
|
14
|
+
ensure that the added items are of the types allowed. All methods behave exactly as their Array
|
15
|
+
counterparts, including additional forms, block processing, etc.
|
16
|
+
|
17
|
+
Defining a TypedArray Class:
|
18
|
+
|
19
|
+
```ruby
|
20
|
+
class ThingsArray < Array
|
21
|
+
extend TypedArray
|
22
|
+
restrict_types Thing1, Thing2
|
23
|
+
end
|
24
|
+
|
25
|
+
things = ThingsArray.new
|
26
|
+
```
|
27
|
+
|
28
|
+
Generating a single TypedArray
|
29
|
+
|
30
|
+
```ruby
|
31
|
+
things = TypedArray(Thing1,Thing2).new
|
32
|
+
|
33
|
+
These classes can be extended, and their accepted-types appended to after their initial definition.
|
34
|
+
}
|
35
|
+
s.email = %q{ruby-dev@yaauie.com}
|
36
|
+
s.extra_rdoc_files = [
|
37
|
+
"LICENSE.txt",
|
38
|
+
"README.rdoc"
|
39
|
+
]
|
40
|
+
s.files = [
|
41
|
+
".document",
|
42
|
+
".rspec",
|
43
|
+
"Gemfile",
|
44
|
+
"Gemfile.lock",
|
45
|
+
"LICENSE.txt",
|
46
|
+
"README.rdoc",
|
47
|
+
"Rakefile",
|
48
|
+
"VERSION",
|
49
|
+
"lib/typed-array.rb",
|
50
|
+
"lib/typed-array/.DS_Store",
|
51
|
+
"lib/typed-array/functions.rb",
|
52
|
+
"spec/spec_helper.rb",
|
53
|
+
"spec/typed-array_spec.rb",
|
54
|
+
"typed-array.gemspec"
|
55
|
+
]
|
56
|
+
s.homepage = %q{http://github.com/yaauie/typed-array}
|
57
|
+
s.licenses = [%q{MIT}]
|
58
|
+
s.require_paths = [%q{lib}]
|
59
|
+
s.rubygems_version = %q{1.8.6}
|
60
|
+
s.summary = %q{Provides methods for creating type-enforced Arrays}
|
61
|
+
|
62
|
+
if s.respond_to? :specification_version then
|
63
|
+
s.specification_version = 3
|
64
|
+
|
65
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
66
|
+
s.add_development_dependency(%q<rspec>, ["~> 2.3.0"])
|
67
|
+
s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
|
68
|
+
s.add_development_dependency(%q<jeweler>, ["~> 1.6.4"])
|
69
|
+
s.add_development_dependency(%q<rcov>, [">= 0"])
|
70
|
+
else
|
71
|
+
s.add_dependency(%q<rspec>, ["~> 2.3.0"])
|
72
|
+
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
73
|
+
s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
|
74
|
+
s.add_dependency(%q<rcov>, [">= 0"])
|
75
|
+
end
|
76
|
+
else
|
77
|
+
s.add_dependency(%q<rspec>, ["~> 2.3.0"])
|
78
|
+
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
79
|
+
s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
|
80
|
+
s.add_dependency(%q<rcov>, [">= 0"])
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
metadata
ADDED
@@ -0,0 +1,114 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: typed-array
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease:
|
5
|
+
version: 0.1.1
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Ryan Biesemeyer
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2011-08-03 00:00:00 Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: rspec
|
17
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
18
|
+
none: false
|
19
|
+
requirements:
|
20
|
+
- - ~>
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 2.3.0
|
23
|
+
type: :development
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: *id001
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: bundler
|
28
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
29
|
+
none: false
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 1.0.0
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: *id002
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: jeweler
|
39
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
40
|
+
none: false
|
41
|
+
requirements:
|
42
|
+
- - ~>
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: 1.6.4
|
45
|
+
type: :development
|
46
|
+
prerelease: false
|
47
|
+
version_requirements: *id003
|
48
|
+
- !ruby/object:Gem::Dependency
|
49
|
+
name: rcov
|
50
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
51
|
+
none: false
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: "0"
|
56
|
+
type: :development
|
57
|
+
prerelease: false
|
58
|
+
version_requirements: *id004
|
59
|
+
description: " All methods that alter the contents of an array that implements this Gem are first checked to\n ensure that the added items are of the types allowed. All methods behave exactly as their Array\n counterparts, including additional forms, block processing, etc.\n\n Defining a TypedArray Class:\n\n ```ruby\n class ThingsArray < Array\n extend TypedArray\n restrict_types Thing1, Thing2\n end\n\n things = ThingsArray.new\n ```\n\n Generating a single TypedArray\n \n ```ruby\n things = TypedArray(Thing1,Thing2).new\n\n These classes can be extended, and their accepted-types appended to after their initial definition.\n"
|
60
|
+
email: ruby-dev@yaauie.com
|
61
|
+
executables: []
|
62
|
+
|
63
|
+
extensions: []
|
64
|
+
|
65
|
+
extra_rdoc_files:
|
66
|
+
- LICENSE.txt
|
67
|
+
- README.rdoc
|
68
|
+
files:
|
69
|
+
- .document
|
70
|
+
- .rspec
|
71
|
+
- Gemfile
|
72
|
+
- Gemfile.lock
|
73
|
+
- LICENSE.txt
|
74
|
+
- README.rdoc
|
75
|
+
- Rakefile
|
76
|
+
- VERSION
|
77
|
+
- lib/typed-array.rb
|
78
|
+
- lib/typed-array/.DS_Store
|
79
|
+
- lib/typed-array/functions.rb
|
80
|
+
- spec/spec_helper.rb
|
81
|
+
- spec/typed-array_spec.rb
|
82
|
+
- typed-array.gemspec
|
83
|
+
homepage: http://github.com/yaauie/typed-array
|
84
|
+
licenses:
|
85
|
+
- MIT
|
86
|
+
post_install_message:
|
87
|
+
rdoc_options: []
|
88
|
+
|
89
|
+
require_paths:
|
90
|
+
- lib
|
91
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
92
|
+
none: false
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
hash: -1404333859744270865
|
97
|
+
segments:
|
98
|
+
- 0
|
99
|
+
version: "0"
|
100
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
101
|
+
none: false
|
102
|
+
requirements:
|
103
|
+
- - ">="
|
104
|
+
- !ruby/object:Gem::Version
|
105
|
+
version: "0"
|
106
|
+
requirements: []
|
107
|
+
|
108
|
+
rubyforge_project:
|
109
|
+
rubygems_version: 1.8.6
|
110
|
+
signing_key:
|
111
|
+
specification_version: 3
|
112
|
+
summary: Provides methods for creating type-enforced Arrays
|
113
|
+
test_files: []
|
114
|
+
|