media_types-serialization 2.0.4 → 2.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.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +32 -32
  3. data/.github/workflows/publish-bookworm.yml +34 -34
  4. data/.github/workflows/publish-sid.yml +34 -34
  5. data/.gitignore +22 -22
  6. data/.idea/.rakeTasks +7 -7
  7. data/.idea/dictionaries/Derk_Jan.xml +6 -6
  8. data/.idea/encodings.xml +3 -3
  9. data/.idea/inspectionProfiles/Project_Default.xml +5 -5
  10. data/.idea/media_types-serialization.iml +76 -76
  11. data/.idea/misc.xml +6 -6
  12. data/.idea/modules.xml +7 -7
  13. data/.idea/runConfigurations/test.xml +19 -19
  14. data/.idea/vcs.xml +5 -5
  15. data/CHANGELOG.md +207 -200
  16. data/CODE_OF_CONDUCT.md +74 -74
  17. data/Gemfile +4 -4
  18. data/Gemfile.lock +176 -169
  19. data/LICENSE.txt +21 -21
  20. data/README.md +1058 -1048
  21. data/Rakefile +10 -10
  22. data/bin/console +14 -14
  23. data/bin/setup +8 -8
  24. data/lib/media_types/problem.rb +67 -67
  25. data/lib/media_types/serialization/base.rb +269 -269
  26. data/lib/media_types/serialization/error.rb +193 -193
  27. data/lib/media_types/serialization/fake_validator.rb +53 -53
  28. data/lib/media_types/serialization/serialization_dsl.rb +139 -135
  29. data/lib/media_types/serialization/serialization_registration.rb +245 -245
  30. data/lib/media_types/serialization/serializers/api_viewer.rb +383 -383
  31. data/lib/media_types/serialization/serializers/common_css.rb +212 -212
  32. data/lib/media_types/serialization/serializers/endpoint_description_serializer.rb +80 -80
  33. data/lib/media_types/serialization/serializers/fallback_not_acceptable_serializer.rb +85 -85
  34. data/lib/media_types/serialization/serializers/fallback_unsupported_media_type_serializer.rb +58 -58
  35. data/lib/media_types/serialization/serializers/input_validation_error_serializer.rb +95 -93
  36. data/lib/media_types/serialization/serializers/problem_serializer.rb +111 -111
  37. data/lib/media_types/serialization/utils/accept_header.rb +77 -77
  38. data/lib/media_types/serialization/utils/accept_language_header.rb +82 -82
  39. data/lib/media_types/serialization/version.rb +7 -7
  40. data/lib/media_types/serialization.rb +689 -689
  41. data/media_types-serialization.gemspec +48 -48
  42. metadata +3 -3
@@ -1,245 +1,245 @@
1
- # frozen_string_literal: true
2
-
3
- require 'media_types/serialization/error'
4
- require 'media_types'
5
-
6
- module MediaTypes
7
- module Serialization
8
- # A collection that manages media type identifier registrations
9
- class SerializationRegistration
10
- def initialize(direction)
11
- self.registrations = {}
12
- self.inout = direction
13
- end
14
-
15
- attr_accessor :registrations, :inout
16
-
17
- def has?(identifier)
18
- registrations.key? identifier
19
- end
20
-
21
- def register_block(serializer, validator, version, block, raw, wildcards: true)
22
- identifier = validator.identifier
23
-
24
- raise DuplicateDefinitionError.new(identifier, inout) if registrations.key? identifier
25
-
26
- raise ValidatorNotDefinedError.new(identifier, inout) unless raw || validator.validatable?
27
-
28
- registration = SerializationBlockRegistration.new serializer, inout, validator, identifier, version, block, raw
29
- registrations[identifier] = registration
30
-
31
- register_wildcards(identifier, registration) if wildcards && inout == :output
32
- end
33
-
34
- def register_alias(serializer, alias_identifier, target_identifier, optional, hide_variant, wildcards: true)
35
- raise DuplicateDefinitionError.new(alias_identifier, inout) if registrations.key? alias_identifier
36
-
37
- unless registrations.key? target_identifier
38
- potential_match = registrations.keys.find do |k|
39
- k.start_with? target_identifier
40
- end
41
- raise VersionedAliasDefinitionError.new(target_identifier, inout, potential_match) unless potential_match.nil?
42
- raise UnbackedAliasDefinitionError.new(target_identifier, inout)
43
- end
44
-
45
- target = registrations[target_identifier]
46
-
47
- result_content_type = alias_identifier
48
- result_content_type += "; variant=#{target_identifier}" unless hide_variant
49
-
50
- registration = SerializationAliasRegistration.new serializer, inout, target.validator, result_content_type, target, optional, hide_variant
51
- registrations[alias_identifier] = registration
52
-
53
- register_wildcards(alias_identifier, registration) if wildcards && inout == :output
54
- end
55
-
56
- def merge(other)
57
- raise Error, 'Trying to merge two SerializationRegistration objects with a different direction.' unless inout == other.inout
58
-
59
- result = SerializationRegistration.new(inout)
60
-
61
- prev_keys = Set.new(registrations.keys)
62
- new_keys = Set.new(other.registrations.keys)
63
- overlap = prev_keys & new_keys
64
-
65
- result.registrations = registrations.merge(other.registrations)
66
- overlap.each do |identifier|
67
- prev_item = registrations[identifier]
68
- new_item = other.registrations[identifier]
69
- merge_result = prev_item.merge(new_item)
70
-
71
- raise DuplicateUsageError.new(identifier, inout, prev_item.serializer, new_item.serializer) if merge_result.nil?
72
-
73
- result.registrations[identifier] = merge_result
74
- end
75
-
76
- result
77
- end
78
-
79
- def decode(victim, media_type, context)
80
- registration = registrations[media_type]
81
- raise UnregisteredMediaTypeUsageError.new(media_type, registrations.keys) if registration.nil?
82
-
83
- registration.decode(victim, context)
84
- end
85
-
86
- def call(victim, media_type, context, dsl: nil, raw: nil)
87
- registration = registrations[media_type]
88
- raise UnregisteredMediaTypeUsageError.new(media_type, registrations.keys) if registration.nil?
89
-
90
- registration.call(victim, context, dsl: dsl, raw: raw)
91
- end
92
-
93
- def identifier_for(input_identifier)
94
- registration = registrations[input_identifier]
95
- raise UnregisteredMediaTypeUsageError.new(media_type, registrations.keys) if registration.nil?
96
-
97
- registration.display_identifier
98
- end
99
-
100
- def filter(views:)
101
- result = SerializationRegistration.new inout
102
-
103
- registrations.each do |identifier, registration|
104
- if views.include? registration.validator.view
105
- result.registrations[identifier] = registration
106
- end
107
- end
108
-
109
- result
110
- end
111
-
112
- private
113
-
114
- def register_wildcards(identifier, registration)
115
- new_alias = SerializationAliasRegistration.new registration.serializer, registration.inout, registration.validator, identifier, registration, true, true
116
-
117
- registrations['*/*'] = new_alias unless has? '*/*'
118
-
119
- partial = "#{identifier.split('/')[0]}/*"
120
- registrations[partial] = new_alias unless has? partial
121
- end
122
- end
123
-
124
- # A registration in a SerializationRegistration collection
125
- class SerializationBaseRegistration
126
- def initialize(serializer, inout, validator, display_identifier)
127
- self.serializer = serializer
128
- self.inout = inout
129
- self.validator = validator
130
- self.display_identifier = display_identifier
131
- end
132
-
133
- def merge(_other)
134
- nil
135
- end
136
-
137
- def decode(_victim, _context)
138
- raise 'Assertion failed, decode function called on base registration.'
139
- end
140
- def call(_victim, _context, dsl: nil, raw: nil)
141
- raise 'Assertion failed, call function called on base registration.'
142
- end
143
-
144
- attr_accessor :serializer, :inout, :validator, :display_identifier
145
- end
146
-
147
- # A registration with a block to be executed when called.
148
- class SerializationBlockRegistration < SerializationBaseRegistration
149
- def initialize(serializer, inout, validator, display_identifier, version, block, raw)
150
- self.version = version
151
- self.block = block
152
- self.raw = raw
153
- super(serializer, inout, validator, display_identifier)
154
- end
155
-
156
- def merge(other)
157
- return nil unless other.is_a?(SerializationAliasRegistration)
158
-
159
- return self if other.optional
160
-
161
- nil
162
- end
163
-
164
- def decode(victim, _context)
165
- raise CannotDecodeOutputError if inout != :input
166
-
167
- unless raw
168
- if defined? Oj::ParseError
169
- begin
170
- victim = MediaTypes::Serialization.json_decoder.call(victim)
171
- validator.validate!(victim, loose: true)
172
- rescue MediaTypes::Scheme::ValidationError, Oj::ParseError, JSON::ParserError, EncodingError => inner
173
- raise InputValidationFailedError, inner
174
- end
175
- else
176
- begin
177
- victim = MediaTypes::Serialization.json_decoder.call(victim)
178
- validator.validate!(victim, loose: true)
179
- rescue MediaTypes::Scheme::ValidationError, JSON::ParserError, EncodingError => inner
180
- raise InputValidationFailedError, inner
181
- end
182
- end
183
- end
184
-
185
- victim
186
- end
187
-
188
- def call(victim, context, dsl: nil, raw: nil)
189
- raw = self.raw if raw.nil?
190
-
191
- result = nil
192
- if dsl.nil?
193
- result = victim
194
- result = block.call(victim, version, context) if block
195
- else
196
- result = dsl.instance_exec victim, version, context, &block
197
- end
198
-
199
- if !raw && inout == :output
200
- begin
201
- validator.validate!(result)
202
- rescue MediaTypes::Scheme::ValidationError => inner
203
- raise OutputValidationFailedError, inner
204
- end
205
- result = MediaTypes::Serialization.json_encoder.call(result)
206
- end
207
-
208
- result
209
- end
210
-
211
- attr_accessor :version, :block, :raw
212
- end
213
-
214
- # A registration that calls another registration when called.
215
- class SerializationAliasRegistration < SerializationBaseRegistration
216
- def initialize(serializer, inout, validator, display_identifier, target, optional, hide_variant)
217
- self.target = target
218
- self.optional = optional
219
- self.hide_variant = hide_variant
220
- super(serializer, inout, validator, display_identifier)
221
- end
222
-
223
- def merge(other)
224
- if optional
225
- return other unless other.is_a?(SerializationAliasRegistration)
226
- else
227
- return nil if other.is_a?(SerializationAliasRegistration) && !other.optional # two non-optional can't merge
228
- return self
229
- end
230
-
231
- other # if both optional, or other is !optional, newer one wins.
232
- end
233
-
234
- def decode(victim, context)
235
- target.decode(victim, context)
236
- end
237
-
238
- def call(victim, context, dsl: nil, raw: nil)
239
- target.call(victim, context, dsl: dsl, raw: raw)
240
- end
241
-
242
- attr_accessor :target, :optional, :hide_variant
243
- end
244
- end
245
- end
1
+ # frozen_string_literal: true
2
+
3
+ require 'media_types/serialization/error'
4
+ require 'media_types'
5
+
6
+ module MediaTypes
7
+ module Serialization
8
+ # A collection that manages media type identifier registrations
9
+ class SerializationRegistration
10
+ def initialize(direction)
11
+ self.registrations = {}
12
+ self.inout = direction
13
+ end
14
+
15
+ attr_accessor :registrations, :inout
16
+
17
+ def has?(identifier)
18
+ registrations.key? identifier
19
+ end
20
+
21
+ def register_block(serializer, validator, version, block, raw, wildcards: true)
22
+ identifier = validator.identifier
23
+
24
+ raise DuplicateDefinitionError.new(identifier, inout) if registrations.key? identifier
25
+
26
+ raise ValidatorNotDefinedError.new(identifier, inout) unless raw || validator.validatable?
27
+
28
+ registration = SerializationBlockRegistration.new serializer, inout, validator, identifier, version, block, raw
29
+ registrations[identifier] = registration
30
+
31
+ register_wildcards(identifier, registration) if wildcards && inout == :output
32
+ end
33
+
34
+ def register_alias(serializer, alias_identifier, target_identifier, optional, hide_variant, wildcards: true)
35
+ raise DuplicateDefinitionError.new(alias_identifier, inout) if registrations.key? alias_identifier
36
+
37
+ unless registrations.key? target_identifier
38
+ potential_match = registrations.keys.find do |k|
39
+ k.start_with? target_identifier
40
+ end
41
+ raise VersionedAliasDefinitionError.new(target_identifier, inout, potential_match) unless potential_match.nil?
42
+ raise UnbackedAliasDefinitionError.new(target_identifier, inout)
43
+ end
44
+
45
+ target = registrations[target_identifier]
46
+
47
+ result_content_type = alias_identifier
48
+ result_content_type += "; variant=#{target_identifier}" unless hide_variant
49
+
50
+ registration = SerializationAliasRegistration.new serializer, inout, target.validator, result_content_type, target, optional, hide_variant
51
+ registrations[alias_identifier] = registration
52
+
53
+ register_wildcards(alias_identifier, registration) if wildcards && inout == :output
54
+ end
55
+
56
+ def merge(other)
57
+ raise Error, 'Trying to merge two SerializationRegistration objects with a different direction.' unless inout == other.inout
58
+
59
+ result = SerializationRegistration.new(inout)
60
+
61
+ prev_keys = Set.new(registrations.keys)
62
+ new_keys = Set.new(other.registrations.keys)
63
+ overlap = prev_keys & new_keys
64
+
65
+ result.registrations = registrations.merge(other.registrations)
66
+ overlap.each do |identifier|
67
+ prev_item = registrations[identifier]
68
+ new_item = other.registrations[identifier]
69
+ merge_result = prev_item.merge(new_item)
70
+
71
+ raise DuplicateUsageError.new(identifier, inout, prev_item.serializer, new_item.serializer) if merge_result.nil?
72
+
73
+ result.registrations[identifier] = merge_result
74
+ end
75
+
76
+ result
77
+ end
78
+
79
+ def decode(victim, media_type, context)
80
+ registration = registrations[media_type]
81
+ raise UnregisteredMediaTypeUsageError.new(media_type, registrations.keys) if registration.nil?
82
+
83
+ registration.decode(victim, context)
84
+ end
85
+
86
+ def call(victim, media_type, context, dsl: nil, raw: nil)
87
+ registration = registrations[media_type]
88
+ raise UnregisteredMediaTypeUsageError.new(media_type, registrations.keys) if registration.nil?
89
+
90
+ registration.call(victim, context, dsl: dsl, raw: raw)
91
+ end
92
+
93
+ def identifier_for(input_identifier)
94
+ registration = registrations[input_identifier]
95
+ raise UnregisteredMediaTypeUsageError.new(media_type, registrations.keys) if registration.nil?
96
+
97
+ registration.display_identifier
98
+ end
99
+
100
+ def filter(views:)
101
+ result = SerializationRegistration.new inout
102
+
103
+ registrations.each do |identifier, registration|
104
+ if views.include? registration.validator.view
105
+ result.registrations[identifier] = registration
106
+ end
107
+ end
108
+
109
+ result
110
+ end
111
+
112
+ private
113
+
114
+ def register_wildcards(identifier, registration)
115
+ new_alias = SerializationAliasRegistration.new registration.serializer, registration.inout, registration.validator, identifier, registration, true, true
116
+
117
+ registrations['*/*'] = new_alias unless has? '*/*'
118
+
119
+ partial = "#{identifier.split('/')[0]}/*"
120
+ registrations[partial] = new_alias unless has? partial
121
+ end
122
+ end
123
+
124
+ # A registration in a SerializationRegistration collection
125
+ class SerializationBaseRegistration
126
+ def initialize(serializer, inout, validator, display_identifier)
127
+ self.serializer = serializer
128
+ self.inout = inout
129
+ self.validator = validator
130
+ self.display_identifier = display_identifier
131
+ end
132
+
133
+ def merge(_other)
134
+ nil
135
+ end
136
+
137
+ def decode(_victim, _context)
138
+ raise 'Assertion failed, decode function called on base registration.'
139
+ end
140
+ def call(_victim, _context, dsl: nil, raw: nil)
141
+ raise 'Assertion failed, call function called on base registration.'
142
+ end
143
+
144
+ attr_accessor :serializer, :inout, :validator, :display_identifier
145
+ end
146
+
147
+ # A registration with a block to be executed when called.
148
+ class SerializationBlockRegistration < SerializationBaseRegistration
149
+ def initialize(serializer, inout, validator, display_identifier, version, block, raw)
150
+ self.version = version
151
+ self.block = block
152
+ self.raw = raw
153
+ super(serializer, inout, validator, display_identifier)
154
+ end
155
+
156
+ def merge(other)
157
+ return nil unless other.is_a?(SerializationAliasRegistration)
158
+
159
+ return self if other.optional
160
+
161
+ nil
162
+ end
163
+
164
+ def decode(victim, _context)
165
+ raise CannotDecodeOutputError if inout != :input
166
+
167
+ unless raw
168
+ if defined? Oj::ParseError
169
+ begin
170
+ victim = MediaTypes::Serialization.json_decoder.call(victim)
171
+ validator.validate!(victim, loose: true)
172
+ rescue MediaTypes::Scheme::ValidationError, Oj::ParseError, JSON::ParserError, EncodingError => inner
173
+ raise InputValidationFailedError, inner
174
+ end
175
+ else
176
+ begin
177
+ victim = MediaTypes::Serialization.json_decoder.call(victim)
178
+ validator.validate!(victim, loose: true)
179
+ rescue MediaTypes::Scheme::ValidationError, JSON::ParserError, EncodingError => inner
180
+ raise InputValidationFailedError, inner
181
+ end
182
+ end
183
+ end
184
+
185
+ victim
186
+ end
187
+
188
+ def call(victim, context, dsl: nil, raw: nil)
189
+ raw = self.raw if raw.nil?
190
+
191
+ result = nil
192
+ if dsl.nil?
193
+ result = victim
194
+ result = block.call(victim, version, context) if block
195
+ else
196
+ result = dsl.instance_exec victim, version, context, &block
197
+ end
198
+
199
+ if !raw && inout == :output
200
+ begin
201
+ validator.validate!(result)
202
+ rescue MediaTypes::Scheme::ValidationError => inner
203
+ raise OutputValidationFailedError, inner
204
+ end
205
+ result = MediaTypes::Serialization.json_encoder.call(result)
206
+ end
207
+
208
+ result
209
+ end
210
+
211
+ attr_accessor :version, :block, :raw
212
+ end
213
+
214
+ # A registration that calls another registration when called.
215
+ class SerializationAliasRegistration < SerializationBaseRegistration
216
+ def initialize(serializer, inout, validator, display_identifier, target, optional, hide_variant)
217
+ self.target = target
218
+ self.optional = optional
219
+ self.hide_variant = hide_variant
220
+ super(serializer, inout, validator, display_identifier)
221
+ end
222
+
223
+ def merge(other)
224
+ if optional
225
+ return other unless other.is_a?(SerializationAliasRegistration)
226
+ else
227
+ return nil if other.is_a?(SerializationAliasRegistration) && !other.optional # two non-optional can't merge
228
+ return self
229
+ end
230
+
231
+ other # if both optional, or other is !optional, newer one wins.
232
+ end
233
+
234
+ def decode(victim, context)
235
+ target.decode(victim, context)
236
+ end
237
+
238
+ def call(victim, context, dsl: nil, raw: nil)
239
+ target.call(victim, context, dsl: dsl, raw: raw)
240
+ end
241
+
242
+ attr_accessor :target, :optional, :hide_variant
243
+ end
244
+ end
245
+ end