summaryrefslogtreecommitdiffstats
path: root/rubygem-protobuf-3.10.3-generate-camel-cased-keys_add-message-from-json_64bit...
diff options
context:
space:
mode:
authorJarek Prokop <jprokop@redhat.com>2021-03-16 20:57:16 +0100
committerJarek Prokop <jprokop@redhat.com>2021-03-17 11:31:00 +0100
commitb1e6ef3d286330630390722fbaa1f3d1477beb7b (patch)
tree635e18dcea6f17de14b1ab4797232f7dbdff6c22 /rubygem-protobuf-3.10.3-generate-camel-cased-keys_add-message-from-json_64bit-int-as-json.patch
parent7488cab98c5ff19de0384dc12abfc0f2c0588947 (diff)
downloadrubygem-protobuf-b1e6ef3d286330630390722fbaa1f3d1477beb7b.tar.gz
rubygem-protobuf-b1e6ef3d286330630390722fbaa1f3d1477beb7b.tar.xz
rubygem-protobuf-b1e6ef3d286330630390722fbaa1f3d1477beb7b.zip
Use only Pull Requests for patch creation.
Using only patches is enough, however to dodge any patch clashes the git rebase was used to do the heavy lifting. Moreover, when doing a git rebase for PR#415 when a merge conflict arises the lib/protobuf/message.rb needs to have both changes manually merged into one. Also apparently one line in test suite rises up with a merge conflict as well and it needs to have `.force_encoding` on the conflicting line. Note: there is a gotcha with another test where git does not make a proper diff since it thinks its a binary file. Git is wrong about this and an extra patch was added to compensate for this.
Diffstat (limited to 'rubygem-protobuf-3.10.3-generate-camel-cased-keys_add-message-from-json_64bit-int-as-json.patch')
-rw-r--r--rubygem-protobuf-3.10.3-generate-camel-cased-keys_add-message-from-json_64bit-int-as-json.patch552
1 files changed, 552 insertions, 0 deletions
diff --git a/rubygem-protobuf-3.10.3-generate-camel-cased-keys_add-message-from-json_64bit-int-as-json.patch b/rubygem-protobuf-3.10.3-generate-camel-cased-keys_add-message-from-json_64bit-int-as-json.patch
new file mode 100644
index 0000000..bd0e11b
--- /dev/null
+++ b/rubygem-protobuf-3.10.3-generate-camel-cased-keys_add-message-from-json_64bit-int-as-json.patch
@@ -0,0 +1,552 @@
+diff --git a/lib/protobuf/field/bytes_field.rb b/lib/protobuf/field/bytes_field.rb
+index 81a3634..e120835 100644
+--- a/lib/protobuf/field/bytes_field.rb
++++ b/lib/protobuf/field/bytes_field.rb
+@@ -48,7 +48,18 @@ module Protobuf
+
+ def coerce!(value)
+ case value
+- when String, Symbol
++ when String
++ if value.encoding == Encoding::ASCII_8BIT
++ # This is a "binary" string
++ value
++ else
++ # Assume the value is Base64 encoded (from JSON)
++ # Ideally we'd do the Base64 decoding while processing the JSON,
++ # but this is tricky to do since we don't know the protobuf field
++ # types when we do that.
++ Base64.decode64(value)
++ end
++ when Symbol
+ value.to_s
+ when NilClass
+ nil
+@@ -59,7 +70,7 @@ module Protobuf
+ end
+ end
+
+- def json_encode(value)
++ def json_encode(value, options={})
+ Base64.strict_encode64(value)
+ end
+ end
+diff --git a/lib/protobuf/field/enum_field.rb b/lib/protobuf/field/enum_field.rb
+index 6993faf..12867ad 100644
+--- a/lib/protobuf/field/enum_field.rb
++++ b/lib/protobuf/field/enum_field.rb
+@@ -37,6 +37,11 @@ module Protobuf
+ type_class.fetch(value) || fail(TypeError, "Invalid Enum value: #{value.inspect} for #{name}")
+ end
+
++ def json_encode(value, options={})
++ enum = type_class.enums.find { |e| e.to_i == value }
++ enum.to_s(:name)
++ end
++
+ private
+
+ ##
+diff --git a/lib/protobuf/field/field_array.rb b/lib/protobuf/field/field_array.rb
+index e4f2eb1..47f9c37 100644
+--- a/lib/protobuf/field/field_array.rb
++++ b/lib/protobuf/field/field_array.rb
+@@ -49,14 +49,14 @@ module Protobuf
+ # Return a hash-representation of the given values for this field type
+ # that is safe to convert to JSON.
+ # The value in this case would be an array.
+- def to_json_hash_value
++ def to_json_hash_value(options = {})
+ if field.respond_to?(:json_encode)
+ map do |value|
+ field.json_encode(value)
+ end
+ else
+ map do |value|
+- value.respond_to?(:to_json_hash_value) ? value.to_json_hash_value : value
++ value.respond_to?(:to_json_hash_value) ? value.to_json_hash_value(options) : value
+ end
+ end
+ end
+@@ -81,6 +81,8 @@ module Protobuf
+
+ if field.is_a?(::Protobuf::Field::EnumField)
+ field.type_class.fetch(value)
++ elsif field.is_a?(::Protobuf::Field::BytesField)
++ field.coerce!(value)
+ elsif field.is_a?(::Protobuf::Field::MessageField) && value.is_a?(field.type_class)
+ value
+ elsif field.is_a?(::Protobuf::Field::MessageField) && value.respond_to?(:to_hash)
+diff --git a/lib/protobuf/field/field_hash.rb b/lib/protobuf/field/field_hash.rb
+index 36b2644..94eedbb 100644
+--- a/lib/protobuf/field/field_hash.rb
++++ b/lib/protobuf/field/field_hash.rb
+@@ -58,14 +58,14 @@ module Protobuf
+ # The value in this case would be the hash itself, right? Unfortunately
+ # not because the values of the map could be messages themselves that we
+ # need to transform.
+- def to_json_hash_value
++ def to_json_hash_value(options = {})
+ if field.respond_to?(:json_encode)
+ each_with_object({}) do |(key, value), hash|
+ hash[key] = field.json_encode(value)
+ end
+ else
+ each_with_object({}) do |(key, value), hash|
+- hash[key] = value.respond_to?(:to_json_hash_value) ? value.to_json_hash_value : value
++ hash[key] = value.respond_to?(:to_json_hash_value) ? value.to_json_hash_value(options) : value
+ end
+ end
+ end
+diff --git a/lib/protobuf/field/int64_field.rb b/lib/protobuf/field/int64_field.rb
+index 3b33889..f2597b2 100644
+--- a/lib/protobuf/field/int64_field.rb
++++ b/lib/protobuf/field/int64_field.rb
+@@ -29,6 +29,13 @@ module Protobuf
+ return false
+ end
+
++ def json_encode(value, options = {})
++ if options[:proto3]
++ value == 0 ? nil : value.to_s
++ else
++ value
++ end
++ end
+ end
+ end
+ end
+diff --git a/lib/protobuf/field/sint64_field.rb b/lib/protobuf/field/sint64_field.rb
+index 2aba7df..0c1c085 100644
+--- a/lib/protobuf/field/sint64_field.rb
++++ b/lib/protobuf/field/sint64_field.rb
+@@ -16,6 +16,13 @@ module Protobuf
+ INT64_MIN
+ end
+
++ def json_encode(value, options = {})
++ if options[:proto3]
++ value == 0 ? nil : value.to_s
++ else
++ value
++ end
++ end
+ end
+ end
+ end
+diff --git a/lib/protobuf/field/string_field.rb b/lib/protobuf/field/string_field.rb
+index 6c9c278..551bdd2 100644
+--- a/lib/protobuf/field/string_field.rb
++++ b/lib/protobuf/field/string_field.rb
+@@ -43,7 +43,7 @@ module Protobuf
+ "#{::Protobuf::Field::VarintField.encode(value_to_encode.bytesize)}#{value_to_encode}"
+ end
+
+- def json_encode(value)
++ def json_encode(value, options={})
+ value
+ end
+ end
+diff --git a/lib/protobuf/field/uint64_field.rb b/lib/protobuf/field/uint64_field.rb
+index 8a060f1..df041fc 100644
+--- a/lib/protobuf/field/uint64_field.rb
++++ b/lib/protobuf/field/uint64_field.rb
+@@ -16,6 +16,13 @@ module Protobuf
+ 0
+ end
+
++ def json_encode(value, options = {})
++ if options[:proto3]
++ value == 0 ? nil : value.to_s
++ else
++ value
++ end
++ end
+ end
+ end
+ end
+diff --git a/lib/protobuf/message.rb b/lib/protobuf/message.rb
+index a13c0d1..eca075d 100644
+--- a/lib/protobuf/message.rb
++++ b/lib/protobuf/message.rb
+@@ -21,6 +21,22 @@ module Protobuf
+ name
+ end
+
++ def self.from_json(json)
++ fields = normalize_json(JSON.parse(json))
++ new(fields)
++ end
++
++ def self.normalize_json(ob)
++ case ob
++ when Array
++ ob.map { |value| normalize_json(value) }
++ when Hash
++ Hash[*ob.flat_map { |key, value| [key.underscore, normalize_json(value)] }]
++ else
++ ob
++ end
++ end
++
+ ##
+ # Constructor
+ #
+@@ -134,29 +150,36 @@ module Protobuf
+ end
+
+ def to_json(options = {})
+- to_json_hash.to_json(options)
++ to_json_hash(options).to_json(options)
+ end
+
+ # Return a hash-representation of the given fields for this message type that
+ # is safe to convert to JSON.
+- def to_json_hash
++ def to_json_hash(options = {})
+ result = {}
+
++ proto3 = options[:proto3] || options[:lower_camel_case]
++
+ @values.each_key do |field_name|
+ value = self[field_name]
+ field = self.class.get_field(field_name, true)
+
+ # NB: to_json_hash_value should come before json_encode so as to handle
+ # repeated fields without extra logic.
+- hashed_value = if value.respond_to?(:to_json_hash_value)
+- value.to_json_hash_value
++ hashed_value = if value.respond_to?(:to_json_hash_value) && !field.is_a?(::Protobuf::Field::EnumField)
++ value.to_json_hash_value(options)
+ elsif field.respond_to?(:json_encode)
+- field.json_encode(value)
++ field.json_encode(value, options)
+ else
+ value
+ end
+
+- result[field.name] = hashed_value
++ if proto3 && (hashed_value.nil? || value == field.class.default)
++ result.delete(field.name)
++ else
++ key = proto3 ? field.name.to_s.camelize(:lower).to_sym : field.name
++ result[key] = hashed_value
++ end
+ end
+
+ result
+diff --git a/spec/encoding/all_types_spec.rb b/spec/encoding/all_types_spec.rb
+index fbd38b4..04ddb86 100644
+--- a/spec/encoding/all_types_spec.rb
++++ b/spec/encoding/all_types_spec.rb
+@@ -18,7 +18,7 @@ RSpec.describe ::Protobuf do
+ :optional_double => 112,
+ :optional_bool => true,
+ :optional_string => "115",
+- :optional_bytes => "116",
++ :optional_bytes => "116".force_encoding(Encoding::ASCII_8BIT),
+ :optional_nested_message => Protobuf_unittest::TestAllTypes::NestedMessage.new(:bb => 118),
+ :optional_foreign_message => Protobuf_unittest::ForeignMessage.new(:c => 119),
+ :optional_import_message => Protobuf_unittest_import::ImportMessage.new(:d => 120),
+@@ -43,7 +43,7 @@ RSpec.describe ::Protobuf do
+ :repeated_double => [212, 312],
+ :repeated_bool => [true, false],
+ :repeated_string => ["215", "315"],
+- :repeated_bytes => ["216", "316"],
++ :repeated_bytes => ["216".force_encoding(Encoding::ASCII_8BIT), "316".force_encoding(Encoding::ASCII_8BIT)],
+ :repeated_nested_message => [
+ ::Protobuf_unittest::TestAllTypes::NestedMessage.new(:bb => 218),
+ ::Protobuf_unittest::TestAllTypes::NestedMessage.new(:bb => 318),
+@@ -88,7 +88,7 @@ RSpec.describe ::Protobuf do
+ :default_double => 412,
+ :default_bool => false,
+ :default_string => "415",
+- :default_bytes => "416",
++ :default_bytes => "416".force_encoding(Encoding::ASCII_8BIT),
+ :default_nested_enum => ::Protobuf_unittest::TestAllTypes::NestedEnum::FOO,
+ :default_foreign_enum => ::Protobuf_unittest::ForeignEnum::FOREIGN_FOO,
+ :default_import_enum => ::Protobuf_unittest_import::ImportEnum::IMPORT_FOO,
+diff --git a/spec/encoding/extreme_values_spec.rb b/spec/encoding/extreme_values_spec.rb
+index 477e695..7f3d516 100644
+Binary files a/spec/encoding/extreme_values_spec.rb and b/spec/encoding/extreme_values_spec.rb differ
+diff --git a/spec/lib/protobuf/field/enum_field_spec.rb b/spec/lib/protobuf/field/enum_field_spec.rb
+index cd72760..c2e04ee 100644
+--- a/spec/lib/protobuf/field/enum_field_spec.rb
++++ b/spec/lib/protobuf/field/enum_field_spec.rb
+@@ -23,4 +23,22 @@ RSpec.describe Protobuf::Field::EnumField do
+ expect(message.decode(instance.encode).enum).to eq(-33)
+ end
+ end
++
++ # https://developers.google.com/protocol-buffers/docs/proto3#json
++ describe '.{to_json, from_json}' do
++ it 'serialises enum value as string' do
++ instance = message.new(:enum => :POSITIVE)
++ expect(instance.to_json).to eq('{"enum":"POSITIVE"}')
++ end
++
++ it 'deserialises enum value as integer' do
++ instance = message.from_json('{"enum":22}')
++ expect(instance.enum).to eq(22)
++ end
++
++ it 'deserialises enum value as string' do
++ instance = message.from_json('{"enum":"NEGATIVE"}')
++ expect(instance.enum).to eq(-33)
++ end
++ end
+ end
+diff --git a/spec/lib/protobuf/field/fixed64_field_spec.rb b/spec/lib/protobuf/field/fixed64_field_spec.rb
+index d7feb12..00ad743 100644
+--- a/spec/lib/protobuf/field/fixed64_field_spec.rb
++++ b/spec/lib/protobuf/field/fixed64_field_spec.rb
+@@ -4,4 +4,30 @@ RSpec.describe Protobuf::Field::Fixed64Field do
+
+ it_behaves_like :packable_field, described_class
+
++ let(:message) do
++ Class.new(::Protobuf::Message) do
++ optional :fixed64, :some_field, 1
++ end
++ end
++
++ # https://developers.google.com/protocol-buffers/docs/proto3#json
++ describe '.{to_json, from_json}' do
++ it 'serialises 0' do
++ instance = message.new(some_field: 0)
++ expect(instance.to_json(proto3: true)).to eq('{}')
++ expect(instance.to_json).to eq('{"some_field":0}')
++ end
++
++ it 'serialises max value' do
++ instance = message.new(some_field: described_class.max)
++ expect(instance.to_json(proto3: true)).to eq('{"someField":"18446744073709551615"}')
++ expect(instance.to_json).to eq('{"some_field":18446744073709551615}')
++ end
++
++ it 'serialises min value' do
++ instance = message.new(some_field: described_class.min)
++ expect(instance.to_json(proto3: true)).to eq('{}')
++ expect(instance.to_json).to eq('{"some_field":0}')
++ end
++ end
+ end
+diff --git a/spec/lib/protobuf/field/int64_field_spec.rb b/spec/lib/protobuf/field/int64_field_spec.rb
+index 1bbe7c0..d0c77d3 100644
+--- a/spec/lib/protobuf/field/int64_field_spec.rb
++++ b/spec/lib/protobuf/field/int64_field_spec.rb
+@@ -4,4 +4,30 @@ RSpec.describe Protobuf::Field::Int64Field do
+
+ it_behaves_like :packable_field, described_class
+
++ let(:message) do
++ Class.new(::Protobuf::Message) do
++ optional :int64, :some_field, 1
++ end
++ end
++
++ # https://developers.google.com/protocol-buffers/docs/proto3#json
++ describe '.{to_json, from_json}' do
++ it 'serialises 0' do
++ instance = message.new(some_field: 0)
++ expect(instance.to_json(proto3: true)).to eq('{}')
++ expect(instance.to_json).to eq('{"some_field":0}')
++ end
++
++ it 'serialises max value' do
++ instance = message.new(some_field: described_class.max)
++ expect(instance.to_json(proto3: true)).to eq('{"someField":"9223372036854775807"}')
++ expect(instance.to_json).to eq('{"some_field":9223372036854775807}')
++ end
++
++ it 'serialises min value' do
++ instance = message.new(some_field: described_class.min)
++ expect(instance.to_json(proto3: true)).to eq('{"someField":"-9223372036854775808"}')
++ expect(instance.to_json).to eq('{"some_field":-9223372036854775808}')
++ end
++ end
+ end
+diff --git a/spec/lib/protobuf/field/sfixed64_field_spec.rb b/spec/lib/protobuf/field/sfixed64_field_spec.rb
+index f380ed5..7988f45 100644
+--- a/spec/lib/protobuf/field/sfixed64_field_spec.rb
++++ b/spec/lib/protobuf/field/sfixed64_field_spec.rb
+@@ -6,4 +6,30 @@ RSpec.describe Protobuf::Field::Sfixed64Field do
+ let(:value) { [-1, 0, 1] }
+ end
+
++ let(:message) do
++ Class.new(::Protobuf::Message) do
++ optional :sfixed64, :some_field, 1
++ end
++ end
++
++ # https://developers.google.com/protocol-buffers/docs/proto3#json
++ describe '.{to_json, from_json}' do
++ it 'serialises 0' do
++ instance = message.new(some_field: 0)
++ expect(instance.to_json(proto3: true)).to eq('{}')
++ expect(instance.to_json).to eq('{"some_field":0}')
++ end
++
++ it 'serialises max value' do
++ instance = message.new(some_field: described_class.max)
++ expect(instance.to_json(proto3: true)).to eq('{"someField":"9223372036854775807"}')
++ expect(instance.to_json).to eq('{"some_field":9223372036854775807}')
++ end
++
++ it 'serialises min value as string' do
++ instance = message.new(some_field: described_class.min)
++ expect(instance.to_json(proto3: true)).to eq('{"someField":"-9223372036854775808"}')
++ expect(instance.to_json).to eq('{"some_field":-9223372036854775808}')
++ end
++ end
+ end
+diff --git a/spec/lib/protobuf/field/sint64_field_spec.rb b/spec/lib/protobuf/field/sint64_field_spec.rb
+index 84ca730..e6fc05f 100644
+--- a/spec/lib/protobuf/field/sint64_field_spec.rb
++++ b/spec/lib/protobuf/field/sint64_field_spec.rb
+@@ -6,4 +6,30 @@ RSpec.describe Protobuf::Field::Sint64Field do
+ let(:value) { [-1, 0, 1] }
+ end
+
++ let(:message) do
++ Class.new(::Protobuf::Message) do
++ optional :sint64, :some_field, 1
++ end
++ end
++
++ # https://developers.google.com/protocol-buffers/docs/proto3#json
++ describe '.{to_json, from_json}' do
++ it 'serialises 0' do
++ instance = message.new(some_field: 0)
++ expect(instance.to_json(proto3: true)).to eq('{}')
++ expect(instance.to_json).to eq('{"some_field":0}')
++ end
++
++ it 'serialises max value as string' do
++ instance = message.new(some_field: described_class.max)
++ expect(instance.to_json(proto3: true)).to eq('{"someField":"9223372036854775807"}')
++ expect(instance.to_json).to eq('{"some_field":9223372036854775807}')
++ end
++
++ it 'serialises min value as string' do
++ instance = message.new(some_field: described_class.min)
++ expect(instance.to_json(proto3: true)).to eq('{"someField":"-9223372036854775808"}')
++ expect(instance.to_json).to eq('{"some_field":-9223372036854775808}')
++ end
++ end
+ end
+diff --git a/spec/lib/protobuf/field/uint64_field_spec.rb b/spec/lib/protobuf/field/uint64_field_spec.rb
+index 61b8d1b..90bc030 100644
+--- a/spec/lib/protobuf/field/uint64_field_spec.rb
++++ b/spec/lib/protobuf/field/uint64_field_spec.rb
+@@ -4,4 +4,30 @@ RSpec.describe Protobuf::Field::Uint64Field do
+
+ it_behaves_like :packable_field, described_class
+
++ let(:message) do
++ Class.new(::Protobuf::Message) do
++ optional :uint64, :some_field, 1
++ end
++ end
++
++ # https://developers.google.com/protocol-buffers/docs/proto3#json
++ describe '.{to_json, from_json}' do
++ it 'serialises 0' do
++ instance = message.new(some_field: 0)
++ expect(instance.to_json(proto3: true)).to eq('{}')
++ expect(instance.to_json).to eq('{"some_field":0}')
++ end
++
++ it 'serialises max value' do
++ instance = message.new(some_field: described_class.max)
++ expect(instance.to_json(proto3: true)).to eq('{"someField":"18446744073709551615"}')
++ expect(instance.to_json).to eq('{"some_field":18446744073709551615}')
++ end
++
++ it 'serialises min value' do
++ instance = message.new(some_field: described_class.min)
++ expect(instance.to_json(proto3: true)).to eq('{}')
++ expect(instance.to_json).to eq('{"some_field":0}')
++ end
++ end
+ end
+diff --git a/spec/lib/protobuf/message_spec.rb b/spec/lib/protobuf/message_spec.rb
+index 96668b6..cd49753 100644
+--- a/spec/lib/protobuf/message_spec.rb
++++ b/spec/lib/protobuf/message_spec.rb
+@@ -429,7 +429,7 @@ RSpec.describe Protobuf::Message do
+ specify { expect(subject.to_json).to eq '{"name":"Test Name","active":false}' }
+
+ context 'for byte fields' do
+- let(:bytes) { "\x06\x8D1HP\x17:b" }
++ let(:bytes) { "\x06\x8D1HP\x17:b".force_encoding(Encoding::ASCII_8BIT) }
+
+ subject do
+ ::Test::ResourceFindRequest.new(:widget_bytes => [bytes])
+@@ -437,6 +437,36 @@ RSpec.describe Protobuf::Message do
+
+ specify { expect(subject.to_json).to eq '{"widget_bytes":["Bo0xSFAXOmI="]}' }
+ end
++
++ context 'using lower camel case field names' do
++ let(:bytes) { "\x06\x8D1HP\x17:b".force_encoding(Encoding::ASCII_8BIT) }
++
++ subject do
++ ::Test::ResourceFindRequest.new(:widget_bytes => [bytes])
++ end
++
++ specify { expect(subject.to_json(:proto3 => true)).to eq '{"widgetBytes":["Bo0xSFAXOmI="]}' }
++ end
++ end
++
++ describe '.from_json' do
++ it 'decodes optional bytes field with base64' do
++ expected_single_bytes = "\x06\x8D1HP\x17:b".unpack('C*')
++ single_bytes = ::Test::ResourceFindRequest
++ .from_json('{"singleBytes":"Bo0xSFAXOmI="}')
++ .single_bytes.unpack('C*')
++
++ expect(single_bytes).to(eq(expected_single_bytes))
++ end
++
++ it 'decodes repeated bytes field with base64' do
++ expected_widget_bytes = ["\x06\x8D1HP\x17:b"].map { |s| s.unpack('C*') }
++ widget_bytes = ::Test::ResourceFindRequest
++ .from_json('{"widgetBytes":["Bo0xSFAXOmI="]}')
++ .widget_bytes.map { |s| s.unpack('C*') }
++
++ expect(widget_bytes).to(eq(expected_widget_bytes))
++ end
+ end
+
+ describe '.to_json' do
+diff --git a/spec/support/protos/resource.pb.rb b/spec/support/protos/resource.pb.rb
+index f81ef52..e765b1c 100644
+--- a/spec/support/protos/resource.pb.rb
++++ b/spec/support/protos/resource.pb.rb
+@@ -72,6 +72,7 @@ module Test
+ optional :bool, :active, 2
+ repeated :string, :widgets, 3
+ repeated :bytes, :widget_bytes, 4
++ optional :bytes, :single_bytes, 5
+ end
+
+ class ResourceSleepRequest
+@@ -169,4 +170,3 @@ module Test
+ end
+
+ end
+-
+diff --git a/spec/support/protos/resource.proto b/spec/support/protos/resource.proto
+index 70b338b..a5573e2 100644
+--- a/spec/support/protos/resource.proto
++++ b/spec/support/protos/resource.proto
+@@ -47,6 +47,7 @@ message ResourceFindRequest {
+ optional bool active = 2;
+ repeated string widgets = 3;
+ repeated bytes widget_bytes = 4;
++ optional bytes single_bytes = 5;
+ }
+
+ message ResourceSleepRequest {