json-schema 2.8.1 → 6.1.0
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/README.md +55 -11
- data/lib/json-schema/attribute.rb +15 -16
- data/lib/json-schema/attributes/additionalitems.rb +1 -0
- data/lib/json-schema/attributes/additionalproperties.rb +4 -7
- data/lib/json-schema/attributes/allof.rb +33 -6
- data/lib/json-schema/attributes/anyof.rb +4 -4
- data/lib/json-schema/attributes/const.rb +15 -0
- data/lib/json-schema/attributes/dependencies.rb +1 -0
- data/lib/json-schema/attributes/disallow.rb +2 -1
- data/lib/json-schema/attributes/divisibleby.rb +1 -1
- data/lib/json-schema/attributes/enum.rb +3 -3
- data/lib/json-schema/attributes/extends.rb +10 -8
- data/lib/json-schema/attributes/format.rb +2 -1
- data/lib/json-schema/attributes/formats/custom.rb +5 -7
- data/lib/json-schema/attributes/formats/date.rb +2 -1
- data/lib/json-schema/attributes/formats/date_time.rb +4 -3
- data/lib/json-schema/attributes/formats/date_time_v4.rb +2 -1
- data/lib/json-schema/attributes/formats/ip.rb +3 -3
- data/lib/json-schema/attributes/formats/time.rb +1 -1
- data/lib/json-schema/attributes/formats/uri.rb +2 -1
- data/lib/json-schema/attributes/items.rb +1 -0
- data/lib/json-schema/attributes/limit.rb +2 -2
- data/lib/json-schema/attributes/limits/numeric.rb +1 -1
- data/lib/json-schema/attributes/maxdecimal.rb +2 -2
- data/lib/json-schema/attributes/not.rb +2 -2
- data/lib/json-schema/attributes/oneof.rb +9 -11
- data/lib/json-schema/attributes/pattern.rb +1 -1
- data/lib/json-schema/attributes/patternproperties.rb +2 -1
- data/lib/json-schema/attributes/properties.rb +10 -10
- data/lib/json-schema/attributes/properties_v4.rb +2 -2
- data/lib/json-schema/attributes/propertynames.rb +23 -0
- data/lib/json-schema/attributes/ref.rb +19 -18
- data/lib/json-schema/attributes/required.rb +6 -5
- data/lib/json-schema/attributes/type.rb +11 -10
- data/lib/json-schema/attributes/type_v4.rb +3 -3
- data/lib/json-schema/attributes/uniqueitems.rb +1 -1
- data/lib/json-schema/errors/validation_error.rb +10 -10
- data/lib/json-schema/schema/reader.rb +4 -2
- data/lib/json-schema/schema/validator.rb +4 -4
- data/lib/json-schema/schema.rb +13 -14
- data/lib/json-schema/util/array_set.rb +2 -4
- data/lib/json-schema/util/uri.rb +100 -77
- data/lib/json-schema/util/uuid.rb +204 -226
- data/lib/json-schema/validator.rb +173 -156
- data/lib/json-schema/validators/draft1.rb +21 -23
- data/lib/json-schema/validators/draft2.rb +22 -24
- data/lib/json-schema/validators/draft3.rb +26 -28
- data/lib/json-schema/validators/draft4.rb +34 -36
- data/lib/json-schema/validators/draft6.rb +36 -36
- data/lib/json-schema/validators/hyper-draft1.rb +2 -3
- data/lib/json-schema/validators/hyper-draft2.rb +2 -3
- data/lib/json-schema/validators/hyper-draft3.rb +2 -3
- data/lib/json-schema/validators/hyper-draft4.rb +2 -3
- data/lib/json-schema/validators/hyper-draft6.rb +2 -3
- data/lib/json-schema.rb +3 -3
- data/resources/draft-06.json +12 -12
- metadata +60 -32
|
@@ -23,262 +23,240 @@
|
|
|
23
23
|
# 2009-02-20: Modified by Pablo Lorenzoni <pablo@propus.com.br> to correctly
|
|
24
24
|
# include the version in the raw_bytes.
|
|
25
25
|
|
|
26
|
-
|
|
27
26
|
require 'digest/md5'
|
|
28
27
|
require 'digest/sha1'
|
|
29
28
|
require 'tmpdir'
|
|
30
29
|
|
|
31
30
|
module JSON
|
|
32
31
|
module Util
|
|
33
|
-
|
|
34
32
|
# Pure ruby UUID generator, which is compatible with RFC4122
|
|
35
33
|
UUID = Struct.new :raw_bytes
|
|
36
|
-
|
|
34
|
+
|
|
37
35
|
class UUID
|
|
38
|
-
|
|
36
|
+
private_class_method :new
|
|
37
|
+
|
|
38
|
+
class << self
|
|
39
|
+
def mask(v, str)
|
|
40
|
+
nstr = str.bytes.to_a
|
|
41
|
+
version = [0, 16, 32, 48, 64, 80][v]
|
|
42
|
+
nstr[6] &= 0b00001111
|
|
43
|
+
nstr[6] |= version
|
|
44
|
+
# nstr[7] &= 0b00001111
|
|
45
|
+
# nstr[7] |= 0b01010000
|
|
46
|
+
nstr[8] &= 0b00111111
|
|
47
|
+
nstr[8] |= 0b10000000
|
|
48
|
+
str = +''
|
|
49
|
+
nstr.each { |s| str << s.chr }
|
|
50
|
+
str
|
|
51
|
+
end
|
|
39
52
|
|
|
40
|
-
|
|
41
|
-
def mask19 v, str # :nodoc
|
|
42
|
-
nstr = str.bytes.to_a
|
|
43
|
-
version = [0, 16, 32, 48, 64, 80][v]
|
|
44
|
-
nstr[6] &= 0b00001111
|
|
45
|
-
nstr[6] |= version
|
|
46
|
-
# nstr[7] &= 0b00001111
|
|
47
|
-
# nstr[7] |= 0b01010000
|
|
48
|
-
nstr[8] &= 0b00111111
|
|
49
|
-
nstr[8] |= 0b10000000
|
|
50
|
-
str = ''
|
|
51
|
-
nstr.each { |s| str << s.chr }
|
|
52
|
-
str
|
|
53
|
-
end
|
|
53
|
+
private :mask
|
|
54
54
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
55
|
+
# UUID generation using SHA1. Recommended over create_md5.
|
|
56
|
+
# Namespace object is another UUID, some of them are pre-defined below.
|
|
57
|
+
def create_sha1(str, namespace)
|
|
58
|
+
sha1 = Digest::SHA1.new
|
|
59
|
+
sha1.update namespace.raw_bytes
|
|
60
|
+
sha1.update str
|
|
61
|
+
sum = sha1.digest
|
|
62
|
+
raw = mask 5, sum[0..15]
|
|
63
|
+
ret = new raw
|
|
64
|
+
ret.freeze
|
|
65
|
+
ret
|
|
66
|
+
end
|
|
67
|
+
alias create_v5 create_sha1
|
|
65
68
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
69
|
+
# UUID generation using MD5 (for backward compat.)
|
|
70
|
+
def create_md5(str, namespace)
|
|
71
|
+
md5 = Digest::MD5.new
|
|
72
|
+
md5.update namespace.raw_bytes
|
|
73
|
+
md5.update str
|
|
74
|
+
sum = md5.digest
|
|
75
|
+
raw = mask 3, sum[0..16]
|
|
76
|
+
ret = new raw
|
|
77
|
+
ret.freeze
|
|
78
|
+
ret
|
|
79
|
+
end
|
|
80
|
+
alias create_v3 create_md5
|
|
74
81
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
82
|
+
# UUID generation using random-number generator. From it's random
|
|
83
|
+
# nature, there's no warranty that the created ID is really universaly
|
|
84
|
+
# unique.
|
|
85
|
+
def create_random
|
|
86
|
+
rnd = [
|
|
87
|
+
rand(0x100000000),
|
|
88
|
+
rand(0x100000000),
|
|
89
|
+
rand(0x100000000),
|
|
90
|
+
rand(0x100000000),
|
|
91
|
+
].pack 'N4'
|
|
92
|
+
raw = mask 4, rnd
|
|
93
|
+
ret = new raw
|
|
94
|
+
ret.freeze
|
|
95
|
+
ret
|
|
96
|
+
end
|
|
97
|
+
alias create_v4 create_random
|
|
88
98
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
md5.update str
|
|
94
|
-
sum = md5.digest
|
|
95
|
-
raw = mask 3, sum[0..16]
|
|
96
|
-
ret = new raw
|
|
97
|
-
ret.freeze
|
|
98
|
-
ret
|
|
99
|
-
end
|
|
100
|
-
alias :create_v3 :create_md5
|
|
99
|
+
def read_state(fp) # :nodoc:
|
|
100
|
+
fp.rewind
|
|
101
|
+
Marshal.load fp.read
|
|
102
|
+
end
|
|
101
103
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
rand(0x100000000),
|
|
108
|
-
rand(0x100000000),
|
|
109
|
-
rand(0x100000000),
|
|
110
|
-
rand(0x100000000),
|
|
111
|
-
].pack "N4"
|
|
112
|
-
raw = mask 4, rnd
|
|
113
|
-
ret = new raw
|
|
114
|
-
ret.freeze
|
|
115
|
-
ret
|
|
116
|
-
end
|
|
117
|
-
alias :create_v4 :create_random
|
|
104
|
+
def write_state(fp, c, m) # :nodoc:
|
|
105
|
+
fp.rewind
|
|
106
|
+
str = Marshal.dump [c, m]
|
|
107
|
+
fp.write str
|
|
108
|
+
end
|
|
118
109
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
Marshal.load fp.read
|
|
122
|
-
end
|
|
110
|
+
private :read_state, :write_state
|
|
111
|
+
STATE_FILE = 'ruby-uuid'
|
|
123
112
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
113
|
+
# create the "version 1" UUID with current system clock, current UTC
|
|
114
|
+
# timestamp, and the IEEE 802 address (so-called MAC address).
|
|
115
|
+
#
|
|
116
|
+
# Speed notice: it's slow. It writes some data into hard drive on every
|
|
117
|
+
# invokation. If you want to speed this up, try remounting tmpdir with a
|
|
118
|
+
# memory based filesystem (such as tmpfs). STILL slow? then no way but
|
|
119
|
+
# rewrite it with c :)
|
|
120
|
+
def create(clock = nil, time = nil, mac_addr = nil)
|
|
121
|
+
c = t = m = nil
|
|
122
|
+
Dir.chdir Dir.tmpdir do
|
|
123
|
+
unless FileTest.exist? STATE_FILE
|
|
124
|
+
# Generate a pseudo MAC address because we have no pure-ruby way
|
|
125
|
+
# to know the MAC address of the NIC this system uses. Note
|
|
126
|
+
# that cheating with pseudo arresses here is completely legal:
|
|
127
|
+
# see Section 4.5 of RFC4122 for details.
|
|
128
|
+
sha1 = Digest::SHA1.new
|
|
129
|
+
256.times do
|
|
130
|
+
r = [rand(0x100000000)].pack 'N'
|
|
131
|
+
sha1.update r
|
|
132
|
+
end
|
|
133
|
+
str = sha1.digest
|
|
134
|
+
r = rand 14 # 20-6
|
|
135
|
+
node = str[r, 6] || str
|
|
136
|
+
nnode = node.bytes.to_a
|
|
137
|
+
nnode[0] |= 0x01
|
|
138
|
+
node = ''
|
|
139
|
+
nnode.each { |s| node << s.chr }
|
|
140
|
+
k = rand 0x40000
|
|
141
|
+
open STATE_FILE, 'w' do |fp|
|
|
142
|
+
fp.flock IO::LOCK_EX
|
|
143
|
+
write_state fp, k, node
|
|
144
|
+
fp.chmod 0o777 # must be world writable
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
open STATE_FILE, 'r+' do |fp|
|
|
148
|
+
fp.flock IO::LOCK_EX
|
|
149
|
+
c, m = read_state fp
|
|
150
|
+
c = clock % 0x4000 if clock
|
|
151
|
+
m = mac_addr if mac_addr
|
|
152
|
+
t = time
|
|
153
|
+
if t.nil?
|
|
154
|
+
# UUID epoch is 1582/Oct/15
|
|
155
|
+
tt = Time.now
|
|
156
|
+
t = (tt.to_i * 10_000_000) + (tt.tv_usec * 10) + 0x01B21DD213814000
|
|
157
|
+
end
|
|
158
|
+
c = c.succ # important; increment here
|
|
159
|
+
write_state fp, c, m
|
|
160
|
+
end
|
|
161
|
+
end
|
|
129
162
|
|
|
130
|
-
|
|
131
|
-
|
|
163
|
+
tl = t & 0xFFFF_FFFF
|
|
164
|
+
tm = t >> 32
|
|
165
|
+
tm &= 0xFFFF
|
|
166
|
+
th = t >> 48
|
|
167
|
+
th &= 0x0FFF
|
|
168
|
+
th |= 0x1000
|
|
169
|
+
cl = c & 0xFF
|
|
170
|
+
ch = c & 0x3F00
|
|
171
|
+
ch >>= 8
|
|
172
|
+
ch |= 0x80
|
|
173
|
+
pack tl, tm, th, cl, ch, m
|
|
174
|
+
end
|
|
175
|
+
alias create_v1 create
|
|
132
176
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
unless FileTest.exist? STATE_FILE then
|
|
144
|
-
# Generate a pseudo MAC address because we have no pure-ruby way
|
|
145
|
-
# to know the MAC address of the NIC this system uses. Note
|
|
146
|
-
# that cheating with pseudo arresses here is completely legal:
|
|
147
|
-
# see Section 4.5 of RFC4122 for details.
|
|
148
|
-
sha1 = Digest::SHA1.new
|
|
149
|
-
256.times do
|
|
150
|
-
r = [rand(0x100000000)].pack "N"
|
|
151
|
-
sha1.update r
|
|
152
|
-
end
|
|
153
|
-
str = sha1.digest
|
|
154
|
-
r = rand 14 # 20-6
|
|
155
|
-
node = str[r, 6] || str
|
|
156
|
-
if RUBY_VERSION >= "1.9.0"
|
|
157
|
-
nnode = node.bytes.to_a
|
|
158
|
-
nnode[0] |= 0x01
|
|
159
|
-
node = ''
|
|
160
|
-
nnode.each { |s| node << s.chr }
|
|
161
|
-
else
|
|
162
|
-
node[0] |= 0x01 # multicast bit
|
|
163
|
-
end
|
|
164
|
-
k = rand 0x40000
|
|
165
|
-
open STATE_FILE, 'w' do |fp|
|
|
166
|
-
fp.flock IO::LOCK_EX
|
|
167
|
-
write_state fp, k, node
|
|
168
|
-
fp.chmod 0o777 # must be world writable
|
|
169
|
-
end
|
|
170
|
-
end
|
|
171
|
-
open STATE_FILE, 'r+' do |fp|
|
|
172
|
-
fp.flock IO::LOCK_EX
|
|
173
|
-
c, m = read_state fp
|
|
174
|
-
c = clock % 0x4000 if clock
|
|
175
|
-
m = mac_addr if mac_addr
|
|
176
|
-
t = time
|
|
177
|
-
if t.nil? then
|
|
178
|
-
# UUID epoch is 1582/Oct/15
|
|
179
|
-
tt = Time.now
|
|
180
|
-
t = tt.to_i*10000000 + tt.tv_usec*10 + 0x01B21DD213814000
|
|
181
|
-
end
|
|
182
|
-
c = c.succ # important; increment here
|
|
183
|
-
write_state fp, c, m
|
|
184
|
-
end
|
|
185
|
-
end
|
|
177
|
+
# A simple GUID parser: just ignores unknown characters and convert
|
|
178
|
+
# hexadecimal dump into 16-octet object.
|
|
179
|
+
def parse(obj)
|
|
180
|
+
str = obj.to_s.sub(/\Aurn:uuid:/, '')
|
|
181
|
+
str.gsub!(/[^0-9A-Fa-f]/, '')
|
|
182
|
+
raw = str[0..31].lines.to_a.pack 'H*'
|
|
183
|
+
ret = new raw
|
|
184
|
+
ret.freeze
|
|
185
|
+
ret
|
|
186
|
+
end
|
|
186
187
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
ch = ch | 0x80
|
|
197
|
-
pack tl, tm, th, cl, ch, m
|
|
198
|
-
end
|
|
199
|
-
alias :create_v1 :create
|
|
188
|
+
# The 'primitive constructor' of this class
|
|
189
|
+
# Note UUID.pack(uuid.unpack) == uuid
|
|
190
|
+
def pack(tl, tm, th, ch, cl, n)
|
|
191
|
+
raw = [tl, tm, th, ch, cl, n].pack 'NnnCCa6'
|
|
192
|
+
ret = new raw
|
|
193
|
+
ret.freeze
|
|
194
|
+
ret
|
|
195
|
+
end
|
|
196
|
+
end
|
|
200
197
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
raw = str[0..31].lines.to_a.pack 'H*'
|
|
207
|
-
ret = new raw
|
|
208
|
-
ret.freeze
|
|
209
|
-
ret
|
|
210
|
-
end
|
|
198
|
+
# The 'primitive deconstructor', or the dual to pack.
|
|
199
|
+
# Note UUID.pack(uuid.unpack) == uuid
|
|
200
|
+
def unpack
|
|
201
|
+
raw_bytes.unpack 'NnnCCa6'
|
|
202
|
+
end
|
|
211
203
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
end
|
|
204
|
+
# Generate the string representation (a.k.a GUID) of this UUID
|
|
205
|
+
def to_s
|
|
206
|
+
a = unpack
|
|
207
|
+
tmp = a[-1].unpack 'C*'
|
|
208
|
+
a[-1] = format '%02x%02x%02x%02x%02x%02x', *tmp
|
|
209
|
+
'%08x-%04x-%04x-%02x%02x-%s' % a
|
|
210
|
+
end
|
|
211
|
+
alias guid to_s
|
|
221
212
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
213
|
+
# Convert into a RFC4122-comforming URN representation
|
|
214
|
+
def to_uri
|
|
215
|
+
'urn:uuid:' + to_s
|
|
216
|
+
end
|
|
217
|
+
alias urn to_uri
|
|
227
218
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
219
|
+
# Convert into 128-bit unsigned integer
|
|
220
|
+
def to_int
|
|
221
|
+
tmp = raw_bytes.unpack 'C*'
|
|
222
|
+
tmp.inject do |r, i|
|
|
223
|
+
(r * 256) | i
|
|
224
|
+
end
|
|
225
|
+
end
|
|
226
|
+
alias to_i to_int
|
|
236
227
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
228
|
+
# Gets the version of this UUID
|
|
229
|
+
# returns nil if bad version
|
|
230
|
+
def version
|
|
231
|
+
a = unpack
|
|
232
|
+
v = (a[2] & 0xF000).to_s(16)[0].chr.to_i
|
|
233
|
+
return v if (1..5).include? v
|
|
242
234
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
tmp = self.raw_bytes.unpack "C*"
|
|
246
|
-
tmp.inject do |r, i|
|
|
247
|
-
r * 256 | i
|
|
248
|
-
end
|
|
249
|
-
end
|
|
250
|
-
alias to_i to_int
|
|
235
|
+
nil
|
|
236
|
+
end
|
|
251
237
|
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
return nil
|
|
259
|
-
end
|
|
238
|
+
# Two UUIDs are said to be equal if and only if their (byte-order
|
|
239
|
+
# canonicalized) integer representations are equivalent. Refer RFC4122 for
|
|
240
|
+
# details.
|
|
241
|
+
def ==(other)
|
|
242
|
+
to_i == other.to_i
|
|
243
|
+
end
|
|
260
244
|
|
|
261
|
-
|
|
262
|
-
# canonicalized) integer representations are equivallent. Refer RFC4122 for
|
|
263
|
-
# details.
|
|
264
|
-
def == other
|
|
265
|
-
to_i == other.to_i
|
|
266
|
-
end
|
|
245
|
+
include Comparable
|
|
267
246
|
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
end
|
|
247
|
+
# UUIDs are comparable (don't know what benefits are there, though).
|
|
248
|
+
def <=>(other)
|
|
249
|
+
to_s <=> other.to_s
|
|
250
|
+
end
|
|
273
251
|
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
252
|
+
# Pre-defined UUID Namespaces described in RFC4122 Appendix C.
|
|
253
|
+
NameSpace_DNS = parse '6ba7b810-9dad-11d1-80b4-00c04fd430c8'
|
|
254
|
+
NameSpace_URL = parse '6ba7b811-9dad-11d1-80b4-00c04fd430c8'
|
|
255
|
+
NameSpace_OID = parse '6ba7b812-9dad-11d1-80b4-00c04fd430c8'
|
|
256
|
+
NameSpace_X500 = parse '6ba7b814-9dad-11d1-80b4-00c04fd430c8'
|
|
279
257
|
|
|
280
|
-
|
|
281
|
-
|
|
258
|
+
# The Nil UUID in RFC4122 Section 4.1.7
|
|
259
|
+
Nil = parse '00000000-0000-0000-0000-000000000000'
|
|
282
260
|
end
|
|
283
261
|
end
|
|
284
|
-
end
|
|
262
|
+
end
|