Module: WebFunction::Type
- Defined in:
- lib/web_function/type.rb,
lib/web_function/type/any.rb,
lib/web_function/type/base.rb,
lib/web_function/type/union.rb,
lib/web_function/type/array_of.rb
Defined Under Namespace
Classes: Any, ArrayOf, Base, Union
Constant Summary
collapse
- ALLOWED_REFINEMENTS =
{
"number" => %w[u32 u64 i32 i64 f32 f64 timestamp].freeze,
"string" => %w[date time datetime uuid base64 email phone url uri ipv4 ipv6 hostname].freeze,
}.freeze
- REFINEMENT_VALIDATORS =
Value-level validators for each refinement, keyed by refinement name. Refinement names are unique across base
types, so a flat table is enough. Must stay in sync with ALLOWED_REFINEMENTS.
{
"u32" => ->(v) { v.is_a?(Integer) && v.between?(0, 0xFFFFFFFF) },
"u64" => ->(v) { v.is_a?(Integer) && v.between?(0, 0xFFFFFFFFFFFFFFFF) },
"i32" => ->(v) { v.is_a?(Integer) && v.between?(-0x80000000, 0x7FFFFFFF) },
"i64" => ->(v) { v.is_a?(Integer) && v.between?(-0x8000000000000000, 0x7FFFFFFFFFFFFFFF) },
"f32" => ->(v) { v.is_a?(Numeric) && v.to_f.finite? && v.to_f.abs <= 3.4028235e38 },
"f64" => ->(v) { v.is_a?(Numeric) && v.to_f.finite? },
"timestamp" => ->(v) { v.is_a?(Integer) && v >= 0 },
"date" => ->(v) { v.match?(/\A\d{4}-\d{2}-\d{2}\z/) },
"time" => ->(v) { v.match?(/\A\d{2}:\d{2}:\d{2}(\.\d+)?\z/) },
"datetime" => ->(v) { v.match?(/\A\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}:\d{2}(\.\d+)?(Z|[+-]\d{2}:\d{2})?\z/) },
"uuid" => ->(v) { v.match?(/\A\h{8}-\h{4}-\h{4}-\h{4}-\h{12}\z/) },
"base64" => ->(v) { (v.length % 4).zero? && v.match?(%r{\A[A-Za-z0-9+/]*={0,2}\z}) },
"email" => ->(v) { v.match?(/\A[^@\s]+@[^@\s]+\.[^@\s]+\z/) },
"phone" => ->(v) { v.match?(/\A\+[1-9]\d{1,14}\z/) },
"url" => ->(v) { (uri = URI.parse(v)).is_a?(URI::HTTP) && !uri.host.nil? rescue false },
"uri" => ->(v) { !URI.parse(v).scheme.nil? rescue false },
"ipv4" => ->(v) { IPAddr.new(v).ipv4? rescue false },
"ipv6" => ->(v) { IPAddr.new(v).ipv6? rescue false },
"hostname" => lambda do |v|
v.match?(%r{\A(?=.{1,253}\z)([a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)(\.[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*\z})
end,
}.freeze
Class Method Summary
collapse
Class Method Details
.any ⇒ Object
136
137
138
|
# File 'lib/web_function/type.rb', line 136
def self.any
Any.new
end
|
.array(of = any) ⇒ Object
114
115
116
|
# File 'lib/web_function/type.rb', line 114
def self.array(of = any)
ArrayOf.new(of)
end
|
.base(type) ⇒ Object
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
|
# File 'lib/web_function/type.rb', line 71
def self.base(type)
base_type, refinement = type.split(".", 2)
case base_type
when "string"
if refinement && !ALLOWED_REFINEMENTS["string"].include?(refinement)
return Type.string
end
Type.string(refinement)
when "number"
if refinement && !ALLOWED_REFINEMENTS["number"].include?(refinement)
return Type.number
end
Type.number(refinement)
when "object"
Type.object(refinement)
when "array"
Type.array
when "boolean"
Type.boolean
when "null"
Type.null
when "any"
Type.any
else
nil
end
end
|
.boolean ⇒ Object
118
119
120
|
# File 'lib/web_function/type.rb', line 118
def self.boolean
Base.new(base_type: "boolean")
end
|
.detect(raw) ⇒ Object
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
|
# File 'lib/web_function/type.rb', line 54
def self.detect(raw)
case raw
when String
Type.base(raw)
when Array
types = raw.map { |type| Type.detect(type) }.compact
if types.empty?
return Type.array(Type.any)
end
Type.array(Type.union(types))
else
return nil
end
end
|
.null ⇒ Object
122
123
124
|
# File 'lib/web_function/type.rb', line 122
def self.null
Base.new(base_type: "null")
end
|
.number(refinement = nil) ⇒ Object
106
107
108
|
# File 'lib/web_function/type.rb', line 106
def self.number(refinement = nil)
Base.new(base_type: "number", refinement: refinement)
end
|
.object(refinement = nil) ⇒ Object
110
111
112
|
# File 'lib/web_function/type.rb', line 110
def self.object(refinement = nil)
Base.new(base_type: "object", refinement: refinement)
end
|
.parse(raw) ⇒ Object
44
45
46
47
48
49
50
51
52
|
# File 'lib/web_function/type.rb', line 44
def self.parse(raw)
types = [*raw].map { |type| Type.detect(type) }.compact
if types.empty?
return Type.any
end
Type.union(types)
end
|
.string(refinement = nil) ⇒ Object
102
103
104
|
# File 'lib/web_function/type.rb', line 102
def self.string(refinement = nil)
Base.new(base_type: "string", refinement: refinement)
end
|
.union(types) ⇒ Object
126
127
128
129
130
131
132
133
134
|
# File 'lib/web_function/type.rb', line 126
def self.union(types)
types = types.uniq
if types.length > 1
Union.new(types)
else
types.first
end
end
|