microsoft_kiota_serialization_form 0.25.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 1bc7ad42ac19325bb2e213d2728f629c4273c7a1601120cff1ae0d302400f1ba
4
+ data.tar.gz: 2ea16cd5ba5613d9c77a66b3dd642eae15b301cdc481336989da5b1c6f96e769
5
+ SHA512:
6
+ metadata.gz: cfb4db07a7a567722d8a248c6c00b16c1611da8ed6377c0060be3f8f92f8aca30a2cd71135cc7bd8aea5a73722991a2a74dddfdb008322684c809cab81a0486a
7
+ data.tar.gz: 923d15873ca60031e87048d452fe2dcef198cc249a7afbc52a4c9747e81249b09949f040c18559082c9125839c7d74bd0a4ec9bf034e4d34414482f13811c109
data/Gemfile ADDED
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ ruby '>= 3.3.0'
6
+
7
+ gem 'microsoft_kiota_abstractions', path: '../../abstractions'
8
+ gem 'rake', '~> 13.0'
9
+ gem 'rspec', '~> 3.0'
10
+
11
+ gemspec
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+ require 'rspec/core/rake_task'
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ task default: :spec
@@ -0,0 +1,195 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'date'
4
+ require 'time'
5
+ require 'uri'
6
+ require 'uuidtools'
7
+ require 'microsoft_kiota_abstractions'
8
+
9
+ module MicrosoftKiotaSerializationForm
10
+ class FormParseNode
11
+ include MicrosoftKiotaAbstractions::ParseNode
12
+
13
+ attr_accessor :on_before_assign_field_values, :on_after_assign_field_values
14
+
15
+ # temporal readers take only their own shape, as in Go, so a union picks the right member
16
+ DATE = /\A\d{4}-\d{2}-\d{2}\z/
17
+ TIME = /\A\d{2}:\d{2}(:\d{2}(\.\d+)?)?\z/
18
+ DATE_TIME = /\A\d{4}-\d{2}-\d{2}[Tt ]\d{2}:\d{2}(:\d{2}(\.\d+)?)?([Zz]|[+-]\d{2}(:?\d{2})?)?\z/
19
+
20
+ READERS = {
21
+ string: ->(value) { value },
22
+ boolean: ->(value) { { 'true' => true, 'false' => false }[value.downcase] },
23
+ number: ->(value) { Integer(value, 10) },
24
+ float: ->(value) { Float(value) },
25
+ guid: ->(value) { UUIDTools::UUID.parse(value) },
26
+ date: ->(value) { Date.parse(value) if DATE.match?(value) },
27
+ time: ->(value) { Time.parse(value) if TIME.match?(value) },
28
+ date_time: ->(value) { DateTime.parse(value) if DATE_TIME.match?(value) },
29
+ duration: ->(value) { MicrosoftKiotaAbstractions::ISODuration.new(value) },
30
+ byte_array: ->(value) { value.unpack1('m0') }
31
+ }.freeze
32
+
33
+ # keyed by the constant the generator passes; an untyped collection arrives as Object
34
+ PRIMITIVE_TYPES = {
35
+ String => :string,
36
+ Object => :string,
37
+ Integer => :number,
38
+ Float => :float,
39
+ UUIDTools::UUID => :guid,
40
+ Date => :date,
41
+ DateTime => :date_time,
42
+ Time => :time,
43
+ MicrosoftKiotaAbstractions::ISODuration => :duration,
44
+ 'boolean' => :boolean,
45
+ 'Boolean' => :boolean
46
+ }.freeze
47
+
48
+ def initialize(raw_value, raw_items = nil)
49
+ raw_value = raw_value.to_s.b
50
+ @raw_value = raw_value
51
+ @value = decode(raw_value)
52
+ @fields = parse_fields(raw_value)
53
+ @raw_items = raw_items
54
+ end
55
+
56
+ # an empty value is an empty string, as .NET reads it; only null is nil
57
+ def get_string_value
58
+ @value unless @value == 'null'
59
+ end
60
+
61
+ def get_boolean_value = read(:boolean)
62
+
63
+ def get_number_value = read(:number)
64
+
65
+ def get_float_value = read(:float)
66
+
67
+ def get_guid_value = read(:guid)
68
+
69
+ def get_date_value = read(:date)
70
+
71
+ def get_time_value = read(:time)
72
+
73
+ def get_date_time_value = read(:date_time)
74
+
75
+ def get_duration_value = read(:duration)
76
+
77
+ def get_byte_array_value = read(:byte_array)
78
+
79
+ def get_collection_of_primitive_values(type)
80
+ raise StandardError, 'Primitive type for deserialization cannot be null' if type.nil?
81
+
82
+ kind = PRIMITIVE_TYPES[type]
83
+ raise StandardError, "Encountered an unknown type during deserialization #{type}" if kind.nil?
84
+
85
+ primitive_items.map { |item| read(kind, item) }
86
+ end
87
+
88
+ def get_collection_of_object_values(_factory)
89
+ raise StandardError, 'Collection of object values is not supported with uri form encoding.'
90
+ end
91
+
92
+ def get_object_value(factory)
93
+ raise StandardError, 'Factory cannot be null' if factory.nil?
94
+
95
+ item = factory.call(self)
96
+ begin
97
+ on_before_assign_field_values&.call(item)
98
+ assign_field_values(item)
99
+ ensure
100
+ on_after_assign_field_values&.call(item)
101
+ end
102
+ item
103
+ end
104
+
105
+ def assign_field_values(item)
106
+ deserializers = item.get_field_deserializers
107
+ by_lower_name = deserializers.transform_keys(&:downcase)
108
+ additional_data = item.respond_to?(:additional_data) ? item.additional_data : nil
109
+ @fields.each_value do |key, raw_values|
110
+ deserializer = deserializers[key] || by_lower_name[key.downcase]
111
+ value = decode(raw_values.join(','))
112
+ if deserializer
113
+ deserializer.call(child_node(raw_values)) unless value == 'null'
114
+ elsif additional_data
115
+ additional_data[key] = value
116
+ end
117
+ end
118
+ end
119
+
120
+ def get_enum_value(type)
121
+ get_enum_values(type).first
122
+ end
123
+
124
+ def get_enum_values(type)
125
+ items.map { |value| enum_member(type, value) unless blank?(value) }
126
+ end
127
+
128
+ alias get_collection_of_enum_values get_enum_values
129
+
130
+ def get_child_node(name)
131
+ raise StandardError, 'Name cannot be null' if name.nil? || name.empty?
132
+
133
+ field = @fields[name.downcase]
134
+ child_node(field[1]) if field
135
+ end
136
+
137
+ private
138
+
139
+ # a stray % is kept as is, like Python's unquote_plus
140
+ def decode(value)
141
+ URI.decode_www_form_component(value.gsub(/%(?!\h\h)/, '%25')).scrub
142
+ end
143
+
144
+ def blank?(value)
145
+ value.nil? || value.empty? || value == 'null'
146
+ end
147
+
148
+ def read(kind, value = @value)
149
+ return if blank?(value)
150
+
151
+ READERS.fetch(kind).call(value)
152
+ rescue StandardError
153
+ nil
154
+ end
155
+
156
+ # the items of a repeated key stay apart; a single value is split on commas
157
+ def items
158
+ return @raw_items.map { |raw| decode(raw) } if @raw_items && @raw_items.size > 1
159
+
160
+ @value.split(',')
161
+ end
162
+
163
+ # only a comma sent as is separates primitive items; the writer encodes one inside an item
164
+ def primitive_items
165
+ (@raw_items || [@raw_value]).flat_map { |raw| raw.split(',') }.map { |raw| decode(raw) }
166
+ end
167
+
168
+ def parse_fields(raw)
169
+ fields = {}
170
+ raw.split('&').each do |pair|
171
+ next unless pair.include?('=')
172
+
173
+ key, value = pair.split('=', 2)
174
+ key = decode(key)
175
+ (fields[key.downcase] ||= [key, []])[1] << value
176
+ end
177
+ fields
178
+ end
179
+
180
+ def child_node(raw_values)
181
+ FormParseNode.new(raw_values.join(','), raw_values).tap do |node|
182
+ node.on_before_assign_field_values = on_before_assign_field_values
183
+ node.on_after_assign_field_values = on_after_assign_field_values
184
+ end
185
+ end
186
+
187
+ # same resolution as JsonParseNode: the wire value first, then the member name
188
+ def enum_member(type, value)
189
+ return value.to_sym unless type.is_a?(Hash)
190
+
191
+ type.each_value { |member| return member if member.to_s == value }
192
+ type[value.to_sym] || type[(value[0].to_s.upcase + value[1..].to_s).to_sym]
193
+ end
194
+ end
195
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'microsoft_kiota_abstractions'
4
+
5
+ module MicrosoftKiotaSerializationForm
6
+ class FormParseNodeFactory
7
+ include MicrosoftKiotaAbstractions::ParseNodeFactory
8
+
9
+ def get_valid_content_type
10
+ 'application/x-www-form-urlencoded'
11
+ end
12
+
13
+ def get_parse_node(content_type, content)
14
+ valid = get_valid_content_type
15
+ raise ArgumentError, 'content type cannot be undefined or empty' if content_type.nil? || content_type.empty?
16
+ raise ArgumentError, "expected a #{valid} content type" unless content_type.casecmp?(valid)
17
+ raise ArgumentError, 'content cannot be undefined or empty' if content.nil?
18
+
19
+ FormParseNode.new(content)
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,155 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'date'
4
+ require 'time'
5
+ require 'uri'
6
+ require 'uuidtools'
7
+ require 'microsoft_kiota_abstractions'
8
+
9
+ module MicrosoftKiotaSerializationForm
10
+ class FormSerializationWriter
11
+ include MicrosoftKiotaAbstractions::SerializationWriter
12
+
13
+ NESTED_OBJECTS = 'Form serialization does not support nested objects.'
14
+
15
+ attr_accessor :on_before_object_serialization, :on_after_object_serialization, :on_start_object_serialization
16
+
17
+ def initialize
18
+ @buffer = +''
19
+ @depth = 0
20
+ end
21
+
22
+ def write_string_value(key, value)
23
+ return if key.nil? || key.empty? || value.nil?
24
+
25
+ @buffer << '&' unless @buffer.empty?
26
+ @buffer << URI.encode_www_form_component(key) << '=' << URI.encode_www_form_component(value)
27
+ end
28
+
29
+ def write_boolean_value(key, value) = write_string_value(key, value&.to_s)
30
+
31
+ def write_number_value(key, value) = write_string_value(key, value&.to_s)
32
+
33
+ def write_float_value(key, value) = write_string_value(key, value&.to_s)
34
+
35
+ def write_guid_value(key, value) = write_string_value(key, value&.to_s)
36
+
37
+ def write_date_value(key, value)
38
+ value = value.strftime('%Y-%m-%d') if value.respond_to?(:strftime)
39
+ write_string_value(key, value)
40
+ end
41
+
42
+ def write_time_value(key, value)
43
+ value = value.strftime(fraction?(value) ? '%H:%M:%S.%6N' : '%H:%M:%S') if value.respond_to?(:strftime)
44
+ write_string_value(key, value)
45
+ end
46
+
47
+ def write_date_time_value(key, value)
48
+ value = value.iso8601(fraction?(value) ? 6 : 0) if value.is_a?(Time) || value.is_a?(DateTime)
49
+ write_string_value(key, value)
50
+ end
51
+
52
+ def write_duration_value(key, value)
53
+ value = value.string if value.is_a?(MicrosoftKiotaAbstractions::ISODuration)
54
+ write_string_value(key, value)
55
+ end
56
+
57
+ def write_byte_array_value(key, value)
58
+ write_string_value(key, [value].pack('m0')) unless value.nil?
59
+ end
60
+
61
+ # a flags value is an Array of members
62
+ def write_enum_value(key, value)
63
+ members = Array(value).compact
64
+ write_string_value(key, members.join(',')) unless members.empty?
65
+ end
66
+
67
+ def write_null_value(key) = write_string_value(key, 'null')
68
+
69
+ def write_collection_of_primitive_values(key, values)
70
+ values&.each { |value| write_any_value(key, value) }
71
+ end
72
+
73
+ def write_collection_of_enum_values(key, values)
74
+ values&.each { |value| write_string_value(key, value&.to_s) }
75
+ end
76
+
77
+ def write_collection_of_object_values(_key, values)
78
+ return if values.nil?
79
+
80
+ raise StandardError, 'Form serialization does not support collections.'
81
+ end
82
+
83
+ # written flat, as .NET does; inside a model only a composed type member (nil key) is allowed
84
+ def write_object_value(key, value, *additional_values_to_merge)
85
+ values = [value, *additional_values_to_merge].compact
86
+ return if values.empty?
87
+ raise StandardError, NESTED_OBJECTS if @depth.positive? && !(key.nil? || key.empty?)
88
+
89
+ writer = child_writer
90
+ values.each { |v| serialize_object(v, writer) }
91
+ content = writer.get_serialized_content
92
+ return if content.empty?
93
+
94
+ @buffer << '&' unless @buffer.empty?
95
+ @buffer << content
96
+ end
97
+
98
+ def write_additional_data(value)
99
+ value&.each { |key, data| write_any_value(key, data) }
100
+ end
101
+
102
+ def write_any_value(key, value)
103
+ case value
104
+ when nil then nil
105
+ when String, Symbol then write_string_value(key, value.to_s)
106
+ when true, false then write_boolean_value(key, value)
107
+ when Integer then write_number_value(key, value)
108
+ when Float then write_float_value(key, value)
109
+ when UUIDTools::UUID then write_guid_value(key, value)
110
+ when DateTime, Time then write_date_time_value(key, value)
111
+ when Date then write_date_value(key, value)
112
+ when MicrosoftKiotaAbstractions::ISODuration then write_duration_value(key, value)
113
+ when Array then write_collection_of_primitive_values(key, value)
114
+ when Hash, MicrosoftKiotaAbstractions::Parsable then raise StandardError, NESTED_OBJECTS
115
+ else raise StandardError, "Encountered an unknown type during serialization #{value.class} with key #{key}"
116
+ end
117
+ end
118
+
119
+ def get_serialized_content
120
+ @buffer.dup
121
+ end
122
+
123
+ protected
124
+
125
+ attr_writer :depth
126
+
127
+ private
128
+
129
+ def fraction?(value)
130
+ fraction = if value.respond_to?(:subsec) then value.subsec
131
+ elsif value.respond_to?(:sec_fraction) then value.sec_fraction
132
+ else 0
133
+ end
134
+ !fraction.zero?
135
+ end
136
+
137
+ # the after hook runs even when writing the model raised, so callbacks can restore their state
138
+ def serialize_object(value, writer)
139
+ on_before_object_serialization&.call(value)
140
+ on_start_object_serialization&.call(value, writer)
141
+ value.serialize(writer)
142
+ ensure
143
+ on_after_object_serialization&.call(value)
144
+ end
145
+
146
+ def child_writer
147
+ FormSerializationWriter.new.tap do |writer|
148
+ writer.depth = @depth + 1
149
+ writer.on_before_object_serialization = on_before_object_serialization
150
+ writer.on_after_object_serialization = on_after_object_serialization
151
+ writer.on_start_object_serialization = on_start_object_serialization
152
+ end
153
+ end
154
+ end
155
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'microsoft_kiota_abstractions'
4
+
5
+ module MicrosoftKiotaSerializationForm
6
+ class FormSerializationWriterFactory
7
+ include MicrosoftKiotaAbstractions::SerializationWriterFactory
8
+
9
+ def get_valid_content_type
10
+ 'application/x-www-form-urlencoded'
11
+ end
12
+
13
+ def get_serialization_writer(content_type)
14
+ valid = get_valid_content_type
15
+ raise ArgumentError, 'content type cannot be undefined or empty' if content_type.nil? || content_type.empty?
16
+ raise ArgumentError, "expected a #{valid} content type" unless content_type.casecmp?(valid)
17
+
18
+ FormSerializationWriter.new
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MicrosoftKiotaSerializationForm
4
+ VERSION = '0.25.0' # x-release-please-version
5
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'microsoft_kiota_serialization_form/form_parse_node'
4
+ require_relative 'microsoft_kiota_serialization_form/form_parse_node_factory'
5
+ require_relative 'microsoft_kiota_serialization_form/form_serialization_writer'
6
+ require_relative 'microsoft_kiota_serialization_form/form_serialization_writer_factory'
7
+ require_relative 'microsoft_kiota_serialization_form/version'
8
+
9
+ module MicrosoftKiotaSerializationForm
10
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'lib/microsoft_kiota_serialization_form/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'microsoft_kiota_serialization_form'
7
+ spec.version = MicrosoftKiotaSerializationForm::VERSION
8
+ spec.authors = 'Microsoft Corporation'
9
+ spec.email = 'graphsdkpub+ruby@microsoft.com'
10
+ spec.description = 'Implementation of Kiota Serialization interfaces for URL-encoded forms'
11
+ spec.summary = 'Microsoft Kiota Serialization - Ruby serialization for building library agnostic http client'
12
+ spec.homepage = 'https://learn.microsoft.com/openapi/kiota/'
13
+ spec.license = 'MIT'
14
+ spec.metadata = {
15
+ 'bug_tracker_uri' => 'https://github.com/microsoft/kiota-ruby/issues',
16
+ 'changelog_uri' => 'https://github.com/microsoft/kiota-ruby/blob/main/CHANGELOG.md',
17
+ 'homepage_uri' => spec.homepage,
18
+ 'source_code_uri' => 'https://github.com/microsoft/kiota-ruby/tree/main/components/serialization/form',
19
+ 'github_repo' => 'ssh://github.com/microsoft/kiota-ruby',
20
+ 'rubygems_mfa_required' => 'true'
21
+ }
22
+ spec.required_ruby_version = '>= 3.3.0'
23
+
24
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
25
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{\A(?:test|spec|features)/}) }
26
+ end
27
+ spec.bindir = 'bin'
28
+ spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
29
+ spec.require_paths = ['lib']
30
+ spec.add_dependency 'microsoft_kiota_abstractions', MicrosoftKiotaSerializationForm::VERSION
31
+ spec.add_dependency 'uuidtools', '>= 2.2', '< 3.1'
32
+ end
metadata ADDED
@@ -0,0 +1,89 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: microsoft_kiota_serialization_form
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.25.0
5
+ platform: ruby
6
+ authors:
7
+ - Microsoft Corporation
8
+ bindir: bin
9
+ cert_chain: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: microsoft_kiota_abstractions
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - '='
17
+ - !ruby/object:Gem::Version
18
+ version: 0.25.0
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - '='
24
+ - !ruby/object:Gem::Version
25
+ version: 0.25.0
26
+ - !ruby/object:Gem::Dependency
27
+ name: uuidtools
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: '2.2'
33
+ - - "<"
34
+ - !ruby/object:Gem::Version
35
+ version: '3.1'
36
+ type: :runtime
37
+ prerelease: false
38
+ version_requirements: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: '2.2'
43
+ - - "<"
44
+ - !ruby/object:Gem::Version
45
+ version: '3.1'
46
+ description: Implementation of Kiota Serialization interfaces for URL-encoded forms
47
+ email: graphsdkpub+ruby@microsoft.com
48
+ executables: []
49
+ extensions: []
50
+ extra_rdoc_files: []
51
+ files:
52
+ - Gemfile
53
+ - Rakefile
54
+ - lib/microsoft_kiota_serialization_form.rb
55
+ - lib/microsoft_kiota_serialization_form/form_parse_node.rb
56
+ - lib/microsoft_kiota_serialization_form/form_parse_node_factory.rb
57
+ - lib/microsoft_kiota_serialization_form/form_serialization_writer.rb
58
+ - lib/microsoft_kiota_serialization_form/form_serialization_writer_factory.rb
59
+ - lib/microsoft_kiota_serialization_form/version.rb
60
+ - microsoft_kiota_serialization_form.gemspec
61
+ homepage: https://learn.microsoft.com/openapi/kiota/
62
+ licenses:
63
+ - MIT
64
+ metadata:
65
+ bug_tracker_uri: https://github.com/microsoft/kiota-ruby/issues
66
+ changelog_uri: https://github.com/microsoft/kiota-ruby/blob/main/CHANGELOG.md
67
+ homepage_uri: https://learn.microsoft.com/openapi/kiota/
68
+ source_code_uri: https://github.com/microsoft/kiota-ruby/tree/main/components/serialization/form
69
+ github_repo: ssh://github.com/microsoft/kiota-ruby
70
+ rubygems_mfa_required: 'true'
71
+ rdoc_options: []
72
+ require_paths:
73
+ - lib
74
+ required_ruby_version: !ruby/object:Gem::Requirement
75
+ requirements:
76
+ - - ">="
77
+ - !ruby/object:Gem::Version
78
+ version: 3.3.0
79
+ required_rubygems_version: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ version: '0'
84
+ requirements: []
85
+ rubygems_version: 3.6.9
86
+ specification_version: 4
87
+ summary: Microsoft Kiota Serialization - Ruby serialization for building library agnostic
88
+ http client
89
+ test_files: []