hash_cast 0.5.2 → 0.5.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -0
- data/Gemfile.lock +1 -1
- data/lib/hash_cast/casters/array_caster.rb +12 -6
- data/lib/hash_cast/casters/integer_caster.rb +29 -10
- data/lib/hash_cast/casters/string_caster.rb +6 -0
- data/lib/hash_cast/config.rb +54 -1
- data/lib/hash_cast/version.rb +1 -1
- data/spec/hash_cast/casters/array_caster_spec.rb +49 -0
- data/spec/hash_cast/casters/integer_caster_spec.rb +49 -0
- data/spec/hash_cast/casters/string_caster_spec.rb +43 -0
- metadata +8 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b1ff1d676f80eaba8132c7027e6b70f59047a31df70a19f55183ecaff1d915cf
|
4
|
+
data.tar.gz: c1d44f71ee442b52abd55703e96dd4eca331e2ef63329e7fc17188d9bc053200
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9e7a988fa4dffefccb42d33249c923fb475b3f1e4605aa959d20ab1e92e44dc6ada092df1afd720eb4f5d5d0484b6182fb3b90822f00d50363f36a38e55b622e
|
7
|
+
data.tar.gz: df5c9a15f7c1ba2c25a7830d1426fb218202f16ce02cecab6e1234e0b8839e8ae31bd8150c15c6a58733b99e7b5d79bc61787d7133f7b12ab9360d7b36fb3a5e
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
**Version 0.5.4**
|
2
|
+
- Integer caster should only allow integer range by default (-2^31, 2^31)
|
3
|
+
|
4
|
+
**Version 0.5.3**
|
5
|
+
- Added optional support for array and string size validation
|
6
|
+
|
1
7
|
**Version 0.5.2**
|
2
8
|
- Rename AttributesCaster to HashCast::RecursiveCasterApplicator, to highlight that it's not a regular Caster
|
3
9
|
|
data/Gemfile.lock
CHANGED
@@ -1,14 +1,20 @@
|
|
1
1
|
class HashCast::Casters::ArrayCaster
|
2
2
|
|
3
3
|
def self.cast(value, attr_name, options = {})
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
4
|
+
unless value.is_a?(Array)
|
5
|
+
raise HashCast::Errors::CastingError, "should be an array"
|
6
|
+
end
|
7
|
+
|
8
|
+
if HashCast.config.array_size_validator_enabled
|
9
|
+
if value.size > HashCast.config.array_size_validator_limit
|
10
|
+
HashCast.config.array_size_validator_callback.call(value, attr_name, options)
|
9
11
|
end
|
12
|
+
end
|
13
|
+
|
14
|
+
if options[:each]
|
15
|
+
cast_array_items(value, attr_name, options)
|
10
16
|
else
|
11
|
-
|
17
|
+
value
|
12
18
|
end
|
13
19
|
end
|
14
20
|
|
@@ -1,17 +1,36 @@
|
|
1
1
|
class HashCast::Casters::IntegerCaster
|
2
2
|
|
3
|
+
DEFAULT_MIN_VALUE = 2**31 * -1
|
4
|
+
DEFAULT_MAX_VALUE = 2**31
|
5
|
+
|
3
6
|
def self.cast(value, attr_name, options = {})
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
Integer(value)
|
9
|
-
rescue ArgumentError => e
|
10
|
-
raise HashCast::Errors::CastingError, "is invalid integer"
|
11
|
-
end
|
12
|
-
else
|
13
|
-
raise HashCast::Errors::CastingError, "should be a integer"
|
7
|
+
integer_value = get_integer_value(value)
|
8
|
+
|
9
|
+
if integer_value < options.fetch(:min_value, DEFAULT_MIN_VALUE)
|
10
|
+
raise HashCast::Errors::CastingError, "should be within allowed range"
|
14
11
|
end
|
12
|
+
|
13
|
+
if integer_value > options.fetch(:max_value, DEFAULT_MAX_VALUE)
|
14
|
+
raise HashCast::Errors::CastingError, "should be within allowed range"
|
15
|
+
end
|
16
|
+
|
17
|
+
integer_value
|
15
18
|
end
|
16
19
|
|
20
|
+
private
|
21
|
+
def self.get_integer_value(value)
|
22
|
+
if value.is_a?(Integer)
|
23
|
+
return value
|
24
|
+
end
|
25
|
+
|
26
|
+
if value.is_a?(String)
|
27
|
+
begin
|
28
|
+
return Integer(value)
|
29
|
+
rescue ArgumentError => e
|
30
|
+
raise HashCast::Errors::CastingError, "is invalid integer"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
raise HashCast::Errors::CastingError, "should be a integer"
|
35
|
+
end
|
17
36
|
end
|
@@ -8,6 +8,12 @@ class HashCast::Casters::StringCaster
|
|
8
8
|
raise HashCast::Errors::CastingError, 'contains invalid characters'
|
9
9
|
end
|
10
10
|
|
11
|
+
if HashCast.config.string_size_validator_enabled
|
12
|
+
if value.size > HashCast.config.string_size_validator_limit
|
13
|
+
HashCast.config.string_size_validator_callback.call(value, attr_name, options)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
11
17
|
casted_value
|
12
18
|
end
|
13
19
|
|
data/lib/hash_cast/config.rb
CHANGED
@@ -1,5 +1,14 @@
|
|
1
1
|
class HashCast::Config
|
2
|
-
|
2
|
+
attr_writer :input_keys, :output_keys, :validate_string_null_byte,
|
3
|
+
:array_size_validator_enabled,
|
4
|
+
:array_size_validator_limit,
|
5
|
+
:array_size_validator_callback,
|
6
|
+
:string_size_validator_enabled,
|
7
|
+
:string_size_validator_limit,
|
8
|
+
:string_size_validator_callback
|
9
|
+
|
10
|
+
DEFAULT_ARRAY_SIZE_VALIDATOR_LIMIT = 1000_000
|
11
|
+
DEFAULT_STRING_SIZE_VALIDATOR_LIMIT = 1000_000
|
3
12
|
|
4
13
|
def input_keys
|
5
14
|
@input_keys || :symbol
|
@@ -14,4 +23,48 @@ class HashCast::Config
|
|
14
23
|
|
15
24
|
@validate_string_null_byte
|
16
25
|
end
|
26
|
+
|
27
|
+
def array_size_validator_enabled
|
28
|
+
return false if @array_size_validator_enabled.nil?
|
29
|
+
|
30
|
+
@array_size_validator_enabled
|
31
|
+
end
|
32
|
+
|
33
|
+
def array_size_validator_limit
|
34
|
+
return DEFAULT_ARRAY_SIZE_VALIDATOR_LIMIT if @array_size_validator_limit.nil?
|
35
|
+
|
36
|
+
@array_size_validator_limit
|
37
|
+
end
|
38
|
+
|
39
|
+
def array_size_validator_callback
|
40
|
+
if @array_size_validator_callback.nil?
|
41
|
+
return lambda{ |value, name, options|
|
42
|
+
raise HashCast::Errors::CastingError, "array is too large"
|
43
|
+
}
|
44
|
+
end
|
45
|
+
|
46
|
+
@array_size_validator_callback
|
47
|
+
end
|
48
|
+
|
49
|
+
def string_size_validator_enabled
|
50
|
+
return false if @string_size_validator_enabled.nil?
|
51
|
+
|
52
|
+
@string_size_validator_enabled
|
53
|
+
end
|
54
|
+
|
55
|
+
def string_size_validator_limit
|
56
|
+
return DEFAULT_STRING_SIZE_VALIDATOR_LIMIT if @string_size_validator_limit.nil?
|
57
|
+
|
58
|
+
@string_size_validator_limit
|
59
|
+
end
|
60
|
+
|
61
|
+
def string_size_validator_callback
|
62
|
+
if @string_size_validator_callback.nil?
|
63
|
+
return lambda{ |value, name, options|
|
64
|
+
raise HashCast::Errors::CastingError, "string is too large"
|
65
|
+
}
|
66
|
+
end
|
67
|
+
|
68
|
+
@string_size_validator_callback
|
69
|
+
end
|
17
70
|
end
|
data/lib/hash_cast/version.rb
CHANGED
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe HashCast::Casters::ArrayCaster do
|
4
|
+
subject { HashCast::Casters::ArrayCaster }
|
5
|
+
|
6
|
+
it "should cast an array" do
|
7
|
+
result = subject.cast([1,2,3], :ids)
|
8
|
+
expect(result).to eq([1,2,3])
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should raise an error for non-array" do
|
12
|
+
expect {
|
13
|
+
subject.cast(1, :ids)
|
14
|
+
}.to raise_error(HashCast::Errors::CastingError, "should be an array")
|
15
|
+
end
|
16
|
+
|
17
|
+
context "array size validation" do
|
18
|
+
after{
|
19
|
+
HashCast.config.array_size_validator_enabled = nil
|
20
|
+
HashCast.config.array_size_validator_limit = nil
|
21
|
+
}
|
22
|
+
|
23
|
+
it "should not raise an error for large array by default" do
|
24
|
+
result = subject.cast([1] * 10_000, :ids)
|
25
|
+
expect(result).to eq([1] * 10_000)
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should raise an error for large array when validation is enabled" do
|
29
|
+
HashCast.config.array_size_validator_enabled = true
|
30
|
+
HashCast.config.array_size_validator_limit = 1000
|
31
|
+
|
32
|
+
expect {
|
33
|
+
subject.cast([1] * 10_000, :ids)
|
34
|
+
}.to raise_error(HashCast::Errors::CastingError, "array is too large")
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should allow overriding the callback" do
|
38
|
+
HashCast.config.array_size_validator_enabled = true
|
39
|
+
HashCast.config.array_size_validator_limit = 1000
|
40
|
+
HashCast.config.array_size_validator_callback = lambda { |value, name, options|
|
41
|
+
raise HashCast::Errors::UnexpectedAttributeError, 'test'
|
42
|
+
}
|
43
|
+
|
44
|
+
expect {
|
45
|
+
subject.cast([1] * 10_000, :ids)
|
46
|
+
}.to raise_error(HashCast::Errors::UnexpectedAttributeError, "test")
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe HashCast::Casters::IntegerCaster do
|
4
|
+
subject { HashCast::Casters::IntegerCaster }
|
5
|
+
|
6
|
+
it "should cast from a numeric string" do
|
7
|
+
result = subject.cast("123", :number)
|
8
|
+
expect(result).to eq(123)
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should cast from an positive integer" do
|
12
|
+
result = subject.cast(10_000, :number)
|
13
|
+
expect(result).to eq(10_000)
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should cast from a negative integer" do
|
17
|
+
result = subject.cast(-10_000, :number)
|
18
|
+
expect(result).to eq(-10_000)
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should cast from a zero" do
|
22
|
+
result = subject.cast(0, :number)
|
23
|
+
expect(result).to eq(0)
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should not cast from a random string" do
|
27
|
+
expect {
|
28
|
+
subject.cast("test", :number)
|
29
|
+
}.to raise_error(HashCast::Errors::CastingError, "is invalid integer")
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should not cast from an array" do
|
33
|
+
expect {
|
34
|
+
subject.cast([1], :number)
|
35
|
+
}.to raise_error(HashCast::Errors::CastingError, "should be a integer")
|
36
|
+
end
|
37
|
+
|
38
|
+
it "only allow values larger than max integer range" do
|
39
|
+
expect {
|
40
|
+
subject.cast(2**40, :number)
|
41
|
+
}.to raise_error(HashCast::Errors::CastingError, "should be within allowed range")
|
42
|
+
end
|
43
|
+
|
44
|
+
it "only allow values smaller than min integer range" do
|
45
|
+
expect {
|
46
|
+
subject.cast(2**40 * -1, :number)
|
47
|
+
}.to raise_error(HashCast::Errors::CastingError, "should be within allowed range")
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe HashCast::Casters::StringCaster do
|
4
|
+
subject { HashCast::Casters::StringCaster }
|
5
|
+
|
6
|
+
it "should cast a string" do
|
7
|
+
result = subject.cast("foobar", :name)
|
8
|
+
expect(result).to eq("foobar")
|
9
|
+
end
|
10
|
+
|
11
|
+
context "string size validation" do
|
12
|
+
after{
|
13
|
+
HashCast.config.string_size_validator_enabled = nil
|
14
|
+
HashCast.config.string_size_validator_limit = nil
|
15
|
+
}
|
16
|
+
|
17
|
+
it "should not raise an error for large string by default" do
|
18
|
+
result = subject.cast("a" * 10_000, :name)
|
19
|
+
expect(result).to eq("a" * 10_000)
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should raise an error for large string when validation is enabled" do
|
23
|
+
HashCast.config.string_size_validator_enabled = true
|
24
|
+
HashCast.config.string_size_validator_limit = 1000
|
25
|
+
|
26
|
+
expect {
|
27
|
+
subject.cast("a" * 10_000, :ids)
|
28
|
+
}.to raise_error(HashCast::Errors::CastingError, "string is too large")
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should allow overriding the callback" do
|
32
|
+
HashCast.config.string_size_validator_enabled = true
|
33
|
+
HashCast.config.string_size_validator_limit = 1000
|
34
|
+
HashCast.config.string_size_validator_callback = lambda { |value, name, options|
|
35
|
+
raise HashCast::Errors::UnexpectedAttributeError, 'test'
|
36
|
+
}
|
37
|
+
|
38
|
+
expect {
|
39
|
+
subject.cast("a" * 10_000, :ids)
|
40
|
+
}.to raise_error(HashCast::Errors::UnexpectedAttributeError, "test")
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hash_cast
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Albert Gazizov
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2025-06-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -78,6 +78,9 @@ files:
|
|
78
78
|
- lib/hash_cast/recursive_caster_applicator.rb
|
79
79
|
- lib/hash_cast/version.rb
|
80
80
|
- spec/hash_cast/caster_spec.rb
|
81
|
+
- spec/hash_cast/casters/array_caster_spec.rb
|
82
|
+
- spec/hash_cast/casters/integer_caster_spec.rb
|
83
|
+
- spec/hash_cast/casters/string_caster_spec.rb
|
81
84
|
- spec/hash_cast/hash_cast_spec.rb
|
82
85
|
- spec/spec_helper.rb
|
83
86
|
homepage: http://github.com/droidlabs/hash_cast
|
@@ -105,5 +108,8 @@ specification_version: 4
|
|
105
108
|
summary: Declarative Hash Caster
|
106
109
|
test_files:
|
107
110
|
- spec/hash_cast/caster_spec.rb
|
111
|
+
- spec/hash_cast/casters/array_caster_spec.rb
|
112
|
+
- spec/hash_cast/casters/integer_caster_spec.rb
|
113
|
+
- spec/hash_cast/casters/string_caster_spec.rb
|
108
114
|
- spec/hash_cast/hash_cast_spec.rb
|
109
115
|
- spec/spec_helper.rb
|