From c9974cd828932167068c8930987a066c31387a89 Mon Sep 17 00:00:00 2001 From: Bo Anderson Date: Wed, 29 Nov 2023 15:18:14 +0000 Subject: [PATCH] Vendor Ruby 3.1 gems --- .gitignore | 4 +- Library/Homebrew/standalone/init.rb | 12 +- .../gems/activesupport-6.1.7.6/MIT-LICENSE | 20 + .../active_support/core_ext/array/access.rb | 104 + .../lib/active_support/core_ext/enumerable.rb | 260 + .../active_support/core_ext/file/atomic.rb | 70 + .../core_ext/hash/deep_merge.rb | 34 + .../core_ext/hash/deep_transform_values.rb | 46 + .../active_support/core_ext/hash/except.rb | 24 + .../lib/active_support/core_ext/hash/keys.rb | 143 + .../lib/active_support/core_ext/hash/slice.rb | 27 + .../core_ext/object/deep_dup.rb | 55 + .../core_ext/object/duplicable.rb | 49 + .../active_support/core_ext/string/exclude.rb | 13 + .../active_support/core_ext/string/filters.rb | 145 + .../active_support/core_ext/string/indent.rb | 45 + .../3.1.0/gems/addressable-2.8.5/LICENSE.txt | 202 + .../gems/addressable-2.8.5/data/unicode.data | Bin 0 -> 115740 bytes .../gems/addressable-2.8.5/lib/addressable.rb | 4 + .../addressable-2.8.5/lib/addressable/idna.rb | 26 + .../lib/addressable/idna/native.rb | 66 + .../lib/addressable/idna/pure.rb | 505 + .../lib/addressable/template.rb | 1029 ++ .../addressable-2.8.5/lib/addressable/uri.rb | 2591 +++ .../lib/addressable/version.rb | 31 + .../ruby/3.1.0/gems/bindata-2.4.15/LICENSE | 25 + .../3.1.0/gems/bindata-2.4.15/lib/bindata.rb | 37 + .../bindata-2.4.15/lib/bindata/alignment.rb | 79 + .../gems/bindata-2.4.15/lib/bindata/array.rb | 344 + .../gems/bindata-2.4.15/lib/bindata/base.rb | 335 + .../lib/bindata/base_primitive.rb | 248 + .../gems/bindata-2.4.15/lib/bindata/bits.rb | 186 + .../gems/bindata-2.4.15/lib/bindata/buffer.rb | 117 + .../gems/bindata-2.4.15/lib/bindata/choice.rb | 186 + .../lib/bindata/count_bytes_remaining.rb | 34 + .../bindata-2.4.15/lib/bindata/delayed_io.rb | 198 + .../gems/bindata-2.4.15/lib/bindata/dsl.rb | 484 + .../gems/bindata-2.4.15/lib/bindata/float.rb | 83 + .../bindata-2.4.15/lib/bindata/framework.rb | 75 + .../gems/bindata-2.4.15/lib/bindata/int.rb | 212 + .../gems/bindata-2.4.15/lib/bindata/io.rb | 496 + .../gems/bindata-2.4.15/lib/bindata/lazy.rb | 109 + .../gems/bindata-2.4.15/lib/bindata/name.rb | 28 + .../gems/bindata-2.4.15/lib/bindata/offset.rb | 94 + .../gems/bindata-2.4.15/lib/bindata/params.rb | 128 + .../bindata-2.4.15/lib/bindata/primitive.rb | 143 + .../gems/bindata-2.4.15/lib/bindata/record.rb | 23 + .../bindata-2.4.15/lib/bindata/registry.rb | 134 + .../gems/bindata-2.4.15/lib/bindata/rest.rb | 34 + .../bindata-2.4.15/lib/bindata/sanitize.rb | 372 + .../gems/bindata-2.4.15/lib/bindata/skip.rb | 133 + .../gems/bindata-2.4.15/lib/bindata/string.rb | 153 + .../bindata-2.4.15/lib/bindata/stringz.rb | 96 + .../gems/bindata-2.4.15/lib/bindata/struct.rb | 422 + .../gems/bindata-2.4.15/lib/bindata/trace.rb | 95 + .../bindata-2.4.15/lib/bindata/uint8_array.rb | 62 + .../bindata-2.4.15/lib/bindata/version.rb | 3 + .../bindata-2.4.15/lib/bindata/virtual.rb | 47 + .../bindata-2.4.15/lib/bindata/warnings.rb | 36 + .../3.1.0/gems/elftools-1.2.0/lib/elftools.rb | 11 + .../elftools-1.2.0/lib/elftools/constants.rb | 722 + .../elftools-1.2.0/lib/elftools/dynamic.rb | 178 + .../elftools-1.2.0/lib/elftools/elf_file.rb | 377 + .../elftools-1.2.0/lib/elftools/exceptions.rb | 15 + .../elftools-1.2.0/lib/elftools/lazy_array.rb | 49 + .../gems/elftools-1.2.0/lib/elftools/note.rb | 125 + .../lib/elftools/sections/dynamic_section.rb | 22 + .../lib/elftools/sections/note_section.rb | 27 + .../lib/elftools/sections/null_section.rb | 18 + .../elftools/sections/relocation_section.rb | 109 + .../lib/elftools/sections/section.rb | 56 + .../lib/elftools/sections/sections.rb | 38 + .../lib/elftools/sections/str_tab_section.rb | 21 + .../lib/elftools/sections/sym_tab_section.rb | 127 + .../lib/elftools/segments/dynamic_segment.rb | 20 + .../lib/elftools/segments/interp_segment.rb | 20 + .../lib/elftools/segments/load_segment.rb | 91 + .../lib/elftools/segments/note_segment.rb | 26 + .../lib/elftools/segments/segment.rb | 56 + .../lib/elftools/segments/segments.rb | 34 + .../elftools-1.2.0/lib/elftools/structs.rb | 219 + .../gems/elftools-1.2.0/lib/elftools/util.rb | 99 + .../elftools-1.2.0/lib/elftools/version.rb | 6 + .../3.1.0/gems/patchelf-1.4.0/lib/patchelf.rb | 10 + .../patchelf-1.4.0/lib/patchelf/alt_saver.rb | 1052 ++ .../gems/patchelf-1.4.0/lib/patchelf/cli.rb | 148 + .../patchelf-1.4.0/lib/patchelf/exceptions.rb | 15 + .../patchelf-1.4.0/lib/patchelf/helper.rb | 84 + .../patchelf-1.4.0/lib/patchelf/logger.rb | 25 + .../gems/patchelf-1.4.0/lib/patchelf/mm.rb | 186 + .../patchelf-1.4.0/lib/patchelf/patcher.rb | 250 + .../gems/patchelf-1.4.0/lib/patchelf/saver.rb | 282 + .../patchelf-1.4.0/lib/patchelf/version.rb | 6 + .../ruby/3.1.0/gems/plist-3.7.0/LICENSE.txt | 20 + .../ruby/3.1.0/gems/plist-3.7.0/lib/plist.rb | 18 + .../gems/plist-3.7.0/lib/plist/generator.rb | 180 + .../gems/plist-3.7.0/lib/plist/parser.rb | 263 + .../gems/plist-3.7.0/lib/plist/version.rb | 5 + .../gems/public_suffix-5.0.4/LICENSE.txt | 22 + .../gems/public_suffix-5.0.4/data/list.txt | 15431 ++++++++++++++++ .../public_suffix-5.0.4/lib/public_suffix.rb | 177 + .../lib/public_suffix/domain.rb | 235 + .../lib/public_suffix/errors.rb | 41 + .../lib/public_suffix/list.rb | 247 + .../lib/public_suffix/rule.rb | 350 + .../lib/public_suffix/version.rb | 14 + .../ruby/3.1.0/gems/ruby-macho-4.0.0/LICENSE | 21 + .../3.1.0/gems/ruby-macho-4.0.0/lib/macho.rb | 61 + .../ruby-macho-4.0.0/lib/macho/exceptions.rb | 242 + .../ruby-macho-4.0.0/lib/macho/fat_file.rb | 440 + .../ruby-macho-4.0.0/lib/macho/headers.rb | 793 + .../lib/macho/load_commands.rb | 1378 ++ .../ruby-macho-4.0.0/lib/macho/macho_file.rb | 652 + .../ruby-macho-4.0.0/lib/macho/sections.rb | 216 + .../ruby-macho-4.0.0/lib/macho/structure.rb | 284 + .../gems/ruby-macho-4.0.0/lib/macho/tools.rb | 115 + .../gems/ruby-macho-4.0.0/lib/macho/utils.rb | 132 + .../gems/ruby-macho-4.0.0/lib/macho/view.rb | 42 + .../lib/sorbet-runtime.rb | 116 + .../lib/types/_types.rb | 316 + .../lib/types/abstract_utils.rb | 50 + .../lib/types/boolean.rb | 8 + .../lib/types/compatibility_patches.rb | 93 + .../lib/types/configuration.rb | 591 + .../lib/types/enum.rb | 377 + .../lib/types/generic.rb | 22 + .../lib/types/helpers.rb | 65 + .../lib/types/interface_wrapper.rb | 162 + .../lib/types/non_forcing_constants.rb | 65 + .../lib/types/private/abstract/data.rb | 36 + .../lib/types/private/abstract/declare.rb | 53 + .../lib/types/private/abstract/hooks.rb | 42 + .../lib/types/private/abstract/validate.rb | 128 + .../lib/types/private/casts.rb | 41 + .../lib/types/private/class_utils.rb | 127 + .../lib/types/private/compiler.rb | 24 + .../lib/types/private/decl_state.rb | 30 + .../lib/types/private/final.rb | 50 + .../lib/types/private/methods/_methods.rb | 581 + .../types/private/methods/call_validation.rb | 217 + .../private/methods/call_validation_2_6.rb | 1203 ++ .../private/methods/call_validation_2_7.rb | 1203 ++ .../lib/types/private/methods/decl_builder.rb | 232 + .../lib/types/private/methods/modes.rb | 28 + .../lib/types/private/methods/signature.rb | 225 + .../private/methods/signature_validation.rb | 225 + .../lib/types/private/mixins/mixins.rb | 27 + .../lib/types/private/retry.rb | 10 + .../lib/types/private/runtime_levels.rb | 62 + .../lib/types/private/sealed.rb | 91 + .../lib/types/private/types/not_typed.rb | 23 + .../lib/types/private/types/string_holder.rb | 26 + .../lib/types/private/types/type_alias.rb | 31 + .../lib/types/private/types/void.rb | 34 + .../lib/types/props/_props.rb | 169 + .../lib/types/props/constructor.rb | 40 + .../lib/types/props/custom_type.rb | 108 + .../lib/types/props/decorator.rb | 671 + .../lib/types/props/errors.rb | 8 + .../types/props/generated_code_validation.rb | 277 + .../props/has_lazily_specialized_methods.rb | 140 + .../lib/types/props/optional.rb | 89 + .../lib/types/props/plugin.rb | 37 + .../lib/types/props/pretty_printable.rb | 107 + .../lib/types/props/private/apply_default.rb | 170 + .../props/private/deserializer_generator.rb | 160 + .../lib/types/props/private/parser.rb | 32 + .../types/props/private/serde_transform.rb | 186 + .../props/private/serializer_generator.rb | 76 + .../lib/types/props/private/setter_factory.rb | 197 + .../lib/types/props/serializable.rb | 374 + .../lib/types/props/type_validation.rb | 111 + .../lib/types/props/utils.rb | 59 + .../lib/types/props/weak_constructor.rb | 67 + .../sorbet-runtime-0.5.10461/lib/types/sig.rb | 30 + .../lib/types/struct.rb | 51 + .../lib/types/types/attached_class.rb | 37 + .../lib/types/types/base.rb | 172 + .../lib/types/types/class_of.rb | 40 + .../lib/types/types/enum.rb | 40 + .../lib/types/types/fixed_array.rb | 86 + .../lib/types/types/fixed_hash.rb | 74 + .../lib/types/types/intersection.rb | 42 + .../lib/types/types/noreturn.rb | 29 + .../lib/types/types/proc.rb | 51 + .../lib/types/types/self_type.rb | 35 + .../lib/types/types/simple.rb | 94 + .../lib/types/types/t_enum.rb | 38 + .../lib/types/types/type_member.rb | 7 + .../lib/types/types/type_parameter.rb | 23 + .../lib/types/types/type_template.rb | 7 + .../lib/types/types/type_variable.rb | 34 + .../lib/types/types/typed_array.rb | 39 + .../lib/types/types/typed_enumerable.rb | 176 + .../lib/types/types/typed_enumerator.rb | 41 + .../lib/types/types/typed_enumerator_lazy.rb | 41 + .../lib/types/types/typed_hash.rb | 48 + .../lib/types/types/typed_range.rb | 31 + .../lib/types/types/typed_set.rb | 53 + .../lib/types/types/union.rb | 91 + .../lib/types/types/untyped.rb | 29 + .../lib/types/utils.rb | 209 + .../ruby/3.1.0/gems/warning-1.3.0/MIT-LICENSE | 18 + .../3.1.0/gems/warning-1.3.0/lib/warning.rb | 296 + 204 files changed, 48307 insertions(+), 6 deletions(-) create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/activesupport-6.1.7.6/MIT-LICENSE create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/activesupport-6.1.7.6/lib/active_support/core_ext/array/access.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/activesupport-6.1.7.6/lib/active_support/core_ext/enumerable.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/activesupport-6.1.7.6/lib/active_support/core_ext/file/atomic.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/activesupport-6.1.7.6/lib/active_support/core_ext/hash/deep_merge.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/activesupport-6.1.7.6/lib/active_support/core_ext/hash/deep_transform_values.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/activesupport-6.1.7.6/lib/active_support/core_ext/hash/except.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/activesupport-6.1.7.6/lib/active_support/core_ext/hash/keys.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/activesupport-6.1.7.6/lib/active_support/core_ext/hash/slice.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/activesupport-6.1.7.6/lib/active_support/core_ext/object/deep_dup.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/activesupport-6.1.7.6/lib/active_support/core_ext/object/duplicable.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/activesupport-6.1.7.6/lib/active_support/core_ext/string/exclude.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/activesupport-6.1.7.6/lib/active_support/core_ext/string/filters.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/activesupport-6.1.7.6/lib/active_support/core_ext/string/indent.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/addressable-2.8.5/LICENSE.txt create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/addressable-2.8.5/data/unicode.data create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/addressable-2.8.5/lib/addressable.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/addressable-2.8.5/lib/addressable/idna.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/addressable-2.8.5/lib/addressable/idna/native.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/addressable-2.8.5/lib/addressable/idna/pure.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/addressable-2.8.5/lib/addressable/template.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/addressable-2.8.5/lib/addressable/uri.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/addressable-2.8.5/lib/addressable/version.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/LICENSE create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/alignment.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/array.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/base.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/base_primitive.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/bits.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/buffer.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/choice.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/count_bytes_remaining.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/delayed_io.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/dsl.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/float.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/framework.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/int.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/io.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/lazy.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/name.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/offset.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/params.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/primitive.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/record.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/registry.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/rest.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/sanitize.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/skip.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/string.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/stringz.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/struct.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/trace.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/uint8_array.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/version.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/virtual.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/warnings.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/constants.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/dynamic.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/elf_file.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/exceptions.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/lazy_array.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/note.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/sections/dynamic_section.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/sections/note_section.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/sections/null_section.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/sections/relocation_section.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/sections/section.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/sections/sections.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/sections/str_tab_section.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/sections/sym_tab_section.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/segments/dynamic_segment.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/segments/interp_segment.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/segments/load_segment.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/segments/note_segment.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/segments/segment.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/segments/segments.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/structs.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/util.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/version.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/patchelf-1.4.0/lib/patchelf.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/patchelf-1.4.0/lib/patchelf/alt_saver.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/patchelf-1.4.0/lib/patchelf/cli.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/patchelf-1.4.0/lib/patchelf/exceptions.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/patchelf-1.4.0/lib/patchelf/helper.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/patchelf-1.4.0/lib/patchelf/logger.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/patchelf-1.4.0/lib/patchelf/mm.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/patchelf-1.4.0/lib/patchelf/patcher.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/patchelf-1.4.0/lib/patchelf/saver.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/patchelf-1.4.0/lib/patchelf/version.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/plist-3.7.0/LICENSE.txt create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/plist-3.7.0/lib/plist.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/plist-3.7.0/lib/plist/generator.rb create mode 100755 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/plist-3.7.0/lib/plist/parser.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/plist-3.7.0/lib/plist/version.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/public_suffix-5.0.4/LICENSE.txt create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/public_suffix-5.0.4/data/list.txt create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/public_suffix-5.0.4/lib/public_suffix.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/public_suffix-5.0.4/lib/public_suffix/domain.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/public_suffix-5.0.4/lib/public_suffix/errors.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/public_suffix-5.0.4/lib/public_suffix/list.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/public_suffix-5.0.4/lib/public_suffix/rule.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/public_suffix-5.0.4/lib/public_suffix/version.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/ruby-macho-4.0.0/LICENSE create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/ruby-macho-4.0.0/lib/macho.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/ruby-macho-4.0.0/lib/macho/exceptions.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/ruby-macho-4.0.0/lib/macho/fat_file.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/ruby-macho-4.0.0/lib/macho/headers.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/ruby-macho-4.0.0/lib/macho/load_commands.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/ruby-macho-4.0.0/lib/macho/macho_file.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/ruby-macho-4.0.0/lib/macho/sections.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/ruby-macho-4.0.0/lib/macho/structure.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/ruby-macho-4.0.0/lib/macho/tools.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/ruby-macho-4.0.0/lib/macho/utils.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/ruby-macho-4.0.0/lib/macho/view.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/sorbet-runtime.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/_types.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/abstract_utils.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/boolean.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/compatibility_patches.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/configuration.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/enum.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/generic.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/helpers.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/interface_wrapper.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/non_forcing_constants.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/abstract/data.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/abstract/declare.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/abstract/hooks.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/abstract/validate.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/casts.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/class_utils.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/compiler.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/decl_state.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/final.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/methods/_methods.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/methods/call_validation.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/methods/call_validation_2_6.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/methods/call_validation_2_7.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/methods/decl_builder.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/methods/modes.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/methods/signature.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/methods/signature_validation.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/mixins/mixins.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/retry.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/runtime_levels.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/sealed.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/types/not_typed.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/types/string_holder.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/types/type_alias.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/types/void.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/props/_props.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/props/constructor.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/props/custom_type.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/props/decorator.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/props/errors.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/props/generated_code_validation.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/props/has_lazily_specialized_methods.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/props/optional.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/props/plugin.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/props/pretty_printable.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/props/private/apply_default.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/props/private/deserializer_generator.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/props/private/parser.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/props/private/serde_transform.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/props/private/serializer_generator.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/props/private/setter_factory.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/props/serializable.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/props/type_validation.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/props/utils.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/props/weak_constructor.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/sig.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/struct.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/attached_class.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/base.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/class_of.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/enum.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/fixed_array.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/fixed_hash.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/intersection.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/noreturn.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/proc.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/self_type.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/simple.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/t_enum.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/type_member.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/type_parameter.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/type_template.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/type_variable.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/typed_array.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/typed_enumerable.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/typed_enumerator.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/typed_enumerator_lazy.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/typed_hash.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/typed_range.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/typed_set.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/union.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/untyped.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/utils.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/warning-1.3.0/MIT-LICENSE create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/warning-1.3.0/lib/warning.rb diff --git a/.gitignore b/.gitignore index 1e87ae707b..e7f8f33dc4 100644 --- a/.gitignore +++ b/.gitignore @@ -37,9 +37,11 @@ **/vendor/bundle/ruby/*/plugins **/vendor/bundle/ruby/*/specifications -# Ignore Ruby gems for versions other than we explicitly vendor +# Ignore Ruby gems for versions other than we explicitly vendor. +# Keep this in sync with the list in standalone/init.rb. **/vendor/bundle/ruby/*/ !**/vendor/bundle/ruby/2.6.0/ +!**/vendor/bundle/ruby/3.1.0/ # Ignore Bundler binary files **/vendor/bundle/ruby/*/gems/**/*.bundle diff --git a/Library/Homebrew/standalone/init.rb b/Library/Homebrew/standalone/init.rb index dec9939945..709fd4251a 100644 --- a/Library/Homebrew/standalone/init.rb +++ b/Library/Homebrew/standalone/init.rb @@ -4,9 +4,9 @@ # This file is included before any other files. It intentionally has typing disabled and has minimal use of `require`. required_ruby_major, required_ruby_minor, = ENV.fetch("HOMEBREW_REQUIRED_RUBY_VERSION", "").split(".").map(&:to_i) -unsupported_ruby = if required_ruby_minor.nil? - # We're probably only running rubocop etc so just assume supported - false +gems_vendored = if required_ruby_minor.nil? + # We're likely here if running RuboCop etc, so just assume we don't need to install gems as we likely already have + true else ruby_major, ruby_minor, = RUBY_VERSION.split(".").map(&:to_i) if ruby_major < required_ruby_major || (ruby_major == required_ruby_major && ruby_minor < required_ruby_minor) @@ -14,7 +14,9 @@ else "You're running #{RUBY_VERSION}." end - ruby_major != required_ruby_major || ruby_minor != required_ruby_minor + # This list should match .gitignore + vendored_versions = ["2.6", "3.1"].freeze + vendored_versions.include?("#{ruby_major}.#{ruby_minor}") end.freeze # We trust base Ruby to provide what we need. @@ -29,7 +31,7 @@ require_relative "../utils/gems" Homebrew.setup_gem_environment!(setup_path: false) # Install gems for Rubies we don't vendor for. -if unsupported_ruby && !ENV["HOMEBREW_SKIP_INITIAL_GEM_INSTALL"] +if !gems_vendored && !ENV["HOMEBREW_SKIP_INITIAL_GEM_INSTALL"] Homebrew.install_bundler_gems!(setup_path: false) ENV["HOMEBREW_SKIP_INITIAL_GEM_INSTALL"] = "1" end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/activesupport-6.1.7.6/MIT-LICENSE b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/activesupport-6.1.7.6/MIT-LICENSE new file mode 100644 index 0000000000..0a0ce3889a --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/activesupport-6.1.7.6/MIT-LICENSE @@ -0,0 +1,20 @@ +Copyright (c) 2005-2022 David Heinemeier Hansson + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/activesupport-6.1.7.6/lib/active_support/core_ext/array/access.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/activesupport-6.1.7.6/lib/active_support/core_ext/array/access.rb new file mode 100644 index 0000000000..ea01e5891c --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/activesupport-6.1.7.6/lib/active_support/core_ext/array/access.rb @@ -0,0 +1,104 @@ +# frozen_string_literal: true + +class Array + # Returns the tail of the array from +position+. + # + # %w( a b c d ).from(0) # => ["a", "b", "c", "d"] + # %w( a b c d ).from(2) # => ["c", "d"] + # %w( a b c d ).from(10) # => [] + # %w().from(0) # => [] + # %w( a b c d ).from(-2) # => ["c", "d"] + # %w( a b c ).from(-10) # => [] + def from(position) + self[position, length] || [] + end + + # Returns the beginning of the array up to +position+. + # + # %w( a b c d ).to(0) # => ["a"] + # %w( a b c d ).to(2) # => ["a", "b", "c"] + # %w( a b c d ).to(10) # => ["a", "b", "c", "d"] + # %w().to(0) # => [] + # %w( a b c d ).to(-2) # => ["a", "b", "c"] + # %w( a b c ).to(-10) # => [] + def to(position) + if position >= 0 + take position + 1 + else + self[0..position] + end + end + + # Returns a new array that includes the passed elements. + # + # [ 1, 2, 3 ].including(4, 5) # => [ 1, 2, 3, 4, 5 ] + # [ [ 0, 1 ] ].including([ [ 1, 0 ] ]) # => [ [ 0, 1 ], [ 1, 0 ] ] + def including(*elements) + self + elements.flatten(1) + end + + # Returns a copy of the Array excluding the specified elements. + # + # ["David", "Rafael", "Aaron", "Todd"].excluding("Aaron", "Todd") # => ["David", "Rafael"] + # [ [ 0, 1 ], [ 1, 0 ] ].excluding([ [ 1, 0 ] ]) # => [ [ 0, 1 ] ] + # + # Note: This is an optimization of Enumerable#excluding that uses Array#- + # instead of Array#reject for performance reasons. + def excluding(*elements) + self - elements.flatten(1) + end + + # Alias for #excluding. + def without(*elements) + excluding(*elements) + end + + # Equal to self[1]. + # + # %w( a b c d e ).second # => "b" + def second + self[1] + end + + # Equal to self[2]. + # + # %w( a b c d e ).third # => "c" + def third + self[2] + end + + # Equal to self[3]. + # + # %w( a b c d e ).fourth # => "d" + def fourth + self[3] + end + + # Equal to self[4]. + # + # %w( a b c d e ).fifth # => "e" + def fifth + self[4] + end + + # Equal to self[41]. Also known as accessing "the reddit". + # + # (1..42).to_a.forty_two # => 42 + def forty_two + self[41] + end + + # Equal to self[-3]. + # + # %w( a b c d e ).third_to_last # => "c" + def third_to_last + self[-3] + end + + # Equal to self[-2]. + # + # %w( a b c d e ).second_to_last # => "d" + def second_to_last + self[-2] + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/activesupport-6.1.7.6/lib/active_support/core_ext/enumerable.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/activesupport-6.1.7.6/lib/active_support/core_ext/enumerable.rb new file mode 100644 index 0000000000..97c918a71f --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/activesupport-6.1.7.6/lib/active_support/core_ext/enumerable.rb @@ -0,0 +1,260 @@ +# frozen_string_literal: true + +module Enumerable + INDEX_WITH_DEFAULT = Object.new + private_constant :INDEX_WITH_DEFAULT + + # Enumerable#sum was added in Ruby 2.4, but it only works with Numeric elements + # when we omit an identity. + + # :stopdoc: + + # We can't use Refinements here because Refinements with Module which will be prepended + # doesn't work well https://bugs.ruby-lang.org/issues/13446 + alias :_original_sum_with_required_identity :sum + private :_original_sum_with_required_identity + + # :startdoc: + + # Calculates a sum from the elements. + # + # payments.sum { |p| p.price * p.tax_rate } + # payments.sum(&:price) + # + # The latter is a shortcut for: + # + # payments.inject(0) { |sum, p| sum + p.price } + # + # It can also calculate the sum without the use of a block. + # + # [5, 15, 10].sum # => 30 + # ['foo', 'bar'].sum # => "foobar" + # [[1, 2], [3, 1, 5]].sum # => [1, 2, 3, 1, 5] + # + # The default sum of an empty list is zero. You can override this default: + # + # [].sum(Payment.new(0)) { |i| i.amount } # => Payment.new(0) + def sum(identity = nil, &block) + if identity + _original_sum_with_required_identity(identity, &block) + elsif block_given? + map(&block).sum(identity) + else + inject(:+) || 0 + end + end + + # Convert an enumerable to a hash, using the block result as the key and the + # element as the value. + # + # people.index_by(&:login) + # # => { "nextangle" => , "chade-" => , ...} + # + # people.index_by { |person| "#{person.first_name} #{person.last_name}" } + # # => { "Chade- Fowlersburg-e" => , "David Heinemeier Hansson" => , ...} + def index_by + if block_given? + result = {} + each { |elem| result[yield(elem)] = elem } + result + else + to_enum(:index_by) { size if respond_to?(:size) } + end + end + + # Convert an enumerable to a hash, using the element as the key and the block + # result as the value. + # + # post = Post.new(title: "hey there", body: "what's up?") + # + # %i( title body ).index_with { |attr_name| post.public_send(attr_name) } + # # => { title: "hey there", body: "what's up?" } + # + # If an argument is passed instead of a block, it will be used as the value + # for all elements: + # + # %i( created_at updated_at ).index_with(Time.now) + # # => { created_at: 2020-03-09 22:31:47, updated_at: 2020-03-09 22:31:47 } + def index_with(default = INDEX_WITH_DEFAULT) + if block_given? + result = {} + each { |elem| result[elem] = yield(elem) } + result + elsif default != INDEX_WITH_DEFAULT + result = {} + each { |elem| result[elem] = default } + result + else + to_enum(:index_with) { size if respond_to?(:size) } + end + end + + # Returns +true+ if the enumerable has more than 1 element. Functionally + # equivalent to enum.to_a.size > 1. Can be called with a block too, + # much like any?, so people.many? { |p| p.age > 26 } returns +true+ + # if more than one person is over 26. + def many? + cnt = 0 + if block_given? + any? do |element| + cnt += 1 if yield element + cnt > 1 + end + else + any? { (cnt += 1) > 1 } + end + end + + # Returns a new array that includes the passed elements. + # + # [ 1, 2, 3 ].including(4, 5) + # # => [ 1, 2, 3, 4, 5 ] + # + # ["David", "Rafael"].including %w[ Aaron Todd ] + # # => ["David", "Rafael", "Aaron", "Todd"] + def including(*elements) + to_a.including(*elements) + end + + # The negative of the Enumerable#include?. Returns +true+ if the + # collection does not include the object. + def exclude?(object) + !include?(object) + end + + # Returns a copy of the enumerable excluding the specified elements. + # + # ["David", "Rafael", "Aaron", "Todd"].excluding "Aaron", "Todd" + # # => ["David", "Rafael"] + # + # ["David", "Rafael", "Aaron", "Todd"].excluding %w[ Aaron Todd ] + # # => ["David", "Rafael"] + # + # {foo: 1, bar: 2, baz: 3}.excluding :bar + # # => {foo: 1, baz: 3} + def excluding(*elements) + elements.flatten!(1) + reject { |element| elements.include?(element) } + end + + # Alias for #excluding. + def without(*elements) + excluding(*elements) + end + + # Extract the given key from each element in the enumerable. + # + # [{ name: "David" }, { name: "Rafael" }, { name: "Aaron" }].pluck(:name) + # # => ["David", "Rafael", "Aaron"] + # + # [{ id: 1, name: "David" }, { id: 2, name: "Rafael" }].pluck(:id, :name) + # # => [[1, "David"], [2, "Rafael"]] + def pluck(*keys) + if keys.many? + map { |element| keys.map { |key| element[key] } } + else + key = keys.first + map { |element| element[key] } + end + end + + # Extract the given key from the first element in the enumerable. + # + # [{ name: "David" }, { name: "Rafael" }, { name: "Aaron" }].pick(:name) + # # => "David" + # + # [{ id: 1, name: "David" }, { id: 2, name: "Rafael" }].pick(:id, :name) + # # => [1, "David"] + def pick(*keys) + return if none? + + if keys.many? + keys.map { |key| first[key] } + else + first[keys.first] + end + end + + # Returns a new +Array+ without the blank items. + # Uses Object#blank? for determining if an item is blank. + # + # [1, "", nil, 2, " ", [], {}, false, true].compact_blank + # # => [1, 2, true] + # + # Set.new([nil, "", 1, 2]) + # # => [2, 1] (or [1, 2]) + # + # When called on a +Hash+, returns a new +Hash+ without the blank values. + # + # { a: "", b: 1, c: nil, d: [], e: false, f: true }.compact_blank + # #=> { b: 1, f: true } + def compact_blank + reject(&:blank?) + end +end + +class Hash + # Hash#reject has its own definition, so this needs one too. + def compact_blank #:nodoc: + reject { |_k, v| v.blank? } + end + + # Removes all blank values from the +Hash+ in place and returns self. + # Uses Object#blank? for determining if a value is blank. + # + # h = { a: "", b: 1, c: nil, d: [], e: false, f: true } + # h.compact_blank! + # # => { b: 1, f: true } + def compact_blank! + # use delete_if rather than reject! because it always returns self even if nothing changed + delete_if { |_k, v| v.blank? } + end +end + +class Range #:nodoc: + # Optimize range sum to use arithmetic progression if a block is not given and + # we have a range of numeric values. + def sum(identity = nil) + if block_given? || !(first.is_a?(Integer) && last.is_a?(Integer)) + super + else + actual_last = exclude_end? ? (last - 1) : last + if actual_last >= first + sum = identity || 0 + sum + (actual_last - first + 1) * (actual_last + first) / 2 + else + identity || 0 + end + end + end +end + +# Using Refinements here in order not to expose our internal method +using Module.new { + refine Array do + alias :orig_sum :sum + end +} + +class Array #:nodoc: + # Array#sum was added in Ruby 2.4 but it only works with Numeric elements. + def sum(init = nil, &block) + if init.is_a?(Numeric) || first.is_a?(Numeric) + init ||= 0 + orig_sum(init, &block) + else + super + end + end + + # Removes all blank elements from the +Array+ in place and returns self. + # Uses Object#blank? for determining if an item is blank. + # + # a = [1, "", nil, 2, " ", [], {}, false, true] + # a.compact_blank! + # # => [1, 2, true] + def compact_blank! + # use delete_if rather than reject! because it always returns self even if nothing changed + delete_if(&:blank?) + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/activesupport-6.1.7.6/lib/active_support/core_ext/file/atomic.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/activesupport-6.1.7.6/lib/active_support/core_ext/file/atomic.rb new file mode 100644 index 0000000000..9deceb1bb4 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/activesupport-6.1.7.6/lib/active_support/core_ext/file/atomic.rb @@ -0,0 +1,70 @@ +# frozen_string_literal: true + +require "fileutils" + +class File + # Write to a file atomically. Useful for situations where you don't + # want other processes or threads to see half-written files. + # + # File.atomic_write('important.file') do |file| + # file.write('hello') + # end + # + # This method needs to create a temporary file. By default it will create it + # in the same directory as the destination file. If you don't like this + # behavior you can provide a different directory but it must be on the + # same physical filesystem as the file you're trying to write. + # + # File.atomic_write('/data/something.important', '/data/tmp') do |file| + # file.write('hello') + # end + def self.atomic_write(file_name, temp_dir = dirname(file_name)) + require "tempfile" unless defined?(Tempfile) + + Tempfile.open(".#{basename(file_name)}", temp_dir) do |temp_file| + temp_file.binmode + return_val = yield temp_file + temp_file.close + + old_stat = if exist?(file_name) + # Get original file permissions + stat(file_name) + else + # If not possible, probe which are the default permissions in the + # destination directory. + probe_stat_in(dirname(file_name)) + end + + if old_stat + # Set correct permissions on new file + begin + chown(old_stat.uid, old_stat.gid, temp_file.path) + # This operation will affect filesystem ACL's + chmod(old_stat.mode, temp_file.path) + rescue Errno::EPERM, Errno::EACCES + # Changing file ownership failed, moving on. + end + end + + # Overwrite original file with temp file + rename(temp_file.path, file_name) + return_val + end + end + + # Private utility method. + def self.probe_stat_in(dir) #:nodoc: + basename = [ + ".permissions_check", + Thread.current.object_id, + Process.pid, + rand(1000000) + ].join(".") + + file_name = join(dir, basename) + FileUtils.touch(file_name) + stat(file_name) + ensure + FileUtils.rm_f(file_name) if file_name + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/activesupport-6.1.7.6/lib/active_support/core_ext/hash/deep_merge.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/activesupport-6.1.7.6/lib/active_support/core_ext/hash/deep_merge.rb new file mode 100644 index 0000000000..9bc50b7bc6 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/activesupport-6.1.7.6/lib/active_support/core_ext/hash/deep_merge.rb @@ -0,0 +1,34 @@ +# frozen_string_literal: true + +class Hash + # Returns a new hash with +self+ and +other_hash+ merged recursively. + # + # h1 = { a: true, b: { c: [1, 2, 3] } } + # h2 = { a: false, b: { x: [3, 4, 5] } } + # + # h1.deep_merge(h2) # => { a: false, b: { c: [1, 2, 3], x: [3, 4, 5] } } + # + # Like with Hash#merge in the standard library, a block can be provided + # to merge values: + # + # h1 = { a: 100, b: 200, c: { c1: 100 } } + # h2 = { b: 250, c: { c1: 200 } } + # h1.deep_merge(h2) { |key, this_val, other_val| this_val + other_val } + # # => { a: 100, b: 450, c: { c1: 300 } } + def deep_merge(other_hash, &block) + dup.deep_merge!(other_hash, &block) + end + + # Same as +deep_merge+, but modifies +self+. + def deep_merge!(other_hash, &block) + merge!(other_hash) do |key, this_val, other_val| + if this_val.is_a?(Hash) && other_val.is_a?(Hash) + this_val.deep_merge(other_val, &block) + elsif block_given? + block.call(key, this_val, other_val) + else + other_val + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/activesupport-6.1.7.6/lib/active_support/core_ext/hash/deep_transform_values.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/activesupport-6.1.7.6/lib/active_support/core_ext/hash/deep_transform_values.rb new file mode 100644 index 0000000000..8ad85c0a6d --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/activesupport-6.1.7.6/lib/active_support/core_ext/hash/deep_transform_values.rb @@ -0,0 +1,46 @@ +# frozen_string_literal: true + +class Hash + # Returns a new hash with all values converted by the block operation. + # This includes the values from the root hash and from all + # nested hashes and arrays. + # + # hash = { person: { name: 'Rob', age: '28' } } + # + # hash.deep_transform_values{ |value| value.to_s.upcase } + # # => {person: {name: "ROB", age: "28"}} + def deep_transform_values(&block) + _deep_transform_values_in_object(self, &block) + end + + # Destructively converts all values by using the block operation. + # This includes the values from the root hash and from all + # nested hashes and arrays. + def deep_transform_values!(&block) + _deep_transform_values_in_object!(self, &block) + end + + private + # Support methods for deep transforming nested hashes and arrays. + def _deep_transform_values_in_object(object, &block) + case object + when Hash + object.transform_values { |value| _deep_transform_values_in_object(value, &block) } + when Array + object.map { |e| _deep_transform_values_in_object(e, &block) } + else + yield(object) + end + end + + def _deep_transform_values_in_object!(object, &block) + case object + when Hash + object.transform_values! { |value| _deep_transform_values_in_object!(value, &block) } + when Array + object.map! { |e| _deep_transform_values_in_object!(e, &block) } + else + yield(object) + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/activesupport-6.1.7.6/lib/active_support/core_ext/hash/except.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/activesupport-6.1.7.6/lib/active_support/core_ext/hash/except.rb new file mode 100644 index 0000000000..ec96929b0a --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/activesupport-6.1.7.6/lib/active_support/core_ext/hash/except.rb @@ -0,0 +1,24 @@ +# frozen_string_literal: true + +class Hash + # Returns a hash that includes everything except given keys. + # hash = { a: true, b: false, c: nil } + # hash.except(:c) # => { a: true, b: false } + # hash.except(:a, :b) # => { c: nil } + # hash # => { a: true, b: false, c: nil } + # + # This is useful for limiting a set of parameters to everything but a few known toggles: + # @person.update(params[:person].except(:admin)) + def except(*keys) + slice(*self.keys - keys) + end unless method_defined?(:except) + + # Removes the given keys from hash and returns it. + # hash = { a: true, b: false, c: nil } + # hash.except!(:c) # => { a: true, b: false } + # hash # => { a: true, b: false } + def except!(*keys) + keys.each { |key| delete(key) } + self + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/activesupport-6.1.7.6/lib/active_support/core_ext/hash/keys.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/activesupport-6.1.7.6/lib/active_support/core_ext/hash/keys.rb new file mode 100644 index 0000000000..f2db61f386 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/activesupport-6.1.7.6/lib/active_support/core_ext/hash/keys.rb @@ -0,0 +1,143 @@ +# frozen_string_literal: true + +class Hash + # Returns a new hash with all keys converted to strings. + # + # hash = { name: 'Rob', age: '28' } + # + # hash.stringify_keys + # # => {"name"=>"Rob", "age"=>"28"} + def stringify_keys + transform_keys(&:to_s) + end + + # Destructively converts all keys to strings. Same as + # +stringify_keys+, but modifies +self+. + def stringify_keys! + transform_keys!(&:to_s) + end + + # Returns a new hash with all keys converted to symbols, as long as + # they respond to +to_sym+. + # + # hash = { 'name' => 'Rob', 'age' => '28' } + # + # hash.symbolize_keys + # # => {:name=>"Rob", :age=>"28"} + def symbolize_keys + transform_keys { |key| key.to_sym rescue key } + end + alias_method :to_options, :symbolize_keys + + # Destructively converts all keys to symbols, as long as they respond + # to +to_sym+. Same as +symbolize_keys+, but modifies +self+. + def symbolize_keys! + transform_keys! { |key| key.to_sym rescue key } + end + alias_method :to_options!, :symbolize_keys! + + # Validates all keys in a hash match *valid_keys, raising + # +ArgumentError+ on a mismatch. + # + # Note that keys are treated differently than HashWithIndifferentAccess, + # meaning that string and symbol keys will not match. + # + # { name: 'Rob', years: '28' }.assert_valid_keys(:name, :age) # => raises "ArgumentError: Unknown key: :years. Valid keys are: :name, :age" + # { name: 'Rob', age: '28' }.assert_valid_keys('name', 'age') # => raises "ArgumentError: Unknown key: :name. Valid keys are: 'name', 'age'" + # { name: 'Rob', age: '28' }.assert_valid_keys(:name, :age) # => passes, raises nothing + def assert_valid_keys(*valid_keys) + valid_keys.flatten! + each_key do |k| + unless valid_keys.include?(k) + raise ArgumentError.new("Unknown key: #{k.inspect}. Valid keys are: #{valid_keys.map(&:inspect).join(', ')}") + end + end + end + + # Returns a new hash with all keys converted by the block operation. + # This includes the keys from the root hash and from all + # nested hashes and arrays. + # + # hash = { person: { name: 'Rob', age: '28' } } + # + # hash.deep_transform_keys{ |key| key.to_s.upcase } + # # => {"PERSON"=>{"NAME"=>"Rob", "AGE"=>"28"}} + def deep_transform_keys(&block) + _deep_transform_keys_in_object(self, &block) + end + + # Destructively converts all keys by using the block operation. + # This includes the keys from the root hash and from all + # nested hashes and arrays. + def deep_transform_keys!(&block) + _deep_transform_keys_in_object!(self, &block) + end + + # Returns a new hash with all keys converted to strings. + # This includes the keys from the root hash and from all + # nested hashes and arrays. + # + # hash = { person: { name: 'Rob', age: '28' } } + # + # hash.deep_stringify_keys + # # => {"person"=>{"name"=>"Rob", "age"=>"28"}} + def deep_stringify_keys + deep_transform_keys(&:to_s) + end + + # Destructively converts all keys to strings. + # This includes the keys from the root hash and from all + # nested hashes and arrays. + def deep_stringify_keys! + deep_transform_keys!(&:to_s) + end + + # Returns a new hash with all keys converted to symbols, as long as + # they respond to +to_sym+. This includes the keys from the root hash + # and from all nested hashes and arrays. + # + # hash = { 'person' => { 'name' => 'Rob', 'age' => '28' } } + # + # hash.deep_symbolize_keys + # # => {:person=>{:name=>"Rob", :age=>"28"}} + def deep_symbolize_keys + deep_transform_keys { |key| key.to_sym rescue key } + end + + # Destructively converts all keys to symbols, as long as they respond + # to +to_sym+. This includes the keys from the root hash and from all + # nested hashes and arrays. + def deep_symbolize_keys! + deep_transform_keys! { |key| key.to_sym rescue key } + end + + private + # Support methods for deep transforming nested hashes and arrays. + def _deep_transform_keys_in_object(object, &block) + case object + when Hash + object.each_with_object({}) do |(key, value), result| + result[yield(key)] = _deep_transform_keys_in_object(value, &block) + end + when Array + object.map { |e| _deep_transform_keys_in_object(e, &block) } + else + object + end + end + + def _deep_transform_keys_in_object!(object, &block) + case object + when Hash + object.keys.each do |key| + value = object.delete(key) + object[yield(key)] = _deep_transform_keys_in_object!(value, &block) + end + object + when Array + object.map! { |e| _deep_transform_keys_in_object!(e, &block) } + else + object + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/activesupport-6.1.7.6/lib/active_support/core_ext/hash/slice.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/activesupport-6.1.7.6/lib/active_support/core_ext/hash/slice.rb new file mode 100644 index 0000000000..56bc5de382 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/activesupport-6.1.7.6/lib/active_support/core_ext/hash/slice.rb @@ -0,0 +1,27 @@ +# frozen_string_literal: true + +class Hash + # Replaces the hash with only the given keys. + # Returns a hash containing the removed key/value pairs. + # + # hash = { a: 1, b: 2, c: 3, d: 4 } + # hash.slice!(:a, :b) # => {:c=>3, :d=>4} + # hash # => {:a=>1, :b=>2} + def slice!(*keys) + omit = slice(*self.keys - keys) + hash = slice(*keys) + hash.default = default + hash.default_proc = default_proc if default_proc + replace(hash) + omit + end + + # Removes and returns the key/value pairs matching the given keys. + # + # hash = { a: 1, b: 2, c: 3, d: 4 } + # hash.extract!(:a, :b) # => {:a=>1, :b=>2} + # hash # => {:c=>3, :d=>4} + def extract!(*keys) + keys.each_with_object(self.class.new) { |key, result| result[key] = delete(key) if has_key?(key) } + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/activesupport-6.1.7.6/lib/active_support/core_ext/object/deep_dup.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/activesupport-6.1.7.6/lib/active_support/core_ext/object/deep_dup.rb new file mode 100644 index 0000000000..5c903917f5 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/activesupport-6.1.7.6/lib/active_support/core_ext/object/deep_dup.rb @@ -0,0 +1,55 @@ +# frozen_string_literal: true + +require "active_support/core_ext/object/duplicable" + +class Object + # Returns a deep copy of object if it's duplicable. If it's + # not duplicable, returns +self+. + # + # object = Object.new + # dup = object.deep_dup + # dup.instance_variable_set(:@a, 1) + # + # object.instance_variable_defined?(:@a) # => false + # dup.instance_variable_defined?(:@a) # => true + def deep_dup + duplicable? ? dup : self + end +end + +class Array + # Returns a deep copy of array. + # + # array = [1, [2, 3]] + # dup = array.deep_dup + # dup[1][2] = 4 + # + # array[1][2] # => nil + # dup[1][2] # => 4 + def deep_dup + map(&:deep_dup) + end +end + +class Hash + # Returns a deep copy of hash. + # + # hash = { a: { b: 'b' } } + # dup = hash.deep_dup + # dup[:a][:c] = 'c' + # + # hash[:a][:c] # => nil + # dup[:a][:c] # => "c" + def deep_dup + hash = dup + each_pair do |key, value| + if (::String === key && key.frozen?) || ::Symbol === key + hash[key] = value.deep_dup + else + hash.delete(key) + hash[key.deep_dup] = value.deep_dup + end + end + hash + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/activesupport-6.1.7.6/lib/active_support/core_ext/object/duplicable.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/activesupport-6.1.7.6/lib/active_support/core_ext/object/duplicable.rb new file mode 100644 index 0000000000..3ebcdca02b --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/activesupport-6.1.7.6/lib/active_support/core_ext/object/duplicable.rb @@ -0,0 +1,49 @@ +# frozen_string_literal: true + +#-- +# Most objects are cloneable, but not all. For example you can't dup methods: +# +# method(:puts).dup # => TypeError: allocator undefined for Method +# +# Classes may signal their instances are not duplicable removing +dup+/+clone+ +# or raising exceptions from them. So, to dup an arbitrary object you normally +# use an optimistic approach and are ready to catch an exception, say: +# +# arbitrary_object.dup rescue object +# +# Rails dups objects in a few critical spots where they are not that arbitrary. +# That rescue is very expensive (like 40 times slower than a predicate), and it +# is often triggered. +# +# That's why we hardcode the following cases and check duplicable? instead of +# using that rescue idiom. +#++ +class Object + # Can you safely dup this object? + # + # False for method objects; + # true otherwise. + def duplicable? + true + end +end + +class Method + # Methods are not duplicable: + # + # method(:puts).duplicable? # => false + # method(:puts).dup # => TypeError: allocator undefined for Method + def duplicable? + false + end +end + +class UnboundMethod + # Unbound methods are not duplicable: + # + # method(:puts).unbind.duplicable? # => false + # method(:puts).unbind.dup # => TypeError: allocator undefined for UnboundMethod + def duplicable? + false + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/activesupport-6.1.7.6/lib/active_support/core_ext/string/exclude.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/activesupport-6.1.7.6/lib/active_support/core_ext/string/exclude.rb new file mode 100644 index 0000000000..8e462689f1 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/activesupport-6.1.7.6/lib/active_support/core_ext/string/exclude.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +class String + # The inverse of String#include?. Returns true if the string + # does not include the other string. + # + # "hello".exclude? "lo" # => false + # "hello".exclude? "ol" # => true + # "hello".exclude? ?h # => false + def exclude?(string) + !include?(string) + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/activesupport-6.1.7.6/lib/active_support/core_ext/string/filters.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/activesupport-6.1.7.6/lib/active_support/core_ext/string/filters.rb new file mode 100644 index 0000000000..7f28bd52f2 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/activesupport-6.1.7.6/lib/active_support/core_ext/string/filters.rb @@ -0,0 +1,145 @@ +# frozen_string_literal: true + +class String + # Returns the string, first removing all whitespace on both ends of + # the string, and then changing remaining consecutive whitespace + # groups into one space each. + # + # Note that it handles both ASCII and Unicode whitespace. + # + # %{ Multi-line + # string }.squish # => "Multi-line string" + # " foo bar \n \t boo".squish # => "foo bar boo" + def squish + dup.squish! + end + + # Performs a destructive squish. See String#squish. + # str = " foo bar \n \t boo" + # str.squish! # => "foo bar boo" + # str # => "foo bar boo" + def squish! + gsub!(/[[:space:]]+/, " ") + strip! + self + end + + # Returns a new string with all occurrences of the patterns removed. + # str = "foo bar test" + # str.remove(" test") # => "foo bar" + # str.remove(" test", /bar/) # => "foo " + # str # => "foo bar test" + def remove(*patterns) + dup.remove!(*patterns) + end + + # Alters the string by removing all occurrences of the patterns. + # str = "foo bar test" + # str.remove!(" test", /bar/) # => "foo " + # str # => "foo " + def remove!(*patterns) + patterns.each do |pattern| + gsub! pattern, "" + end + + self + end + + # Truncates a given +text+ after a given length if +text+ is longer than length: + # + # 'Once upon a time in a world far far away'.truncate(27) + # # => "Once upon a time in a wo..." + # + # Pass a string or regexp :separator to truncate +text+ at a natural break: + # + # 'Once upon a time in a world far far away'.truncate(27, separator: ' ') + # # => "Once upon a time in a..." + # + # 'Once upon a time in a world far far away'.truncate(27, separator: /\s/) + # # => "Once upon a time in a..." + # + # The last characters will be replaced with the :omission string (defaults to "...") + # for a total length not exceeding length: + # + # 'And they found that many people were sleeping better.'.truncate(25, omission: '... (continued)') + # # => "And they f... (continued)" + def truncate(truncate_at, options = {}) + return dup unless length > truncate_at + + omission = options[:omission] || "..." + length_with_room_for_omission = truncate_at - omission.length + stop = \ + if options[:separator] + rindex(options[:separator], length_with_room_for_omission) || length_with_room_for_omission + else + length_with_room_for_omission + end + + +"#{self[0, stop]}#{omission}" + end + + # Truncates +text+ to at most bytesize bytes in length without + # breaking string encoding by splitting multibyte characters or breaking + # grapheme clusters ("perceptual characters") by truncating at combining + # characters. + # + # >> "🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪".size + # => 20 + # >> "🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪".bytesize + # => 80 + # >> "🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪".truncate_bytes(20) + # => "🔪🔪🔪🔪…" + # + # The truncated text ends with the :omission string, defaulting + # to "…", for a total length not exceeding bytesize. + def truncate_bytes(truncate_at, omission: "…") + omission ||= "" + + case + when bytesize <= truncate_at + dup + when omission.bytesize > truncate_at + raise ArgumentError, "Omission #{omission.inspect} is #{omission.bytesize}, larger than the truncation length of #{truncate_at} bytes" + when omission.bytesize == truncate_at + omission.dup + else + self.class.new.tap do |cut| + cut_at = truncate_at - omission.bytesize + + scan(/\X/) do |grapheme| + if cut.bytesize + grapheme.bytesize <= cut_at + cut << grapheme + else + break + end + end + + cut << omission + end + end + end + + # Truncates a given +text+ after a given number of words (words_count): + # + # 'Once upon a time in a world far far away'.truncate_words(4) + # # => "Once upon a time..." + # + # Pass a string or regexp :separator to specify a different separator of words: + # + # 'Once
upon
a
time
in
a
world'.truncate_words(5, separator: '
') + # # => "Once
upon
a
time
in..." + # + # The last characters will be replaced with the :omission string (defaults to "..."): + # + # 'And they found that many people were sleeping better.'.truncate_words(5, omission: '... (continued)') + # # => "And they found that many... (continued)" + def truncate_words(words_count, options = {}) + sep = options[:separator] || /\s+/ + sep = Regexp.escape(sep.to_s) unless Regexp === sep + if self =~ /\A((?>.+?#{sep}){#{words_count - 1}}.+?)#{sep}.*/m + $1 + (options[:omission] || "...") + else + dup + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/activesupport-6.1.7.6/lib/active_support/core_ext/string/indent.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/activesupport-6.1.7.6/lib/active_support/core_ext/string/indent.rb new file mode 100644 index 0000000000..af9d181487 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/activesupport-6.1.7.6/lib/active_support/core_ext/string/indent.rb @@ -0,0 +1,45 @@ +# frozen_string_literal: true + +class String + # Same as +indent+, except it indents the receiver in-place. + # + # Returns the indented string, or +nil+ if there was nothing to indent. + def indent!(amount, indent_string = nil, indent_empty_lines = false) + indent_string = indent_string || self[/^[ \t]/] || " " + re = indent_empty_lines ? /^/ : /^(?!$)/ + gsub!(re, indent_string * amount) + end + + # Indents the lines in the receiver: + # + # < + # def some_method + # some_code + # end + # + # The second argument, +indent_string+, specifies which indent string to + # use. The default is +nil+, which tells the method to make a guess by + # peeking at the first indented line, and fallback to a space if there is + # none. + # + # " foo".indent(2) # => " foo" + # "foo\n\t\tbar".indent(2) # => "\t\tfoo\n\t\t\t\tbar" + # "foo".indent(2, "\t") # => "\t\tfoo" + # + # While +indent_string+ is typically one space or tab, it may be any string. + # + # The third argument, +indent_empty_lines+, is a flag that says whether + # empty lines should be indented. Default is false. + # + # "foo\n\nbar".indent(2) # => " foo\n\n bar" + # "foo\n\nbar".indent(2, nil, true) # => " foo\n \n bar" + # + def indent(amount, indent_string = nil, indent_empty_lines = false) + dup.tap { |_| _.indent!(amount, indent_string, indent_empty_lines) } + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/addressable-2.8.5/LICENSE.txt b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/addressable-2.8.5/LICENSE.txt new file mode 100644 index 0000000000..ef51da2b0e --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/addressable-2.8.5/LICENSE.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/addressable-2.8.5/data/unicode.data b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/addressable-2.8.5/data/unicode.data new file mode 100644 index 0000000000000000000000000000000000000000..cdfc22418a51396f2b89cfc1afb2c892b30d7e3f GIT binary patch literal 115740 zcmZ_12b5J+^1cnNb^vqEBBEk$GAIU;(2|rW7|C36YN7#Xa?TmaIp^4*AS#FrX2sNG zvoqu5ncw`sxAxt;>fLwwttB&6Pd%s3Is5Dr?&(W&VdkK;(U&KleD2~zkwlT~?CeDQ z>_lzLI%Fs6Sk^H+kz-jRJMoldow5^kE$f_}sApN1>_mObx@IRDSk^5&(a^H)*@>qu z>ye#!#_Ytap z!Jm)G2wUDzxBPb)pO6u@yrFLSUtxSoM%a#q$t^c0IQ#urJ$?b|<* zf2m6})h+iCs{g{D6J&%fZ>n4VZx~;Z5w^UkZux&;d`(8!uBN(O|Aq058ZDB&F-v`f z>i^--w@Jfo`Tvj?>JqJV%YBq6`X+=oabA)Ww!KxdKTc^lZ{f@&Cv1JI?54saNfmPs!lr{4IkkIhw~oJQ*y#+va6ZJDt4?>_3m@U6hx1XQ==M$X2nx(Lbz;$2`)D|LJ%9iXJ4)rF>2 zJGxR^xd_Td;$37;D|LJ%9iUu@R_UhI(9!b|lnn7Q%xR;JkE8>XbhOGetw!=Nx<>i9@HKq-b+7n@e&=s0cVA}E)L zcZoS|)bWvYfO0WfU20lQ)qDiyGVv}mr>#0Zk`7QVMXSrbCbyroD}-L5M5+LnL%Y(t z)zYcuBPdsica=Hq)bWvYfN~{TU2R$|omxJEa*cS`nA1)jA4vx&SEJRnrq$As_Ysuq z#JkR%cIx;@IzYJ=t*$q%md;WiLAgP^8_a2^j*p}RlBP$omM&P2$~TPCIpc zBpsmKh*me7R$FJOkD%Nl-Yw>IP{&8o0m{v2b*pK$bx3^#tdGpB<(K9UYlZbhpS zrq$LV^%0cY#k<{{4(j+wIzTCbRwYfVt*$KR1N-N_HT!`G;kF>G@mzO4p5#)s~1gctmEJ#C@+ckk~zKA@sV_Z z@*-NjY+7R-2OmLcC0;9YdaL6j=>X+rv}$cy6J4W^ptKRMjX8bP@sV_Z(i*MWn$|?u z=p!iY#A|0xA9Z{r9iX&DtM*=VGr5D%4oaj7&>mVx>(*2s9ee~OAzs3qTy=aT9iVhX zt4^jh)f3-GP&$j(*_>Q;d?X#9bV92xrZv?Q-$zioir3YgTy=aT9iVhUt8S(>O};F` z#lc5Vx{KG{oLqH$Bpsl1L#rO9HPvf~kD&AvuctY=>i9@HKG@5tQEI z^)@G09Un;tD810Ck7>>I-0=~VT=88Fm5qyv;bXw}!W7OMFON=G4Kl5zKKS_v$}8f% zV$MKyd?X#948n%LYFbM@y?g}aHSu0EXP`Phk`7Q_MXT4nhMR4AZ}$M{ezui1ByhRe zHcrF;3}uoh%jYSPs#6ka!xRDx7dl*tQ~`!zy(1I?G?D%znT!%|loF{rC6P8-AwV-( za14{?LdG%~Crge~B2}j((k3Vb_(teNCM~4ZBqq-ZnapI0EHy=mRGpGYo2n4tWm#|< zlQu%8D@mmNT^9U1MrMXW0DN9Zq|Ic~QOGPNvt`NIN~G!({1i?hKzCViK9gQT7BI;b zvd|OvfHGGfRa}JfBI&-!obE@1<0I+d+9c8zbMqxamne}cz+&w3QiTA^gf3GeRe+_? zmMa7pEStK5$x887Dv_#F5^1Xx0_4epYniMQZ=DjUIwg^|ULn9JS#X0V?gAZlylHX> zP~Ip@ZZs!X2ggU!!L>=GZQ|x*r1@qhV})#CvQ?JcszjB?HyDO zxj+6ru&eHKS0F4R0+xS=mTh}TtEkAb?^-pZUie&m7=`!TA8njb&wn(27yPjFJxoh> z(IN`63x{kDz=c-bdziSI0-v0m_GH^|5J9 zRr3*)PsIDgoLqH$Bpsl9j8>njmUVDmcm~rD(r03RM%G@ld?;NYeTsIUlQ=KjqNSbt zK?tNT#QcJ+y=M7PxahyzuiIY3IJE z0O@Nnzb0$1Sw565kiJ5@Z@efs?g;`X0DenL53`~2A*Aob{En=pX8BOMK>8N#3Qc@( zxr!l#bW+TdWUVmEhtdU7A=;fX@!$v*LkQ`#n5W6Il^*n=bb)jV?ap}7eXKYu^sEx8 z0-S+%PWxrn4#y`%P|k~Y-kc8V_((cHIfqu?n^spfA3^y+ydTWztd5VQ1C;O4>POQW z>Jzn(p!_7>Pv&%2$4Alu%8zLEvuauIuGV18W&el_u(9bpf$ zLI~+MF@H1b$P~3gC|w}^igtfeF|$+fLgbFzpS^%b(~O!e{e9ziEcqAr$F9RQ2PSVD ze+K_u+W$^Vw$&mEvgBWFy|u$xj>8@<1%HzUe>10pIzEyPQ2vTme-G=Cb8WiNe=ylE zQ-wXB1~!)9p+=|5urhpc60`B1t*`Zu=z zza)+@(T9-!Pt5-#Yq?oIlrE6|i+2Abah8cbg!KQ!{C{NaG|Pw51=9b}u1H$)0K41e zL^;3~K`AOvFGbC1bu>6Wk`7Rc;1N2_v}#8uYbzH)xj?)N%xR^LkE8>XG_<T=T>=^A|m3lU^bwS+ z#JkFzUh4QrIzYJ+t*$n$sjksSP_7a08gp{h@sV_Zay43AYg$uXqmQ6mC*F1DX+gw7TB3#z&X?6URqTZV>MVb9$@eBk2I;dbGOHv?i+g2+B?3-DFN5b$lcppxlU7 zH+#+9ByJIUixQ~<+zjnj>sCkaFFt~Dn|QaG(@`BCNe3vmqE$)l4{(RjJCsNjpd_?X z3IXmEdZ!Yp0+fPwmxu0p7QRYRE%~|!%H87KZB8qF5#%H30Oc;UDs5UVeP!z-DEEkW zk2&qs@sV_ZQW~x9RW0k_41Ej;A*B1nypOEyX8BOMK)M(0?k91&i9Uq%fS3=EwaqLa zN*74?quqll;)f<-%zOmpA@LqEr@J~nk`7QFM5}Dovff*->kJ{JGGdk?YlB%nlrE66 z(XOnDcy;K$g@ohkBPiv>D`(CCb$lcppp-?c#$J=Bi6L?y9D@5`6M`cIjsR>%aJ0bD zfXxYx5jY001;L2|Cjvf4aFW1DfG-oADsU=b8-mjWP6O;naHhbSfavP~UWUBF0-OQZ zo!~ry^8kAhoG)-bU@pN00v7-dCb(SSa=<)-s|2nB97S-w!1aJ*2yPO%32-dI%>p+A zP9eBM;10lz0pitYN4fa93(h8^8He39(c#U8)7>Y3N4F5|r7gA^%{aVE@ixYL6mKVd zB>9vo6J&?s^nNPuBsxIp7e?__{N(rBq{o*Lcc+!x>=O|mqkX=Lc=F3_(&y`lyYDu- zKHo&#{nXR(LgN{SmuUNwhSR$!Jw?>Lp>{1!6Ya0=8KW6TrYkOT0p@1WbM7w<$@Uga z$Fk9{F0RX(vG9P{EC$P%9Q-7 zl>F+H{2G^kuj6^G%fHtAx|IC-l>CO2{6?2sznfhCh4#BS#lIybzcnSlEhR6JlHcy~ zBig@YN`6O*Un(WPGbO((CBNI{*1vR0eou;jZ%Te&N`8Mz{y<9pU`qZ_N}ipPmr2RX zrsU;P^74|W>u^t|E z=T9;Q_`!|*b*b4G;EOgXYpU&X8>u=ec}`0HRLb&oQ}TK#dHs~-8>HkfyZlEzQms<* z)-L}+>wP3Il8}Ku;%;ghxSbxDEEkb)^_2KvxL%uI)5X#sNe*Z7|J_2vcp*9}!#&3! zA6Th_974C~2vZ6ss}e$t`C1wHk-GMb>W>m4d+cl*!vdmN7XbWI2;}gsfolu8@^X z-V?Hl$zdU@J;CWwFgtv+K|=^f#9BkvGP8UL;eD~zlC?>vM}ZIVaYUpMxPGl8ahr)g zlyeEf|oDlV!QdSZ=dl zPEPeH0;d3OAvjgwRKTqSrwN<}xQ*a+fztuE6PzJ%2H*~YGX>5B+(~ejz*&I12n80OJN=&xJ=+Oz;_5P7q}eoU4knFt^jlN4;0TPRKD54pHAS=71q5f_)~9rI{8EEGe0-P6mUWrrz&O!TLA;1qpe^4S-fbXIGs1V>Mp+6~+D!`A>epU$Z zi_l+`NEP5`Xum21_)X|d#a>=H|LwC$OYkEdIhp_gB*7 zdV!)`G>Tl9yj<}EiZ8wt69mYb?G{J0Mx zG#2YZUapCdioVSkmxNr-BwNT8Ov(tkl1W)1 zS1~CkNtpUISQ>;I#s;1*}ByI)T>#Rwj78!0Q34 zcqr3tr%g8>%5;Qy1H^}E=^F*!2>1xWn*`njSe4+-0&fO;~ zZ31rte1c#Jfh7Q|5xiaC?SRz@mK0bLum-_91l|EylVB-;@o(8c9#AhN=Z(G}vcMG|#K`aWf5v?XoU>aa!T6&9J z@_i^bH;5NNY(h(4DDXnSrUWk%coASTg6RU&0h`-;KAfR9vJlFR4q^txXKCq7fti3U z2xbY)0&GdJn80Fy&k-yxusGoJ9?Dqmww?5$-1i_}4DkgLciN!)P;Pw?FM;@?i67?a zNf|=9`$4=E;!CtWmkGQK@MVPnt%SBxB2|Ewp|w^B&_-w*B~k@w4Xv$0fObOLDUm8b zTWIYS0(21CL5WlW+C%H85FjBmp+u?x9ieqn2+&z*XC+bv=mf2cLV&J9yDE_?Ko@A; z6asV?+FglM0lGo!p%9>_(4I=93eW>uFNFZTh4xk=Re)a5`X~g*6`HF=ssMeU_4N>w z=fkbxn-UsA>L+GDvbLG!L+JvkFWU9jbpQ+yIzWk30s2E5s1RU~&_PP13NR4bD+&Q# z75b_YsRFzL?KOn}uM2%$iBthzgEm+pz!0HBlt>j|Ftj{@^aHSADf#e}d_+nI{1Za~K0!$VzhmO@*u5MYJS6-uNEupHV-g#fFBu2LdZfR)fzD+E|0bd3_J0<4C%Rw2MTq3e`L z6<{s2^$Gzt2;HDWssQVuZBz)bN$4geQU%xuZL>mvEkd^_kt)DuXj>HmY!kXoiBti$ zLfftoV298hN~8*~9okNX0K0_lQX*A=ozQkG1lS{Vj}oZ@?1r{iAwa&+d?iu^*b8l+ zLV*23_bZVqz&>bic_=sG8G6eMA*2Ih9w2MGSw565klsSOgSrlYw}rl~M5+J>p}ngR z;60)5DUm9`yU^ZO2yj&BQ6*9Zcputv4`m-F+1B|G(uZPxNY+NPd?;NY9Y?#5NSve( zMd%#fID9PT$7F3Z%ZJhh(no0bi5HV^%!GcbM5+LvK>LjPO}EYSA*9d6{G6<9X8BOM zK>7^rzR-05d@1xxB~k_W0@?}d_wg*_h1S=>*z+Z6ccPP2R{T_Bx8yE7!(5Tjj~PG`kDOV&=?2_H%qNN3RQ9Eoq3 z=tD^7#XL{eKC^r%T_Bx9yYIc|#^eW~KPZtZ!1vI8w0VhADqBIYkV#~f)zsP z0_iVk_g52-uh8{|5Ypeo{F_-Hj#Mjz(go6A(e9rn9$%wk2qFDT%zv5n;aIgoC|w}^ z6Ya`eL{E{eE&?sfq_vQ8Oxg%3&!nx83QXDwsmP?gkV;HC2&v4ZqmU|05<(tk(n-i8 zOgamx%A|{sN11dL@)(nDLLO(*UC0wmdI+h;q^FSTOnM2a!KAm4noRl#sl_B$$dgR^ z3aQPcpO89C`U}ZnGC;^vOa=<6%Vdy{dQ4ssQlH7ILK-l6O-Mr~uM2sa$zUPRFc~7G z5tE@p8Z*fg(uBz{Ax)VK7t)N$2qCSM$h-w8a}hqf6D%vREMOag0rTrvL{LtShiC;41{{ z39JYBD#7{!>jS<mV1iEzd>U{F!Dj?M12~jmBY}+o^9VK;*cfma z!6pKm01hYERA5uU5d@nFYz8wQ+Fj)%p^}Z=Cx3B9>P06RFr{r^7{%s3&9e|}2-MoPXQC1045FG|UmxZKvaG$mh_ zk}prmSES@CU2fyKDkWc?;;%`muT9C9v~fl=M1HcS(A^rh6p4LDRjG-l%E5q&I20U(%a3 zeM{0?G(8~ct(v|qDZMx=nT{MU!Z7c@Sn=gl|HX$8x>MkeNSS7e3!PHRlrKkp8I%w@ zFEn(<$p@4|D2NllHy;Hf$_RW=R&rmG<;=T zZkty&rCu&2FQ4L9NU2v$$t$J!l~eL6Dfz=G%RiD*ubPrSn&Ll}Qhz+9{zOV%EhVp> zvV4t{dd-x2t(5wcDfQYZ^*Sl_oRs=gDfvBF$#XZSWbwkKD+`zIO7|-JBPmUxMlQE0)HtQyBqe`V@*;_Jw@cG`BSPZV z+JdzitcApBEm@n%T1cGs9BcDf3yIU7XKfK{A#vIZtSx3OBu;ygwKc4T#Az?Fwt=;f zIBl~! z!QV8ZaFY(cCT^+vqS;bSC2gVC(`J&stm&K7bMyYfE&gG(c%de)=ewkB89|yRPJ1s! z(=8OuB~Ck%qPdTtaxoFjK99c7+8ADGNL;rMM6>;U>Jp@Wif$WGxK)poCT^*^tc_$X zBu=Zx+K9q!Iz7-WnK-S!XtoVU;`9VH*)h9thx<#pvcHsbcmAb@f3fpCuGPbFdL&NYkJGOu4J+Nfrf~Oc z-SKZyON+F0@nyPHX5n7nU2%A$kyd zxqPVRy_0S5cQT6?=5H#@cXK03T$?^_v0=JcZpvcr!(&*?K1udXYVKyTZ*$>3_xBk@ z)5LY}m(=7#ZL%~(XGDMQu!TE>#B~@DbwJ5F43tt)+v7ng`70^;t10>5lzfQfMG|4e zY@aZE$;55ZP`8-9j>=2Phe>WH_=uG9$dr7lx#JR6@JyzJ!Q^?ssT;ufnU z8iojoe9oyNsSWQ(*G1{7>yZ|r_Megou_yv^9k}C)iniaj({f|1W)bSC%yedkO zTk$B=CoGFN74aG8d_awTJ@t#{8sr0%0=Q`WKL^!d?X#9T!>cb zrd2<>Nn5!HN``nD=CoGFN74aGI$C9_mUVEXe*ZLtkg~+gB5Q?NK9nwyGSRM>ikUTa zEPMo|xOm0QX{(Npqyv;%gXDM1mzC#?l7mLIzEyPP)edz zDbwocx#lA%cZzqXIUUvUk#vAk3a#!ktxotJMW&CS+%4YS=5$oYN74bxU1(L>v^sjO z`3TBA;@x9TM|FH89iWs(t9wnWbJX9LuvIRCa-VqjnbT1nA4vx&_oCJPrse1q^bwQ? z#CyP;ggQQw4p8n#s|QufIyliTy*`BWkeCmVwZSYON*72EqFuI%nRSB~A}D3VD`QS) zb$lcppk$*}S<~w3!S)f9a^jUUr?Wafk`7SHqE&g*>gvVUM^Gw=SHYal>i9@HKq-$_ z6-}$BYxEJ6O5#;Ar;9p1k`7QRqE%(pik;l4zXZ-=XjR0m!rqQ>Hp26IzEyPP->#plcqJ$HTnojZSiWG(@h;8Ne3uTqE#K! z8t8%c5tJP9a?I(bj*p}RlsahjlxYq0K>G+vUGeIg(@h;8Ne3uTp;bNAvJTp>f(ap{ z`eN26%YF&QLH#8d^+c+Nb`41Me_t6ti9|d1WkE;{#cW8H|Lb95>E9GFs-xDE9? z1f{8XP0i_{j*p}RlqP7^%(SOO>3kx+ec8I6Yn{5da2_h=>VlAT0O5?v6H*z*i|#c&|VPt1@`8W=VR#v z?Rm6(QPs>wdb0Qk%1h$CWKJ)2d?X#9yogpWo7Pyz!$(kBiPy@U-s<>BIzV|Dty-Jb zSjWRhP}+#s#+=^j_((cHX^mEGRm(awC#+IKNbSUIN7h`kd?;NYwMD!3BrY`3hmbmm z*@3J@X8BOMKx&V69aY2;T^vk{p(Vsku(yOfA4?}_9nrFrs+moK7$PX0#p`TNA9Z{r z9iVhVt1hNB(INH`l&<1+HK&g{K9UYlx}a4z)0*fU@)4Bo;&nHtk2*e*4p6$GRS(me z=tbE_P48?gOlx{{ssC)`BPhMa>upZ1IzEyPP%;X5ba)3F|(Qe!)!i+@~U{R zn$uSuA4vx&ub|ayrZv-P=p!hvi}$)Yebw=ibb#_2S`9X>dAJc~`UuJp@rIbwPaPjg z2PlKlYN%<=^~U8RD0$-LnbS`lA4vx&L(yuOY0bmPW2?d=!Eo`0o6}DnA4vx&!_aDk zY0dTQ_Ystl;*B(?pE^F04p2s*)hN@N>yY{g%4qRMo6}DnA4vx&qtI%MY0v5!eFSB! zcw^1!ua1wT1C%jnHO{nWbsT&IWxROf&FQa>kE8>XacDKcv=+KXA3>QY-b8Z-sN*B) z0A&JNO){;e{>yVdf-+gW$>t1H$4Alu$|SU!Vp>ZbQXfH?D&ACc2CCyD=>TO4T1_*p zrCxM>1ZBE-)6E&Ej*p}Rlxb)+!?cd7`N+MKo@qiK9djQ!VU`K~^dBi7tM&sLO$ z7>~uKRXaM`-(7qJWr=u8%xR^LkE8>X#b~uuwXB0f!&O2}x01x6VK1be+i6Iv#9T$zVzYcGT_CMQyVWEP z4cB~Wm*-#Str2q#S&Pl`p>%{nhXd`LC0!tGMZ4`PxoS^%0a^;_Wi0ojN{}4p4TY)o#;jg+W2nFmiju z+ha~Ub$lcppzKDgy{6R)1AaICK9UYl_M+83)v^xS?_mugr2S&EE|B)2-J2wi(V2vHVZOa3=38W~Hp_?71=5>ncYwq(VL)UAn;^B`HP&GMmi zfph@v-X?KO7!+w2M(&W9hsauOmJg*1q_@%T9ThQmcG79>V`%S+`!0LC$n&vug7ywt zzNcztPS}$WK{+hmVRI7d_((cHc@M3Qn3ki{(nnC<7w>&@66*L!IzTysR!2>1sG5(U zd?4Nj=5$xbN74bxQM4*Bt)XtbkDweA@0dB=)$x&ZfKq@~$5qQZIL#)d40>cJCTpu%K9nwyK0>=sNSqe-LN+u^-A~2*l&r00`B1t* z`ULGhBXOEdN*_Y{T+GkO+G>^$r3<9b(C!Nri=Esv&ZcCDp?xXtm+Xxv&&SdU+81bf zLe;Ey7V1EU5Yks-enr+IvwSFBAe}(FuSr~}1C4g!O7e}E-;lM)EFVf2NMEDfw07ibByph*G}?tL$w@I!lC{VzA4(TUg=lw*#D(GPkzsVV z97w0dJWbXjvwSFBAe}{fPOdsWk`7SLpw&6knuY;Et1xQk z#XE0Kt~x%F4p7da)%U7py<|=1*j8 zG|Pw51=5db_cMtb!d}RRhF$$d%wNdbXqFG93#6aX?pG2w*rE3!q~FB+jjWAk`B1t* z`W5Z|MB;{UxMb_X1o^X=e=_POaa?``w%Y>i9@H zK=}(={nfMi9@HK=~_L{oS+{VQkSV9Dsj__YZRhsN*B)0Ojv! z^-t4UgmFcyJpY*gFY*3m&H#0MBpsmq6RnEe7QUR6h2K9O{_oLezM4}GgwlE)W5b*|xSE`7upF|_$V|+zN)El8*#p+~IeT*;shh-E-6->9i_aUUq#k?W1bl0cr%(+6W8`Z+9^fwe+ z4CPAkZenjX?X-`fTqWMk?CC#7>iUJ5bG3N4u&4hh2R!>%Ij#|}gnC&8J8WNli0{dW zR2qYFdnD@a?g&Tv9ue<>SW-o-O`obP#usKpy%*{otm>l`RDHI(Pt^OMmSR;O{ajan z<+)$f`=Q>+sy_d@u3mjW)CZv6#p*&jAAF3j(1`jV)Vo<-M5>SRl^jtYf?8VDtb&;~ zrapvJLd<(2O9ynO&Y#=Gx>qgiz)G4IK88|Ky!+T&MV^nL+#%lm?CH-`T<_J5cZ-*;p8Nv_de!zJzEdMoWejqeNYvrm z73O0V5vxEft0J~uAI~htmup0Q7-~6IH_;&a7+=*9^%1D$S=DDq*VRw5s-jkfT7gyl zhen|4zcliwsEM9mHnNLqWW$yYE4$@$qZfne5@yGJ*c%qD)hYF5Dl+j}2EdP2;c$kJV3pfjhMSWl^i{ibKA5JRahUS0O+87kkNp=yX%k3D*Z zLccI`YKm8%J$i;hzu?sp?`ieqA1w(-I)v`WFwaCv*ik4h#CK|>PYaA&BNef)^t2OV z*R3&2^qiBg&pFRYzvs}e39Iy+gMP_2q8U_+>`Jr2ctsII3b4DIJt$9=QduRdf|m5 z)-<_h_GklVCu8($F5b(wb;m~Ak@X?IcOp_p>_)3d)Z;rk9N&b935cy##8%NWPKfaZ z6j3`tZNn-(#IOKY(3C?E#HX@Y;#jjXiqC$+u^m_TqJCkDhVz?HQ+o zcsOsu%GH#9Zp;zdN5%-~znz7wLUSeW{y11jvJ( z-?kGXo`Beox@`!1>H@sZ73nKT{i)l2+cqEKO^S&BggC&u9UJGnB?G*X5$Ru$23j{< z!NXAqAzs*t_#?zY)NOp|<^sI>6X_>NuTVF=X=UMZ&cn2&+R#^)bG|BI;R3GEZ zETWEuI*ip}r1}`&L=kly)ZwfSC)LOJUW=&Xp^jj61gSp8mr_KX0Cgm*BT4l!zTzV4 zM5v=!9Yv~-p$!&yG<&1T^D&em;*DW%40%3=GE}^=?2RSQ$58Ub8^_)_@_Y@6hE$M_ZUqRqlkPiA!ysXoT9pBHsD z)G4ekCe_FIjq{?;fjX7dC8YWozpY->xlpIEx|CEO;}_J6IuGh}R+o|LWBhV^QRhRQ z!Rm5SeT?5{FX|gmXR^A2R3GDa;fuNe>MT}QlImk6PZLNBEd6y=)4+t4gtx`$vTJS?spyJ(c9=Dtg#_h!ypcjXIpP z++lOy50_6r;fvzE#W+HJW?CN~Lg*vb`_#w%cvt$k0L9$o?%Uy?8MYa(?2{p^gJON4 zYr~Azj~y1fT`Pzs_wi9)Szv+WM@bpSW04dFQY0G5<0{GLBt1`jh_AuOHhqBu_hBUJ zsj@3vGQJe?ONbwth=2P$40{OO=6{@2+?Y=aQ`rTs{F!wq(08TSJlgEfO*u9u>{?a` zU6(IR!E0#UGaq7Ok0-a-4$5r10{9Tthhm+GdWC&L+i(TwE7n&@%k7r`wNe=cEiW>$08x%4MT;TTZ40RZyZ*q?L&?#plCA`Lg z;zE2GMYiT=Y|S|mhler1uF?>kCuOWDK6I=5-jsr6I!YnLstS{PZxdyiO%xx(Iw{tV zQ7@e+%XFd)6ziv?<%TGHC@*jUii47SXKPzzZ#aDj>#SJ6*xC;0i!5Bd>1g~)tMbpO z83oCQBso~WX*vDnX6H(e}97?+sThi=FhlN_hPc91Rm`|CJ5>FAmmUNt|G! z4_&XnlQP;4mJgls4^=SN>E<6|C;d|;`8k3f1s`I2`pZWBD`~l-5MJ99xB$fgV*H!> z=nFu30hyfb@)`!#f2fcDHE|gQ$zKsC?_Xg2m;30h7ueJ4?_&L*^*ONBUlo&q+o}Kg zCduc5knzMKcrU}#qQhPs?b8oF{ui=P_28UJbj@>aSuS>kF%t75@z_)izCWF;&pC9YPrYR2ui>q3ti#q7{_(C0bEwKcbbC_9t3d=>Vctlnx|%pVC1_ zGf$10qWl%(>5nRXm1t?DuMxdR>FY$hDIHAI#%Bo8GU^T`T2^Tu(Q-PSi$t z1W_B|kwk5TM-jCV9!=Cncnnb+;ju=e5guopMtD3?8{r8=ZG=}E&1lqHhvK+k`pwfH zrsN+{$-q=h|{l97XCUVKbevjx!qmAY+Be%S9t@Ly=}Yy@uKs7|lGe(fCEg+dR}={q%_ED$g*U@s3?YvkasCld2app58%e zaiVpUUi^pjl0T%E678rRE;E|(w)^F1?oM^N;q)ApulPfHCDD57UPZKv(rbt|PvvAa!6 zs#J(7&rwB|vAfRmRFN&P$_rGHZdQ4bDwU$jOIFE}_2_`UYz2Rbz+1c9G3#1cAtNVw z@xa?UskF9AW{#G6NvVyMGIE-^mEh;yQfX_I^ib#{g?3iRXcpF!E0y+E$!wMav?GOXRH*4U>@_KLr$X|a!>^f;LJuk=WC?tqL-@7M zioL9unF!U^Qf-ZDZ>we``X>9fkzyMZ`&cpE*V;<0Eo!+|%joOZ*-nb>Q0!~P%)Vir z?WNit)qYmZLe($aLCPIa?r-IcME~R_b(CU96bD!_-PaOQOQ1H;Y8m}~*G^LGgyJA8 zX7&&3>@3yJsJ>#=ba!);gNj-g)Lx}po8;znm0DNSUZYyuWUZUjx}o+u)w(8Y-KEwY zwK=|q7m}w&Ogg$#${f3U_FR^xkmO@0t!HT(Nj`Sc2PBQ8)rHte1uRjgk=*GROSDZR zd7CaQnVgTZN2Bs=n?meXm&MX3l6>r>i&+{=l8>EKilrqa`PfN!v9ydNA3N!OFX1_} z_^DBA@ShwQS9-uomnKVGeaNavJ z=x)MeD)`6=JygK@mj=aRC-r2B4*qC9_`PfNo zSz1hzkDauRrIjT4*h%YIT1AqNowR|aH6;1iNrfbhrV}#6PCCg_zI7VyV<(*=Y0PAk zLhPi|EYbCJ3|~)wWQk_x7@nCwu|zX-4A0D;S=vh54?qy-L3NCWO%cb>XvO-1~d+9%#a9P7+2$wTFmT-B);|NzUJf3hx!xIQsGCYxRWy6yQS1~-< zaAuio<5QT^eokdhJ35Uy?df#pw5v0i)4tARPCGk`IqmIi=Cr$WnA85wC0>^HcOLQ5 zt!$#tXWrWQ8_e4nU%2rPm-s>o`>F7hFMKJ5 zH>u#>{eqp4!dp}bZ;!r`!T~CTcR^oE;UEsNa1}dH1mbCQaDP5 z=Du)F3LjA6SzkCWg#s$H@P+TCaEuDc_xJdgjuehlp_MFwFIEcQUP>mOJ({*o)^FcA@qO)!h4dnW(7kM(tCowNI{ZkJR>{_8HaOkB?-! zqP7>c&#C5q1SB&SwS3gRpjsl?bDz}qq4p)!IwfoSrM4fn6IAP*ti36Uw0jl+5yzQp<1_O&x2Ash}ySQb3adzX^h(2sC`GZ9?9hnN$n77g;eXA zti2<(cThV?wO+~EyHa}>wNq5=jLtl_VZ1EkK7{>F{D*z^&ny;s$ow-qli%f$@4*y}_)6`Q7V+)MFNpYlb%y$o0o*waW$}=LqPSm&`Ix!tU&VavF6CDjH#BE;P%zUDI|KP^|mWVIW{%;(wsFTs3? z9k1J&FSYF~8S&&7TIGDXBjPsBr6O)Wr@xc=vMsuucQIc#N%`H(*V}w3&3uC$uX~tp zoTz>7jrd~a_eI?L+|PW|di5WO_$K8KGT&kI^Pz~_d6yk=>r*D;_Uo9-GT*gX*IO>) zb{!}mak~ywV7_Oo_Nf?gTW=-i^zW-yj`&pVQ-yiH9mj_wzDWH?B5w1cD)aq$>OV^S z+$cLQ9*el0M~^cfJy!cX!F<{V<<%l?<5QjajFIZsh`611H6y-M{aO*X>(!IYXWDhL zcEoM|)L}k%qxR2XKF`MIsfgQstuFJmw%&To*V*|}KjOCi4VbUDT>Y;^&9hb*~xoQLA-(nn&E`)w2=bqkfBs+j-ZL`DmLz z&qdsx6P}N_jl&Df$E?-$zQ}ySFy${re6;eHnNPL*SF4CGSHCs$X|t5KiMZWg+D6>w zTf2zcylu~XhRu@>5uc*#?Z|w#9hXGJ^VRRfe2!huJ4f7(R~P1U&F{*5fgP7_5x4WD zd&KR$=)rucUAKEOUvBrKUJG`+o*`!c{iH*Xq&fVB5uzQVOlQ7vhmQXY z=9@++pBZs`zMU0u8@JiaH_z8TbC_?l=YhEqx9j0N=G$%l%xAva#{UiGd+hvLz(^)8CIeJ)!}{D+}-UN2!j+|HM!%tzXIE{nL$hvgBs{wtVIx8t>v`3yV0tC-KS z``T*ebL@JxCgOHIT+4i}-M`i`pKsf_KH_iaao-SeyDw~vxP4CC#C(Cx^UV=or~S7? z+~&zv<_qomxsCZ^+pq1+m)Jbn5plcD>}0-thHlTUh}-kb?uf5de-HE3wmo~9ubHKO ze#C8i_Ay^;&&m5EZqNB|M%=E4Z$;d$&j*;Vv-buEnQyW6zRi4>okxcvZugycnD4ee z??!x&j>CJ*_t@v7!x6XZ_K}F&ynR37Hvf-C-0sUCFyA{tx2GWDQv+jah9=KE}aKZ&?q2R@CsZBLPGeIH1FiR)gWMNjD8DY?((XEeXx<=<=m zfXlzt{6Uu&YW`44UQzNQD7$Z&*j`m8ewN-kRf)JgdT1cGMjr z4VrZuz}imk782KOV2Wnlpjo$9Slh$hLgKo;nxa`ZXx42SYa_T@NL;tsqFtgFojGwj z*Ehj6C#!_-;TD@07i_g}_<|hBpsedJT1cF>k+m?%+)6{@ zw9Tw-;%*^v+E&)Kuoe=hZD%da9=FnvIBh3uJGfg&oVJ^_U95$~X?s}<)55JZBu?AM zT0VCRiPPR>Z9i)vaoPdW@`jM6iPH|THjK59IPG25!d#SH$P0e1yI8 zDbIY^P<;xkz2_9)xP2yi zG~)Id^RbBAyT`{PZl8UgU_Q)dTD6GVyMpQww|C|>B0fsDzh=bkXH2ysZtp0bjJSQ) zs2y?p3|=SV_U9M?IMjGrw2F?VVolh}$^#iMX9#xe>SXt8c{ZyyzEkoB#bIZu5LV#BH7r zjJVD7K@qok{z}Acp1&G#o42n;+}^3a&V0DtPX|Zb=GBmh+x!{Ie59R6c@ekm8OD6L z&7a{Bw|9vnB5w0)B=Zq=pB)u(yU&h}xSbbcB5v31u@SfH_PB`Kc{)DgHV-F6+^+Le zi1T;brZV4c<2;S|PP;!&Cw_LWy%U~6{LD_fZ_bRk&9_+*xBKaA;^(K?ahyZ^41ITQ zF7ussyyivRp3~+NKfBbldb zDi_3+;a0gYu8gqCMR8@MRnp_iXscwzm9bXIj4R`;k`-4bSfyB8nP`>bab=QKE{-dc zt#V0RnPQbot#XNs^~vFjtaw>m92ylbkBfOx@rt-OJStup7e_?JtK#CwsCac;932&} ziHl>S;4Jw*T=<)QSpYjI4LUL7#Al;#hc>dl&E-fT*TI{x1&sE>@XLe7s%AH&}JA9p0?&8Xsopc)B&6Tsm*Vr

5U6}*?X%Dr4UH*b_x?&Au+ab%VIxpHpfR;xS^Rpza<%7a|_VI-YW4{_z} zyal#QHdoHgTxOLrQDxz3tCWo@^XT}Lwyj3c2<^1SfR;kF9?>E!A zUWqH`m(fwE%$2iaXxyrB<;4quE=HD`)o7(XP&w??=*+s}WbW*#5k1l}vuk(JJEh+M;#D z?KMQ3h}&aO+lbr8_;wMu$G-LvAFVgl4iUG4exj$*CPgIh- zla_L$lH8lL)Hf>0ok>gmqLSQ~wA4Q;$z4fH1EP}Lle9E2D#;y5OM{}4+>f+0*h-oF zfIEaaJ>U*yP7ky6luu^9&|c6?VLs2!^r^&g zE73mFh~q}0d^&O5MwHJWj+=<`nZ$7mQ9g?}ZXn8M6Fp)8vzg+v)ac#O<>DS;TF6e;#prFZM;mH|g~FGU7J9Pek0_+kO>syS#iIal71o z6LC9DzKwXkZqIiSx9^-4GS9Qq;bg?^{nx38+XLR|h}-SyOvLRy(bFk#?E&w6 z#O-$QeZ=j-?}v!ngWr!4w+FeOB5v=&e~!4_4t|Nay%+m6;`W~Iw}{(q^iL7D_sD;a zxZTeF5^+0Uevi1FFMo}=oiBfjxScP5kGS2o{tx1pL zNpi7Ov1+Uo8=uF6e@Uva4vX`)U1|chZSCni2)6r|rB*R?cIsVjReX18Jr>t-yTVFn zyWSlX8;~olip|Cvm!)jgRgr+jv1@~Qv#&M*t40T#@Yh%ghfGSC3~pp>RIfGXI`8By zk^`4Fil^3friE7c7Dhb6*PDYqOLznAVsNlu z*jl?>-)sUlW0O>e+8nzjs^TDGJnfcoYibpp?Row-t76sLWW!_w>;x=f0`_rR^89j} zX9Iq_IcT!O9q#BPEolO_e^0WBPNzHmplVl`Qe1WOg!lbUs}?_`G?HGD&R!NI@_ukOjK=H%0#89yxy`_!g}T6 zAFfn(6)k5DHXhCrxBa&7 zh$@+b9mH+Op7bhP3C-uYYnnahREesyuvL6;AC9V67L(sj&qq?LIC*#KEUg+(a~+G9^`t6~nk;SK~YN0>#n zd3DUe=HYAP$?L5NIVNDx7VsVUDJ!ABl){;4gHzWWEROG=+kLa1m9T0lrQ9s)rwB6a z(LJky2^czDVIbI1YxoCM+pwpjDxQV#IA?qPj8(C1*e`j~;Dg@C1nd`tReC@hTM1jW zMlK!nfYijQ=!`1187H`HSW^?w8DnC1mS$GMfTJXn|Mbw!yyeZ!!P;>&qi3XNt(uj6 zo=(daR4BuRmQ*Oqh3BYHjtkFIp*$B}ph5*Myhw$LTzH8JmALRS6)JO~6&0#*p|ut8 z#(^tsxDxGqTdqVq-;OKM-nZvUwEG>n677FSu0#Wn;7T+CowyPWL1(T+W6*^vWur0Z z%9Usgx^X2MgYI03#-ImRqA}=cmCTM$x6*T_m+_3YhIQ32hBI5Y>ZLr_ct-bT ziu)4o(MItg!^O|;+H!7`{RHO~DxI6P?(7tMhwv(u&MsZSZ#!S3(z#g^&TY0gDz97V zigOEBpWQq0%-%Wtrh2dm89l1$HVz@&&G1menFV`|=NZrFYIqpo&W48*u3KH#If8I~ z!y^gTHayC3W}8-Bw99DYS)I8s#tIodo>YG<;ckY<8OEL(A0P1!+Gc|BjIM?!67Fnx z65%=nwaH||nVpGGAzq*ORN}RXPb1!h_;lmN3ih5FHdWU=!zx)_xiFIoZMiUu3Z1zy z+X@-&yXqR|5bkDpu3?O`@p;BGx*DEOxQ*dA2zNHTz;IUAt_SRe%0eo%;ld&-WHMiD zJgYMomQVq!usiuuDqs~>SY`#R!uWFIvI;A#utKq}r$$Zhtz){!}|z#HoTv3eZy}W&g@)ZPm*sDuTT7d@vK%4c70Gc{-6~ys`pg;mQk6Xz?tJAQk=E1u__|N5@~buQ2K z^4#}cd+qh@y>@&tuTgyWtv-I8;!C>v_zjBt-0$NzDem0a$8T}m#m8?`eD44sze90f z%vbMnj8(pexOU$Ma29zVd9A*KeB&QbeBW(8-iEmLeSL7k+|Ky}$af&G)%6nJOeNwv z{dgZp0Mzc<6+^HSd9AM9d^@`+?vG2U4=KKSptnDwxCgfBQ^e8xmGnmbX9QX?*iE1{ zgU<=HVNgY&ErTS1b_`Mk+A~NK=)fRDpd*7UK>U6sZQ&P8)V6=gL~Z<6Ow`tY%|vbf zH%!#_f6GJ-z;{g42z<{(4Z#mg)EN9oq?H^29CBkMrzBLYZHMsicLyA*43T=Q-k4m`a3wAXIIT3$#eEl?XKOe>?be*)7w6HG(`{|;174$iy{U9XGZ!5-~q+eOw zpM-^OppvGNRU7~zRj@9e_o5bTCBlCoq^HZNIudLp!hs}I$VX~o!Bip~1R*m`9&Sd0 ztwcDOgxT`#fmkq=2#1hRA`eev!Bip~3L%>(j|(HgRw5h*Ayt~^Hq%rh98N;HyfYoO zkTR7BM?gsDPq!`DN`xax7%Ok2MJ=RFCBjh z%(NADpll^VT?p9?ZlG)>LOlq{wepZ6?xd+is1G5vRh}fqoivpQ4IpHuj&^-8l?W%1 zuyBDBOeI1?2&p1@#u~4}R3bEjkSUOlI7EW2L^zp*x$@bCSTL0cr$9*hSG=`9x zIn{R3Rw6VZVXfO?Ql=82DTH*9yhj`L!B!$PgOD}vbwz@$L}(77s$#h9gRMk36+&|O zdMnsUgwseUaxZt%R3fy1kecXsIa7(yl7wXw-8h&^gjNvJ=BZY^ne=?CH3`LwZ3}5r zNegWt*dI-dUo86h#I__%bK{UPm9)@~gz4^dkTI1A?MYZKZ(78wFqH@$AY^B{Q#SXOgf^p47)Jm`a4R zAY{h61IJb(oDCs6%DvpS65$*YHo87!O(nv)5HicA*jLk5BAf>yS>g^oTZwQ!30qtr zlBN>j0to5Veltxa!i5krLn>S!OeMla5Yi*&yIsyyB3w*DiM(MSkEE$YxCBC`%uVLD z65&z^*cduz#ZMT65$#a+>wCSq#65&AznF{xE+e(CoAf(o~yChqQ(4T}Nw^yf3CBgs* znId<$Xe$vOhL9TLPAIk#VIYL`WY>bNM0f;3)uxqpByABgr^}S zi`*<{D-i~hFy5Uvlco}32npuPC(+^0Uqi_wVe@jg+nY*S$cK=c>h5`MCBje=w)!2$ zR3Z$6kY3>SYFmjg971-AyN$Ay2n8f8aV=y`B|;$yo7^OpHI)b>NZ35aZf4e0B8-HP zG=DlK9w_=FGDQ$l#qO%uR?@;K5>~i#cgj>EjE0bT)=fdS5@8I4{up#4VUggozN+=C_<9!B!$nB4L6% z^wOphVKNDe{nenUM3_RtdN&SfQ;9GYLS~3R^h_nfG!nKfvM+bWR3c0#VWOL1GNuw? z288TjHx9NEp_qixZY#2;5@9BUWTD$9Z6(4i5=OdJBuyp4Y!W88rzlBNi7*F3+I&6% z=A@~lh2;=ZgWXlJtwdM>Aw9<36x&LKl_ZRJXT7wkM0kdT3U_p;O(nuA2$>;n60?;E zt080y-JxeI5!R4U>>i?KO(jAZ3A5YiLil$8SZj1Ybp^oLP+J$vlED|MA!tOYLgpDTZyn4LNedI7Pb;$ z3klD-tw@?mgl9=u<*uufrV^n7LTZY8PHQU>wvrIMg?SD_x?qgmOj}6{&yz6SO(1Dg ziSPo1%)~8jrZtraFG9!;ae}Qxc!>n_#SZ;>$1Ju6O|N`$vbD0kNnX;X>t4uq_~$FY?N??SL&ZjW9p{+j!H z5K@KiwXl`6@IHj>bbsiXN`wy}BnP{#u$2hgNGNyXkTjJD+aaXZyURseiLe7gW{VSS zB|;^Hq@RLpB|-v1YM6VfW-AePk}%hu{ZpnAVHbq(o%@FnvNPNaV=HOlBM8YtcRH|@ z2p^L$&fQ-mO(nu7B&>EfVo6hp@F|4UH2+M@R3dyv!Yns|q)a8kZW88~x&y~lB79DQ z`P&H59+jfMl28R9J5+=A)bJ|oQdBK!j(Gs<1d*-C_eAtVdk%WW$W_V~kp{vlcD9zWVjggr^vw8(B|(o`bUfRHNk zGmNQ3*b73s%)J9*D-rgFkX-2=P}oX@eITUD-Ge(@iBOY-8SZj1WhxPBLC9=zmj|{I zp*9Kg-1EtdsYIv)A#46pRkRIjEytWeIND_+O zZFSmIA{<4+0(U)`HkAlRld#bBA#ExVj$y%__0kKa65&`97P-?w+EgMO2O&Gl?US|= z;dlt?HU5s(R3e-}LWR4vPn$}Fx)3tc+yr7P5$cn$%w0!iOeI1?2-(3-u$2gnNXU16 z$eK!oCM1-&$1GV>iO`e<_gZ92q!OVS2@Bjzn>CdP%}H42_Nc6>MA+j`|GoTLy?e(K zh{Stx+{ec?IPUA?y%5*#-5dJeDu=%hLzEqGr6rn(gc3 zt)o(wsEf7L+96jf64&EcE+8bX&#_ER5;x#@k{`sAI4<^aLyqPCNE&Ixv0T(hd@{$f zV@Z4p$1=T0+!%4qrhbi0Oe*8BWQV#A=}5|SD7F-(6Dc#G*iw|! zNhyY6OHs}sWhN9`igFeyv!U2hlygX#3&obAoJ-0)D7F;kd{RoF*iw`WNLc{ImZDrl z$|5MX6y;)47DKV6D3_2@3dNS9TuRCkD7F;kGE$a8v85=TNtwLe-tX1fVM|diCuRJ0 zd$$!I0aA+6g_L3_wiM+GQWik5r6^Y#CH~`W(J{CK^IBJcS_%1tgZNj4<8BeGX~+-f-ME9N!m?@8?)< z<)rNg!g0TF{9rhKh+}!2CT;f*#{?;58)-W~91rDK?ry~%7LJE=ERO`mE(phk92fdm zXGAz2$?-IA7lq?d9Ltvuq$i`p@feQfajMv3!|}LqJU$#x;8^aYr0t2}cv3i?9FC`O zT;|7QYB-)2j;Dv?864v*RUD3IhT~b`cs9qFzvqPGxg6sRI4>N}5630pcmc(`aF$va zju&w(cMbAdE)K_~;dn_nUP|#!oQs!*gZE5-gS9Pj3Mgg>}H564v;CIDxxhCHB=GWmn+trW0PRfQ=K?=yfF0_`T;L}S(5s(wfnPMh>-K9d@LMkM zy8`qw{gDg&nG5^{P-_=X`hSPxf5P#<;dqa~{6oEX?^y0%>peBVOj1LE1df}%G{BCz zw+8YkS@ytv7?je=YifX%*U~`V)t07eD?q)fqXBxguLkJVehijUulCmfy*fYx^y)tf zP_GWu0KGa$1N7=(2Fs{dhbTbnI8+0y<1h`dj>8!&ufzr(p#ZJpNCqpYS4Sy8OB~H$ zB`tA`23YyA3Q$wWF({*^j@JN9ouC0;s1p^Sb<}0BmWHIB0<=VZ2J5I-4KzTnPSOCq zYN!CMqY;Dk)T@&fpe0UWuz^5h1{Yj|Q=g0Y@R9b%g@dt1C4?uexf0UR}kYfO^$U z0b0k^8ekpWHNZNqVK9=`ajgc}@*Wys%db;_deu_{^s1Kz=+*TEDpw^|`AeJ|7_266 zBZ0&S0yhEdTQ@N(fhQR^D>9nMEsBgGa;qX^iQJ~hI3l+zGM@T&2S|J+herf=Y9JqH zmTRWo3eXter2#Ir@74f=-$w%s{yhvzsaN-EfL`@gfO>VG2I$rO8lYDXXnv(|y z-~7F(04?zngM7NUeOUwa>J<&pt5+4Ev)X?(z*+5o4EX-*H4U)x*EPV(-%x-y@J$VH zoWI3@Z?oRk04sk-1FZaA1!(2(G2ok~_cg#eKF|Q`*roujW4i{}z#R*;t zi6jF)O{6ry5@`lyw2q7hSR%`yoR;`P11#|+fkZwXgI{TYWAJMRe4Y3WgWezK#4*BfgLPNh7|I{28cD<$AhE|3w2_W&O%vBQ5cp23X>E z2AgP!KQzD+e=;beCH~R?OZ?5CoR;`U11#|`gB7&I9)Ht&AuAGCVowIkX^9#dV2QmL ztfVFO)&NWF!(c5fQBwmfQH#MkTB5cFSfUPtayo_Ws{tmb{WQSjw7&wh2OppS-68yk zK^cJq8LTC65QB9D4rajn?jagr%MWG1`|e>HV2Q&S@VWngQ>- z$7p~hj%C36?r|DmiQ^gYzI%cOSmHzmyzkc4087+k!251}4X{K52E6Z{qyd&_$bk3V zMjBw>Jy`?nyQe5X`)*?eXoqXUfcM>|40zvd#(?+T<_vf{PSpV0ahe9$jur~gcC=(r zmcUu06@zjDtr@JRrrI#zo2IrJpu6ofKzG|S;4SZ<0h;Ql0h;Q>fV+D-1HNxLgTdki zJ{xjoF3=TVzsl&=ng-=6jre}GTW)l9HAD?|*Jvf7YZOZG<@dGK5k{^@b%e3Ij#0E# z^u|}u+^83$6^UVVcD%ki!V{Yt7?oA>K;5VjKP9-S8lqF%%?hc`-;x{MS{>o-w%e*9 z8u{CEqdOQyxA`=NcjiXD6^h0X*OqrNDzA(N*uP70cW%^2qviCX+@nx5P}l+P&5in2 zL)4A?a-;hht&2L39pC|tc*pLS8$HM#qBlPg`>Ie-!K`44s!o&MyZuAtRJT<&eS3@)!gBcA~yXcVW z2%XQXj?nphjh55(=+N9~m`1$G!*inoh14b&=0+nJMSCIjaAY+^165QVVKhc*#FO6W zYKR&fqY*#s99s?1QWG>J&j8AW&8v|Y1uquGQiOQYipFXbFY@#O)~-0BG3n5PjpIKMi=QY8wh zOcL%*ozg4mO_K2jLM?X09wK*Iw8`!mNJS@Z5XI!jN%gq&~ieF z=z%Ap6$+{CTFGdnYVaA2xWQElsRmawigp_6#u`S^EJ~=1QGBFeyUH2qxpyriJ;AOc zRJl>DYdxXpITm+g1Ec7fDxF3*GKww^sE3;v#UqbPk;SJ4 zN<^bU=sQA{YZF81s{!8=O5`c@1JD7LixWem|KW!3M-B6%4aWyVej*s35~Kg{g_xfS z#+`|GJAY033&YiwWr;$1fch)LjZt?-Qipycm?(^vGrM2kni z@v(dGLO(_=RgN#+w^BL2&(Rur&6|BIZGvfAN>A}_J4ze-v^}Md`?Le4Px`bY(%PR7 zMxQ&W9A5}HUFG<={2408r=-qQISz`mRF0eTvsI1{@Sme{oQBR-`6$0#=c#rb+ubQW-KW=3+R3NaQhK&edr(@>r`I8kjuh-&J(1VM-rS2)?9JCxioN*;O0hTJ zh*a&(H>n(Z^UcU>Ht@Z^h0;boy_M1?KD~`n{JO>Mls5P79h9Eo(>p0W%cs35J=3Rm zQ+k6>`%rq4Pw%0$p-=Cn^c*8_0YnSnup6Lq9Cia$j>GN| z#;kYs!CpgA$pX?0ByTb8@;rJtt@%^ul!|^BK_|tIw8OL}6usa-o9*(QRagt+v z06Z0r)8RN1jNgGeJRB)r?jn4kD#=jPmiRuy-$y# zw1ZENrnI9^kD(L~ERLlV4>yjZ6gT6?Q;OT}6DY+k`iYd{K}cOnaf4lt(sQN1eQKQh zZ;L)P>JvE6g7ad~fWY|{oF9Xe2wY&n1u}{$;1mLv zSa3-U8WXtGf=gr2gurDMTo!|-1Ug&LIR?!LTyDYTF=$Spiv?X`a4LZ-EVv>DrxCc) zf-7Utf;$ikVl-}aqb1A(wPW#lT7x%5+zkO<)N9;Dk>c^~p#Lg#nyI~Dt)*xaR5WB;$ zlVWyK#4aRur(q3a)-Ylh5$kPOqnI^{*u})|GVJ7-ogA@Ch}~`2DKR@GVwV!@V_4&u zHICS2#O^VyNz9r=tTVBD4Qm>+rV+cGSYN}M#jIJxx)8h1u;wvq9t|Stn6-%5Rm2`NtYyqvMywmLhYV{KvsMwinpl6sTF0z)#JUq3 zU|5@&wTaj@#2z-RZOqz6>{?<24Qm&(b`k4A>=DD-$ElCw25xbrkJ*uYkiFgUQ&ApLQJixw*(x<$8E7It(cAn2~Q~4;L->&k} zKEFfdxRtt-^Zd=;@2zq?h`5XMym{WgTjjWP?4xpAAl{>LTn65&@+H3gzMSWy{rgmo z_U~6Y+J8Xh`M&*rD&OMs2RYB1@AHRLzQE`GRldmQ15{q>^M_Tw)aL_Ljz@rxsCF=O9_K@G z{LWW7=I0WXqdyB&j>owRRgU9*k;?HHb+O7Z50t8WgWs+tD#!e=ROOqzzf9$rHi<(T)LRXOIp3YBBtdqL%x_g+-_IN#5gR6gG4 zFRL8$1n!KFQ~=sT}j_>nfk({WnxT)#q=j9P{v7DxdECw^fdL;60UN-hN-@ zGkrTBsC<^sx2YWS{C1UNp5LKz%=0@{j(L8U$}!J>sB&DVeTux+3(!B~81` 0 && segment.size < 64 + IDN::Idna.toASCII(segment, IDN::Idna::ALLOW_UNASSIGNED) + elsif segment.size >= 64 + segment + else + '' + end + end.join('.') + end + + def self.to_unicode(value) + value.to_s.split('.', -1).map do |segment| + if segment.size > 0 && segment.size < 64 + IDN::Idna.toUnicode(segment, IDN::Idna::ALLOW_UNASSIGNED) + elsif segment.size >= 64 + segment + else + '' + end + end.join('.') + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/addressable-2.8.5/lib/addressable/idna/pure.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/addressable-2.8.5/lib/addressable/idna/pure.rb new file mode 100644 index 0000000000..3d6ffbadf2 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/addressable-2.8.5/lib/addressable/idna/pure.rb @@ -0,0 +1,505 @@ +# frozen_string_literal: true + +#-- +# Copyright (C) Bob Aman +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#++ + + +module Addressable + module IDNA + # This module is loosely based on idn_actionmailer by Mick Staugaard, + # the unicode library by Yoshida Masato, and the punycode implementation + # by Kazuhiro Nishiyama. Most of the code was copied verbatim, but + # some reformatting was done, and some translation from C was done. + # + # Without their code to work from as a base, we'd all still be relying + # on the presence of libidn. Which nobody ever seems to have installed. + # + # Original sources: + # http://github.com/staugaard/idn_actionmailer + # http://www.yoshidam.net/Ruby.html#unicode + # http://rubyforge.org/frs/?group_id=2550 + + + UNICODE_TABLE = File.expand_path( + File.join(File.dirname(__FILE__), '../../..', 'data/unicode.data') + ) + + ACE_PREFIX = "xn--" + + UTF8_REGEX = /\A(?: + [\x09\x0A\x0D\x20-\x7E] # ASCII + | [\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte + | \xE0[\xA0-\xBF][\x80-\xBF] # excluding overlongs + | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2} # straight 3-byte + | \xED[\x80-\x9F][\x80-\xBF] # excluding surrogates + | \xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3 + | [\xF1-\xF3][\x80-\xBF]{3} # planes 4nil5 + | \xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16 + )*\z/mnx + + UTF8_REGEX_MULTIBYTE = /(?: + [\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte + | \xE0[\xA0-\xBF][\x80-\xBF] # excluding overlongs + | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2} # straight 3-byte + | \xED[\x80-\x9F][\x80-\xBF] # excluding surrogates + | \xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3 + | [\xF1-\xF3][\x80-\xBF]{3} # planes 4nil5 + | \xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16 + )/mnx + + # :startdoc: + + # Converts from a Unicode internationalized domain name to an ASCII + # domain name as described in RFC 3490. + def self.to_ascii(input) + input = input.to_s unless input.is_a?(String) + input = input.dup.force_encoding(Encoding::UTF_8).unicode_normalize(:nfkc) + if input.respond_to?(:force_encoding) + input.force_encoding(Encoding::ASCII_8BIT) + end + if input =~ UTF8_REGEX && input =~ UTF8_REGEX_MULTIBYTE + parts = unicode_downcase(input).split('.') + parts.map! do |part| + if part.respond_to?(:force_encoding) + part.force_encoding(Encoding::ASCII_8BIT) + end + if part =~ UTF8_REGEX && part =~ UTF8_REGEX_MULTIBYTE + ACE_PREFIX + punycode_encode(part) + else + part + end + end + parts.join('.') + else + input + end + end + + # Converts from an ASCII domain name to a Unicode internationalized + # domain name as described in RFC 3490. + def self.to_unicode(input) + input = input.to_s unless input.is_a?(String) + parts = input.split('.') + parts.map! do |part| + if part =~ /^#{ACE_PREFIX}(.+)/ + begin + punycode_decode(part[/^#{ACE_PREFIX}(.+)/, 1]) + rescue Addressable::IDNA::PunycodeBadInput + # toUnicode is explicitly defined as never-fails by the spec + part + end + else + part + end + end + output = parts.join('.') + if output.respond_to?(:force_encoding) + output.force_encoding(Encoding::UTF_8) + end + output + end + + class << self + # @deprecated Use {String#unicode_normalize(:nfkc)} instead + def unicode_normalize_kc(value) + value.to_s.unicode_normalize(:nfkc) + end + + extend Gem::Deprecate + deprecate :unicode_normalize_kc, "String#unicode_normalize(:nfkc)", 2023, 4 + end + + ## + # Unicode aware downcase method. + # + # @api private + # @param [String] input + # The input string. + # @return [String] The downcased result. + def self.unicode_downcase(input) + input = input.to_s unless input.is_a?(String) + unpacked = input.unpack("U*") + unpacked.map! { |codepoint| lookup_unicode_lowercase(codepoint) } + return unpacked.pack("U*") + end + private_class_method :unicode_downcase + + def self.lookup_unicode_lowercase(codepoint) + codepoint_data = UNICODE_DATA[codepoint] + (codepoint_data ? + (codepoint_data[UNICODE_DATA_LOWERCASE] || codepoint) : + codepoint) + end + private_class_method :lookup_unicode_lowercase + + UNICODE_DATA_COMBINING_CLASS = 0 + UNICODE_DATA_EXCLUSION = 1 + UNICODE_DATA_CANONICAL = 2 + UNICODE_DATA_COMPATIBILITY = 3 + UNICODE_DATA_UPPERCASE = 4 + UNICODE_DATA_LOWERCASE = 5 + UNICODE_DATA_TITLECASE = 6 + + begin + if defined?(FakeFS) + fakefs_state = FakeFS.activated? + FakeFS.deactivate! + end + # This is a sparse Unicode table. Codepoints without entries are + # assumed to have the value: [0, 0, nil, nil, nil, nil, nil] + UNICODE_DATA = File.open(UNICODE_TABLE, "rb") do |file| + Marshal.load(file.read) + end + ensure + if defined?(FakeFS) + FakeFS.activate! if fakefs_state + end + end + + COMPOSITION_TABLE = {} + UNICODE_DATA.each do |codepoint, data| + canonical = data[UNICODE_DATA_CANONICAL] + exclusion = data[UNICODE_DATA_EXCLUSION] + + if canonical && exclusion == 0 + COMPOSITION_TABLE[canonical.unpack("C*")] = codepoint + end + end + + UNICODE_MAX_LENGTH = 256 + ACE_MAX_LENGTH = 256 + + PUNYCODE_BASE = 36 + PUNYCODE_TMIN = 1 + PUNYCODE_TMAX = 26 + PUNYCODE_SKEW = 38 + PUNYCODE_DAMP = 700 + PUNYCODE_INITIAL_BIAS = 72 + PUNYCODE_INITIAL_N = 0x80 + PUNYCODE_DELIMITER = 0x2D + + PUNYCODE_MAXINT = 1 << 64 + + PUNYCODE_PRINT_ASCII = + "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n" + + "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n" + + " !\"\#$%&'()*+,-./" + + "0123456789:;<=>?" + + "@ABCDEFGHIJKLMNO" + + "PQRSTUVWXYZ[\\]^_" + + "`abcdefghijklmno" + + "pqrstuvwxyz{|}~\n" + + # Input is invalid. + class PunycodeBadInput < StandardError; end + # Output would exceed the space provided. + class PunycodeBigOutput < StandardError; end + # Input needs wider integers to process. + class PunycodeOverflow < StandardError; end + + def self.punycode_encode(unicode) + unicode = unicode.to_s unless unicode.is_a?(String) + input = unicode.unpack("U*") + output = [0] * (ACE_MAX_LENGTH + 1) + input_length = input.size + output_length = [ACE_MAX_LENGTH] + + # Initialize the state + n = PUNYCODE_INITIAL_N + delta = out = 0 + max_out = output_length[0] + bias = PUNYCODE_INITIAL_BIAS + + # Handle the basic code points: + input_length.times do |j| + if punycode_basic?(input[j]) + if max_out - out < 2 + raise PunycodeBigOutput, + "Output would exceed the space provided." + end + output[out] = input[j] + out += 1 + end + end + + h = b = out + + # h is the number of code points that have been handled, b is the + # number of basic code points, and out is the number of characters + # that have been output. + + if b > 0 + output[out] = PUNYCODE_DELIMITER + out += 1 + end + + # Main encoding loop: + + while h < input_length + # All non-basic code points < n have been + # handled already. Find the next larger one: + + m = PUNYCODE_MAXINT + input_length.times do |j| + m = input[j] if (n...m) === input[j] + end + + # Increase delta enough to advance the decoder's + # state to , but guard against overflow: + + if m - n > (PUNYCODE_MAXINT - delta) / (h + 1) + raise PunycodeOverflow, "Input needs wider integers to process." + end + delta += (m - n) * (h + 1) + n = m + + input_length.times do |j| + # Punycode does not need to check whether input[j] is basic: + if input[j] < n + delta += 1 + if delta == 0 + raise PunycodeOverflow, + "Input needs wider integers to process." + end + end + + if input[j] == n + # Represent delta as a generalized variable-length integer: + + q = delta; k = PUNYCODE_BASE + while true + if out >= max_out + raise PunycodeBigOutput, + "Output would exceed the space provided." + end + t = ( + if k <= bias + PUNYCODE_TMIN + elsif k >= bias + PUNYCODE_TMAX + PUNYCODE_TMAX + else + k - bias + end + ) + break if q < t + output[out] = + punycode_encode_digit(t + (q - t) % (PUNYCODE_BASE - t)) + out += 1 + q = (q - t) / (PUNYCODE_BASE - t) + k += PUNYCODE_BASE + end + + output[out] = punycode_encode_digit(q) + out += 1 + bias = punycode_adapt(delta, h + 1, h == b) + delta = 0 + h += 1 + end + end + + delta += 1 + n += 1 + end + + output_length[0] = out + + outlen = out + outlen.times do |j| + c = output[j] + unless c >= 0 && c <= 127 + raise StandardError, "Invalid output char." + end + unless PUNYCODE_PRINT_ASCII[c] + raise PunycodeBadInput, "Input is invalid." + end + end + + output[0..outlen].map { |x| x.chr }.join("").sub(/\0+\z/, "") + end + private_class_method :punycode_encode + + def self.punycode_decode(punycode) + input = [] + output = [] + + if ACE_MAX_LENGTH * 2 < punycode.size + raise PunycodeBigOutput, "Output would exceed the space provided." + end + punycode.each_byte do |c| + unless c >= 0 && c <= 127 + raise PunycodeBadInput, "Input is invalid." + end + input.push(c) + end + + input_length = input.length + output_length = [UNICODE_MAX_LENGTH] + + # Initialize the state + n = PUNYCODE_INITIAL_N + + out = i = 0 + max_out = output_length[0] + bias = PUNYCODE_INITIAL_BIAS + + # Handle the basic code points: Let b be the number of input code + # points before the last delimiter, or 0 if there is none, then + # copy the first b code points to the output. + + b = 0 + input_length.times do |j| + b = j if punycode_delimiter?(input[j]) + end + if b > max_out + raise PunycodeBigOutput, "Output would exceed the space provided." + end + + b.times do |j| + unless punycode_basic?(input[j]) + raise PunycodeBadInput, "Input is invalid." + end + output[out] = input[j] + out+=1 + end + + # Main decoding loop: Start just after the last delimiter if any + # basic code points were copied; start at the beginning otherwise. + + in_ = b > 0 ? b + 1 : 0 + while in_ < input_length + + # in_ is the index of the next character to be consumed, and + # out is the number of code points in the output array. + + # Decode a generalized variable-length integer into delta, + # which gets added to i. The overflow checking is easier + # if we increase i as we go, then subtract off its starting + # value at the end to obtain delta. + + oldi = i; w = 1; k = PUNYCODE_BASE + while true + if in_ >= input_length + raise PunycodeBadInput, "Input is invalid." + end + digit = punycode_decode_digit(input[in_]) + in_+=1 + if digit >= PUNYCODE_BASE + raise PunycodeBadInput, "Input is invalid." + end + if digit > (PUNYCODE_MAXINT - i) / w + raise PunycodeOverflow, "Input needs wider integers to process." + end + i += digit * w + t = ( + if k <= bias + PUNYCODE_TMIN + elsif k >= bias + PUNYCODE_TMAX + PUNYCODE_TMAX + else + k - bias + end + ) + break if digit < t + if w > PUNYCODE_MAXINT / (PUNYCODE_BASE - t) + raise PunycodeOverflow, "Input needs wider integers to process." + end + w *= PUNYCODE_BASE - t + k += PUNYCODE_BASE + end + + bias = punycode_adapt(i - oldi, out + 1, oldi == 0) + + # I was supposed to wrap around from out + 1 to 0, + # incrementing n each time, so we'll fix that now: + + if i / (out + 1) > PUNYCODE_MAXINT - n + raise PunycodeOverflow, "Input needs wider integers to process." + end + n += i / (out + 1) + i %= out + 1 + + # Insert n at position i of the output: + + # not needed for Punycode: + # raise PUNYCODE_INVALID_INPUT if decode_digit(n) <= base + if out >= max_out + raise PunycodeBigOutput, "Output would exceed the space provided." + end + + #memmove(output + i + 1, output + i, (out - i) * sizeof *output) + output[i + 1, out - i] = output[i, out - i] + output[i] = n + i += 1 + + out += 1 + end + + output_length[0] = out + + output.pack("U*") + end + private_class_method :punycode_decode + + def self.punycode_basic?(codepoint) + codepoint < 0x80 + end + private_class_method :punycode_basic? + + def self.punycode_delimiter?(codepoint) + codepoint == PUNYCODE_DELIMITER + end + private_class_method :punycode_delimiter? + + def self.punycode_encode_digit(d) + d + 22 + 75 * ((d < 26) ? 1 : 0) + end + private_class_method :punycode_encode_digit + + # Returns the numeric value of a basic codepoint + # (for use in representing integers) in the range 0 to + # base - 1, or PUNYCODE_BASE if codepoint does not represent a value. + def self.punycode_decode_digit(codepoint) + if codepoint - 48 < 10 + codepoint - 22 + elsif codepoint - 65 < 26 + codepoint - 65 + elsif codepoint - 97 < 26 + codepoint - 97 + else + PUNYCODE_BASE + end + end + private_class_method :punycode_decode_digit + + # Bias adaptation method + def self.punycode_adapt(delta, numpoints, firsttime) + delta = firsttime ? delta / PUNYCODE_DAMP : delta >> 1 + # delta >> 1 is a faster way of doing delta / 2 + delta += delta / numpoints + difference = PUNYCODE_BASE - PUNYCODE_TMIN + + k = 0 + while delta > (difference * PUNYCODE_TMAX) / 2 + delta /= difference + k += PUNYCODE_BASE + end + + k + (difference + 1) * delta / (delta + PUNYCODE_SKEW) + end + private_class_method :punycode_adapt + end + # :startdoc: +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/addressable-2.8.5/lib/addressable/template.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/addressable-2.8.5/lib/addressable/template.rb new file mode 100644 index 0000000000..bc5204154f --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/addressable-2.8.5/lib/addressable/template.rb @@ -0,0 +1,1029 @@ +# frozen_string_literal: true + +#-- +# Copyright (C) Bob Aman +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#++ + + +require "addressable/version" +require "addressable/uri" + +module Addressable + ## + # This is an implementation of a URI template based on + # RFC 6570 (http://tools.ietf.org/html/rfc6570). + class Template + # Constants used throughout the template code. + anything = + Addressable::URI::CharacterClasses::RESERVED + + Addressable::URI::CharacterClasses::UNRESERVED + + + variable_char_class = + Addressable::URI::CharacterClasses::ALPHA + + Addressable::URI::CharacterClasses::DIGIT + '_' + + var_char = + "(?>(?:[#{variable_char_class}]|%[a-fA-F0-9][a-fA-F0-9])+)" + RESERVED = + "(?:[#{anything}]|%[a-fA-F0-9][a-fA-F0-9])" + UNRESERVED = + "(?:[#{ + Addressable::URI::CharacterClasses::UNRESERVED + }]|%[a-fA-F0-9][a-fA-F0-9])" + variable = + "(?:#{var_char}(?:\\.?#{var_char})*)" + varspec = + "(?:(#{variable})(\\*|:\\d+)?)" + VARNAME = + /^#{variable}$/ + VARSPEC = + /^#{varspec}$/ + VARIABLE_LIST = + /^#{varspec}(?:,#{varspec})*$/ + operator = + "+#./;?&=,!@|" + EXPRESSION = + /\{([#{operator}])?(#{varspec}(?:,#{varspec})*)\}/ + + + LEADERS = { + '?' => '?', + '/' => '/', + '#' => '#', + '.' => '.', + ';' => ';', + '&' => '&' + } + JOINERS = { + '?' => '&', + '.' => '.', + ';' => ';', + '&' => '&', + '/' => '/' + } + + ## + # Raised if an invalid template value is supplied. + class InvalidTemplateValueError < StandardError + end + + ## + # Raised if an invalid template operator is used in a pattern. + class InvalidTemplateOperatorError < StandardError + end + + ## + # Raised if an invalid template operator is used in a pattern. + class TemplateOperatorAbortedError < StandardError + end + + ## + # This class represents the data that is extracted when a Template + # is matched against a URI. + class MatchData + ## + # Creates a new MatchData object. + # MatchData objects should never be instantiated directly. + # + # @param [Addressable::URI] uri + # The URI that the template was matched against. + def initialize(uri, template, mapping) + @uri = uri.dup.freeze + @template = template + @mapping = mapping.dup.freeze + end + + ## + # @return [Addressable::URI] + # The URI that the Template was matched against. + attr_reader :uri + + ## + # @return [Addressable::Template] + # The Template used for the match. + attr_reader :template + + ## + # @return [Hash] + # The mapping that resulted from the match. + # Note that this mapping does not include keys or values for + # variables that appear in the Template, but are not present + # in the URI. + attr_reader :mapping + + ## + # @return [Array] + # The list of variables that were present in the Template. + # Note that this list will include variables which do not appear + # in the mapping because they were not present in URI. + def variables + self.template.variables + end + alias_method :keys, :variables + alias_method :names, :variables + + ## + # @return [Array] + # The list of values that were captured by the Template. + # Note that this list will include nils for any variables which + # were in the Template, but did not appear in the URI. + def values + @values ||= self.variables.inject([]) do |accu, key| + accu << self.mapping[key] + accu + end + end + alias_method :captures, :values + + ## + # Accesses captured values by name or by index. + # + # @param [String, Symbol, Fixnum] key + # Capture index or name. Note that when accessing by with index + # of 0, the full URI will be returned. The intention is to mimic + # the ::MatchData#[] behavior. + # + # @param [#to_int, nil] len + # If provided, an array of values will be returend with the given + # parameter used as length. + # + # @return [Array, String, nil] + # The captured value corresponding to the index or name. If the + # value was not provided or the key is unknown, nil will be + # returned. + # + # If the second parameter is provided, an array of that length will + # be returned instead. + def [](key, len = nil) + if len + to_a[key, len] + elsif String === key or Symbol === key + mapping[key.to_s] + else + to_a[key] + end + end + + ## + # @return [Array] + # Array with the matched URI as first element followed by the captured + # values. + def to_a + [to_s, *values] + end + + ## + # @return [String] + # The matched URI as String. + def to_s + uri.to_s + end + alias_method :string, :to_s + + # Returns multiple captured values at once. + # + # @param [String, Symbol, Fixnum] *indexes + # Indices of the captures to be returned + # + # @return [Array] + # Values corresponding to given indices. + # + # @see Addressable::Template::MatchData#[] + def values_at(*indexes) + indexes.map { |i| self[i] } + end + + ## + # Returns a String representation of the MatchData's state. + # + # @return [String] The MatchData's state, as a String. + def inspect + sprintf("#<%s:%#0x RESULT:%s>", + self.class.to_s, self.object_id, self.mapping.inspect) + end + + ## + # Dummy method for code expecting a ::MatchData instance + # + # @return [String] An empty string. + def pre_match + "" + end + alias_method :post_match, :pre_match + end + + ## + # Creates a new Addressable::Template object. + # + # @param [#to_str] pattern The URI Template pattern. + # + # @return [Addressable::Template] The initialized Template object. + def initialize(pattern) + if !pattern.respond_to?(:to_str) + raise TypeError, "Can't convert #{pattern.class} into String." + end + @pattern = pattern.to_str.dup.freeze + end + + ## + # Freeze URI, initializing instance variables. + # + # @return [Addressable::URI] The frozen URI object. + def freeze + self.variables + self.variable_defaults + self.named_captures + super + end + + ## + # @return [String] The Template object's pattern. + attr_reader :pattern + + ## + # Returns a String representation of the Template object's state. + # + # @return [String] The Template object's state, as a String. + def inspect + sprintf("#<%s:%#0x PATTERN:%s>", + self.class.to_s, self.object_id, self.pattern) + end + + ## + # Returns true if the Template objects are equal. This method + # does NOT normalize either Template before doing the comparison. + # + # @param [Object] template The Template to compare. + # + # @return [TrueClass, FalseClass] + # true if the Templates are equivalent, false + # otherwise. + def ==(template) + return false unless template.kind_of?(Template) + return self.pattern == template.pattern + end + + ## + # Addressable::Template makes no distinction between `==` and `eql?`. + # + # @see #== + alias_method :eql?, :== + + ## + # Extracts a mapping from the URI using a URI Template pattern. + # + # @param [Addressable::URI, #to_str] uri + # The URI to extract from. + # + # @param [#restore, #match] processor + # A template processor object may optionally be supplied. + # + # The object should respond to either the restore or + # match messages or both. The restore method should + # take two parameters: `[String] name` and `[String] value`. + # The restore method should reverse any transformations that + # have been performed on the value to ensure a valid URI. + # The match method should take a single + # parameter: `[String] name`. The match method should return + # a String containing a regular expression capture group for + # matching on that particular variable. The default value is `".*?"`. + # The match method has no effect on multivariate operator + # expansions. + # + # @return [Hash, NilClass] + # The Hash mapping that was extracted from the URI, or + # nil if the URI didn't match the template. + # + # @example + # class ExampleProcessor + # def self.restore(name, value) + # return value.gsub(/\+/, " ") if name == "query" + # return value + # end + # + # def self.match(name) + # return ".*?" if name == "first" + # return ".*" + # end + # end + # + # uri = Addressable::URI.parse( + # "http://example.com/search/an+example+search+query/" + # ) + # Addressable::Template.new( + # "http://example.com/search/{query}/" + # ).extract(uri, ExampleProcessor) + # #=> {"query" => "an example search query"} + # + # uri = Addressable::URI.parse("http://example.com/a/b/c/") + # Addressable::Template.new( + # "http://example.com/{first}/{second}/" + # ).extract(uri, ExampleProcessor) + # #=> {"first" => "a", "second" => "b/c"} + # + # uri = Addressable::URI.parse("http://example.com/a/b/c/") + # Addressable::Template.new( + # "http://example.com/{first}/{-list|/|second}/" + # ).extract(uri) + # #=> {"first" => "a", "second" => ["b", "c"]} + def extract(uri, processor=nil) + match_data = self.match(uri, processor) + return (match_data ? match_data.mapping : nil) + end + + ## + # Extracts match data from the URI using a URI Template pattern. + # + # @param [Addressable::URI, #to_str] uri + # The URI to extract from. + # + # @param [#restore, #match] processor + # A template processor object may optionally be supplied. + # + # The object should respond to either the restore or + # match messages or both. The restore method should + # take two parameters: `[String] name` and `[String] value`. + # The restore method should reverse any transformations that + # have been performed on the value to ensure a valid URI. + # The match method should take a single + # parameter: `[String] name`. The match method should return + # a String containing a regular expression capture group for + # matching on that particular variable. The default value is `".*?"`. + # The match method has no effect on multivariate operator + # expansions. + # + # @return [Hash, NilClass] + # The Hash mapping that was extracted from the URI, or + # nil if the URI didn't match the template. + # + # @example + # class ExampleProcessor + # def self.restore(name, value) + # return value.gsub(/\+/, " ") if name == "query" + # return value + # end + # + # def self.match(name) + # return ".*?" if name == "first" + # return ".*" + # end + # end + # + # uri = Addressable::URI.parse( + # "http://example.com/search/an+example+search+query/" + # ) + # match = Addressable::Template.new( + # "http://example.com/search/{query}/" + # ).match(uri, ExampleProcessor) + # match.variables + # #=> ["query"] + # match.captures + # #=> ["an example search query"] + # + # uri = Addressable::URI.parse("http://example.com/a/b/c/") + # match = Addressable::Template.new( + # "http://example.com/{first}/{+second}/" + # ).match(uri, ExampleProcessor) + # match.variables + # #=> ["first", "second"] + # match.captures + # #=> ["a", "b/c"] + # + # uri = Addressable::URI.parse("http://example.com/a/b/c/") + # match = Addressable::Template.new( + # "http://example.com/{first}{/second*}/" + # ).match(uri) + # match.variables + # #=> ["first", "second"] + # match.captures + # #=> ["a", ["b", "c"]] + def match(uri, processor=nil) + uri = Addressable::URI.parse(uri) unless uri.is_a?(Addressable::URI) + mapping = {} + + # First, we need to process the pattern, and extract the values. + expansions, expansion_regexp = + parse_template_pattern(pattern, processor) + + return nil unless uri.to_str.match(expansion_regexp) + unparsed_values = uri.to_str.scan(expansion_regexp).flatten + + if uri.to_str == pattern + return Addressable::Template::MatchData.new(uri, self, mapping) + elsif expansions.size > 0 + index = 0 + expansions.each do |expansion| + _, operator, varlist = *expansion.match(EXPRESSION) + varlist.split(',').each do |varspec| + _, name, modifier = *varspec.match(VARSPEC) + mapping[name] ||= nil + case operator + when nil, '+', '#', '/', '.' + unparsed_value = unparsed_values[index] + name = varspec[VARSPEC, 1] + value = unparsed_value + value = value.split(JOINERS[operator]) if value && modifier == '*' + when ';', '?', '&' + if modifier == '*' + if unparsed_values[index] + value = unparsed_values[index].split(JOINERS[operator]) + value = value.inject({}) do |acc, v| + key, val = v.split('=') + val = "" if val.nil? + acc[key] = val + acc + end + end + else + if (unparsed_values[index]) + name, value = unparsed_values[index].split('=') + value = "" if value.nil? + end + end + end + if processor != nil && processor.respond_to?(:restore) + value = processor.restore(name, value) + end + if processor == nil + if value.is_a?(Hash) + value = value.inject({}){|acc, (k, v)| + acc[Addressable::URI.unencode_component(k)] = + Addressable::URI.unencode_component(v) + acc + } + elsif value.is_a?(Array) + value = value.map{|v| Addressable::URI.unencode_component(v) } + else + value = Addressable::URI.unencode_component(value) + end + end + if !mapping.has_key?(name) || mapping[name].nil? + # Doesn't exist, set to value (even if value is nil) + mapping[name] = value + end + index = index + 1 + end + end + return Addressable::Template::MatchData.new(uri, self, mapping) + else + return nil + end + end + + ## + # Expands a URI template into another URI template. + # + # @param [Hash] mapping The mapping that corresponds to the pattern. + # @param [#validate, #transform] processor + # An optional processor object may be supplied. + # @param [Boolean] normalize_values + # Optional flag to enable/disable unicode normalization. Default: true + # + # The object should respond to either the validate or + # transform messages or both. Both the validate and + # transform methods should take two parameters: name and + # value. The validate method should return true + # or false; true if the value of the variable is valid, + # false otherwise. An InvalidTemplateValueError + # exception will be raised if the value is invalid. The transform + # method should return the transformed variable value as a String. + # If a transform method is used, the value will not be percent + # encoded automatically. Unicode normalization will be performed both + # before and after sending the value to the transform method. + # + # @return [Addressable::Template] The partially expanded URI template. + # + # @example + # Addressable::Template.new( + # "http://example.com/{one}/{two}/" + # ).partial_expand({"one" => "1"}).pattern + # #=> "http://example.com/1/{two}/" + # + # Addressable::Template.new( + # "http://example.com/{?one,two}/" + # ).partial_expand({"one" => "1"}).pattern + # #=> "http://example.com/?one=1{&two}/" + # + # Addressable::Template.new( + # "http://example.com/{?one,two,three}/" + # ).partial_expand({"one" => "1", "three" => 3}).pattern + # #=> "http://example.com/?one=1{&two}&three=3" + def partial_expand(mapping, processor=nil, normalize_values=true) + result = self.pattern.dup + mapping = normalize_keys(mapping) + result.gsub!( EXPRESSION ) do |capture| + transform_partial_capture(mapping, capture, processor, normalize_values) + end + return Addressable::Template.new(result) + end + + ## + # Expands a URI template into a full URI. + # + # @param [Hash] mapping The mapping that corresponds to the pattern. + # @param [#validate, #transform] processor + # An optional processor object may be supplied. + # @param [Boolean] normalize_values + # Optional flag to enable/disable unicode normalization. Default: true + # + # The object should respond to either the validate or + # transform messages or both. Both the validate and + # transform methods should take two parameters: name and + # value. The validate method should return true + # or false; true if the value of the variable is valid, + # false otherwise. An InvalidTemplateValueError + # exception will be raised if the value is invalid. The transform + # method should return the transformed variable value as a String. + # If a transform method is used, the value will not be percent + # encoded automatically. Unicode normalization will be performed both + # before and after sending the value to the transform method. + # + # @return [Addressable::URI] The expanded URI template. + # + # @example + # class ExampleProcessor + # def self.validate(name, value) + # return !!(value =~ /^[\w ]+$/) if name == "query" + # return true + # end + # + # def self.transform(name, value) + # return value.gsub(/ /, "+") if name == "query" + # return value + # end + # end + # + # Addressable::Template.new( + # "http://example.com/search/{query}/" + # ).expand( + # {"query" => "an example search query"}, + # ExampleProcessor + # ).to_str + # #=> "http://example.com/search/an+example+search+query/" + # + # Addressable::Template.new( + # "http://example.com/search/{query}/" + # ).expand( + # {"query" => "an example search query"} + # ).to_str + # #=> "http://example.com/search/an%20example%20search%20query/" + # + # Addressable::Template.new( + # "http://example.com/search/{query}/" + # ).expand( + # {"query" => "bogus!"}, + # ExampleProcessor + # ).to_str + # #=> Addressable::Template::InvalidTemplateValueError + def expand(mapping, processor=nil, normalize_values=true) + result = self.pattern.dup + mapping = normalize_keys(mapping) + result.gsub!( EXPRESSION ) do |capture| + transform_capture(mapping, capture, processor, normalize_values) + end + return Addressable::URI.parse(result) + end + + ## + # Returns an Array of variables used within the template pattern. + # The variables are listed in the Array in the order they appear within + # the pattern. Multiple occurrences of a variable within a pattern are + # not represented in this Array. + # + # @return [Array] The variables present in the template's pattern. + def variables + @variables ||= ordered_variable_defaults.map { |var, val| var }.uniq + end + alias_method :keys, :variables + alias_method :names, :variables + + ## + # Returns a mapping of variables to their default values specified + # in the template. Variables without defaults are not returned. + # + # @return [Hash] Mapping of template variables to their defaults + def variable_defaults + @variable_defaults ||= + Hash[*ordered_variable_defaults.reject { |k, v| v.nil? }.flatten] + end + + ## + # Coerces a template into a `Regexp` object. This regular expression will + # behave very similarly to the actual template, and should match the same + # URI values, but it cannot fully handle, for example, values that would + # extract to an `Array`. + # + # @return [Regexp] A regular expression which should match the template. + def to_regexp + _, source = parse_template_pattern(pattern) + Regexp.new(source) + end + + ## + # Returns the source of the coerced `Regexp`. + # + # @return [String] The source of the `Regexp` given by {#to_regexp}. + # + # @api private + def source + self.to_regexp.source + end + + ## + # Returns the named captures of the coerced `Regexp`. + # + # @return [Hash] The named captures of the `Regexp` given by {#to_regexp}. + # + # @api private + def named_captures + self.to_regexp.named_captures + end + + private + def ordered_variable_defaults + @ordered_variable_defaults ||= begin + expansions, _ = parse_template_pattern(pattern) + expansions.flat_map do |capture| + _, _, varlist = *capture.match(EXPRESSION) + varlist.split(',').map do |varspec| + varspec[VARSPEC, 1] + end + end + end + end + + + ## + # Loops through each capture and expands any values available in mapping + # + # @param [Hash] mapping + # Set of keys to expand + # @param [String] capture + # The expression to expand + # @param [#validate, #transform] processor + # An optional processor object may be supplied. + # @param [Boolean] normalize_values + # Optional flag to enable/disable unicode normalization. Default: true + # + # The object should respond to either the validate or + # transform messages or both. Both the validate and + # transform methods should take two parameters: name and + # value. The validate method should return true + # or false; true if the value of the variable is valid, + # false otherwise. An InvalidTemplateValueError exception + # will be raised if the value is invalid. The transform method + # should return the transformed variable value as a String. If a + # transform method is used, the value will not be percent encoded + # automatically. Unicode normalization will be performed both before and + # after sending the value to the transform method. + # + # @return [String] The expanded expression + def transform_partial_capture(mapping, capture, processor = nil, + normalize_values = true) + _, operator, varlist = *capture.match(EXPRESSION) + + vars = varlist.split(",") + + if operator == "?" + # partial expansion of form style query variables sometimes requires a + # slight reordering of the variables to produce a valid url. + first_to_expand = vars.find { |varspec| + _, name, _ = *varspec.match(VARSPEC) + mapping.key?(name) && !mapping[name].nil? + } + + vars = [first_to_expand] + vars.reject {|varspec| varspec == first_to_expand} if first_to_expand + end + + vars. + inject("".dup) do |acc, varspec| + _, name, _ = *varspec.match(VARSPEC) + next_val = if mapping.key? name + transform_capture(mapping, "{#{operator}#{varspec}}", + processor, normalize_values) + else + "{#{operator}#{varspec}}" + end + # If we've already expanded at least one '?' operator with non-empty + # value, change to '&' + operator = "&" if (operator == "?") && (next_val != "") + acc << next_val + end + end + + ## + # Transforms a mapped value so that values can be substituted into the + # template. + # + # @param [Hash] mapping The mapping to replace captures + # @param [String] capture + # The expression to replace + # @param [#validate, #transform] processor + # An optional processor object may be supplied. + # @param [Boolean] normalize_values + # Optional flag to enable/disable unicode normalization. Default: true + # + # + # The object should respond to either the validate or + # transform messages or both. Both the validate and + # transform methods should take two parameters: name and + # value. The validate method should return true + # or false; true if the value of the variable is valid, + # false otherwise. An InvalidTemplateValueError exception + # will be raised if the value is invalid. The transform method + # should return the transformed variable value as a String. If a + # transform method is used, the value will not be percent encoded + # automatically. Unicode normalization will be performed both before and + # after sending the value to the transform method. + # + # @return [String] The expanded expression + def transform_capture(mapping, capture, processor=nil, + normalize_values=true) + _, operator, varlist = *capture.match(EXPRESSION) + return_value = varlist.split(',').inject([]) do |acc, varspec| + _, name, modifier = *varspec.match(VARSPEC) + value = mapping[name] + unless value == nil || value == {} + allow_reserved = %w(+ #).include?(operator) + # Common primitives where the .to_s output is well-defined + if Numeric === value || Symbol === value || + value == true || value == false + value = value.to_s + end + length = modifier.gsub(':', '').to_i if modifier =~ /^:\d+/ + + unless (Hash === value) || + value.respond_to?(:to_ary) || value.respond_to?(:to_str) + raise TypeError, + "Can't convert #{value.class} into String or Array." + end + + value = normalize_value(value) if normalize_values + + if processor == nil || !processor.respond_to?(:transform) + # Handle percent escaping + if allow_reserved + encode_map = + Addressable::URI::CharacterClasses::RESERVED + + Addressable::URI::CharacterClasses::UNRESERVED + else + encode_map = Addressable::URI::CharacterClasses::UNRESERVED + end + if value.kind_of?(Array) + transformed_value = value.map do |val| + if length + Addressable::URI.encode_component(val[0...length], encode_map) + else + Addressable::URI.encode_component(val, encode_map) + end + end + unless modifier == "*" + transformed_value = transformed_value.join(',') + end + elsif value.kind_of?(Hash) + transformed_value = value.map do |key, val| + if modifier == "*" + "#{ + Addressable::URI.encode_component( key, encode_map) + }=#{ + Addressable::URI.encode_component( val, encode_map) + }" + else + "#{ + Addressable::URI.encode_component( key, encode_map) + },#{ + Addressable::URI.encode_component( val, encode_map) + }" + end + end + unless modifier == "*" + transformed_value = transformed_value.join(',') + end + else + if length + transformed_value = Addressable::URI.encode_component( + value[0...length], encode_map) + else + transformed_value = Addressable::URI.encode_component( + value, encode_map) + end + end + end + + # Process, if we've got a processor + if processor != nil + if processor.respond_to?(:validate) + if !processor.validate(name, value) + display_value = value.kind_of?(Array) ? value.inspect : value + raise InvalidTemplateValueError, + "#{name}=#{display_value} is an invalid template value." + end + end + if processor.respond_to?(:transform) + transformed_value = processor.transform(name, value) + if normalize_values + transformed_value = normalize_value(transformed_value) + end + end + end + acc << [name, transformed_value] + end + acc + end + return "" if return_value.empty? + join_values(operator, return_value) + end + + ## + # Takes a set of values, and joins them together based on the + # operator. + # + # @param [String, Nil] operator One of the operators from the set + # (?,&,+,#,;,/,.), or nil if there wasn't one. + # @param [Array] return_value + # The set of return values (as [variable_name, value] tuples) that will + # be joined together. + # + # @return [String] The transformed mapped value + def join_values(operator, return_value) + leader = LEADERS.fetch(operator, '') + joiner = JOINERS.fetch(operator, ',') + case operator + when '&', '?' + leader + return_value.map{|k,v| + if v.is_a?(Array) && v.first =~ /=/ + v.join(joiner) + elsif v.is_a?(Array) + v.map{|inner_value| "#{k}=#{inner_value}"}.join(joiner) + else + "#{k}=#{v}" + end + }.join(joiner) + when ';' + return_value.map{|k,v| + if v.is_a?(Array) && v.first =~ /=/ + ';' + v.join(";") + elsif v.is_a?(Array) + ';' + v.map{|inner_value| "#{k}=#{inner_value}"}.join(";") + else + v && v != '' ? ";#{k}=#{v}" : ";#{k}" + end + }.join + else + leader + return_value.map{|k,v| v}.join(joiner) + end + end + + ## + # Takes a set of values, and joins them together based on the + # operator. + # + # @param [Hash, Array, String] value + # Normalizes unicode keys and values with String#unicode_normalize (NFC) + # + # @return [Hash, Array, String] The normalized values + def normalize_value(value) + # Handle unicode normalization + if value.respond_to?(:to_ary) + value.to_ary.map! { |val| normalize_value(val) } + elsif value.kind_of?(Hash) + value = value.inject({}) { |acc, (k, v)| + acc[normalize_value(k)] = normalize_value(v) + acc + } + else + value = value.to_s if !value.kind_of?(String) + if value.encoding != Encoding::UTF_8 + value = value.dup.force_encoding(Encoding::UTF_8) + end + value = value.unicode_normalize(:nfc) + end + value + end + + ## + # Generates a hash with string keys + # + # @param [Hash] mapping A mapping hash to normalize + # + # @return [Hash] + # A hash with stringified keys + def normalize_keys(mapping) + return mapping.inject({}) do |accu, pair| + name, value = pair + if Symbol === name + name = name.to_s + elsif name.respond_to?(:to_str) + name = name.to_str + else + raise TypeError, + "Can't convert #{name.class} into String." + end + accu[name] = value + accu + end + end + + ## + # Generates the Regexp that parses a template pattern. Memoizes the + # value if template processor not set (processors may not be deterministic) + # + # @param [String] pattern The URI template pattern. + # @param [#match] processor The template processor to use. + # + # @return [Array, Regexp] + # An array of expansion variables nad a regular expression which may be + # used to parse a template pattern + def parse_template_pattern(pattern, processor = nil) + if processor.nil? && pattern == @pattern + @cached_template_parse ||= + parse_new_template_pattern(pattern, processor) + else + parse_new_template_pattern(pattern, processor) + end + end + + ## + # Generates the Regexp that parses a template pattern. + # + # @param [String] pattern The URI template pattern. + # @param [#match] processor The template processor to use. + # + # @return [Array, Regexp] + # An array of expansion variables nad a regular expression which may be + # used to parse a template pattern + def parse_new_template_pattern(pattern, processor = nil) + # Escape the pattern. The two gsubs restore the escaped curly braces + # back to their original form. Basically, escape everything that isn't + # within an expansion. + escaped_pattern = Regexp.escape( + pattern + ).gsub(/\\\{(.*?)\\\}/) do |escaped| + escaped.gsub(/\\(.)/, "\\1") + end + + expansions = [] + + # Create a regular expression that captures the values of the + # variables in the URI. + regexp_string = escaped_pattern.gsub( EXPRESSION ) do |expansion| + + expansions << expansion + _, operator, varlist = *expansion.match(EXPRESSION) + leader = Regexp.escape(LEADERS.fetch(operator, '')) + joiner = Regexp.escape(JOINERS.fetch(operator, ',')) + combined = varlist.split(',').map do |varspec| + _, name, modifier = *varspec.match(VARSPEC) + + result = processor && processor.respond_to?(:match) ? processor.match(name) : nil + if result + "(?<#{name}>#{ result })" + else + group = case operator + when '+' + "#{ RESERVED }*?" + when '#' + "#{ RESERVED }*?" + when '/' + "#{ UNRESERVED }*?" + when '.' + "#{ UNRESERVED.gsub('\.', '') }*?" + when ';' + "#{ UNRESERVED }*=?#{ UNRESERVED }*?" + when '?' + "#{ UNRESERVED }*=#{ UNRESERVED }*?" + when '&' + "#{ UNRESERVED }*=#{ UNRESERVED }*?" + else + "#{ UNRESERVED }*?" + end + if modifier == '*' + "(?<#{name}>#{group}(?:#{joiner}?#{group})*)?" + else + "(?<#{name}>#{group})?" + end + end + end.join("#{joiner}?") + "(?:|#{leader}#{combined})" + end + + # Ensure that the regular expression matches the whole URI. + regexp_string = "\\A#{regexp_string}\\z" + return expansions, Regexp.new(regexp_string) + end + + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/addressable-2.8.5/lib/addressable/uri.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/addressable-2.8.5/lib/addressable/uri.rb new file mode 100644 index 0000000000..08ee3348a7 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/addressable-2.8.5/lib/addressable/uri.rb @@ -0,0 +1,2591 @@ +# frozen_string_literal: true + +#-- +# Copyright (C) Bob Aman +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#++ + + +require "addressable/version" +require "addressable/idna" +require "public_suffix" + +## +# Addressable is a library for processing links and URIs. +module Addressable + ## + # This is an implementation of a URI parser based on + # RFC 3986, + # RFC 3987. + class URI + ## + # Raised if something other than a uri is supplied. + class InvalidURIError < StandardError + end + + ## + # Container for the character classes specified in + # RFC 3986. + # + # Note: Concatenated and interpolated `String`s are not affected by the + # `frozen_string_literal` directive and must be frozen explicitly. + # + # Interpolated `String`s *were* frozen this way before Ruby 3.0: + # https://bugs.ruby-lang.org/issues/17104 + module CharacterClasses + ALPHA = "a-zA-Z" + DIGIT = "0-9" + GEN_DELIMS = "\\:\\/\\?\\#\\[\\]\\@" + SUB_DELIMS = "\\!\\$\\&\\'\\(\\)\\*\\+\\,\\;\\=" + RESERVED = (GEN_DELIMS + SUB_DELIMS).freeze + UNRESERVED = (ALPHA + DIGIT + "\\-\\.\\_\\~").freeze + PCHAR = (UNRESERVED + SUB_DELIMS + "\\:\\@").freeze + SCHEME = (ALPHA + DIGIT + "\\-\\+\\.").freeze + HOST = (UNRESERVED + SUB_DELIMS + "\\[\\:\\]").freeze + AUTHORITY = (PCHAR + "\\[\\]").freeze + PATH = (PCHAR + "\\/").freeze + QUERY = (PCHAR + "\\/\\?").freeze + FRAGMENT = (PCHAR + "\\/\\?").freeze + end + + module NormalizeCharacterClasses + HOST = /[^#{CharacterClasses::HOST}]/ + UNRESERVED = /[^#{CharacterClasses::UNRESERVED}]/ + PCHAR = /[^#{CharacterClasses::PCHAR}]/ + SCHEME = /[^#{CharacterClasses::SCHEME}]/ + FRAGMENT = /[^#{CharacterClasses::FRAGMENT}]/ + QUERY = %r{[^a-zA-Z0-9\-\.\_\~\!\$\'\(\)\*\+\,\=\:\@\/\?%]|%(?!2B|2b)} + end + + SLASH = '/' + EMPTY_STR = '' + + URIREGEX = /^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?$/ + + PORT_MAPPING = { + "http" => 80, + "https" => 443, + "ftp" => 21, + "tftp" => 69, + "sftp" => 22, + "ssh" => 22, + "svn+ssh" => 22, + "telnet" => 23, + "nntp" => 119, + "gopher" => 70, + "wais" => 210, + "ldap" => 389, + "prospero" => 1525 + }.freeze + + ## + # Returns a URI object based on the parsed string. + # + # @param [String, Addressable::URI, #to_str] uri + # The URI string to parse. + # No parsing is performed if the object is already an + # Addressable::URI. + # + # @return [Addressable::URI] The parsed URI. + def self.parse(uri) + # If we were given nil, return nil. + return nil unless uri + # If a URI object is passed, just return itself. + return uri.dup if uri.kind_of?(self) + + # If a URI object of the Ruby standard library variety is passed, + # convert it to a string, then parse the string. + # We do the check this way because we don't want to accidentally + # cause a missing constant exception to be thrown. + if uri.class.name =~ /^URI\b/ + uri = uri.to_s + end + + # Otherwise, convert to a String + begin + uri = uri.to_str + rescue TypeError, NoMethodError + raise TypeError, "Can't convert #{uri.class} into String." + end unless uri.is_a?(String) + + # This Regexp supplied as an example in RFC 3986, and it works great. + scan = uri.scan(URIREGEX) + fragments = scan[0] + scheme = fragments[1] + authority = fragments[3] + path = fragments[4] + query = fragments[6] + fragment = fragments[8] + user = nil + password = nil + host = nil + port = nil + if authority != nil + # The Regexp above doesn't split apart the authority. + userinfo = authority[/^([^\[\]]*)@/, 1] + if userinfo != nil + user = userinfo.strip[/^([^:]*):?/, 1] + password = userinfo.strip[/:(.*)$/, 1] + end + + host = authority.sub( + /^([^\[\]]*)@/, EMPTY_STR + ).sub( + /:([^:@\[\]]*?)$/, EMPTY_STR + ) + + port = authority[/:([^:@\[\]]*?)$/, 1] + port = nil if port == EMPTY_STR + end + + return new( + :scheme => scheme, + :user => user, + :password => password, + :host => host, + :port => port, + :path => path, + :query => query, + :fragment => fragment + ) + end + + ## + # Converts an input to a URI. The input does not have to be a valid + # URI — the method will use heuristics to guess what URI was intended. + # This is not standards-compliant, merely user-friendly. + # + # @param [String, Addressable::URI, #to_str] uri + # The URI string to parse. + # No parsing is performed if the object is already an + # Addressable::URI. + # @param [Hash] hints + # A Hash of hints to the heuristic parser. + # Defaults to {:scheme => "http"}. + # + # @return [Addressable::URI] The parsed URI. + def self.heuristic_parse(uri, hints={}) + # If we were given nil, return nil. + return nil unless uri + # If a URI object is passed, just return itself. + return uri.dup if uri.kind_of?(self) + + # If a URI object of the Ruby standard library variety is passed, + # convert it to a string, then parse the string. + # We do the check this way because we don't want to accidentally + # cause a missing constant exception to be thrown. + if uri.class.name =~ /^URI\b/ + uri = uri.to_s + end + + unless uri.respond_to?(:to_str) + raise TypeError, "Can't convert #{uri.class} into String." + end + # Otherwise, convert to a String + uri = uri.to_str.dup.strip + hints = { + :scheme => "http" + }.merge(hints) + case uri + when /^http:\//i + uri.sub!(/^http:\/+/i, "http://") + when /^https:\//i + uri.sub!(/^https:\/+/i, "https://") + when /^feed:\/+http:\//i + uri.sub!(/^feed:\/+http:\/+/i, "feed:http://") + when /^feed:\//i + uri.sub!(/^feed:\/+/i, "feed://") + when %r[^file:/{4}]i + uri.sub!(%r[^file:/+]i, "file:////") + when %r[^file://localhost/]i + uri.sub!(%r[^file://localhost/+]i, "file:///") + when %r[^file:/+]i + uri.sub!(%r[^file:/+]i, "file:///") + when /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/ + uri.sub!(/^/, hints[:scheme] + "://") + when /\A\d+\..*:\d+\z/ + uri = "#{hints[:scheme]}://#{uri}" + end + match = uri.match(URIREGEX) + fragments = match.captures + authority = fragments[3] + if authority && authority.length > 0 + new_authority = authority.tr("\\", "/").gsub(" ", "%20") + # NOTE: We want offset 4, not 3! + offset = match.offset(4) + uri = uri.dup + uri[offset[0]...offset[1]] = new_authority + end + parsed = self.parse(uri) + if parsed.scheme =~ /^[^\/?#\.]+\.[^\/?#]+$/ + parsed = self.parse(hints[:scheme] + "://" + uri) + end + if parsed.path.include?(".") + if parsed.path[/\b@\b/] + parsed.scheme = "mailto" unless parsed.scheme + elsif new_host = parsed.path[/^([^\/]+\.[^\/]*)/, 1] + parsed.defer_validation do + new_path = parsed.path.sub( + Regexp.new("^" + Regexp.escape(new_host)), EMPTY_STR) + parsed.host = new_host + parsed.path = new_path + parsed.scheme = hints[:scheme] unless parsed.scheme + end + end + end + return parsed + end + + ## + # Converts a path to a file scheme URI. If the path supplied is + # relative, it will be returned as a relative URI. If the path supplied + # is actually a non-file URI, it will parse the URI as if it had been + # parsed with Addressable::URI.parse. Handles all of the + # various Microsoft-specific formats for specifying paths. + # + # @param [String, Addressable::URI, #to_str] path + # Typically a String path to a file or directory, but + # will return a sensible return value if an absolute URI is supplied + # instead. + # + # @return [Addressable::URI] + # The parsed file scheme URI or the original URI if some other URI + # scheme was provided. + # + # @example + # base = Addressable::URI.convert_path("/absolute/path/") + # uri = Addressable::URI.convert_path("relative/path") + # (base + uri).to_s + # #=> "file:///absolute/path/relative/path" + # + # Addressable::URI.convert_path( + # "c:\\windows\\My Documents 100%20\\foo.txt" + # ).to_s + # #=> "file:///c:/windows/My%20Documents%20100%20/foo.txt" + # + # Addressable::URI.convert_path("http://example.com/").to_s + # #=> "http://example.com/" + def self.convert_path(path) + # If we were given nil, return nil. + return nil unless path + # If a URI object is passed, just return itself. + return path if path.kind_of?(self) + unless path.respond_to?(:to_str) + raise TypeError, "Can't convert #{path.class} into String." + end + # Otherwise, convert to a String + path = path.to_str.strip + + path.sub!(/^file:\/?\/?/, EMPTY_STR) if path =~ /^file:\/?\/?/ + path = SLASH + path if path =~ /^([a-zA-Z])[\|:]/ + uri = self.parse(path) + + if uri.scheme == nil + # Adjust windows-style uris + uri.path.sub!(/^\/?([a-zA-Z])[\|:][\\\/]/) do + "/#{$1.downcase}:/" + end + uri.path.tr!("\\", SLASH) + if File.exist?(uri.path) && + File.stat(uri.path).directory? + uri.path.chomp!(SLASH) + uri.path = uri.path + '/' + end + + # If the path is absolute, set the scheme and host. + if uri.path.start_with?(SLASH) + uri.scheme = "file" + uri.host = EMPTY_STR + end + uri.normalize! + end + + return uri + end + + ## + # Joins several URIs together. + # + # @param [String, Addressable::URI, #to_str] *uris + # The URIs to join. + # + # @return [Addressable::URI] The joined URI. + # + # @example + # base = "http://example.com/" + # uri = Addressable::URI.parse("relative/path") + # Addressable::URI.join(base, uri) + # #=> # + def self.join(*uris) + uri_objects = uris.collect do |uri| + unless uri.respond_to?(:to_str) + raise TypeError, "Can't convert #{uri.class} into String." + end + uri.kind_of?(self) ? uri : self.parse(uri.to_str) + end + result = uri_objects.shift.dup + uri_objects.each do |uri| + result.join!(uri) + end + return result + end + + ## + # Tables used to optimize encoding operations in `self.encode_component` + # and `self.normalize_component` + SEQUENCE_ENCODING_TABLE = (0..255).map do |byte| + format("%02x", byte).freeze + end.freeze + + SEQUENCE_UPCASED_PERCENT_ENCODING_TABLE = (0..255).map do |byte| + format("%%%02X", byte).freeze + end.freeze + + ## + # Percent encodes a URI component. + # + # @param [String, #to_str] component The URI component to encode. + # + # @param [String, Regexp] character_class + # The characters which are not percent encoded. If a String + # is passed, the String must be formatted as a regular + # expression character class. (Do not include the surrounding square + # brackets.) For example, "b-zB-Z0-9" would cause + # everything but the letters 'b' through 'z' and the numbers '0' through + # '9' to be percent encoded. If a Regexp is passed, the + # value /[^b-zB-Z0-9]/ would have the same effect. A set of + # useful String values may be found in the + # Addressable::URI::CharacterClasses module. The default + # value is the reserved plus unreserved character classes specified in + # RFC 3986. + # + # @param [Regexp] upcase_encoded + # A string of characters that may already be percent encoded, and whose + # encodings should be upcased. This allows normalization of percent + # encodings for characters not included in the + # character_class. + # + # @return [String] The encoded component. + # + # @example + # Addressable::URI.encode_component("simple/example", "b-zB-Z0-9") + # => "simple%2Fex%61mple" + # Addressable::URI.encode_component("simple/example", /[^b-zB-Z0-9]/) + # => "simple%2Fex%61mple" + # Addressable::URI.encode_component( + # "simple/example", Addressable::URI::CharacterClasses::UNRESERVED + # ) + # => "simple%2Fexample" + def self.encode_component(component, character_class= + CharacterClasses::RESERVED + CharacterClasses::UNRESERVED, + upcase_encoded='') + return nil if component.nil? + + begin + if component.kind_of?(Symbol) || + component.kind_of?(Numeric) || + component.kind_of?(TrueClass) || + component.kind_of?(FalseClass) + component = component.to_s + else + component = component.to_str + end + rescue TypeError, NoMethodError + raise TypeError, "Can't convert #{component.class} into String." + end if !component.is_a? String + + if ![String, Regexp].include?(character_class.class) + raise TypeError, + "Expected String or Regexp, got #{character_class.inspect}" + end + if character_class.kind_of?(String) + character_class = /[^#{character_class}]/ + end + # We can't perform regexps on invalid UTF sequences, but + # here we need to, so switch to ASCII. + component = component.dup + component.force_encoding(Encoding::ASCII_8BIT) + # Avoiding gsub! because there are edge cases with frozen strings + component = component.gsub(character_class) do |char| + SEQUENCE_UPCASED_PERCENT_ENCODING_TABLE[char.ord] + end + if upcase_encoded.length > 0 + upcase_encoded_chars = upcase_encoded.bytes.map do |byte| + SEQUENCE_ENCODING_TABLE[byte] + end + component = component.gsub(/%(#{upcase_encoded_chars.join('|')})/, + &:upcase) + end + + return component + end + + class << self + alias_method :escape_component, :encode_component + end + + ## + # Unencodes any percent encoded characters within a URI component. + # This method may be used for unencoding either components or full URIs, + # however, it is recommended to use the unencode_component + # alias when unencoding components. + # + # @param [String, Addressable::URI, #to_str] uri + # The URI or component to unencode. + # + # @param [Class] return_type + # The type of object to return. + # This value may only be set to String or + # Addressable::URI. All other values are invalid. Defaults + # to String. + # + # @param [String] leave_encoded + # A string of characters to leave encoded. If a percent encoded character + # in this list is encountered then it will remain percent encoded. + # + # @return [String, Addressable::URI] + # The unencoded component or URI. + # The return type is determined by the return_type + # parameter. + def self.unencode(uri, return_type=String, leave_encoded='') + return nil if uri.nil? + + begin + uri = uri.to_str + rescue NoMethodError, TypeError + raise TypeError, "Can't convert #{uri.class} into String." + end if !uri.is_a? String + if ![String, ::Addressable::URI].include?(return_type) + raise TypeError, + "Expected Class (String or Addressable::URI), " + + "got #{return_type.inspect}" + end + + result = uri.gsub(/%[0-9a-f]{2}/i) do |sequence| + c = sequence[1..3].to_i(16).chr + c.force_encoding(sequence.encoding) + leave_encoded.include?(c) ? sequence : c + end + + result.force_encoding(Encoding::UTF_8) + if return_type == String + return result + elsif return_type == ::Addressable::URI + return ::Addressable::URI.parse(result) + end + end + + class << self + alias_method :unescape, :unencode + alias_method :unencode_component, :unencode + alias_method :unescape_component, :unencode + end + + + ## + # Normalizes the encoding of a URI component. + # + # @param [String, #to_str] component The URI component to encode. + # + # @param [String, Regexp] character_class + # The characters which are not percent encoded. If a String + # is passed, the String must be formatted as a regular + # expression character class. (Do not include the surrounding square + # brackets.) For example, "b-zB-Z0-9" would cause + # everything but the letters 'b' through 'z' and the numbers '0' + # through '9' to be percent encoded. If a Regexp is passed, + # the value /[^b-zB-Z0-9]/ would have the same effect. A + # set of useful String values may be found in the + # Addressable::URI::CharacterClasses module. The default + # value is the reserved plus unreserved character classes specified in + # RFC 3986. + # + # @param [String] leave_encoded + # When character_class is a String then + # leave_encoded is a string of characters that should remain + # percent encoded while normalizing the component; if they appear percent + # encoded in the original component, then they will be upcased ("%2f" + # normalized to "%2F") but otherwise left alone. + # + # @return [String] The normalized component. + # + # @example + # Addressable::URI.normalize_component("simpl%65/%65xampl%65", "b-zB-Z") + # => "simple%2Fex%61mple" + # Addressable::URI.normalize_component( + # "simpl%65/%65xampl%65", /[^b-zB-Z]/ + # ) + # => "simple%2Fex%61mple" + # Addressable::URI.normalize_component( + # "simpl%65/%65xampl%65", + # Addressable::URI::CharacterClasses::UNRESERVED + # ) + # => "simple%2Fexample" + # Addressable::URI.normalize_component( + # "one%20two%2fthree%26four", + # "0-9a-zA-Z &/", + # "/" + # ) + # => "one two%2Fthree&four" + def self.normalize_component(component, character_class= + CharacterClasses::RESERVED + CharacterClasses::UNRESERVED, + leave_encoded='') + return nil if component.nil? + + begin + component = component.to_str + rescue NoMethodError, TypeError + raise TypeError, "Can't convert #{component.class} into String." + end if !component.is_a? String + + if ![String, Regexp].include?(character_class.class) + raise TypeError, + "Expected String or Regexp, got #{character_class.inspect}" + end + if character_class.kind_of?(String) + leave_re = if leave_encoded.length > 0 + character_class = "#{character_class}%" unless character_class.include?('%') + + bytes = leave_encoded.bytes + leave_encoded_pattern = bytes.map { |b| SEQUENCE_ENCODING_TABLE[b] }.join('|') + "|%(?!#{leave_encoded_pattern}|#{leave_encoded_pattern.upcase})" + end + + character_class = if leave_re + /[^#{character_class}]#{leave_re}/ + else + /[^#{character_class}]/ + end + end + # We can't perform regexps on invalid UTF sequences, but + # here we need to, so switch to ASCII. + component = component.dup + component.force_encoding(Encoding::ASCII_8BIT) + unencoded = self.unencode_component(component, String, leave_encoded) + begin + encoded = self.encode_component( + unencoded.unicode_normalize(:nfc), + character_class, + leave_encoded + ) + rescue ArgumentError + encoded = self.encode_component(unencoded) + end + encoded.force_encoding(Encoding::UTF_8) + return encoded + end + + ## + # Percent encodes any special characters in the URI. + # + # @param [String, Addressable::URI, #to_str] uri + # The URI to encode. + # + # @param [Class] return_type + # The type of object to return. + # This value may only be set to String or + # Addressable::URI. All other values are invalid. Defaults + # to String. + # + # @return [String, Addressable::URI] + # The encoded URI. + # The return type is determined by the return_type + # parameter. + def self.encode(uri, return_type=String) + return nil if uri.nil? + + begin + uri = uri.to_str + rescue NoMethodError, TypeError + raise TypeError, "Can't convert #{uri.class} into String." + end if !uri.is_a? String + + if ![String, ::Addressable::URI].include?(return_type) + raise TypeError, + "Expected Class (String or Addressable::URI), " + + "got #{return_type.inspect}" + end + uri_object = uri.kind_of?(self) ? uri : self.parse(uri) + encoded_uri = Addressable::URI.new( + :scheme => self.encode_component(uri_object.scheme, + Addressable::URI::CharacterClasses::SCHEME), + :authority => self.encode_component(uri_object.authority, + Addressable::URI::CharacterClasses::AUTHORITY), + :path => self.encode_component(uri_object.path, + Addressable::URI::CharacterClasses::PATH), + :query => self.encode_component(uri_object.query, + Addressable::URI::CharacterClasses::QUERY), + :fragment => self.encode_component(uri_object.fragment, + Addressable::URI::CharacterClasses::FRAGMENT) + ) + if return_type == String + return encoded_uri.to_s + elsif return_type == ::Addressable::URI + return encoded_uri + end + end + + class << self + alias_method :escape, :encode + end + + ## + # Normalizes the encoding of a URI. Characters within a hostname are + # not percent encoded to allow for internationalized domain names. + # + # @param [String, Addressable::URI, #to_str] uri + # The URI to encode. + # + # @param [Class] return_type + # The type of object to return. + # This value may only be set to String or + # Addressable::URI. All other values are invalid. Defaults + # to String. + # + # @return [String, Addressable::URI] + # The encoded URI. + # The return type is determined by the return_type + # parameter. + def self.normalized_encode(uri, return_type=String) + begin + uri = uri.to_str + rescue NoMethodError, TypeError + raise TypeError, "Can't convert #{uri.class} into String." + end if !uri.is_a? String + + if ![String, ::Addressable::URI].include?(return_type) + raise TypeError, + "Expected Class (String or Addressable::URI), " + + "got #{return_type.inspect}" + end + uri_object = uri.kind_of?(self) ? uri : self.parse(uri) + components = { + :scheme => self.unencode_component(uri_object.scheme), + :user => self.unencode_component(uri_object.user), + :password => self.unencode_component(uri_object.password), + :host => self.unencode_component(uri_object.host), + :port => (uri_object.port.nil? ? nil : uri_object.port.to_s), + :path => self.unencode_component(uri_object.path), + :query => self.unencode_component(uri_object.query), + :fragment => self.unencode_component(uri_object.fragment) + } + components.each do |key, value| + if value != nil + begin + components[key] = value.to_str.unicode_normalize(:nfc) + rescue ArgumentError + # Likely a malformed UTF-8 character, skip unicode normalization + components[key] = value.to_str + end + end + end + encoded_uri = Addressable::URI.new( + :scheme => self.encode_component(components[:scheme], + Addressable::URI::CharacterClasses::SCHEME), + :user => self.encode_component(components[:user], + Addressable::URI::CharacterClasses::UNRESERVED), + :password => self.encode_component(components[:password], + Addressable::URI::CharacterClasses::UNRESERVED), + :host => components[:host], + :port => components[:port], + :path => self.encode_component(components[:path], + Addressable::URI::CharacterClasses::PATH), + :query => self.encode_component(components[:query], + Addressable::URI::CharacterClasses::QUERY), + :fragment => self.encode_component(components[:fragment], + Addressable::URI::CharacterClasses::FRAGMENT) + ) + if return_type == String + return encoded_uri.to_s + elsif return_type == ::Addressable::URI + return encoded_uri + end + end + + ## + # Encodes a set of key/value pairs according to the rules for the + # application/x-www-form-urlencoded MIME type. + # + # @param [#to_hash, #to_ary] form_values + # The form values to encode. + # + # @param [TrueClass, FalseClass] sort + # Sort the key/value pairs prior to encoding. + # Defaults to false. + # + # @return [String] + # The encoded value. + def self.form_encode(form_values, sort=false) + if form_values.respond_to?(:to_hash) + form_values = form_values.to_hash.to_a + elsif form_values.respond_to?(:to_ary) + form_values = form_values.to_ary + else + raise TypeError, "Can't convert #{form_values.class} into Array." + end + + form_values = form_values.inject([]) do |accu, (key, value)| + if value.kind_of?(Array) + value.each do |v| + accu << [key.to_s, v.to_s] + end + else + accu << [key.to_s, value.to_s] + end + accu + end + + if sort + # Useful for OAuth and optimizing caching systems + form_values = form_values.sort + end + escaped_form_values = form_values.map do |(key, value)| + # Line breaks are CRLF pairs + [ + self.encode_component( + key.gsub(/(\r\n|\n|\r)/, "\r\n"), + CharacterClasses::UNRESERVED + ).gsub("%20", "+"), + self.encode_component( + value.gsub(/(\r\n|\n|\r)/, "\r\n"), + CharacterClasses::UNRESERVED + ).gsub("%20", "+") + ] + end + return escaped_form_values.map do |(key, value)| + "#{key}=#{value}" + end.join("&") + end + + ## + # Decodes a String according to the rules for the + # application/x-www-form-urlencoded MIME type. + # + # @param [String, #to_str] encoded_value + # The form values to decode. + # + # @return [Array] + # The decoded values. + # This is not a Hash because of the possibility for + # duplicate keys. + def self.form_unencode(encoded_value) + if !encoded_value.respond_to?(:to_str) + raise TypeError, "Can't convert #{encoded_value.class} into String." + end + encoded_value = encoded_value.to_str + split_values = encoded_value.split("&").map do |pair| + pair.split("=", 2) + end + return split_values.map do |(key, value)| + [ + key ? self.unencode_component( + key.gsub("+", "%20")).gsub(/(\r\n|\n|\r)/, "\n") : nil, + value ? (self.unencode_component( + value.gsub("+", "%20")).gsub(/(\r\n|\n|\r)/, "\n")) : nil + ] + end + end + + ## + # Creates a new uri object from component parts. + # + # @option [String, #to_str] scheme The scheme component. + # @option [String, #to_str] user The user component. + # @option [String, #to_str] password The password component. + # @option [String, #to_str] userinfo + # The userinfo component. If this is supplied, the user and password + # components must be omitted. + # @option [String, #to_str] host The host component. + # @option [String, #to_str] port The port component. + # @option [String, #to_str] authority + # The authority component. If this is supplied, the user, password, + # userinfo, host, and port components must be omitted. + # @option [String, #to_str] path The path component. + # @option [String, #to_str] query The query component. + # @option [String, #to_str] fragment The fragment component. + # + # @return [Addressable::URI] The constructed URI object. + def initialize(options={}) + if options.has_key?(:authority) + if (options.keys & [:userinfo, :user, :password, :host, :port]).any? + raise ArgumentError, + "Cannot specify both an authority and any of the components " + + "within the authority." + end + end + if options.has_key?(:userinfo) + if (options.keys & [:user, :password]).any? + raise ArgumentError, + "Cannot specify both a userinfo and either the user or password." + end + end + + reset_ivs + + defer_validation do + # Bunch of crazy logic required because of the composite components + # like userinfo and authority. + self.scheme = options[:scheme] if options[:scheme] + self.user = options[:user] if options[:user] + self.password = options[:password] if options[:password] + self.userinfo = options[:userinfo] if options[:userinfo] + self.host = options[:host] if options[:host] + self.port = options[:port] if options[:port] + self.authority = options[:authority] if options[:authority] + self.path = options[:path] if options[:path] + self.query = options[:query] if options[:query] + self.query_values = options[:query_values] if options[:query_values] + self.fragment = options[:fragment] if options[:fragment] + end + + to_s # force path validation + end + + ## + # Freeze URI, initializing instance variables. + # + # @return [Addressable::URI] The frozen URI object. + def freeze + self.normalized_scheme + self.normalized_user + self.normalized_password + self.normalized_userinfo + self.normalized_host + self.normalized_port + self.normalized_authority + self.normalized_site + self.normalized_path + self.normalized_query + self.normalized_fragment + self.hash + super + end + + ## + # The scheme component for this URI. + # + # @return [String] The scheme component. + attr_reader :scheme + + ## + # The scheme component for this URI, normalized. + # + # @return [String] The scheme component, normalized. + def normalized_scheme + return nil unless self.scheme + if @normalized_scheme == NONE + @normalized_scheme = if self.scheme =~ /^\s*ssh\+svn\s*$/i + "svn+ssh".dup + else + Addressable::URI.normalize_component( + self.scheme.strip.downcase, + Addressable::URI::NormalizeCharacterClasses::SCHEME + ) + end + end + # All normalized values should be UTF-8 + force_utf8_encoding_if_needed(@normalized_scheme) + @normalized_scheme + end + + ## + # Sets the scheme component for this URI. + # + # @param [String, #to_str] new_scheme The new scheme component. + def scheme=(new_scheme) + if new_scheme && !new_scheme.respond_to?(:to_str) + raise TypeError, "Can't convert #{new_scheme.class} into String." + elsif new_scheme + new_scheme = new_scheme.to_str + end + if new_scheme && new_scheme !~ /\A[a-z][a-z0-9\.\+\-]*\z/i + raise InvalidURIError, "Invalid scheme format: '#{new_scheme}'" + end + @scheme = new_scheme + @scheme = nil if @scheme.to_s.strip.empty? + + # Reset dependent values + @normalized_scheme = NONE + remove_composite_values + + # Ensure we haven't created an invalid URI + validate() + end + + ## + # The user component for this URI. + # + # @return [String] The user component. + attr_reader :user + + ## + # The user component for this URI, normalized. + # + # @return [String] The user component, normalized. + def normalized_user + return nil unless self.user + return @normalized_user unless @normalized_user == NONE + @normalized_user = begin + if normalized_scheme =~ /https?/ && self.user.strip.empty? && + (!self.password || self.password.strip.empty?) + nil + else + Addressable::URI.normalize_component( + self.user.strip, + Addressable::URI::NormalizeCharacterClasses::UNRESERVED + ) + end + end + # All normalized values should be UTF-8 + force_utf8_encoding_if_needed(@normalized_user) + @normalized_user + end + + ## + # Sets the user component for this URI. + # + # @param [String, #to_str] new_user The new user component. + def user=(new_user) + if new_user && !new_user.respond_to?(:to_str) + raise TypeError, "Can't convert #{new_user.class} into String." + end + @user = new_user ? new_user.to_str : nil + + # You can't have a nil user with a non-nil password + if password != nil + @user = EMPTY_STR unless user + end + + # Reset dependent values + @userinfo = nil + @normalized_userinfo = NONE + @authority = nil + @normalized_user = NONE + remove_composite_values + + # Ensure we haven't created an invalid URI + validate() + end + + ## + # The password component for this URI. + # + # @return [String] The password component. + attr_reader :password + + ## + # The password component for this URI, normalized. + # + # @return [String] The password component, normalized. + def normalized_password + return nil unless self.password + return @normalized_password unless @normalized_password == NONE + @normalized_password = begin + if self.normalized_scheme =~ /https?/ && self.password.strip.empty? && + (!self.user || self.user.strip.empty?) + nil + else + Addressable::URI.normalize_component( + self.password.strip, + Addressable::URI::NormalizeCharacterClasses::UNRESERVED + ) + end + end + # All normalized values should be UTF-8 + force_utf8_encoding_if_needed(@normalized_password) + @normalized_password + end + + ## + # Sets the password component for this URI. + # + # @param [String, #to_str] new_password The new password component. + def password=(new_password) + if new_password && !new_password.respond_to?(:to_str) + raise TypeError, "Can't convert #{new_password.class} into String." + end + @password = new_password ? new_password.to_str : nil + + # You can't have a nil user with a non-nil password + if @password != nil + self.user = EMPTY_STR if user.nil? + end + + # Reset dependent values + @userinfo = nil + @normalized_userinfo = NONE + @authority = nil + @normalized_password = NONE + remove_composite_values + + # Ensure we haven't created an invalid URI + validate() + end + + ## + # The userinfo component for this URI. + # Combines the user and password components. + # + # @return [String] The userinfo component. + def userinfo + current_user = self.user + current_password = self.password + (current_user || current_password) && @userinfo ||= begin + if current_user && current_password + "#{current_user}:#{current_password}" + elsif current_user && !current_password + "#{current_user}" + end + end + end + + ## + # The userinfo component for this URI, normalized. + # + # @return [String] The userinfo component, normalized. + def normalized_userinfo + return nil unless self.userinfo + return @normalized_userinfo unless @normalized_userinfo == NONE + @normalized_userinfo = begin + current_user = self.normalized_user + current_password = self.normalized_password + if !current_user && !current_password + nil + elsif current_user && current_password + "#{current_user}:#{current_password}".dup + elsif current_user && !current_password + "#{current_user}".dup + end + end + # All normalized values should be UTF-8 + force_utf8_encoding_if_needed(@normalized_userinfo) + @normalized_userinfo + end + + ## + # Sets the userinfo component for this URI. + # + # @param [String, #to_str] new_userinfo The new userinfo component. + def userinfo=(new_userinfo) + if new_userinfo && !new_userinfo.respond_to?(:to_str) + raise TypeError, "Can't convert #{new_userinfo.class} into String." + end + new_user, new_password = if new_userinfo + [ + new_userinfo.to_str.strip[/^(.*):/, 1], + new_userinfo.to_str.strip[/:(.*)$/, 1] + ] + else + [nil, nil] + end + + # Password assigned first to ensure validity in case of nil + self.password = new_password + self.user = new_user + + # Reset dependent values + @authority = nil + remove_composite_values + + # Ensure we haven't created an invalid URI + validate() + end + + ## + # The host component for this URI. + # + # @return [String] The host component. + attr_reader :host + + ## + # The host component for this URI, normalized. + # + # @return [String] The host component, normalized. + def normalized_host + return nil unless self.host + + @normalized_host ||= begin + if !self.host.strip.empty? + result = ::Addressable::IDNA.to_ascii( + URI.unencode_component(self.host.strip.downcase) + ) + if result =~ /[^\.]\.$/ + # Single trailing dots are unnecessary. + result = result[0...-1] + end + result = Addressable::URI.normalize_component( + result, + NormalizeCharacterClasses::HOST + ) + result + else + EMPTY_STR.dup + end + end + # All normalized values should be UTF-8 + force_utf8_encoding_if_needed(@normalized_host) + @normalized_host + end + + ## + # Sets the host component for this URI. + # + # @param [String, #to_str] new_host The new host component. + def host=(new_host) + if new_host && !new_host.respond_to?(:to_str) + raise TypeError, "Can't convert #{new_host.class} into String." + end + @host = new_host ? new_host.to_str : nil + + # Reset dependent values + @authority = nil + @normalized_host = nil + remove_composite_values + + # Ensure we haven't created an invalid URI + validate() + end + + ## + # This method is same as URI::Generic#host except + # brackets for IPv6 (and 'IPvFuture') addresses are removed. + # + # @see Addressable::URI#host + # + # @return [String] The hostname for this URI. + def hostname + v = self.host + /\A\[(.*)\]\z/ =~ v ? $1 : v + end + + ## + # This method is same as URI::Generic#host= except + # the argument can be a bare IPv6 address (or 'IPvFuture'). + # + # @see Addressable::URI#host= + # + # @param [String, #to_str] new_hostname The new hostname for this URI. + def hostname=(new_hostname) + if new_hostname && + (new_hostname.respond_to?(:ipv4?) || new_hostname.respond_to?(:ipv6?)) + new_hostname = new_hostname.to_s + elsif new_hostname && !new_hostname.respond_to?(:to_str) + raise TypeError, "Can't convert #{new_hostname.class} into String." + end + v = new_hostname ? new_hostname.to_str : nil + v = "[#{v}]" if /\A\[.*\]\z/ !~ v && /:/ =~ v + self.host = v + end + + ## + # Returns the top-level domain for this host. + # + # @example + # Addressable::URI.parse("http://www.example.co.uk").tld # => "co.uk" + def tld + PublicSuffix.parse(self.host, ignore_private: true).tld + end + + ## + # Sets the top-level domain for this URI. + # + # @param [String, #to_str] new_tld The new top-level domain. + def tld=(new_tld) + replaced_tld = host.sub(/#{tld}\z/, new_tld) + self.host = PublicSuffix::Domain.new(replaced_tld).to_s + end + + ## + # Returns the public suffix domain for this host. + # + # @example + # Addressable::URI.parse("http://www.example.co.uk").domain # => "example.co.uk" + def domain + PublicSuffix.domain(self.host, ignore_private: true) + end + + ## + # The authority component for this URI. + # Combines the user, password, host, and port components. + # + # @return [String] The authority component. + def authority + self.host && @authority ||= begin + authority = String.new + if self.userinfo != nil + authority << "#{self.userinfo}@" + end + authority << self.host + if self.port != nil + authority << ":#{self.port}" + end + authority + end + end + + ## + # The authority component for this URI, normalized. + # + # @return [String] The authority component, normalized. + def normalized_authority + return nil unless self.authority + @normalized_authority ||= begin + authority = String.new + if self.normalized_userinfo != nil + authority << "#{self.normalized_userinfo}@" + end + authority << self.normalized_host + if self.normalized_port != nil + authority << ":#{self.normalized_port}" + end + authority + end + # All normalized values should be UTF-8 + force_utf8_encoding_if_needed(@normalized_authority) + @normalized_authority + end + + ## + # Sets the authority component for this URI. + # + # @param [String, #to_str] new_authority The new authority component. + def authority=(new_authority) + if new_authority + if !new_authority.respond_to?(:to_str) + raise TypeError, "Can't convert #{new_authority.class} into String." + end + new_authority = new_authority.to_str + new_userinfo = new_authority[/^([^\[\]]*)@/, 1] + if new_userinfo + new_user = new_userinfo.strip[/^([^:]*):?/, 1] + new_password = new_userinfo.strip[/:(.*)$/, 1] + end + new_host = new_authority.sub( + /^([^\[\]]*)@/, EMPTY_STR + ).sub( + /:([^:@\[\]]*?)$/, EMPTY_STR + ) + new_port = + new_authority[/:([^:@\[\]]*?)$/, 1] + end + + # Password assigned first to ensure validity in case of nil + self.password = new_password + self.user = new_user + self.host = new_host + self.port = new_port + + # Reset dependent values + @userinfo = nil + @normalized_userinfo = NONE + remove_composite_values + + # Ensure we haven't created an invalid URI + validate() + end + + ## + # The origin for this URI, serialized to ASCII, as per + # RFC 6454, section 6.2. + # + # @return [String] The serialized origin. + def origin + if self.scheme && self.authority + if self.normalized_port + "#{self.normalized_scheme}://#{self.normalized_host}" + + ":#{self.normalized_port}" + else + "#{self.normalized_scheme}://#{self.normalized_host}" + end + else + "null" + end + end + + ## + # Sets the origin for this URI, serialized to ASCII, as per + # RFC 6454, section 6.2. This assignment will reset the `userinfo` + # component. + # + # @param [String, #to_str] new_origin The new origin component. + def origin=(new_origin) + if new_origin + if !new_origin.respond_to?(:to_str) + raise TypeError, "Can't convert #{new_origin.class} into String." + end + new_origin = new_origin.to_str + new_scheme = new_origin[/^([^:\/?#]+):\/\//, 1] + unless new_scheme + raise InvalidURIError, 'An origin cannot omit the scheme.' + end + new_host = new_origin[/:\/\/([^\/?#:]+)/, 1] + unless new_host + raise InvalidURIError, 'An origin cannot omit the host.' + end + new_port = new_origin[/:([^:@\[\]\/]*?)$/, 1] + end + + self.scheme = new_scheme + self.host = new_host + self.port = new_port + self.userinfo = nil + + # Reset dependent values + @userinfo = nil + @normalized_userinfo = NONE + @authority = nil + @normalized_authority = nil + remove_composite_values + + # Ensure we haven't created an invalid URI + validate() + end + + # Returns an array of known ip-based schemes. These schemes typically + # use a similar URI form: + # //:@:/ + def self.ip_based_schemes + return self.port_mapping.keys + end + + # Returns a hash of common IP-based schemes and their default port + # numbers. Adding new schemes to this hash, as necessary, will allow + # for better URI normalization. + def self.port_mapping + PORT_MAPPING + end + + ## + # The port component for this URI. + # This is the port number actually given in the URI. This does not + # infer port numbers from default values. + # + # @return [Integer] The port component. + attr_reader :port + + ## + # The port component for this URI, normalized. + # + # @return [Integer] The port component, normalized. + def normalized_port + return nil unless self.port + return @normalized_port unless @normalized_port == NONE + @normalized_port = begin + if URI.port_mapping[self.normalized_scheme] == self.port + nil + else + self.port + end + end + end + + ## + # Sets the port component for this URI. + # + # @param [String, Integer, #to_s] new_port The new port component. + def port=(new_port) + if new_port != nil && new_port.respond_to?(:to_str) + new_port = Addressable::URI.unencode_component(new_port.to_str) + end + + if new_port.respond_to?(:valid_encoding?) && !new_port.valid_encoding? + raise InvalidURIError, "Invalid encoding in port" + end + + if new_port != nil && !(new_port.to_s =~ /^\d+$/) + raise InvalidURIError, + "Invalid port number: #{new_port.inspect}" + end + + @port = new_port.to_s.to_i + @port = nil if @port == 0 + + # Reset dependent values + @authority = nil + @normalized_port = NONE + remove_composite_values + + # Ensure we haven't created an invalid URI + validate() + end + + ## + # The inferred port component for this URI. + # This method will normalize to the default port for the URI's scheme if + # the port isn't explicitly specified in the URI. + # + # @return [Integer] The inferred port component. + def inferred_port + if self.port.to_i == 0 + self.default_port + else + self.port.to_i + end + end + + ## + # The default port for this URI's scheme. + # This method will always returns the default port for the URI's scheme + # regardless of the presence of an explicit port in the URI. + # + # @return [Integer] The default port. + def default_port + URI.port_mapping[self.scheme.strip.downcase] if self.scheme + end + + ## + # The combination of components that represent a site. + # Combines the scheme, user, password, host, and port components. + # Primarily useful for HTTP and HTTPS. + # + # For example, "http://example.com/path?query" would have a + # site value of "http://example.com". + # + # @return [String] The components that identify a site. + def site + (self.scheme || self.authority) && @site ||= begin + site_string = "".dup + site_string << "#{self.scheme}:" if self.scheme != nil + site_string << "//#{self.authority}" if self.authority != nil + site_string + end + end + + ## + # The normalized combination of components that represent a site. + # Combines the scheme, user, password, host, and port components. + # Primarily useful for HTTP and HTTPS. + # + # For example, "http://example.com/path?query" would have a + # site value of "http://example.com". + # + # @return [String] The normalized components that identify a site. + def normalized_site + return nil unless self.site + @normalized_site ||= begin + site_string = "".dup + if self.normalized_scheme != nil + site_string << "#{self.normalized_scheme}:" + end + if self.normalized_authority != nil + site_string << "//#{self.normalized_authority}" + end + site_string + end + # All normalized values should be UTF-8 + force_utf8_encoding_if_needed(@normalized_site) + @normalized_site + end + + ## + # Sets the site value for this URI. + # + # @param [String, #to_str] new_site The new site value. + def site=(new_site) + if new_site + if !new_site.respond_to?(:to_str) + raise TypeError, "Can't convert #{new_site.class} into String." + end + new_site = new_site.to_str + # These two regular expressions derived from the primary parsing + # expression + self.scheme = new_site[/^(?:([^:\/?#]+):)?(?:\/\/(?:[^\/?#]*))?$/, 1] + self.authority = new_site[ + /^(?:(?:[^:\/?#]+):)?(?:\/\/([^\/?#]*))?$/, 1 + ] + else + self.scheme = nil + self.authority = nil + end + end + + ## + # The path component for this URI. + # + # @return [String] The path component. + attr_reader :path + + NORMPATH = /^(?!\/)[^\/:]*:.*$/ + ## + # The path component for this URI, normalized. + # + # @return [String] The path component, normalized. + def normalized_path + @normalized_path ||= begin + path = self.path.to_s + if self.scheme == nil && path =~ NORMPATH + # Relative paths with colons in the first segment are ambiguous. + path = path.sub(":", "%2F") + end + # String#split(delimeter, -1) uses the more strict splitting behavior + # found by default in Python. + result = path.strip.split(SLASH, -1).map do |segment| + Addressable::URI.normalize_component( + segment, + Addressable::URI::NormalizeCharacterClasses::PCHAR + ) + end.join(SLASH) + + result = URI.normalize_path(result) + if result.empty? && + ["http", "https", "ftp", "tftp"].include?(self.normalized_scheme) + result = SLASH.dup + end + result + end + # All normalized values should be UTF-8 + force_utf8_encoding_if_needed(@normalized_path) + @normalized_path + end + + ## + # Sets the path component for this URI. + # + # @param [String, #to_str] new_path The new path component. + def path=(new_path) + if new_path && !new_path.respond_to?(:to_str) + raise TypeError, "Can't convert #{new_path.class} into String." + end + @path = (new_path || EMPTY_STR).to_str + if !@path.empty? && @path[0..0] != SLASH && host != nil + @path = "/#{@path}" + end + + # Reset dependent values + @normalized_path = nil + remove_composite_values + + # Ensure we haven't created an invalid URI + validate() + end + + ## + # The basename, if any, of the file in the path component. + # + # @return [String] The path's basename. + def basename + # Path cannot be nil + return File.basename(self.path).sub(/;[^\/]*$/, EMPTY_STR) + end + + ## + # The extname, if any, of the file in the path component. + # Empty string if there is no extension. + # + # @return [String] The path's extname. + def extname + return nil unless self.path + return File.extname(self.basename) + end + + ## + # The query component for this URI. + # + # @return [String] The query component. + attr_reader :query + + ## + # The query component for this URI, normalized. + # + # @return [String] The query component, normalized. + def normalized_query(*flags) + return nil unless self.query + return @normalized_query unless @normalized_query == NONE + @normalized_query = begin + modified_query_class = Addressable::URI::CharacterClasses::QUERY.dup + # Make sure possible key-value pair delimiters are escaped. + modified_query_class.sub!("\\&", "").sub!("\\;", "") + pairs = (query || "").split("&", -1) + pairs.delete_if(&:empty?).uniq! if flags.include?(:compacted) + pairs.sort! if flags.include?(:sorted) + component = pairs.map do |pair| + Addressable::URI.normalize_component( + pair, + Addressable::URI::NormalizeCharacterClasses::QUERY, + "+" + ) + end.join("&") + component == "" ? nil : component + end + # All normalized values should be UTF-8 + force_utf8_encoding_if_needed(@normalized_query) + @normalized_query + end + + ## + # Sets the query component for this URI. + # + # @param [String, #to_str] new_query The new query component. + def query=(new_query) + if new_query && !new_query.respond_to?(:to_str) + raise TypeError, "Can't convert #{new_query.class} into String." + end + @query = new_query ? new_query.to_str : nil + + # Reset dependent values + @normalized_query = NONE + remove_composite_values + end + + ## + # Converts the query component to a Hash value. + # + # @param [Class] return_type The return type desired. Value must be either + # `Hash` or `Array`. + # + # @return [Hash, Array, nil] The query string parsed as a Hash or Array + # or nil if the query string is blank. + # + # @example + # Addressable::URI.parse("?one=1&two=2&three=3").query_values + # #=> {"one" => "1", "two" => "2", "three" => "3"} + # Addressable::URI.parse("?one=two&one=three").query_values(Array) + # #=> [["one", "two"], ["one", "three"]] + # Addressable::URI.parse("?one=two&one=three").query_values(Hash) + # #=> {"one" => "three"} + # Addressable::URI.parse("?").query_values + # #=> {} + # Addressable::URI.parse("").query_values + # #=> nil + def query_values(return_type=Hash) + empty_accumulator = Array == return_type ? [] : {} + if return_type != Hash && return_type != Array + raise ArgumentError, "Invalid return type. Must be Hash or Array." + end + return nil if self.query == nil + split_query = self.query.split("&").map do |pair| + pair.split("=", 2) if pair && !pair.empty? + end.compact + return split_query.inject(empty_accumulator.dup) do |accu, pair| + # I'd rather use key/value identifiers instead of array lookups, + # but in this case I really want to maintain the exact pair structure, + # so it's best to make all changes in-place. + pair[0] = URI.unencode_component(pair[0]) + if pair[1].respond_to?(:to_str) + value = pair[1].to_str + # I loathe the fact that I have to do this. Stupid HTML 4.01. + # Treating '+' as a space was just an unbelievably bad idea. + # There was nothing wrong with '%20'! + # If it ain't broke, don't fix it! + value = value.tr("+", " ") if ["http", "https", nil].include?(scheme) + pair[1] = URI.unencode_component(value) + end + if return_type == Hash + accu[pair[0]] = pair[1] + else + accu << pair + end + accu + end + end + + ## + # Sets the query component for this URI from a Hash object. + # An empty Hash or Array will result in an empty query string. + # + # @param [Hash, #to_hash, Array] new_query_values The new query values. + # + # @example + # uri.query_values = {:a => "a", :b => ["c", "d", "e"]} + # uri.query + # # => "a=a&b=c&b=d&b=e" + # uri.query_values = [['a', 'a'], ['b', 'c'], ['b', 'd'], ['b', 'e']] + # uri.query + # # => "a=a&b=c&b=d&b=e" + # uri.query_values = [['a', 'a'], ['b', ['c', 'd', 'e']]] + # uri.query + # # => "a=a&b=c&b=d&b=e" + # uri.query_values = [['flag'], ['key', 'value']] + # uri.query + # # => "flag&key=value" + def query_values=(new_query_values) + if new_query_values == nil + self.query = nil + return nil + end + + if !new_query_values.is_a?(Array) + if !new_query_values.respond_to?(:to_hash) + raise TypeError, + "Can't convert #{new_query_values.class} into Hash." + end + new_query_values = new_query_values.to_hash + new_query_values = new_query_values.map do |key, value| + key = key.to_s if key.kind_of?(Symbol) + [key, value] + end + # Useful default for OAuth and caching. + # Only to be used for non-Array inputs. Arrays should preserve order. + new_query_values.sort! + end + + # new_query_values have form [['key1', 'value1'], ['key2', 'value2']] + buffer = "".dup + new_query_values.each do |key, value| + encoded_key = URI.encode_component( + key, CharacterClasses::UNRESERVED + ) + if value == nil + buffer << "#{encoded_key}&" + elsif value.kind_of?(Array) + value.each do |sub_value| + encoded_value = URI.encode_component( + sub_value, CharacterClasses::UNRESERVED + ) + buffer << "#{encoded_key}=#{encoded_value}&" + end + else + encoded_value = URI.encode_component( + value, CharacterClasses::UNRESERVED + ) + buffer << "#{encoded_key}=#{encoded_value}&" + end + end + self.query = buffer.chop + end + + ## + # The HTTP request URI for this URI. This is the path and the + # query string. + # + # @return [String] The request URI required for an HTTP request. + def request_uri + return nil if self.absolute? && self.scheme !~ /^https?$/i + return ( + (!self.path.empty? ? self.path : SLASH) + + (self.query ? "?#{self.query}" : EMPTY_STR) + ) + end + + ## + # Sets the HTTP request URI for this URI. + # + # @param [String, #to_str] new_request_uri The new HTTP request URI. + def request_uri=(new_request_uri) + if !new_request_uri.respond_to?(:to_str) + raise TypeError, "Can't convert #{new_request_uri.class} into String." + end + if self.absolute? && self.scheme !~ /^https?$/i + raise InvalidURIError, + "Cannot set an HTTP request URI for a non-HTTP URI." + end + new_request_uri = new_request_uri.to_str + path_component = new_request_uri[/^([^\?]*)\??(?:.*)$/, 1] + query_component = new_request_uri[/^(?:[^\?]*)\?(.*)$/, 1] + path_component = path_component.to_s + path_component = (!path_component.empty? ? path_component : SLASH) + self.path = path_component + self.query = query_component + + # Reset dependent values + remove_composite_values + end + + ## + # The fragment component for this URI. + # + # @return [String] The fragment component. + attr_reader :fragment + + ## + # The fragment component for this URI, normalized. + # + # @return [String] The fragment component, normalized. + def normalized_fragment + return nil unless self.fragment + return @normalized_fragment unless @normalized_fragment == NONE + @normalized_fragment = begin + component = Addressable::URI.normalize_component( + self.fragment, + Addressable::URI::NormalizeCharacterClasses::FRAGMENT + ) + component == "" ? nil : component + end + # All normalized values should be UTF-8 + force_utf8_encoding_if_needed(@normalized_fragment) + @normalized_fragment + end + + ## + # Sets the fragment component for this URI. + # + # @param [String, #to_str] new_fragment The new fragment component. + def fragment=(new_fragment) + if new_fragment && !new_fragment.respond_to?(:to_str) + raise TypeError, "Can't convert #{new_fragment.class} into String." + end + @fragment = new_fragment ? new_fragment.to_str : nil + + # Reset dependent values + @normalized_fragment = NONE + remove_composite_values + + # Ensure we haven't created an invalid URI + validate() + end + + ## + # Determines if the scheme indicates an IP-based protocol. + # + # @return [TrueClass, FalseClass] + # true if the scheme indicates an IP-based protocol. + # false otherwise. + def ip_based? + if self.scheme + return URI.ip_based_schemes.include?( + self.scheme.strip.downcase) + end + return false + end + + ## + # Determines if the URI is relative. + # + # @return [TrueClass, FalseClass] + # true if the URI is relative. false + # otherwise. + def relative? + return self.scheme.nil? + end + + ## + # Determines if the URI is absolute. + # + # @return [TrueClass, FalseClass] + # true if the URI is absolute. false + # otherwise. + def absolute? + return !relative? + end + + ## + # Joins two URIs together. + # + # @param [String, Addressable::URI, #to_str] The URI to join with. + # + # @return [Addressable::URI] The joined URI. + def join(uri) + if !uri.respond_to?(:to_str) + raise TypeError, "Can't convert #{uri.class} into String." + end + if !uri.kind_of?(URI) + # Otherwise, convert to a String, then parse. + uri = URI.parse(uri.to_str) + end + if uri.to_s.empty? + return self.dup + end + + joined_scheme = nil + joined_user = nil + joined_password = nil + joined_host = nil + joined_port = nil + joined_path = nil + joined_query = nil + joined_fragment = nil + + # Section 5.2.2 of RFC 3986 + if uri.scheme != nil + joined_scheme = uri.scheme + joined_user = uri.user + joined_password = uri.password + joined_host = uri.host + joined_port = uri.port + joined_path = URI.normalize_path(uri.path) + joined_query = uri.query + else + if uri.authority != nil + joined_user = uri.user + joined_password = uri.password + joined_host = uri.host + joined_port = uri.port + joined_path = URI.normalize_path(uri.path) + joined_query = uri.query + else + if uri.path == nil || uri.path.empty? + joined_path = self.path + if uri.query != nil + joined_query = uri.query + else + joined_query = self.query + end + else + if uri.path[0..0] == SLASH + joined_path = URI.normalize_path(uri.path) + else + base_path = self.path.dup + base_path = EMPTY_STR if base_path == nil + base_path = URI.normalize_path(base_path) + + # Section 5.2.3 of RFC 3986 + # + # Removes the right-most path segment from the base path. + if base_path.include?(SLASH) + base_path.sub!(/\/[^\/]+$/, SLASH) + else + base_path = EMPTY_STR + end + + # If the base path is empty and an authority segment has been + # defined, use a base path of SLASH + if base_path.empty? && self.authority != nil + base_path = SLASH + end + + joined_path = URI.normalize_path(base_path + uri.path) + end + joined_query = uri.query + end + joined_user = self.user + joined_password = self.password + joined_host = self.host + joined_port = self.port + end + joined_scheme = self.scheme + end + joined_fragment = uri.fragment + + return self.class.new( + :scheme => joined_scheme, + :user => joined_user, + :password => joined_password, + :host => joined_host, + :port => joined_port, + :path => joined_path, + :query => joined_query, + :fragment => joined_fragment + ) + end + alias_method :+, :join + + ## + # Destructive form of join. + # + # @param [String, Addressable::URI, #to_str] The URI to join with. + # + # @return [Addressable::URI] The joined URI. + # + # @see Addressable::URI#join + def join!(uri) + replace_self(self.join(uri)) + end + + ## + # Merges a URI with a Hash of components. + # This method has different behavior from join. Any + # components present in the hash parameter will override the + # original components. The path component is not treated specially. + # + # @param [Hash, Addressable::URI, #to_hash] The components to merge with. + # + # @return [Addressable::URI] The merged URI. + # + # @see Hash#merge + def merge(hash) + unless hash.respond_to?(:to_hash) + raise TypeError, "Can't convert #{hash.class} into Hash." + end + hash = hash.to_hash + + if hash.has_key?(:authority) + if (hash.keys & [:userinfo, :user, :password, :host, :port]).any? + raise ArgumentError, + "Cannot specify both an authority and any of the components " + + "within the authority." + end + end + if hash.has_key?(:userinfo) + if (hash.keys & [:user, :password]).any? + raise ArgumentError, + "Cannot specify both a userinfo and either the user or password." + end + end + + uri = self.class.new + uri.defer_validation do + # Bunch of crazy logic required because of the composite components + # like userinfo and authority. + uri.scheme = + hash.has_key?(:scheme) ? hash[:scheme] : self.scheme + if hash.has_key?(:authority) + uri.authority = + hash.has_key?(:authority) ? hash[:authority] : self.authority + end + if hash.has_key?(:userinfo) + uri.userinfo = + hash.has_key?(:userinfo) ? hash[:userinfo] : self.userinfo + end + if !hash.has_key?(:userinfo) && !hash.has_key?(:authority) + uri.user = + hash.has_key?(:user) ? hash[:user] : self.user + uri.password = + hash.has_key?(:password) ? hash[:password] : self.password + end + if !hash.has_key?(:authority) + uri.host = + hash.has_key?(:host) ? hash[:host] : self.host + uri.port = + hash.has_key?(:port) ? hash[:port] : self.port + end + uri.path = + hash.has_key?(:path) ? hash[:path] : self.path + uri.query = + hash.has_key?(:query) ? hash[:query] : self.query + uri.fragment = + hash.has_key?(:fragment) ? hash[:fragment] : self.fragment + end + + return uri + end + + ## + # Destructive form of merge. + # + # @param [Hash, Addressable::URI, #to_hash] The components to merge with. + # + # @return [Addressable::URI] The merged URI. + # + # @see Addressable::URI#merge + def merge!(uri) + replace_self(self.merge(uri)) + end + + ## + # Returns the shortest normalized relative form of this URI that uses the + # supplied URI as a base for resolution. Returns an absolute URI if + # necessary. This is effectively the opposite of route_to. + # + # @param [String, Addressable::URI, #to_str] uri The URI to route from. + # + # @return [Addressable::URI] + # The normalized relative URI that is equivalent to the original URI. + def route_from(uri) + uri = URI.parse(uri).normalize + normalized_self = self.normalize + if normalized_self.relative? + raise ArgumentError, "Expected absolute URI, got: #{self.to_s}" + end + if uri.relative? + raise ArgumentError, "Expected absolute URI, got: #{uri.to_s}" + end + if normalized_self == uri + return Addressable::URI.parse("##{normalized_self.fragment}") + end + components = normalized_self.to_hash + if normalized_self.scheme == uri.scheme + components[:scheme] = nil + if normalized_self.authority == uri.authority + components[:user] = nil + components[:password] = nil + components[:host] = nil + components[:port] = nil + if normalized_self.path == uri.path + components[:path] = nil + if normalized_self.query == uri.query + components[:query] = nil + end + else + if uri.path != SLASH and components[:path] + self_splitted_path = split_path(components[:path]) + uri_splitted_path = split_path(uri.path) + self_dir = self_splitted_path.shift + uri_dir = uri_splitted_path.shift + while !self_splitted_path.empty? && !uri_splitted_path.empty? and self_dir == uri_dir + self_dir = self_splitted_path.shift + uri_dir = uri_splitted_path.shift + end + components[:path] = (uri_splitted_path.fill('..') + [self_dir] + self_splitted_path).join(SLASH) + end + end + end + end + # Avoid network-path references. + if components[:host] != nil + components[:scheme] = normalized_self.scheme + end + return Addressable::URI.new( + :scheme => components[:scheme], + :user => components[:user], + :password => components[:password], + :host => components[:host], + :port => components[:port], + :path => components[:path], + :query => components[:query], + :fragment => components[:fragment] + ) + end + + ## + # Returns the shortest normalized relative form of the supplied URI that + # uses this URI as a base for resolution. Returns an absolute URI if + # necessary. This is effectively the opposite of route_from. + # + # @param [String, Addressable::URI, #to_str] uri The URI to route to. + # + # @return [Addressable::URI] + # The normalized relative URI that is equivalent to the supplied URI. + def route_to(uri) + return URI.parse(uri).route_from(self) + end + + ## + # Returns a normalized URI object. + # + # NOTE: This method does not attempt to fully conform to specifications. + # It exists largely to correct other people's failures to read the + # specifications, and also to deal with caching issues since several + # different URIs may represent the same resource and should not be + # cached multiple times. + # + # @return [Addressable::URI] The normalized URI. + def normalize + # This is a special exception for the frequently misused feed + # URI scheme. + if normalized_scheme == "feed" + if self.to_s =~ /^feed:\/*http:\/*/ + return URI.parse( + self.to_s[/^feed:\/*(http:\/*.*)/, 1] + ).normalize + end + end + + return self.class.new( + :scheme => normalized_scheme, + :authority => normalized_authority, + :path => normalized_path, + :query => normalized_query, + :fragment => normalized_fragment + ) + end + + ## + # Destructively normalizes this URI object. + # + # @return [Addressable::URI] The normalized URI. + # + # @see Addressable::URI#normalize + def normalize! + replace_self(self.normalize) + end + + ## + # Creates a URI suitable for display to users. If semantic attacks are + # likely, the application should try to detect these and warn the user. + # See RFC 3986, + # section 7.6 for more information. + # + # @return [Addressable::URI] A URI suitable for display purposes. + def display_uri + display_uri = self.normalize + display_uri.host = ::Addressable::IDNA.to_unicode(display_uri.host) + return display_uri + end + + ## + # Returns true if the URI objects are equal. This method + # normalizes both URIs before doing the comparison, and allows comparison + # against Strings. + # + # @param [Object] uri The URI to compare. + # + # @return [TrueClass, FalseClass] + # true if the URIs are equivalent, false + # otherwise. + def ===(uri) + if uri.respond_to?(:normalize) + uri_string = uri.normalize.to_s + else + begin + uri_string = ::Addressable::URI.parse(uri).normalize.to_s + rescue InvalidURIError, TypeError + return false + end + end + return self.normalize.to_s == uri_string + end + + ## + # Returns true if the URI objects are equal. This method + # normalizes both URIs before doing the comparison. + # + # @param [Object] uri The URI to compare. + # + # @return [TrueClass, FalseClass] + # true if the URIs are equivalent, false + # otherwise. + def ==(uri) + return false unless uri.kind_of?(URI) + return self.normalize.to_s == uri.normalize.to_s + end + + ## + # Returns true if the URI objects are equal. This method + # does NOT normalize either URI before doing the comparison. + # + # @param [Object] uri The URI to compare. + # + # @return [TrueClass, FalseClass] + # true if the URIs are equivalent, false + # otherwise. + def eql?(uri) + return false unless uri.kind_of?(URI) + return self.to_s == uri.to_s + end + + ## + # A hash value that will make a URI equivalent to its normalized + # form. + # + # @return [Integer] A hash of the URI. + def hash + @hash ||= self.to_s.hash * -1 + end + + ## + # Clones the URI object. + # + # @return [Addressable::URI] The cloned URI. + def dup + duplicated_uri = self.class.new( + :scheme => self.scheme ? self.scheme.dup : nil, + :user => self.user ? self.user.dup : nil, + :password => self.password ? self.password.dup : nil, + :host => self.host ? self.host.dup : nil, + :port => self.port, + :path => self.path ? self.path.dup : nil, + :query => self.query ? self.query.dup : nil, + :fragment => self.fragment ? self.fragment.dup : nil + ) + return duplicated_uri + end + + ## + # Omits components from a URI. + # + # @param [Symbol] *components The components to be omitted. + # + # @return [Addressable::URI] The URI with components omitted. + # + # @example + # uri = Addressable::URI.parse("http://example.com/path?query") + # #=> # + # uri.omit(:scheme, :authority) + # #=> # + def omit(*components) + invalid_components = components - [ + :scheme, :user, :password, :userinfo, :host, :port, :authority, + :path, :query, :fragment + ] + unless invalid_components.empty? + raise ArgumentError, + "Invalid component names: #{invalid_components.inspect}." + end + duplicated_uri = self.dup + duplicated_uri.defer_validation do + components.each do |component| + duplicated_uri.send((component.to_s + "=").to_sym, nil) + end + duplicated_uri.user = duplicated_uri.normalized_user + end + duplicated_uri + end + + ## + # Destructive form of omit. + # + # @param [Symbol] *components The components to be omitted. + # + # @return [Addressable::URI] The URI with components omitted. + # + # @see Addressable::URI#omit + def omit!(*components) + replace_self(self.omit(*components)) + end + + ## + # Determines if the URI is an empty string. + # + # @return [TrueClass, FalseClass] + # Returns true if empty, false otherwise. + def empty? + return self.to_s.empty? + end + + ## + # Converts the URI to a String. + # + # @return [String] The URI's String representation. + def to_s + if self.scheme == nil && self.path != nil && !self.path.empty? && + self.path =~ NORMPATH + raise InvalidURIError, + "Cannot assemble URI string with ambiguous path: '#{self.path}'" + end + @uri_string ||= begin + uri_string = String.new + uri_string << "#{self.scheme}:" if self.scheme != nil + uri_string << "//#{self.authority}" if self.authority != nil + uri_string << self.path.to_s + uri_string << "?#{self.query}" if self.query != nil + uri_string << "##{self.fragment}" if self.fragment != nil + uri_string.force_encoding(Encoding::UTF_8) + uri_string + end + end + + ## + # URI's are glorified Strings. Allow implicit conversion. + alias_method :to_str, :to_s + + ## + # Returns a Hash of the URI components. + # + # @return [Hash] The URI as a Hash of components. + def to_hash + return { + :scheme => self.scheme, + :user => self.user, + :password => self.password, + :host => self.host, + :port => self.port, + :path => self.path, + :query => self.query, + :fragment => self.fragment + } + end + + ## + # Returns a String representation of the URI object's state. + # + # @return [String] The URI object's state, as a String. + def inspect + sprintf("#<%s:%#0x URI:%s>", URI.to_s, self.object_id, self.to_s) + end + + ## + # This method allows you to make several changes to a URI simultaneously, + # which separately would cause validation errors, but in conjunction, + # are valid. The URI will be revalidated as soon as the entire block has + # been executed. + # + # @param [Proc] block + # A set of operations to perform on a given URI. + def defer_validation + raise LocalJumpError, "No block given." unless block_given? + @validation_deferred = true + yield + @validation_deferred = false + validate + ensure + @validation_deferred = false + end + + def encode_with(coder) + instance_variables.each do |ivar| + value = instance_variable_get(ivar) + if value != NONE + key = ivar.to_s.slice(1..-1) + coder[key] = value + end + end + nil + end + + def init_with(coder) + reset_ivs + coder.map.each do |key, value| + instance_variable_set("@#{key}", value) + end + nil + end + + protected + SELF_REF = '.' + PARENT = '..' + + RULE_2A = /\/\.\/|\/\.$/ + RULE_2B_2C = /\/([^\/]*)\/\.\.\/|\/([^\/]*)\/\.\.$/ + RULE_2D = /^\.\.?\/?/ + RULE_PREFIXED_PARENT = /^\/\.\.?\/|^(\/\.\.?)+\/?$/ + + ## + # Resolves paths to their simplest form. + # + # @param [String] path The path to normalize. + # + # @return [String] The normalized path. + def self.normalize_path(path) + # Section 5.2.4 of RFC 3986 + + return if path.nil? + normalized_path = path.dup + loop do + mod ||= normalized_path.gsub!(RULE_2A, SLASH) + + pair = normalized_path.match(RULE_2B_2C) + if pair + parent = pair[1] + current = pair[2] + else + parent = nil + current = nil + end + + regexp = "/#{Regexp.escape(parent.to_s)}/\\.\\./|" + regexp += "(/#{Regexp.escape(current.to_s)}/\\.\\.$)" + + if pair && ((parent != SELF_REF && parent != PARENT) || + (current != SELF_REF && current != PARENT)) + mod ||= normalized_path.gsub!(Regexp.new(regexp), SLASH) + end + + mod ||= normalized_path.gsub!(RULE_2D, EMPTY_STR) + # Non-standard, removes prefixed dotted segments from path. + mod ||= normalized_path.gsub!(RULE_PREFIXED_PARENT, SLASH) + break if mod.nil? + end + + normalized_path + end + + ## + # Ensures that the URI is valid. + def validate + return if !!@validation_deferred + if self.scheme != nil && self.ip_based? && + (self.host == nil || self.host.empty?) && + (self.path == nil || self.path.empty?) + raise InvalidURIError, + "Absolute URI missing hierarchical segment: '#{self.to_s}'" + end + if self.host == nil + if self.port != nil || + self.user != nil || + self.password != nil + raise InvalidURIError, "Hostname not supplied: '#{self.to_s}'" + end + end + if self.path != nil && !self.path.empty? && self.path[0..0] != SLASH && + self.authority != nil + raise InvalidURIError, + "Cannot have a relative path with an authority set: '#{self.to_s}'" + end + if self.path != nil && !self.path.empty? && + self.path[0..1] == SLASH + SLASH && self.authority == nil + raise InvalidURIError, + "Cannot have a path with two leading slashes " + + "without an authority set: '#{self.to_s}'" + end + unreserved = CharacterClasses::UNRESERVED + sub_delims = CharacterClasses::SUB_DELIMS + if !self.host.nil? && (self.host =~ /[<>{}\/\\\?\#\@"[[:space:]]]/ || + (self.host[/^\[(.*)\]$/, 1] != nil && self.host[/^\[(.*)\]$/, 1] !~ + Regexp.new("^[#{unreserved}#{sub_delims}:]*$"))) + raise InvalidURIError, "Invalid character in host: '#{self.host.to_s}'" + end + return nil + end + + ## + # Replaces the internal state of self with the specified URI's state. + # Used in destructive operations to avoid massive code repetition. + # + # @param [Addressable::URI] uri The URI to replace self with. + # + # @return [Addressable::URI] self. + def replace_self(uri) + # Reset dependent values + reset_ivs + + @scheme = uri.scheme + @user = uri.user + @password = uri.password + @host = uri.host + @port = uri.port + @path = uri.path + @query = uri.query + @fragment = uri.fragment + return self + end + + ## + # Splits path string with "/" (slash). + # It is considered that there is empty string after last slash when + # path ends with slash. + # + # @param [String] path The path to split. + # + # @return [Array] An array of parts of path. + def split_path(path) + splitted = path.split(SLASH) + splitted << EMPTY_STR if path.end_with? SLASH + splitted + end + + ## + # Resets composite values for the entire URI + # + # @api private + def remove_composite_values + @uri_string = nil + @hash = nil + end + + ## + # Converts the string to be UTF-8 if it is not already UTF-8 + # + # @api private + def force_utf8_encoding_if_needed(str) + if str && str.encoding != Encoding::UTF_8 + str.force_encoding(Encoding::UTF_8) + end + end + + private + + ## + # Resets instance variables + # + # @api private + def reset_ivs + @scheme = nil + @user = nil + @normalized_scheme = NONE + @normalized_user = NONE + @uri_string = nil + @hash = nil + @userinfo = nil + @normalized_userinfo = NONE + @authority = nil + @password = nil + @normalized_authority = nil + @port = nil + @normalized_password = NONE + @host = nil + @normalized_host = nil + @normalized_port = NONE + @path = EMPTY_STR + @normalized_path = nil + @normalized_query = NONE + @fragment = nil + @normalized_fragment = NONE + @query = nil + end + + NONE = Module.new.freeze + + private_constant :NONE + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/addressable-2.8.5/lib/addressable/version.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/addressable-2.8.5/lib/addressable/version.rb new file mode 100644 index 0000000000..fe6a62f4f4 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/addressable-2.8.5/lib/addressable/version.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true + +#-- +# Copyright (C) Bob Aman +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#++ + + +# Used to prevent the class/module from being loaded more than once +if !defined?(Addressable::VERSION) + module Addressable + module VERSION + MAJOR = 2 + MINOR = 8 + TINY = 5 + + STRING = [MAJOR, MINOR, TINY].join('.') + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/LICENSE b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/LICENSE new file mode 100644 index 0000000000..991663e7b4 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/LICENSE @@ -0,0 +1,25 @@ +BSD 2-Clause License + +Copyright (c) 2007-2022, Dion Mendel +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata.rb new file mode 100644 index 0000000000..02a8390443 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata.rb @@ -0,0 +1,37 @@ +# BinData -- Binary data manipulator. +# Copyright (c) 2007 - 2018 Dion Mendel. + +require 'bindata/version' +require 'bindata/array' +require 'bindata/bits' +require 'bindata/buffer' +require 'bindata/choice' +require 'bindata/count_bytes_remaining' +require 'bindata/delayed_io' +require 'bindata/float' +require 'bindata/int' +require 'bindata/primitive' +require 'bindata/record' +require 'bindata/rest' +require 'bindata/skip' +require 'bindata/string' +require 'bindata/stringz' +require 'bindata/struct' +require 'bindata/trace' +require 'bindata/uint8_array' +require 'bindata/virtual' +require 'bindata/alignment' +require 'bindata/warnings' + +# = BinData +# +# A declarative way to read and write structured binary data. +# +# A full reference manual is available online at +# https://github.com/dmendel/bindata/wiki +# +# == License +# +# BinData is released under the same license as Ruby. +# +# Copyright (c) 2007 - 2018 Dion Mendel. diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/alignment.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/alignment.rb new file mode 100644 index 0000000000..baa517ac9c --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/alignment.rb @@ -0,0 +1,79 @@ +require 'bindata/base_primitive' + +module BinData + # Resets the stream alignment to the next byte. This is + # only useful when using bit-based primitives. + # + # class MyRec < BinData::Record + # bit4 :a + # resume_byte_alignment + # bit4 :b + # end + # + # MyRec.read("\x12\x34") #=> {"a" => 1, "b" => 3} + # + class ResumeByteAlignment < BinData::Base + def clear?; true; end + def assign(val); end + def snapshot; nil; end + def do_num_bytes; 0; end + + def do_read(io) + io.reset_read_bits + end + + def do_write(io) + io.flushbits + end + end + + # A monkey patch to force byte-aligned primitives to + # become bit-aligned. This allows them to be used at + # non byte based boundaries. + # + # class BitString < BinData::String + # bit_aligned + # end + # + # class MyRecord < BinData::Record + # bit4 :preamble + # bit_string :str, length: 2 + # end + # + module BitAligned + class BitAlignedIO + def initialize(io) + @io = io + end + def readbytes(n) + n.times.inject("") do |bytes, _| + bytes += @io.readbits(8, :big).chr + end + end + end + + def bit_aligned? + true + end + + def read_and_return_value(io) + super(BitAlignedIO.new(io)) + end + + def do_num_bytes + super.to_f + end + + def do_write(io) + value_to_binary_string(_value).each_byte { |v| io.writebits(v, 8, :big) } + end + end + + def BasePrimitive.bit_aligned + include BitAligned + end + + def Primitive.bit_aligned + fail "'bit_aligned' is not needed for BinData::Primitives" + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/array.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/array.rb new file mode 100644 index 0000000000..147a6110c5 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/array.rb @@ -0,0 +1,344 @@ +require 'bindata/base' +require 'bindata/dsl' + +module BinData + # An Array is a list of data objects of the same type. + # + # require 'bindata' + # + # data = "\x03\x04\x05\x06\x07\x08\x09" + # + # obj = BinData::Array.new(type: :int8, initial_length: 6) + # obj.read(data) #=> [3, 4, 5, 6, 7, 8] + # + # obj = BinData::Array.new(type: :int8, + # read_until: -> { index == 1 }) + # obj.read(data) #=> [3, 4] + # + # obj = BinData::Array.new(type: :int8, + # read_until: -> { element >= 6 }) + # obj.read(data) #=> [3, 4, 5, 6] + # + # obj = BinData::Array.new(type: :int8, + # read_until: -> { array[index] + array[index - 1] == 13 }) + # obj.read(data) #=> [3, 4, 5, 6, 7] + # + # obj = BinData::Array.new(type: :int8, read_until: :eof) + # obj.read(data) #=> [3, 4, 5, 6, 7, 8, 9] + # + # == Parameters + # + # Parameters may be provided at initialisation to control the behaviour of + # an object. These params are: + # + # :type:: The symbol representing the data type of the + # array elements. If the type is to have params + # passed to it, then it should be provided as + # [type_symbol, hash_params]. + # :initial_length:: The initial length of the array. + # :read_until:: While reading, elements are read until this + # condition is true. This is typically used to + # read an array until a sentinel value is found. + # The variables +index+, +element+ and +array+ + # are made available to any lambda assigned to + # this parameter. If the value of this parameter + # is the symbol :eof, then the array will read + # as much data from the stream as possible. + # + # Each data object in an array has the variable +index+ made available + # to any lambda evaluated as a parameter of that data object. + class Array < BinData::Base + extend DSLMixin + include Enumerable + + dsl_parser :array + arg_processor :array + + mandatory_parameter :type + optional_parameters :initial_length, :read_until + mutually_exclusive_parameters :initial_length, :read_until + + def initialize_shared_instance + @element_prototype = get_parameter(:type) + if get_parameter(:read_until) == :eof + extend ReadUntilEOFPlugin + elsif has_parameter?(:read_until) + extend ReadUntilPlugin + elsif has_parameter?(:initial_length) + extend InitialLengthPlugin + end + + super + end + + def initialize_instance + @element_list = nil + end + + def clear? + @element_list.nil? || elements.all?(&:clear?) + end + + def assign(array) + return if self.equal?(array) # prevent self assignment + raise ArgumentError, "can't set a nil value for #{debug_name}" if array.nil? + + @element_list = [] + concat(array) + end + + def snapshot + elements.collect(&:snapshot) + end + + def find_index(obj) + elements.index(obj) + end + alias index find_index + + # Returns the first index of +obj+ in self. + # + # Uses equal? for the comparator. + def find_index_of(obj) + elements.index { |el| el.equal?(obj) } + end + + def push(*args) + insert(-1, *args) + self + end + alias << push + + def unshift(*args) + insert(0, *args) + self + end + + def concat(array) + insert(-1, *array.to_ary) + self + end + + def insert(index, *objs) + extend_array(index - 1) + abs_index = (index >= 0) ? index : index + 1 + length + + # insert elements before... + new_elements = objs.map { new_element } + elements.insert(index, *new_elements) + + # ...assigning values + objs.each_with_index do |obj, i| + self[abs_index + i] = obj + end + + self + end + + # Returns the element at +index+. + def [](arg1, arg2 = nil) + if arg1.respond_to?(:to_int) && arg2.nil? + slice_index(arg1.to_int) + elsif arg1.respond_to?(:to_int) && arg2.respond_to?(:to_int) + slice_start_length(arg1.to_int, arg2.to_int) + elsif arg1.is_a?(Range) && arg2.nil? + slice_range(arg1) + else + raise TypeError, "can't convert #{arg1} into Integer" unless arg1.respond_to?(:to_int) + raise TypeError, "can't convert #{arg2} into Integer" unless arg2.respond_to?(:to_int) + end + end + alias slice [] + + def slice_index(index) + extend_array(index) + at(index) + end + + def slice_start_length(start, length) + elements[start, length] + end + + def slice_range(range) + elements[range] + end + private :slice_index, :slice_start_length, :slice_range + + # Returns the element at +index+. Unlike +slice+, if +index+ is out + # of range the array will not be automatically extended. + def at(index) + elements[index] + end + + # Sets the element at +index+. + def []=(index, value) + extend_array(index) + elements[index].assign(value) + end + + # Returns the first element, or the first +n+ elements, of the array. + # If the array is empty, the first form returns nil, and the second + # form returns an empty array. + def first(n = nil) + if n.nil? && empty? + # explicitly return nil as arrays grow automatically + nil + elsif n.nil? + self[0] + else + self[0, n] + end + end + + # Returns the last element, or the last +n+ elements, of the array. + # If the array is empty, the first form returns nil, and the second + # form returns an empty array. + def last(n = nil) + if n.nil? + self[-1] + else + n = length if n > length + self[-n, n] + end + end + + def length + elements.length + end + alias size length + + def empty? + length.zero? + end + + # Allow this object to be used in array context. + def to_ary + collect { |el| el } + end + + def each + elements.each { |el| yield el } + end + + def debug_name_of(child) #:nodoc: + index = find_index_of(child) + "#{debug_name}[#{index}]" + end + + def offset_of(child) #:nodoc: + index = find_index_of(child) + sum = sum_num_bytes_below_index(index) + + child.bit_aligned? ? sum.floor : sum.ceil + end + + def do_write(io) #:nodoc: + elements.each { |el| el.do_write(io) } + end + + def do_num_bytes #:nodoc: + sum_num_bytes_for_all_elements + end + + #--------------- + private + + def extend_array(max_index) + max_length = max_index + 1 + while elements.length < max_length + append_new_element + end + end + + def elements + @element_list ||= [] + end + + def append_new_element + element = new_element + elements << element + element + end + + def new_element + @element_prototype.instantiate(nil, self) + end + + def sum_num_bytes_for_all_elements + sum_num_bytes_below_index(length) + end + + def sum_num_bytes_below_index(index) + (0...index).inject(0) do |sum, i| + nbytes = elements[i].do_num_bytes + + if nbytes.is_a?(Integer) + sum.ceil + nbytes + else + sum + nbytes + end + end + end + end + + class ArrayArgProcessor < BaseArgProcessor + def sanitize_parameters!(obj_class, params) #:nodoc: + # ensure one of :initial_length and :read_until exists + unless params.has_at_least_one_of?(:initial_length, :read_until) + params[:initial_length] = 0 + end + + params.warn_replacement_parameter(:length, :initial_length) + params.warn_replacement_parameter(:read_length, :initial_length) + params.must_be_integer(:initial_length) + + params.merge!(obj_class.dsl_params) + params.sanitize_object_prototype(:type) + end + end + + # Logic for the :read_until parameter + module ReadUntilPlugin + def do_read(io) + loop do + element = append_new_element + element.do_read(io) + variables = { index: self.length - 1, element: self.last, array: self } + break if eval_parameter(:read_until, variables) + end + end + end + + # Logic for the read_until: :eof parameter + module ReadUntilEOFPlugin + def do_read(io) + loop do + element = append_new_element + begin + element.do_read(io) + rescue EOFError, IOError + elements.pop + break + end + end + end + end + + # Logic for the :initial_length parameter + module InitialLengthPlugin + def do_read(io) + elements.each { |el| el.do_read(io) } + end + + def elements + if @element_list.nil? + @element_list = [] + eval_parameter(:initial_length).times do + @element_list << new_element + end + end + + @element_list + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/base.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/base.rb new file mode 100644 index 0000000000..15fd398201 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/base.rb @@ -0,0 +1,335 @@ +require 'bindata/framework' +require 'bindata/io' +require 'bindata/lazy' +require 'bindata/name' +require 'bindata/params' +require 'bindata/registry' +require 'bindata/sanitize' + +module BinData + # This is the abstract base class for all data objects. + class Base + extend AcceptedParametersPlugin + include Framework + include RegisterNamePlugin + + class << self + # Instantiates this class and reads from +io+, returning the newly + # created data object. +args+ will be used when instantiating. + def read(io, *args, &block) + obj = self.new(*args) + obj.read(io, &block) + obj + end + + # The arg processor for this class. + def arg_processor(name = nil) + @arg_processor ||= nil + + if name + @arg_processor = "#{name}_arg_processor".gsub(/(?:^|_)(.)/) { $1.upcase }.to_sym + elsif @arg_processor.is_a? Symbol + @arg_processor = BinData.const_get(@arg_processor).new + elsif @arg_processor.nil? + @arg_processor = superclass.arg_processor + else + @arg_processor + end + end + + # The name of this class as used by Records, Arrays etc. + def bindata_name + RegisteredClasses.underscore_name(name) + end + + # Call this method if this class is abstract and not to be used. + def unregister_self + RegisteredClasses.unregister(name) + end + + # Registers all subclasses of this class for use + def register_subclasses #:nodoc: + singleton_class.send(:undef_method, :inherited) + define_singleton_method(:inherited) do |subclass| + RegisteredClasses.register(subclass.name, subclass) + register_subclasses + end + end + + private :unregister_self, :register_subclasses + end + + # Register all subclasses of this class. + register_subclasses + + # Set the initial arg processor. + arg_processor :base + + # Creates a new data object. + # + # Args are optional, but if present, must be in the following order. + # + # +value+ is a value that is +assign+ed immediately after initialization. + # + # +parameters+ is a hash containing symbol keys. Some parameters may + # reference callable objects (methods or procs). + # + # +parent+ is the parent data object (e.g. struct, array, choice) this + # object resides under. + # + def initialize(*args) + value, @params, @parent = extract_args(args) + + initialize_shared_instance + initialize_instance + assign(value) if value + end + + attr_accessor :parent + protected :parent= + + # Creates a new data object based on this instance. + # + # All parameters will be be duplicated. Use this method + # when creating multiple objects with the same parameters. + def new(value = nil, parent = nil) + obj = clone + obj.parent = parent if parent + obj.initialize_instance + obj.assign(value) if value + + obj + end + + # Returns the result of evaluating the parameter identified by +key+. + # + # +overrides+ is an optional +parameters+ like hash that allow the + # parameters given at object construction to be overridden. + # + # Returns nil if +key+ does not refer to any parameter. + def eval_parameter(key, overrides = nil) + value = get_parameter(key) + if value.is_a?(Symbol) || value.respond_to?(:arity) + lazy_evaluator.lazy_eval(value, overrides) + else + value + end + end + + # Returns a lazy evaluator for this object. + def lazy_evaluator #:nodoc: + @lazy ||= LazyEvaluator.new(self) + end + + # Returns the parameter referenced by +key+. + # Use this method if you are sure the parameter is not to be evaluated. + # You most likely want #eval_parameter. + def get_parameter(key) + @params[key] + end + + # Returns whether +key+ exists in the +parameters+ hash. + def has_parameter?(key) + @params.has_parameter?(key) + end + + # Resets the internal state to that of a newly created object. + def clear + initialize_instance + end + + # Reads data into this data object. + def read(io, &block) + io = BinData::IO::Read.new(io) unless BinData::IO::Read === io + + start_read do + clear + do_read(io) + end + block.call(self) if block_given? + + self + end + + # Writes the value for this data object to +io+. + def write(io, &block) + io = BinData::IO::Write.new(io) unless BinData::IO::Write === io + + do_write(io) + io.flush + + block.call(self) if block_given? + + self + end + + # Returns the number of bytes it will take to write this data object. + def num_bytes + do_num_bytes.ceil + end + + # Returns the string representation of this data object. + def to_binary_s(&block) + io = BinData::IO.create_string_io + write(io, &block) + io.string + end + + # Returns the hexadecimal string representation of this data object. + def to_hex(&block) + to_binary_s(&block).unpack('H*')[0] + end + + # Return a human readable representation of this data object. + def inspect + snapshot.inspect + end + + # Return a string representing this data object. + def to_s + snapshot.to_s + end + + # Work with Ruby's pretty-printer library. + def pretty_print(pp) #:nodoc: + pp.pp(snapshot) + end + + # Override and delegate =~ as it is defined in Object. + def =~(other) + snapshot =~ other + end + + # Returns a user friendly name of this object for debugging purposes. + def debug_name + if @parent + @parent.debug_name_of(self) + else + "obj" + end + end + + # Returns the offset (in bytes) of this object with respect to its most + # distant ancestor. + def abs_offset + if @parent + @parent.abs_offset + @parent.offset_of(self) + else + 0 + end + end + + # Returns the offset (in bytes) of this object with respect to its parent. + def rel_offset + if @parent + @parent.offset_of(self) + else + 0 + end + end + + def ==(other) #:nodoc: + # double dispatch + other == snapshot + end + + # A version of +respond_to?+ used by the lazy evaluator. It doesn't + # reinvoke the evaluator so as to avoid infinite evaluation loops. + def safe_respond_to?(symbol, include_private = false) #:nodoc: + base_respond_to?(symbol, include_private) + end + + alias base_respond_to? respond_to? + + #--------------- + private + + def extract_args(args) + self.class.arg_processor.extract_args(self.class, args) + end + + def start_read + top_level_set(:in_read, true) + yield + ensure + top_level_set(:in_read, false) + end + + # Is this object tree currently being read? Used by BasePrimitive. + def reading? + top_level_get(:in_read) + end + + def top_level_set(sym, value) + top_level.instance_variable_set("@tl_#{sym}", value) + end + + def top_level_get(sym) + tl = top_level + tl.instance_variable_defined?("@tl_#{sym}") && + tl.instance_variable_get("@tl_#{sym}") + end + + def top_level + if parent.nil? + tl = self + else + tl = parent + tl = tl.parent while tl.parent + end + + tl + end + + def binary_string(str) + str.to_s.dup.force_encoding(Encoding::BINARY) + end + end + + # ArgProcessors process the arguments passed to BinData::Base.new into + # the form required to initialise the BinData object. + # + # Any passed parameters are sanitized so the BinData object doesn't + # need to perform error checking on the parameters. + class BaseArgProcessor + @@empty_hash = Hash.new.freeze + + # Takes the arguments passed to BinData::Base.new and + # extracts [value, sanitized_parameters, parent]. + def extract_args(obj_class, obj_args) + value, params, parent = separate_args(obj_class, obj_args) + sanitized_params = SanitizedParameters.sanitize(params, obj_class) + + [value, sanitized_params, parent] + end + + # Separates the arguments passed to BinData::Base.new into + # [value, parameters, parent]. Called by #extract_args. + def separate_args(_obj_class, obj_args) + args = obj_args.dup + value = parameters = parent = nil + + if args.length > 1 && args.last.is_a?(BinData::Base) + parent = args.pop + end + + if args.length > 0 && args.last.is_a?(Hash) + parameters = args.pop + end + + if args.length > 0 + value = args.pop + end + + parameters ||= @@empty_hash + + [value, parameters, parent] + end + + # Performs sanity checks on the given parameters. + # This method converts the parameters to the form expected + # by the data object. + def sanitize_parameters!(obj_class, obj_params) + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/base_primitive.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/base_primitive.rb new file mode 100644 index 0000000000..3b2b4839e7 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/base_primitive.rb @@ -0,0 +1,248 @@ +require 'bindata/base' + +module BinData + # A BinData::BasePrimitive object is a container for a value that has a + # particular binary representation. A value corresponds to a primitive type + # such as as integer, float or string. Only one value can be contained by + # this object. This value can be read from or written to an IO stream. + # + # require 'bindata' + # + # obj = BinData::Uint8.new(initial_value: 42) + # obj #=> 42 + # obj.assign(5) + # obj #=> 5 + # obj.clear + # obj #=> 42 + # + # obj = BinData::Uint8.new(value: 42) + # obj #=> 42 + # obj.assign(5) + # obj #=> 42 + # + # obj = BinData::Uint8.new(assert: 3) + # obj.read("\005") #=> BinData::ValidityError: value is '5' but expected '3' + # + # obj = BinData::Uint8.new(assert: -> { value < 5 }) + # obj.read("\007") #=> BinData::ValidityError: value not as expected + # + # == Parameters + # + # Parameters may be provided at initialisation to control the behaviour of + # an object. These params include those for BinData::Base as well as: + # + # [:initial_value] This is the initial value to use before one is + # either #read or explicitly set with #value=. + # [:value] The object will always have this value. + # Calls to #value= are ignored when + # using this param. While reading, #value + # will return the value of the data read from the + # IO, not the result of the :value param. + # [:assert] Raise an error unless the value read or assigned + # meets this criteria. The variable +value+ is + # made available to any lambda assigned to this + # parameter. A boolean return indicates success + # or failure. Any other return is compared to + # the value just read in. + # [:asserted_value] Equivalent to :assert and :value. + # + class BasePrimitive < BinData::Base + unregister_self + + optional_parameters :initial_value, :value, :assert, :asserted_value + mutually_exclusive_parameters :initial_value, :value + mutually_exclusive_parameters :asserted_value, :value, :assert + + def initialize_shared_instance + extend InitialValuePlugin if has_parameter?(:initial_value) + extend ValuePlugin if has_parameter?(:value) + extend AssertPlugin if has_parameter?(:assert) + extend AssertedValuePlugin if has_parameter?(:asserted_value) + super + end + + def initialize_instance + @value = nil + end + + def clear? #:nodoc: + @value.nil? + end + + def assign(val) + raise ArgumentError, "can't set a nil value for #{debug_name}" if val.nil? + + raw_val = val.respond_to?(:snapshot) ? val.snapshot : val + @value = + begin + raw_val.dup + rescue TypeError + # can't dup Fixnums + raw_val + end + end + + def snapshot + _value + end + + def value + snapshot + end + + def value=(val) + assign(val) + end + + def respond_to?(symbol, include_private = false) #:nodoc: + child = snapshot + child.respond_to?(symbol, include_private) || super + end + + def method_missing(symbol, *args, &block) #:nodoc: + child = snapshot + if child.respond_to?(symbol) + self.class.class_eval \ + "def #{symbol}(*args, &block);" \ + " snapshot.#{symbol}(*args, &block);" \ + "end" + child.__send__(symbol, *args, &block) + else + super + end + end + + def <=>(other) + snapshot <=> other + end + + def eql?(other) + # double dispatch + other.eql?(snapshot) + end + + def hash + snapshot.hash + end + + def do_read(io) #:nodoc: + @value = read_and_return_value(io) + end + + def do_write(io) #:nodoc: + io.writebytes(value_to_binary_string(_value)) + end + + def do_num_bytes #:nodoc: + value_to_binary_string(_value).length + end + + #--------------- + private + + # The unmodified value of this data object. Note that #snapshot calls this + # method. This indirection is so that #snapshot can be overridden in + # subclasses to modify the presentation value. + def _value + @value != nil ? @value : sensible_default + end + + # Logic for the :value parameter + module ValuePlugin + def assign(val) + # Ignored + end + + def _value + reading? ? @value : eval_parameter(:value) + end + end + + # Logic for the :initial_value parameter + module InitialValuePlugin + def _value + @value != nil ? @value : eval_parameter(:initial_value) + end + end + + # Logic for the :assert parameter + module AssertPlugin + def assign(val) + super(val) + assert! + end + + def do_read(io) #:nodoc: + super(io) + assert! + end + + def assert! + current_value = snapshot + expected = eval_parameter(:assert, value: current_value) + + msg = + if !expected + "value '#{current_value}' not as expected" + elsif expected != true && current_value != expected + "value is '#{current_value}' but expected '#{expected}'" + else + nil + end + + raise ValidityError, "#{msg} for #{debug_name}" if msg + end + end + + # Logic for the :asserted_value parameter + module AssertedValuePlugin + def assign(val) + assert_value(val) + super(val) + end + + def _value + reading? ? @value : eval_parameter(:asserted_value) + end + + def do_read(io) #:nodoc: + super(io) + assert! + end + + def assert! + assert_value(snapshot) + end + + def assert_value(current_value) + expected = eval_parameter(:asserted_value, value: current_value) + if current_value != expected + raise ValidityError, + "value is '#{current_value}' but " \ + "expected '#{expected}' for #{debug_name}" + end + end + end + + ########################################################################### + # To be implemented by subclasses + + # Return the string representation that +val+ will take when written. + def value_to_binary_string(val) + raise NotImplementedError + end + + # Read a number of bytes from +io+ and return the value they represent. + def read_and_return_value(io) + raise NotImplementedError + end + + # Return a sensible default for this data. + def sensible_default + raise NotImplementedError + end + + # To be implemented by subclasses + ########################################################################### + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/bits.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/bits.rb new file mode 100644 index 0000000000..a862f40ab1 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/bits.rb @@ -0,0 +1,186 @@ +require 'thread' +require 'bindata/base_primitive' + +module BinData + # Defines a number of classes that contain a bit based integer. + # The integer is defined by endian and number of bits. + + module BitField #:nodoc: all + @@mutex = Mutex.new + + class << self + def define_class(name, nbits, endian, signed = :unsigned) + @@mutex.synchronize do + unless BinData.const_defined?(name) + new_class = Class.new(BinData::BasePrimitive) + BitField.define_methods(new_class, nbits, endian.to_sym, signed.to_sym) + RegisteredClasses.register(name, new_class) + + BinData.const_set(name, new_class) + end + end + + BinData.const_get(name) + end + + def define_methods(bit_class, nbits, endian, signed) + bit_class.module_eval <<-END + #{create_params_code(nbits)} + + def assign(val) + #{create_nbits_code(nbits)} + #{create_clamp_code(nbits, signed)} + super(val) + end + + def do_write(io) + #{create_nbits_code(nbits)} + val = _value + #{create_int2uint_code(nbits, signed)} + io.writebits(val, #{nbits}, :#{endian}) + end + + def do_num_bytes + #{create_nbits_code(nbits)} + #{create_do_num_bytes_code(nbits)} + end + + def bit_aligned? + true + end + + #--------------- + private + + def read_and_return_value(io) + #{create_nbits_code(nbits)} + val = io.readbits(#{nbits}, :#{endian}) + #{create_uint2int_code(nbits, signed)} + val + end + + def sensible_default + 0 + end + END + end + + def create_params_code(nbits) + if nbits == :nbits + "mandatory_parameter :nbits" + else + "" + end + end + + def create_nbits_code(nbits) + if nbits == :nbits + "nbits = eval_parameter(:nbits)" + else + "" + end + end + + def create_do_num_bytes_code(nbits) + if nbits == :nbits + "nbits / 8.0" + else + nbits / 8.0 + end + end + + def create_clamp_code(nbits, signed) + if nbits == :nbits + create_dynamic_clamp_code(signed) + else + create_fixed_clamp_code(nbits, signed) + end + end + + def create_dynamic_clamp_code(signed) + if signed == :signed + max = "(1 << (nbits - 1)) - 1" + min = "-((#{max}) + 1)" + else + max = "(1 << nbits) - 1" + min = "0" + end + + "val = val.clamp(#{min}, #{max})" + end + + def create_fixed_clamp_code(nbits, signed) + if nbits == 1 && signed == :signed + raise "signed bitfield must have more than one bit" + end + + if signed == :signed + max = "(1 << (#{nbits} - 1)) - 1" + min = "-((#{max}) + 1)" + else + min = "0" + max = "(1 << #{nbits}) - 1" + end + + clamp = "(val = val.clamp(#{min}, #{max}))" + + if nbits == 1 + # allow single bits to be used as booleans + clamp = "(val == true) ? 1 : (not val) ? 0 : #{clamp}" + end + + "val = #{clamp}" + end + + def create_int2uint_code(nbits, signed) + if signed != :signed + "" + elsif nbits == :nbits + "val &= (1 << nbits) - 1" + else + "val &= #{(1 << nbits) - 1}" + end + end + + def create_uint2int_code(nbits, signed) + if signed != :signed + "" + elsif nbits == :nbits + "val -= (1 << nbits) if (val >= (1 << (nbits - 1)))" + else + "val -= #{1 << nbits} if (val >= #{1 << (nbits - 1)})" + end + end + end + end + + # Create classes for dynamic bitfields + { + "Bit" => :big, + "BitLe" => :little, + "Sbit" => [:big, :signed], + "SbitLe" => [:little, :signed], + }.each_pair { |name, args| BitField.define_class(name, :nbits, *args) } + + # Create classes on demand + module BitFieldFactory + def const_missing(name) + mappings = { + /^Bit(\d+)$/ => :big, + /^Bit(\d+)le$/ => :little, + /^Sbit(\d+)$/ => [:big, :signed], + /^Sbit(\d+)le$/ => [:little, :signed] + } + + mappings.each_pair do |regex, args| + if regex =~ name.to_s + nbits = $1.to_i + return BitField.define_class(name, nbits, *args) + end + end + + super(name) + end + end + BinData.extend BitFieldFactory +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/buffer.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/buffer.rb new file mode 100644 index 0000000000..b504c6cdf3 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/buffer.rb @@ -0,0 +1,117 @@ +require 'bindata/base' +require 'bindata/dsl' + +module BinData + # A Buffer is conceptually a substream within a data stream. It has a + # defined size and it will always read or write the exact number of bytes to + # fill the buffer. Short reads will skip over unused bytes and short writes + # will pad the substream with "\0" bytes. + # + # require 'bindata' + # + # obj = BinData::Buffer.new(length: 5, type: [:string, {value: "abc"}]) + # obj.to_binary_s #=> "abc\000\000" + # + # + # class MyBuffer < BinData::Buffer + # default_parameter length: 8 + # + # endian :little + # + # uint16 :num1 + # uint16 :num2 + # # padding occurs here + # end + # + # obj = MyBuffer.read("\001\000\002\000\000\000\000\000") + # obj.num1 #=> 1 + # obj.num1 #=> 2 + # obj.raw_num_bytes #=> 4 + # obj.num_bytes #=> 8 + # + # + # class StringTable < BinData::Record + # endian :little + # + # uint16 :table_size_in_bytes + # buffer :strings, length: :table_size_in_bytes do + # array read_until: :eof do + # uint8 :len + # string :str, length: :len + # end + # end + # end + # + # + # == Parameters + # + # Parameters may be provided at initialisation to control the behaviour of + # an object. These params are: + # + # :length:: The number of bytes in the buffer. + # :type:: The single type inside the buffer. Use a struct if + # multiple fields are required. + class Buffer < BinData::Base + extend DSLMixin + + dsl_parser :buffer + arg_processor :buffer + + mandatory_parameters :length, :type + + def initialize_instance + @type = get_parameter(:type).instantiate(nil, self) + end + + # The number of bytes used, ignoring the padding imposed by the buffer. + def raw_num_bytes + @type.num_bytes + end + + def clear? + @type.clear? + end + + def assign(val) + @type.assign(val) + end + + def snapshot + @type.snapshot + end + + def respond_to?(symbol, include_private = false) #:nodoc: + @type.respond_to?(symbol, include_private) || super + end + + def method_missing(symbol, *args, &block) #:nodoc: + @type.__send__(symbol, *args, &block) + end + + def do_read(io) #:nodoc: + io.with_buffer(eval_parameter(:length)) do + @type.do_read(io) + end + end + + def do_write(io) #:nodoc: + io.with_buffer(eval_parameter(:length)) do + @type.do_write(io) + end + end + + def do_num_bytes #:nodoc: + eval_parameter(:length) + end + end + + class BufferArgProcessor < BaseArgProcessor + include MultiFieldArgSeparator + + def sanitize_parameters!(obj_class, params) + params.merge!(obj_class.dsl_params) + params.must_be_integer(:length) + params.sanitize_object_prototype(:type) + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/choice.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/choice.rb new file mode 100644 index 0000000000..a06f36e3cf --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/choice.rb @@ -0,0 +1,186 @@ +require 'bindata/base' +require 'bindata/dsl' + +module BinData + # A Choice is a collection of data objects of which only one is active + # at any particular time. Method calls will be delegated to the active + # choice. + # + # require 'bindata' + # + # type1 = [:string, {value: "Type1"}] + # type2 = [:string, {value: "Type2"}] + # + # choices = {5 => type1, 17 => type2} + # a = BinData::Choice.new(choices: choices, selection: 5) + # a # => "Type1" + # + # choices = [ type1, type2 ] + # a = BinData::Choice.new(choices: choices, selection: 1) + # a # => "Type2" + # + # choices = [ nil, nil, nil, type1, nil, type2 ] + # a = BinData::Choice.new(choices: choices, selection: 3) + # a # => "Type1" + # + # + # Chooser = Struct.new(:choice) + # mychoice = Chooser.new + # mychoice.choice = 'big' + # + # choices = {'big' => :uint16be, 'little' => :uint16le} + # a = BinData::Choice.new(choices: choices, copy_on_change: true, + # selection: -> { mychoice.choice }) + # a.assign(256) + # a.to_binary_s #=> "\001\000" + # + # mychoice.choice = 'little' + # a.to_binary_s #=> "\000\001" + # + # == Parameters + # + # Parameters may be provided at initialisation to control the behaviour of + # an object. These params are: + # + # :choices:: Either an array or a hash specifying the possible + # data objects. The format of the + # array/hash.values is a list of symbols + # representing the data object type. If a choice + # is to have params passed to it, then it should + # be provided as [type_symbol, hash_params]. An + # implementation constraint is that the hash may + # not contain symbols as keys, with the exception + # of :default. :default is to be used when then + # :selection does not exist in the :choices hash. + # :selection:: An index/key into the :choices array/hash which + # specifies the currently active choice. + # :copy_on_change:: If set to true, copy the value of the previous + # selection to the current selection whenever the + # selection changes. Default is false. + class Choice < BinData::Base + extend DSLMixin + + dsl_parser :choice + arg_processor :choice + + mandatory_parameters :choices, :selection + optional_parameter :copy_on_change + + def initialize_shared_instance + extend CopyOnChangePlugin if eval_parameter(:copy_on_change) == true + super + end + + def initialize_instance + @choices = {} + @last_selection = nil + end + + # Returns the current selection. + def selection + selection = eval_parameter(:selection) + if selection.nil? + raise IndexError, ":selection returned nil for #{debug_name}" + end + selection + end + + def respond_to?(symbol, include_private = false) #:nodoc: + current_choice.respond_to?(symbol, include_private) || super + end + + def method_missing(symbol, *args, &block) #:nodoc: + current_choice.__send__(symbol, *args, &block) + end + + %w(clear? assign snapshot do_read do_write do_num_bytes).each do |m| + module_eval <<-END + def #{m}(*args) + current_choice.#{m}(*args) + end + END + end + + #--------------- + private + + def current_choice + current_selection = selection + @choices[current_selection] ||= instantiate_choice(current_selection) + end + + def instantiate_choice(selection) + prototype = get_parameter(:choices)[selection] + if prototype.nil? + raise IndexError, "selection '#{selection}' does not exist in :choices for #{debug_name}" + end + prototype.instantiate(nil, self) + end + end + + class ChoiceArgProcessor < BaseArgProcessor + def sanitize_parameters!(obj_class, params) #:nodoc: + params.merge!(obj_class.dsl_params) + + params.sanitize_choices(:choices) do |choices| + hash_choices = choices_as_hash(choices) + ensure_valid_keys(hash_choices) + hash_choices + end + end + + #------------- + private + + def choices_as_hash(choices) + if choices.respond_to?(:to_ary) + key_array_by_index(choices.to_ary) + else + choices + end + end + + def key_array_by_index(array) + result = {} + array.each_with_index do |el, i| + result[i] = el unless el.nil? + end + result + end + + def ensure_valid_keys(choices) + if choices.key?(nil) + raise ArgumentError, ":choices hash may not have nil key" + end + if choices.keys.detect { |key| key.is_a?(Symbol) && key != :default } + raise ArgumentError, ":choices hash may not have symbols for keys" + end + end + end + + # Logic for the :copy_on_change parameter + module CopyOnChangePlugin + def current_choice + obj = super + copy_previous_value(obj) + obj + end + + def copy_previous_value(obj) + current_selection = selection + prev = get_previous_choice(current_selection) + obj.assign(prev) unless prev.nil? + remember_current_selection(current_selection) + end + + def get_previous_choice(selection) + if @last_selection && selection != @last_selection + @choices[@last_selection] + end + end + + def remember_current_selection(selection) + @last_selection = selection + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/count_bytes_remaining.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/count_bytes_remaining.rb new file mode 100644 index 0000000000..c90b7ba268 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/count_bytes_remaining.rb @@ -0,0 +1,34 @@ +require "bindata/base_primitive" + +module BinData + # Counts the number of bytes remaining in the input stream from the current + # position to the end of the stream. This only makes sense for seekable + # streams. + # + # require 'bindata' + # + # class A < BinData::Record + # count_bytes_remaining :bytes_remaining + # string :all_data, read_length: :bytes_remaining + # end + # + # obj = A.read("abcdefghij") + # obj.all_data #=> "abcdefghij" + # + class CountBytesRemaining < BinData::BasePrimitive + #--------------- + private + + def value_to_binary_string(val) + "" + end + + def read_and_return_value(io) + io.num_bytes_remaining + end + + def sensible_default + 0 + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/delayed_io.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/delayed_io.rb new file mode 100644 index 0000000000..451bb06c7e --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/delayed_io.rb @@ -0,0 +1,198 @@ +require 'bindata/base' +require 'bindata/dsl' + +module BinData + # BinData declarations are evaluated in a single pass. + # However, some binary formats require multi pass processing. A common + # reason is seeking backwards in the input stream. + # + # DelayedIO supports multi pass processing. It works by ignoring the normal + # #read or #write calls. The user must explicitly call the #read_now! or + # #write_now! methods to process an additional pass. This additional pass + # must specify the abs_offset of the I/O operation. + # + # require 'bindata' + # + # obj = BinData::DelayedIO.new(read_abs_offset: 3, type: :uint16be) + # obj.read("\x00\x00\x00\x11\x12") + # obj #=> 0 + # + # obj.read_now! + # obj #=> 0x1112 + # + # - OR - + # + # obj.read("\x00\x00\x00\x11\x12") { obj.read_now! } #=> 0x1122 + # + # obj.to_binary_s { obj.write_now! } #=> "\x00\x00\x00\x11\x12" + # + # You can use the +auto_call_delayed_io+ keyword to cause #read and #write to + # automatically perform the extra passes. + # + # class ReversePascalString < BinData::Record + # auto_call_delayed_io + # + # delayed_io :str, read_abs_offset: 0 do + # string read_length: :len + # end + # count_bytes_remaining :total_size + # skip to_abs_offset: -> { total_size - 1 } + # uint8 :len, value: -> { str.length } + # end + # + # s = ReversePascalString.read("hello\x05") + # s.to_binary_s #=> "hello\x05" + # + # + # == Parameters + # + # Parameters may be provided at initialisation to control the behaviour of + # an object. These params are: + # + # :read_abs_offset:: The abs_offset to start reading at. + # :type:: The single type inside the delayed io. Use + # a struct if multiple fields are required. + class DelayedIO < BinData::Base + extend DSLMixin + + dsl_parser :delayed_io + arg_processor :delayed_io + + mandatory_parameters :read_abs_offset, :type + + def initialize_instance + @type = get_parameter(:type).instantiate(nil, self) + @abs_offset = nil + @read_io = nil + @write_io = nil + end + + def clear? + @type.clear? + end + + def assign(val) + @type.assign(val) + end + + def snapshot + @type.snapshot + end + + def num_bytes + @type.num_bytes + end + + def respond_to?(symbol, include_private = false) #:nodoc: + @type.respond_to?(symbol, include_private) || super + end + + def method_missing(symbol, *args, &block) #:nodoc: + @type.__send__(symbol, *args, &block) + end + + def abs_offset + @abs_offset || eval_parameter(:read_abs_offset) + end + + # Sets the +abs_offset+ to use when writing this object. + def abs_offset=(offset) + @abs_offset = offset + end + + def rel_offset + abs_offset + end + + def do_read(io) #:nodoc: + @read_io = io + end + + def do_write(io) #:nodoc: + @write_io = io + end + + def do_num_bytes #:nodoc: + 0 + end + + def include_obj? + ! has_parameter?(:onlyif) || eval_parameter(:onlyif) + end + + # DelayedIO objects aren't read when #read is called. + # The reading is delayed until this method is called. + def read_now! + return unless include_obj? + raise IOError, "read from where?" unless @read_io + + @read_io.seekbytes(abs_offset - @read_io.offset) + start_read do + @type.do_read(@read_io) + end + end + + # DelayedIO objects aren't written when #write is called. + # The writing is delayed until this method is called. + def write_now! + return unless include_obj? + raise IOError, "write to where?" unless @write_io + + @write_io.seekbytes(abs_offset - @write_io.offset) + @type.do_write(@write_io) + end + end + + class DelayedIoArgProcessor < BaseArgProcessor + include MultiFieldArgSeparator + + def sanitize_parameters!(obj_class, params) + params.merge!(obj_class.dsl_params) + params.must_be_integer(:read_abs_offset) + params.sanitize_object_prototype(:type) + end + end + + # Add +auto_call_delayed_io+ keyword to BinData::Base. + class Base + class << self + # The +auto_call_delayed_io+ keyword sets a data object tree to perform + # multi pass I/O automatically. + def auto_call_delayed_io + include AutoCallDelayedIO + + return if DelayedIO.method_defined? :initialize_instance_without_record_io + + DelayedIO.send(:alias_method, :initialize_instance_without_record_io, :initialize_instance) + DelayedIO.send(:define_method, :initialize_instance) do + if @parent && !defined? @delayed_io_recorded + @delayed_io_recorded = true + list = top_level_get(:delayed_ios) + list << self if list + end + + initialize_instance_without_record_io + end + end + end + + module AutoCallDelayedIO + def initialize_shared_instance + top_level_set(:delayed_ios, []) + super + end + + def read(io) + super(io) { top_level_get(:delayed_ios).each(&:read_now!) } + end + + def write(io, *_) + super(io) { top_level_get(:delayed_ios).each(&:write_now!) } + end + + def num_bytes + to_binary_s.size + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/dsl.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/dsl.rb new file mode 100644 index 0000000000..115fe0531d --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/dsl.rb @@ -0,0 +1,484 @@ +module BinData + # Extracts args for Records and Buffers. + # + # Foo.new(bar: "baz) is ambiguous as to whether :bar is a value or parameter. + # + # BaseArgExtractor always assumes :bar is parameter. This extractor correctly + # identifies it as value or parameter. + module MultiFieldArgSeparator + def separate_args(obj_class, obj_args) + value, parameters, parent = super(obj_class, obj_args) + + if parameters_is_value?(obj_class, value, parameters) + value = parameters + parameters = {} + end + + [value, parameters, parent] + end + + def parameters_is_value?(obj_class, value, parameters) + if value.nil? && !parameters.empty? + field_names_in_parameters?(obj_class, parameters) + else + false + end + end + + def field_names_in_parameters?(obj_class, parameters) + field_names = obj_class.fields.field_names + param_keys = parameters.keys + + !(field_names & param_keys).empty? + end + end + + # BinData classes that are part of the DSL must be extended by this. + module DSLMixin + def dsl_parser(parser_type = nil) + @dsl_parser ||= begin + parser_type ||= superclass.dsl_parser.parser_type + DSLParser.new(self, parser_type) + end + end + + def method_missing(symbol, *args, &block) #:nodoc: + dsl_parser.__send__(symbol, *args, &block) + end + + # Assert object is not an array or string. + def to_ary; nil; end + def to_str; nil; end + + # A DSLParser parses and accumulates field definitions of the form + # + # type name, params + # + # where: + # * +type+ is the under_scored name of a registered type + # * +name+ is the (possible optional) name of the field + # * +params+ is a hash containing any parameters + # + class DSLParser + def initialize(the_class, parser_type) + raise "unknown parser type #{parser_type}" unless parser_abilities[parser_type] + + @the_class = the_class + @parser_type = parser_type + @validator = DSLFieldValidator.new(the_class, self) + @endian = nil + end + + attr_reader :parser_type + + def endian(endian = nil) + if endian + set_endian(endian) + elsif @endian.nil? + set_endian(parent_attribute(:endian)) + end + @endian + end + + def search_prefix(*args) + @search_prefix ||= parent_attribute(:search_prefix, []).dup + + prefix = args.collect(&:to_sym).compact + unless prefix.empty? + if fields? + dsl_raise SyntaxError, "search_prefix must be called before defining fields" + end + + @search_prefix = prefix.concat(@search_prefix) + end + + @search_prefix + end + + def hide(*args) + if option?(:hidden_fields) + @hide ||= parent_attribute(:hide, []).dup + + hidden = args.collect(&:to_sym).compact + @hide.concat(hidden) + + @hide + end + end + + def fields + @fields ||= SanitizedFields.new(hints, parent_fields) + end + + def dsl_params + abilities = parser_abilities[@parser_type] + send(abilities.at(0), abilities.at(1)) + end + + def method_missing(*args, &block) + ensure_hints + parse_and_append_field(*args, &block) + end + + #------------- + private + + def parser_abilities + @abilities ||= { + struct: [:to_struct_params, :struct, [:multiple_fields, :optional_fieldnames, :hidden_fields]], + array: [:to_object_params, :type, [:multiple_fields, :optional_fieldnames]], + buffer: [:to_object_params, :type, [:multiple_fields, :optional_fieldnames, :hidden_fields]], + choice: [:to_choice_params, :choices, [:multiple_fields, :all_or_none_fieldnames, :fieldnames_are_values]], + delayed_io: [:to_object_params, :type, [:multiple_fields, :optional_fieldnames, :hidden_fields]], + primitive: [:to_struct_params, :struct, [:multiple_fields, :optional_fieldnames]], + skip: [:to_object_params, :until_valid, [:multiple_fields, :optional_fieldnames]], + } + end + + def option?(opt) + parser_abilities[@parser_type].at(2).include?(opt) + end + + def ensure_hints + endian + search_prefix + end + + def hints + { endian: endian, search_prefix: search_prefix } + end + + def set_endian(endian) + if endian + if fields? + dsl_raise SyntaxError, "endian must be called before defining fields" + end + if !valid_endian?(endian) + dsl_raise ArgumentError, "unknown value for endian '#{endian}'" + end + + if endian == :big_and_little + DSLBigAndLittleEndianHandler.handle(@the_class) + end + + @endian = endian + end + end + + def valid_endian?(endian) + [:big, :little, :big_and_little].include?(endian) + end + + def parent_fields + parent_attribute(:fields) + end + + def fields? + defined?(@fields) && !@fields.empty? + end + + def parse_and_append_field(*args, &block) + parser = DSLFieldParser.new(hints, *args, &block) + begin + @validator.validate_field(parser.name) + append_field(parser.type, parser.name, parser.params) + rescue Exception => err + dsl_raise err.class, err.message + end + end + + def append_field(type, name, params) + fields.add_field(type, name, params) + rescue BinData::UnRegisteredTypeError => err + raise TypeError, "unknown type '#{err.message}'" + end + + def parent_attribute(attr, default = nil) + parent = @the_class.superclass + parser = parent.respond_to?(:dsl_parser) ? parent.dsl_parser : nil + if parser && parser.respond_to?(attr) + parser.send(attr) + else + default + end + end + + def dsl_raise(exception, msg) + backtrace = caller + backtrace.shift while %r{bindata/dsl.rb} =~ backtrace.first + + raise exception, "#{msg} in #{@the_class}", backtrace + end + + def to_object_params(key) + case fields.length + when 0 + {} + when 1 + {key => fields[0].prototype} + else + {key=> [:struct, to_struct_params]} + end + end + + def to_choice_params(key) + if fields.empty? + {} + elsif fields.all_field_names_blank? + {key => fields.collect(&:prototype)} + else + choices = {} + fields.each { |f| choices[f.name] = f.prototype } + {key => choices} + end + end + + def to_struct_params(*unused) + result = {fields: fields} + if !endian.nil? + result[:endian] = endian + end + if !search_prefix.empty? + result[:search_prefix] = search_prefix + end + if option?(:hidden_fields) && !hide.empty? + result[:hide] = hide + end + + result + end + end + + # Handles the :big_and_little endian option. + # This option creates two subclasses, each handling + # :big or :little endian. + class DSLBigAndLittleEndianHandler + class << self + def handle(bnl_class) + make_class_abstract(bnl_class) + create_subclasses_with_endian(bnl_class) + override_new_in_class(bnl_class) + delegate_field_creation(bnl_class) + fixup_subclass_hierarchy(bnl_class) + end + + def make_class_abstract(bnl_class) + bnl_class.send(:unregister_self) + end + + def create_subclasses_with_endian(bnl_class) + instance_eval "class ::#{bnl_class}Be < ::#{bnl_class}; endian :big; end" + instance_eval "class ::#{bnl_class}Le < ::#{bnl_class}; endian :little; end" + end + + def override_new_in_class(bnl_class) + endian_classes = { + big: class_with_endian(bnl_class, :big), + little: class_with_endian(bnl_class, :little), + } + bnl_class.define_singleton_method(:new) do |*args| + if self == bnl_class + _, options, _ = arg_processor.separate_args(self, args) + delegate = endian_classes[options[:endian]] + return delegate.new(*args) if delegate + end + + super(*args) + end + end + + def delegate_field_creation(bnl_class) + endian_classes = { + big: class_with_endian(bnl_class, :big), + little: class_with_endian(bnl_class, :little), + } + + parser = bnl_class.dsl_parser + parser.define_singleton_method(:parse_and_append_field) do |*args, &block| + endian_classes[:big].send(*args, &block) + endian_classes[:little].send(*args, &block) + end + end + + def fixup_subclass_hierarchy(bnl_class) + parent = bnl_class.superclass + if obj_attribute(parent, :endian) == :big_and_little + be_subclass = class_with_endian(bnl_class, :big) + be_parent = class_with_endian(parent, :big) + be_fields = obj_attribute(be_parent, :fields) + + le_subclass = class_with_endian(bnl_class, :little) + le_parent = class_with_endian(parent, :little) + le_fields = obj_attribute(le_parent, :fields) + + be_subclass.dsl_parser.define_singleton_method(:parent_fields) do + be_fields + end + le_subclass.dsl_parser.define_singleton_method(:parent_fields) do + le_fields + end + end + end + + def class_with_endian(class_name, endian) + hints = { + endian: endian, + search_prefix: class_name.dsl_parser.search_prefix, + } + RegisteredClasses.lookup(class_name, hints) + end + + def obj_attribute(obj, attr) + obj.dsl_parser.send(attr) + end + end + end + + # Extracts the details from a field declaration. + class DSLFieldParser + def initialize(hints, symbol, *args, &block) + @hints = hints + @type = symbol + @name = name_from_field_declaration(args) + @params = params_from_field_declaration(args, &block) + end + + attr_reader :type, :name, :params + + def name_from_field_declaration(args) + name, _ = args + if name == "" || name.is_a?(Hash) + nil + else + name + end + end + + def params_from_field_declaration(args, &block) + params = params_from_args(args) + + if block_given? + params.merge(params_from_block(&block)) + else + params + end + end + + def params_from_args(args) + name, params = args + params = name if name.is_a?(Hash) + + params || {} + end + + def params_from_block(&block) + bindata_classes = { + array: BinData::Array, + buffer: BinData::Buffer, + choice: BinData::Choice, + delayed_io: BinData::DelayedIO, + skip: BinData::Skip, + struct: BinData::Struct, + } + + if bindata_classes.include?(@type) + parser = DSLParser.new(bindata_classes[@type], @type) + parser.endian(@hints[:endian]) + parser.search_prefix(*@hints[:search_prefix]) + parser.instance_eval(&block) + + parser.dsl_params + else + {} + end + end + end + + # Validates a field defined in a DSLMixin. + class DSLFieldValidator + def initialize(the_class, parser) + @the_class = the_class + @dsl_parser = parser + end + + def validate_field(name) + if must_not_have_a_name_failed?(name) + raise SyntaxError, "field must not have a name" + end + + if all_or_none_names_failed?(name) + raise SyntaxError, "fields must either all have names, or none must have names" + end + + if must_have_a_name_failed?(name) + raise SyntaxError, "field must have a name" + end + + ensure_valid_name(name) + end + + def ensure_valid_name(name) + if name && !option?(:fieldnames_are_values) + if malformed_name?(name) + raise SyntaxError, "field '#{name}' is an illegal fieldname" + end + + if duplicate_name?(name) + raise SyntaxError, "duplicate field '#{name}'" + end + + if name_shadows_method?(name) + raise SyntaxError, "field '#{name}' shadows an existing method" + end + + if name_is_reserved?(name) + raise SyntaxError, "field '#{name}' is a reserved name" + end + end + end + + def must_not_have_a_name_failed?(name) + option?(:no_fieldnames) && !name.nil? + end + + def must_have_a_name_failed?(name) + option?(:mandatory_fieldnames) && name.nil? + end + + def all_or_none_names_failed?(name) + if option?(:all_or_none_fieldnames) && !fields.empty? + all_names_blank = fields.all_field_names_blank? + no_names_blank = fields.no_field_names_blank? + + (!name.nil? && all_names_blank) || (name.nil? && no_names_blank) + else + false + end + end + + def malformed_name?(name) + /^[a-z_]\w*$/ !~ name.to_s + end + + def duplicate_name?(name) + fields.field_name?(name) + end + + def name_shadows_method?(name) + @the_class.method_defined?(name) + end + + def name_is_reserved?(name) + BinData::Struct::RESERVED.include?(name.to_sym) + end + + def fields + @dsl_parser.fields + end + + def option?(opt) + @dsl_parser.send(:option?, opt) + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/float.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/float.rb new file mode 100644 index 0000000000..98a470817f --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/float.rb @@ -0,0 +1,83 @@ +require 'bindata/base_primitive' + +module BinData + # Defines a number of classes that contain a floating point number. + # The float is defined by precision and endian. + + module FloatingPoint #:nodoc: all + class << self + PRECISION = { + single: 4, + double: 8, + } + + PACK_CODE = { + [:single, :little] => 'e', + [:single, :big] => 'g', + [:double, :little] => 'E', + [:double, :big] => 'G', + } + + def define_methods(float_class, precision, endian) + float_class.module_eval <<-END + def do_num_bytes + #{create_num_bytes_code(precision)} + end + + #--------------- + private + + def sensible_default + 0.0 + end + + def value_to_binary_string(val) + #{create_to_binary_s_code(precision, endian)} + end + + def read_and_return_value(io) + #{create_read_code(precision, endian)} + end + END + end + + def create_num_bytes_code(precision) + PRECISION[precision] + end + + def create_read_code(precision, endian) + nbytes = PRECISION[precision] + unpack = PACK_CODE[[precision, endian]] + + "io.readbytes(#{nbytes}).unpack('#{unpack}').at(0)" + end + + def create_to_binary_s_code(precision, endian) + pack = PACK_CODE[[precision, endian]] + + "[val].pack('#{pack}')" + end + end + end + + + # Single precision floating point number in little endian format + class FloatLe < BinData::BasePrimitive + FloatingPoint.define_methods(self, :single, :little) + end + + # Single precision floating point number in big endian format + class FloatBe < BinData::BasePrimitive + FloatingPoint.define_methods(self, :single, :big) + end + + # Double precision floating point number in little endian format + class DoubleLe < BinData::BasePrimitive + FloatingPoint.define_methods(self, :double, :little) + end + + # Double precision floating point number in big endian format + class DoubleBe < BinData::BasePrimitive + FloatingPoint.define_methods(self, :double, :big) + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/framework.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/framework.rb new file mode 100644 index 0000000000..ab652c2de3 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/framework.rb @@ -0,0 +1,75 @@ +module BinData + # Error raised when unexpected results occur when reading data from IO. + class ValidityError < StandardError ; end + + # All methods provided by the framework are to be implemented or overridden + # by subclasses of BinData::Base. + module Framework + # Initializes the state of the object. All instance variables that + # are used by the object must be initialized here. + def initialize_instance + end + + # Initialises state that is shared by objects with the same parameters. + # + # This should only be used when optimising for performance. Instance + # variables set here, and changes to the singleton class will be shared + # between all objects that are initialized with the same parameters. + # This method is called only once for a particular set of parameters. + def initialize_shared_instance + end + + # Returns true if the object has not been changed since creation. + def clear? + raise NotImplementedError + end + + # Assigns the value of +val+ to this data object. Note that +val+ must + # always be deep copied to ensure no aliasing problems can occur. + def assign(val) + raise NotImplementedError + end + + # Returns a snapshot of this data object. + def snapshot + raise NotImplementedError + end + + # Returns the debug name of +child+. This only needs to be implemented + # by objects that contain child objects. + def debug_name_of(child) #:nodoc: + debug_name + end + + # Returns the offset of +child+. This only needs to be implemented + # by objects that contain child objects. + def offset_of(child) #:nodoc: + 0 + end + + # Is this object aligned on non-byte boundaries? + def bit_aligned? + false + end + + # Reads the data for this data object from +io+. + def do_read(io) #:nodoc: + raise NotImplementedError + end + + # Writes the value for this data to +io+. + def do_write(io) #:nodoc: + raise NotImplementedError + end + + # Returns the number of bytes it will take to write this data. + def do_num_bytes #:nodoc: + raise NotImplementedError + end + + # Set visibility requirements of methods to implement + public :clear?, :assign, :snapshot, :debug_name_of, :offset_of + protected :initialize_instance, :initialize_shared_instance + protected :do_read, :do_write, :do_num_bytes + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/int.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/int.rb new file mode 100644 index 0000000000..cfad2d6ff6 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/int.rb @@ -0,0 +1,212 @@ +require 'thread' +require 'bindata/base_primitive' + +module BinData + # Defines a number of classes that contain an integer. The integer + # is defined by endian, signedness and number of bytes. + + module Int #:nodoc: all + @@mutex = Mutex.new + + class << self + def define_class(name, nbits, endian, signed) + @@mutex.synchronize do + unless BinData.const_defined?(name) + new_class = Class.new(BinData::BasePrimitive) + Int.define_methods(new_class, nbits, endian.to_sym, signed.to_sym) + RegisteredClasses.register(name, new_class) + + BinData.const_set(name, new_class) + end + end + + BinData.const_get(name) + end + + def define_methods(int_class, nbits, endian, signed) + raise "nbits must be divisible by 8" unless (nbits % 8).zero? + + int_class.module_eval <<-END + def assign(val) + #{create_clamp_code(nbits, signed)} + super(val) + end + + def do_num_bytes + #{nbits / 8} + end + + #--------------- + private + + def sensible_default + 0 + end + + def value_to_binary_string(val) + #{create_clamp_code(nbits, signed)} + #{create_to_binary_s_code(nbits, endian, signed)} + end + + def read_and_return_value(io) + #{create_read_code(nbits, endian, signed)} + end + END + end + + #------------- + private + + def create_clamp_code(nbits, signed) + if signed == :signed + max = "(1 << (#{nbits} - 1)) - 1" + min = "-((#{max}) + 1)" + else + max = "(1 << #{nbits}) - 1" + min = "0" + end + + "val = val.clamp(#{min}, #{max})" + end + + def create_read_code(nbits, endian, signed) + read_str = create_raw_read_code(nbits, endian, signed) + + if need_signed_conversion_code?(nbits, signed) + "val = #{read_str} ; #{create_uint2int_code(nbits)}" + else + read_str + end + end + + def create_raw_read_code(nbits, endian, signed) + # special case 8bit integers for speed + if nbits == 8 + "io.readbytes(1).ord" + else + unpack_str = create_read_unpack_code(nbits, endian, signed) + assemble_str = create_read_assemble_code(nbits, endian, signed) + + "(#{unpack_str} ; #{assemble_str})" + end + end + + def create_read_unpack_code(nbits, endian, signed) + nbytes = nbits / 8 + pack_directive = pack_directive(nbits, endian, signed) + + "ints = io.readbytes(#{nbytes}).unpack('#{pack_directive}')" + end + + def create_read_assemble_code(nbits, endian, signed) + nwords = nbits / bits_per_word(nbits) + + idx = (0...nwords).to_a + idx.reverse! if endian == :big + + parts = (0...nwords).collect do |i| + "(ints.at(#{idx[i]}) << #{bits_per_word(nbits) * i})" + end + parts[0] = parts[0].sub(/ << 0\b/, "") # Remove " << 0" for optimisation + + parts.join(" + ") + end + + def create_to_binary_s_code(nbits, endian, signed) + # special case 8bit integers for speed + return "(val & 0xff).chr" if nbits == 8 + + pack_directive = pack_directive(nbits, endian, signed) + words = val_as_packed_words(nbits, endian, signed) + pack_str = "[#{words}].pack('#{pack_directive}')" + + if need_signed_conversion_code?(nbits, signed) + "#{create_int2uint_code(nbits)} ; #{pack_str}" + else + pack_str + end + end + + def val_as_packed_words(nbits, endian, signed) + nwords = nbits / bits_per_word(nbits) + mask = (1 << bits_per_word(nbits)) - 1 + + vals = (0...nwords).collect { |i| "val >> #{bits_per_word(nbits) * i}" } + vals[0] = vals[0].sub(/ >> 0\b/, "") # Remove " >> 0" for optimisation + vals.reverse! if (endian == :big) + + vals = vals.collect { |val| "#{val} & #{mask}" } # TODO: "& mask" is needed to work around jruby bug. Remove this line when fixed. + vals.join(",") + end + + def create_int2uint_code(nbits) + "val &= #{(1 << nbits) - 1}" + end + + def create_uint2int_code(nbits) + "(val >= #{1 << (nbits - 1)}) ? val - #{1 << nbits} : val" + end + + def bits_per_word(nbits) + (nbits % 64).zero? ? 64 : + (nbits % 32).zero? ? 32 : + (nbits % 16).zero? ? 16 : + 8 + end + + def pack_directive(nbits, endian, signed) + nwords = nbits / bits_per_word(nbits) + + directives = { 8 => "C", 16 => "S", 32 => "L", 64 => "Q" } + + d = directives[bits_per_word(nbits)] + d += ((endian == :big) ? ">" : "<") unless d == "C" + + if signed == :signed && directives.key?(nbits) + (d * nwords).downcase + else + d * nwords + end + end + + def need_signed_conversion_code?(nbits, signed) + signed == :signed && ![64, 32, 16].include?(nbits) + end + end + end + + + # Unsigned 1 byte integer. + class Uint8 < BinData::BasePrimitive + Int.define_methods(self, 8, :little, :unsigned) + end + + # Signed 1 byte integer. + class Int8 < BinData::BasePrimitive + Int.define_methods(self, 8, :little, :signed) + end + + # Create classes on demand + module IntFactory + def const_missing(name) + mappings = { + /^Uint(\d+)be$/ => [:big, :unsigned], + /^Uint(\d+)le$/ => [:little, :unsigned], + /^Int(\d+)be$/ => [:big, :signed], + /^Int(\d+)le$/ => [:little, :signed], + } + + mappings.each_pair do |regex, args| + if regex =~ name.to_s + nbits = $1.to_i + if nbits > 0 && (nbits % 8).zero? + return Int.define_class(name, nbits, *args) + end + end + end + + super + end + end + BinData.extend IntFactory +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/io.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/io.rb new file mode 100644 index 0000000000..22e0b19d40 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/io.rb @@ -0,0 +1,496 @@ +require 'stringio' + +module BinData + # A wrapper around an IO object. The wrapper provides a consistent + # interface for BinData objects to use when accessing the IO. + module IO + + # Common operations for both Read and Write. + module Common + def initialize(io) + if self.class === io + raise ArgumentError, "io must not be a #{self.class}" + end + + # wrap strings in a StringIO + if io.respond_to?(:to_str) + io = BinData::IO.create_string_io(io.to_str) + end + + @raw_io = io + @buffer_end_points = nil + + extend seekable? ? SeekableStream : UnSeekableStream + stream_init + end + + #------------- + private + + def seekable? + @raw_io.pos + rescue NoMethodError, Errno::ESPIPE, Errno::EPIPE, Errno::EINVAL + nil + end + + def seek(n) + seek_raw(buffer_limited_n(n)) + end + + def buffer_limited_n(n) + if @buffer_end_points + if n.nil? || n > 0 + max = @buffer_end_points[1] - offset + n = max if n.nil? || n > max + else + min = @buffer_end_points[0] - offset + n = min if n < min + end + end + + n + end + + def with_buffer_common(n) + prev = @buffer_end_points + if prev + avail = prev[1] - offset + n = avail if n > avail + end + @buffer_end_points = [offset, offset + n] + begin + yield(*@buffer_end_points) + ensure + @buffer_end_points = prev + end + end + + # Use #seek and #pos on seekable streams + module SeekableStream + # The number of bytes remaining in the input stream. + def num_bytes_remaining + start_mark = @raw_io.pos + @raw_io.seek(0, ::IO::SEEK_END) + end_mark = @raw_io.pos + + if @buffer_end_points + if @buffer_end_points[1] < end_mark + end_mark = @buffer_end_points[1] + end + end + + bytes_remaining = end_mark - start_mark + @raw_io.seek(start_mark, ::IO::SEEK_SET) + + bytes_remaining + end + + # All io calls in +block+ are rolled back after this + # method completes. + def with_readahead + mark = @raw_io.pos + begin + yield + ensure + @raw_io.seek(mark, ::IO::SEEK_SET) + end + end + + #----------- + private + + def stream_init + @initial_pos = @raw_io.pos + end + + def offset_raw + @raw_io.pos - @initial_pos + end + + def seek_raw(n) + @raw_io.seek(n, ::IO::SEEK_CUR) + end + + def read_raw(n) + @raw_io.read(n) + end + + def write_raw(data) + @raw_io.write(data) + end + end + + # Manually keep track of offset for unseekable streams. + module UnSeekableStream + def offset_raw + @offset + end + + # The number of bytes remaining in the input stream. + def num_bytes_remaining + raise IOError, "stream is unseekable" + end + + # All io calls in +block+ are rolled back after this + # method completes. + def with_readahead + mark = @offset + @read_data = "" + @in_readahead = true + + class << self + alias_method :read_raw_without_readahead, :read_raw + alias_method :read_raw, :read_raw_with_readahead + end + + begin + yield + ensure + @offset = mark + @in_readahead = false + end + end + + #----------- + private + + def stream_init + @offset = 0 + end + + def read_raw(n) + data = @raw_io.read(n) + @offset += data.size if data + data + end + + def read_raw_with_readahead(n) + data = "" + + unless @read_data.empty? || @in_readahead + bytes_to_consume = [n, @read_data.length].min + data += @read_data.slice!(0, bytes_to_consume) + n -= bytes_to_consume + + if @read_data.empty? + class << self + alias_method :read_raw, :read_raw_without_readahead + end + end + end + + raw_data = @raw_io.read(n) + data += raw_data if raw_data + + if @in_readahead + @read_data += data + end + + @offset += data.size + + data + end + + def write_raw(data) + @offset += data.size + @raw_io.write(data) + end + + def seek_raw(n) + raise IOError, "stream is unseekable" if n < 0 + + # NOTE: how do we seek on a writable stream? + + # skip over data in 8k blocks + while n > 0 + bytes_to_read = [n, 8192].min + read_raw(bytes_to_read) + n -= bytes_to_read + end + end + end + end + + # Creates a StringIO around +str+. + def self.create_string_io(str = "") + s = StringIO.new(str.dup.force_encoding(Encoding::BINARY)) + s.binmode + s + end + + # Create a new IO Read wrapper around +io+. +io+ must provide #read, + # #pos if reading the current stream position and #seek if setting the + # current stream position. If +io+ is a string it will be automatically + # wrapped in an StringIO object. + # + # The IO can handle bitstreams in either big or little endian format. + # + # M byte1 L M byte2 L + # S 76543210 S S fedcba98 S + # B B B B + # + # In big endian format: + # readbits(6), readbits(5) #=> [765432, 10fed] + # + # In little endian format: + # readbits(6), readbits(5) #=> [543210, a9876] + # + class Read + include Common + + def initialize(io) + super(io) + + # bits when reading + @rnbits = 0 + @rval = 0 + @rendian = nil + end + + # Sets a buffer of +n+ bytes on the io stream. Any reading or seeking + # calls inside the +block+ will be contained within this buffer. + def with_buffer(n) + with_buffer_common(n) do + yield + read + end + end + + # Returns the current offset of the io stream. Offset will be rounded + # up when reading bitfields. + def offset + offset_raw + end + + # Seek +n+ bytes from the current position in the io stream. + def seekbytes(n) + reset_read_bits + seek(n) + end + + # Reads exactly +n+ bytes from +io+. + # + # If the data read is nil an EOFError is raised. + # + # If the data read is too short an IOError is raised. + def readbytes(n) + reset_read_bits + read(n) + end + + # Reads all remaining bytes from the stream. + def read_all_bytes + reset_read_bits + read + end + + # Reads exactly +nbits+ bits from the stream. +endian+ specifies whether + # the bits are stored in +:big+ or +:little+ endian format. + def readbits(nbits, endian) + if @rendian != endian + # don't mix bits of differing endian + reset_read_bits + @rendian = endian + end + + if endian == :big + read_big_endian_bits(nbits) + else + read_little_endian_bits(nbits) + end + end + + # Discards any read bits so the stream becomes aligned at the + # next byte boundary. + def reset_read_bits + @rnbits = 0 + @rval = 0 + end + + #--------------- + private + + def read(n = nil) + str = read_raw(buffer_limited_n(n)) + if n + raise EOFError, "End of file reached" if str.nil? + raise IOError, "data truncated" if str.size < n + end + str + end + + def read_big_endian_bits(nbits) + while @rnbits < nbits + accumulate_big_endian_bits + end + + val = (@rval >> (@rnbits - nbits)) & mask(nbits) + @rnbits -= nbits + @rval &= mask(@rnbits) + + val + end + + def accumulate_big_endian_bits + byte = read(1).unpack('C').at(0) & 0xff + @rval = (@rval << 8) | byte + @rnbits += 8 + end + + def read_little_endian_bits(nbits) + while @rnbits < nbits + accumulate_little_endian_bits + end + + val = @rval & mask(nbits) + @rnbits -= nbits + @rval >>= nbits + + val + end + + def accumulate_little_endian_bits + byte = read(1).unpack('C').at(0) & 0xff + @rval = @rval | (byte << @rnbits) + @rnbits += 8 + end + + def mask(nbits) + (1 << nbits) - 1 + end + end + + # Create a new IO Write wrapper around +io+. +io+ must provide #write. + # If +io+ is a string it will be automatically wrapped in an StringIO + # object. + # + # The IO can handle bitstreams in either big or little endian format. + # + # See IO::Read for more information. + class Write + include Common + def initialize(io) + super(io) + + @wnbits = 0 + @wval = 0 + @wendian = nil + end + + # Sets a buffer of +n+ bytes on the io stream. Any writes inside the + # +block+ will be contained within this buffer. If less than +n+ bytes + # are written inside the block, the remainder will be padded with '\0' + # bytes. + def with_buffer(n) + with_buffer_common(n) do |_buf_start, buf_end| + yield + write("\0" * (buf_end - offset)) + end + end + + # Returns the current offset of the io stream. Offset will be rounded + # up when writing bitfields. + def offset + offset_raw + (@wnbits > 0 ? 1 : 0) + end + + # Seek +n+ bytes from the current position in the io stream. + def seekbytes(n) + flushbits + seek(n) + end + + # Writes the given string of bytes to the io stream. + def writebytes(str) + flushbits + write(str) + end + + # Writes +nbits+ bits from +val+ to the stream. +endian+ specifies whether + # the bits are to be stored in +:big+ or +:little+ endian format. + def writebits(val, nbits, endian) + if @wendian != endian + # don't mix bits of differing endian + flushbits + @wendian = endian + end + + clamped_val = val & mask(nbits) + + if endian == :big + write_big_endian_bits(clamped_val, nbits) + else + write_little_endian_bits(clamped_val, nbits) + end + end + + # To be called after all +writebits+ have been applied. + def flushbits + raise "Internal state error nbits = #{@wnbits}" if @wnbits >= 8 + + if @wnbits > 0 + writebits(0, 8 - @wnbits, @wendian) + end + end + alias flush flushbits + + #--------------- + private + + def write(data) + n = buffer_limited_n(data.size) + if n < data.size + data = data[0, n] + end + + write_raw(data) + end + + def write_big_endian_bits(val, nbits) + while nbits > 0 + bits_req = 8 - @wnbits + if nbits >= bits_req + msb_bits = (val >> (nbits - bits_req)) & mask(bits_req) + nbits -= bits_req + val &= mask(nbits) + + @wval = (@wval << bits_req) | msb_bits + write(@wval.chr) + + @wval = 0 + @wnbits = 0 + else + @wval = (@wval << nbits) | val + @wnbits += nbits + nbits = 0 + end + end + end + + def write_little_endian_bits(val, nbits) + while nbits > 0 + bits_req = 8 - @wnbits + if nbits >= bits_req + lsb_bits = val & mask(bits_req) + nbits -= bits_req + val >>= bits_req + + @wval = @wval | (lsb_bits << @wnbits) + write(@wval.chr) + + @wval = 0 + @wnbits = 0 + else + @wval = @wval | (val << @wnbits) + @wnbits += nbits + nbits = 0 + end + end + end + + def mask(nbits) + (1 << nbits) - 1 + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/lazy.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/lazy.rb new file mode 100644 index 0000000000..0726072022 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/lazy.rb @@ -0,0 +1,109 @@ +module BinData + # A LazyEvaluator is bound to a data object. The evaluator will evaluate + # lambdas in the context of this data object. These lambdas + # are those that are passed to data objects as parameters, e.g.: + # + # BinData::String.new(value: -> { %w(a test message).join(" ") }) + # + # As a shortcut, :foo is the equivalent of lambda { foo }. + # + # When evaluating lambdas, unknown methods are resolved in the context of the + # parent of the bound data object. Resolution is attempted firstly as keys + # in #parameters, and secondly as methods in this parent. This + # resolution propagates up the chain of parent data objects. + # + # An evaluation will recurse until it returns a result that is not + # a lambda or a symbol. + # + # This resolution process makes the lambda easier to read as we just write + # field instead of obj.field. + class LazyEvaluator + + # Creates a new evaluator. All lazy evaluation is performed in the + # context of +obj+. + def initialize(obj) + @obj = obj + end + + def lazy_eval(val, overrides = nil) + @overrides = overrides if overrides + if val.is_a? Symbol + __send__(val) + elsif callable?(val) + instance_exec(&val) + else + val + end + end + + # Returns a LazyEvaluator for the parent of this data object. + def parent + if @obj.parent + @obj.parent.lazy_evaluator + else + nil + end + end + + # Returns the index of this data object inside it's nearest container + # array. + def index + return @overrides[:index] if defined?(@overrides) && @overrides.key?(:index) + + child = @obj + parent = @obj.parent + while parent + if parent.respond_to?(:find_index_of) + return parent.find_index_of(child) + end + child = parent + parent = parent.parent + end + raise NoMethodError, "no index found" + end + + def method_missing(symbol, *args) + return @overrides[symbol] if defined?(@overrides) && @overrides.key?(symbol) + + if @obj.parent + eval_symbol_in_parent_context(symbol, args) + else + super + end + end + + #--------------- + private + + def eval_symbol_in_parent_context(symbol, args) + result = resolve_symbol_in_parent_context(symbol, args) + recursively_eval(result, args) + end + + def resolve_symbol_in_parent_context(symbol, args) + obj_parent = @obj.parent + + if obj_parent.has_parameter?(symbol) + obj_parent.get_parameter(symbol) + elsif obj_parent.safe_respond_to?(symbol, true) + obj_parent.__send__(symbol, *args) + else + symbol + end + end + + def recursively_eval(val, args) + if val.is_a?(Symbol) + parent.__send__(val, *args) + elsif callable?(val) + parent.instance_exec(&val) + else + val + end + end + + def callable?(obj) + Proc === obj || Method === obj || UnboundMethod === obj + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/name.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/name.rb new file mode 100644 index 0000000000..bd22b50312 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/name.rb @@ -0,0 +1,28 @@ +module BinData + # == Parameters + # + # Parameters may be provided at initialisation to control the behaviour of + # an object. These parameters are: + # + # :name:: The name that this object can be referred to may be + # set explicitly. This is only useful when dynamically + # generating types. + #

+  #                    BinData::Struct.new(name: :my_struct, fields: ...)
+  #                    array = BinData::Array.new(type: :my_struct)
+  #                  
+ module RegisterNamePlugin + + def self.included(base) #:nodoc: + # The registered name may be provided explicitly. + base.optional_parameter :name + end + + def initialize_shared_instance + if has_parameter?(:name) + RegisteredClasses.register(get_parameter(:name), self) + end + super + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/offset.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/offset.rb new file mode 100644 index 0000000000..7b9a61e658 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/offset.rb @@ -0,0 +1,94 @@ +module BinData + # WARNING: THIS IS UNSUPPORTED!! + # + # This was a (failed) experimental feature that allowed seeking within the + # input stream. It remains here for backwards compatability for the few + # people that used it. + # + # The official way to skip around the stream is to use BinData::Skip with + # the `:to_abs_offset` parameter. + # + # == Parameters + # + # Parameters may be provided at initialisation to control the behaviour of + # an object. These parameters are: + # + # [:check_offset] Raise an error if the current IO offset doesn't + # meet this criteria. A boolean return indicates + # success or failure. Any other return is compared + # to the current offset. The variable +offset+ + # is made available to any lambda assigned to + # this parameter. This parameter is only checked + # before reading. + # [:adjust_offset] Ensures that the current IO offset is at this + # position before reading. This is like + # :check_offset, except that it will + # adjust the IO offset instead of raising an error. + module CheckOrAdjustOffsetPlugin + + def self.included(base) #:nodoc: + base.optional_parameters :check_offset, :adjust_offset + base.mutually_exclusive_parameters :check_offset, :adjust_offset + end + + def initialize_shared_instance + extend CheckOffsetMixin if has_parameter?(:check_offset) + extend AdjustOffsetMixin if has_parameter?(:adjust_offset) + super + end + + module CheckOffsetMixin + def do_read(io) #:nodoc: + check_offset(io) + super(io) + end + + #--------------- + private + + def check_offset(io) + actual_offset = io.offset + expected = eval_parameter(:check_offset, offset: actual_offset) + + if !expected + raise ValidityError, "offset not as expected for #{debug_name}" + elsif actual_offset != expected && expected != true + raise ValidityError, + "offset is '#{actual_offset}' but " + + "expected '#{expected}' for #{debug_name}" + end + end + end + + module AdjustOffsetMixin + def do_read(io) #:nodoc: + adjust_offset(io) + super(io) + end + + #--------------- + private + + def adjust_offset(io) + actual_offset = io.offset + expected = eval_parameter(:adjust_offset) + if actual_offset != expected + begin + seek = expected - actual_offset + io.seekbytes(seek) + warn "adjusting stream position by #{seek} bytes" if $VERBOSE + rescue + raise ValidityError, + "offset is '#{actual_offset}' but couldn't seek to " + + "expected '#{expected}' for #{debug_name}" + end + end + end + end + end + + # Add these offset options to Base + class Base + include CheckOrAdjustOffsetPlugin + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/params.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/params.rb new file mode 100644 index 0000000000..cb34dff682 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/params.rb @@ -0,0 +1,128 @@ +require 'bindata/lazy' + +module BinData + module AcceptedParametersPlugin + # Mandatory parameters must be present when instantiating a data object. + def mandatory_parameters(*args) + accepted_parameters.mandatory(*args) + end + + # Optional parameters may be present when instantiating a data object. + def optional_parameters(*args) + accepted_parameters.optional(*args) + end + + # Default parameters can be overridden when instantiating a data object. + def default_parameters(*args) + accepted_parameters.default(*args) + end + + # Mutually exclusive parameters may not all be present when + # instantiating a data object. + def mutually_exclusive_parameters(*args) + accepted_parameters.mutually_exclusive(*args) + end + + alias mandatory_parameter mandatory_parameters + alias optional_parameter optional_parameters + alias default_parameter default_parameters + + def accepted_parameters #:nodoc: + @accepted_parameters ||= begin + ancestor_params = superclass.respond_to?(:accepted_parameters) ? + superclass.accepted_parameters : nil + AcceptedParameters.new(ancestor_params) + end + end + + # BinData objects accept parameters when initializing. AcceptedParameters + # allow a BinData class to declaratively identify accepted parameters as + # mandatory, optional, default or mutually exclusive. + class AcceptedParameters + def initialize(ancestor_parameters = nil) + if ancestor_parameters + @mandatory = ancestor_parameters.mandatory.dup + @optional = ancestor_parameters.optional.dup + @default = ancestor_parameters.default.dup + @mutually_exclusive = ancestor_parameters.mutually_exclusive.dup + else + @mandatory = [] + @optional = [] + @default = Hash.new + @mutually_exclusive = [] + end + end + + def mandatory(*args) + unless args.empty? + @mandatory.concat(to_syms(args)) + @mandatory.uniq! + end + @mandatory + end + + def optional(*args) + unless args.empty? + @optional.concat(to_syms(args)) + @optional.uniq! + end + @optional + end + + def default(args = nil) + if args + to_syms(args.keys) # call for side effect of validating names + args.each_pair do |param, value| + @default[param.to_sym] = value + end + end + @default + end + + def mutually_exclusive(*args) + arg1 = args.shift + until args.empty? + args.each do |arg2| + @mutually_exclusive.push([arg1.to_sym, arg2.to_sym]) + @mutually_exclusive.uniq! + end + arg1 = args.shift + end + @mutually_exclusive + end + + def all + (@mandatory + @optional + @default.keys).uniq + end + + #--------------- + private + + def to_syms(args) + syms = args.collect(&:to_sym) + ensure_valid_names(syms) + syms + end + + def ensure_valid_names(names) + invalid_names = self.class.invalid_parameter_names + names.each do |name| + if invalid_names.include?(name) + raise NameError.new("Rename parameter '#{name}' " \ + "as it shadows an existing method.", name) + end + end + end + + def self.invalid_parameter_names + @invalid_names ||= begin + all_names = LazyEvaluator.instance_methods(true) + allowed_names = [:name, :type] + invalid_names = (all_names - allowed_names).uniq + + Hash[*invalid_names.collect { |key| [key.to_sym, true] }.flatten] + end + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/primitive.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/primitive.rb new file mode 100644 index 0000000000..9b9bd8d41d --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/primitive.rb @@ -0,0 +1,143 @@ +require 'bindata/base_primitive' +require 'bindata/dsl' +require 'bindata/struct' + +module BinData + # A Primitive is a declarative way to define a new BinData data type. + # The data type must contain a primitive value only, i.e numbers or strings. + # For new data types that contain multiple values see BinData::Record. + # + # To define a new data type, set fields as if for Record and add a + # #get and #set method to extract / convert the data between the fields + # and the #value of the object. + # + # require 'bindata' + # + # class PascalString < BinData::Primitive + # uint8 :len, value: -> { data.length } + # string :data, read_length: :len + # + # def get + # self.data + # end + # + # def set(v) + # self.data = v + # end + # end + # + # ps = PascalString.new(initial_value: "hello") + # ps.to_binary_s #=> "\005hello" + # ps.read("\003abcde") + # ps #=> "abc" + # + # # Unsigned 24 bit big endian integer + # class Uint24be < BinData::Primitive + # uint8 :byte1 + # uint8 :byte2 + # uint8 :byte3 + # + # def get + # (self.byte1 << 16) | (self.byte2 << 8) | self.byte3 + # end + # + # def set(v) + # v = 0 if v < 0 + # v = 0xffffff if v > 0xffffff + # + # self.byte1 = (v >> 16) & 0xff + # self.byte2 = (v >> 8) & 0xff + # self.byte3 = v & 0xff + # end + # end + # + # u24 = Uint24be.new + # u24.read("\x12\x34\x56") + # "0x%x" % u24 #=> 0x123456 + # + # == Parameters + # + # Primitive objects accept all the parameters that BinData::BasePrimitive do. + # + class Primitive < BasePrimitive + extend DSLMixin + + unregister_self + dsl_parser :primitive + arg_processor :primitive + + mandatory_parameter :struct_params + + def initialize_instance + super + @struct = BinData::Struct.new(get_parameter(:struct_params), self) + end + + def respond_to?(symbol, include_private = false) #:nodoc: + @struct.respond_to?(symbol, include_private) || super + end + + def method_missing(symbol, *args, &block) #:nodoc: + if @struct.respond_to?(symbol) + @struct.__send__(symbol, *args, &block) + else + super + end + end + + def assign(val) + super(val) + set(_value) + @value = get + end + + def debug_name_of(child) #:nodoc: + debug_name + "-internal-" + end + + def do_write(io) + set(_value) + @struct.do_write(io) + end + + def do_num_bytes + set(_value) + @struct.do_num_bytes + end + + #--------------- + private + + def sensible_default + get + end + + def read_and_return_value(io) + @struct.do_read(io) + get + end + + ########################################################################### + # To be implemented by subclasses + + # Extracts the value for this data object from the fields of the + # internal struct. + def get + raise NotImplementedError + end + + # Sets the fields of the internal struct to represent +v+. + def set(v) + raise NotImplementedError + end + + # To be implemented by subclasses + ########################################################################### + end + + class PrimitiveArgProcessor < BaseArgProcessor + def sanitize_parameters!(obj_class, params) + params[:struct_params] = params.create_sanitized_params(obj_class.dsl_params, BinData::Struct) + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/record.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/record.rb new file mode 100644 index 0000000000..b011cf5e1c --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/record.rb @@ -0,0 +1,23 @@ +require 'bindata/dsl' +require 'bindata/struct' + +module BinData + # A Record is a declarative wrapper around Struct. + # + # See +Struct+ for more info. + class Record < BinData::Struct + extend DSLMixin + + unregister_self + dsl_parser :struct + arg_processor :record + end + + class RecordArgProcessor < StructArgProcessor + include MultiFieldArgSeparator + + def sanitize_parameters!(obj_class, params) + super(obj_class, params.merge!(obj_class.dsl_params)) + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/registry.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/registry.rb new file mode 100644 index 0000000000..fc47740bd5 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/registry.rb @@ -0,0 +1,134 @@ +module BinData + + class UnRegisteredTypeError < StandardError ; end + + # This registry contains a register of name -> class mappings. + # + # Numerics (integers and floating point numbers) have an endian property as + # part of their name (e.g. int32be, float_le). + # + # Classes can be looked up based on their full name or an abbreviated +name+ + # with +hints+. + # + # There are two hints supported, :endian and :search_prefix. + # + # #lookup("int32", { endian: :big }) will return Int32Be. + # + # #lookup("my_type", { search_prefix: :ns }) will return NsMyType. + # + # Names are stored in under_score_style, not camelCase. + class Registry + + def initialize + @registry = {} + end + + def register(name, class_to_register) + return if name.nil? || class_to_register.nil? + + formatted_name = underscore_name(name) + warn_if_name_is_already_registered(formatted_name, class_to_register) + + @registry[formatted_name] = class_to_register + end + + def unregister(name) + @registry.delete(underscore_name(name)) + end + + def lookup(name, hints = {}) + the_class = @registry[normalize_name(name, hints)] + if the_class + the_class + elsif @registry[normalize_name(name, hints.merge(endian: :big))] + raise(UnRegisteredTypeError, "#{name}, do you need to specify endian?") + else + raise(UnRegisteredTypeError, name) + end + end + + # Convert CamelCase +name+ to underscore style. + def underscore_name(name) + name. + to_s. + sub(/.*::/, ""). + gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2'). + gsub(/([a-z\d])([A-Z])/, '\1_\2'). + tr("-", "_"). + downcase + end + + #--------------- + private + + def normalize_name(name, hints) + name = underscore_name(name) + + if !registered?(name) + search_prefix = [""].concat(Array(hints[:search_prefix])) + search_prefix.each do |prefix| + nwp = name_with_prefix(name, prefix) + if registered?(nwp) + name = nwp + break + end + + nwe = name_with_endian(nwp, hints[:endian]) + if registered?(nwe) + name = nwe + break + end + end + end + + name + end + + def name_with_prefix(name, prefix) + prefix = prefix.to_s.chomp("_") + if prefix == "" + name + else + "#{prefix}_#{name}" + end + end + + def name_with_endian(name, endian) + return name if endian.nil? + + suffix = (endian == :little) ? "le" : "be" + if /^u?int\d+$/ =~ name + name + suffix + else + name + "_" + suffix + end + end + + def registered?(name) + register_dynamic_class(name) unless @registry.key?(name) + + @registry.key?(name) + end + + def register_dynamic_class(name) + if /^u?int\d+(le|be)$/ =~ name || /^s?bit\d+(le)?$/ =~ name + class_name = name.gsub(/(?:^|_)(.)/) { $1.upcase } + begin + BinData.const_get(class_name) + rescue NameError + end + end + end + + def warn_if_name_is_already_registered(name, class_to_register) + prev_class = @registry[name] + if $VERBOSE && prev_class && prev_class != class_to_register + warn "warning: replacing registered class #{prev_class} " \ + "with #{class_to_register}" + end + end + end + + # A singleton registry of all registered classes. + RegisteredClasses = Registry.new +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/rest.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/rest.rb new file mode 100644 index 0000000000..cdc104459c --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/rest.rb @@ -0,0 +1,34 @@ +require "bindata/base_primitive" + +module BinData + # Rest will consume the input stream from the current position to the end of + # the stream. This will mainly be useful for debugging and developing. + # + # require 'bindata' + # + # class A < BinData::Record + # string :a, read_length: 5 + # rest :rest + # end + # + # obj = A.read("abcdefghij") + # obj.a #=> "abcde" + # obj.rest #=" "fghij" + # + class Rest < BinData::BasePrimitive + #--------------- + private + + def value_to_binary_string(val) + val + end + + def read_and_return_value(io) + io.read_all_bytes + end + + def sensible_default + "" + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/sanitize.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/sanitize.rb new file mode 100644 index 0000000000..7325b206b0 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/sanitize.rb @@ -0,0 +1,372 @@ +require 'bindata/registry' + +module BinData + + # Subclasses of this are sanitized + class SanitizedParameter; end + + class SanitizedPrototype < SanitizedParameter + def initialize(obj_type, obj_params, hints) + raw_hints = hints.dup + if raw_hints[:endian].respond_to?(:endian) + raw_hints[:endian] = raw_hints[:endian].endian + end + obj_params ||= {} + + if BinData::Base === obj_type + obj_class = obj_type + else + obj_class = RegisteredClasses.lookup(obj_type, raw_hints) + end + + if BinData::Base === obj_class + @factory = obj_class + else + @obj_class = obj_class + @obj_params = SanitizedParameters.new(obj_params, @obj_class, hints) + end + end + + def has_parameter?(param) + if defined? @factory + @factory.has_parameter?(param) + else + @obj_params.has_parameter?(param) + end + end + + def instantiate(value = nil, parent = nil) + @factory ||= @obj_class.new(@obj_params) + + @factory.new(value, parent) + end + end + #---------------------------------------------------------------------------- + + class SanitizedField < SanitizedParameter + def initialize(name, field_type, field_params, hints) + @name = name + @prototype = SanitizedPrototype.new(field_type, field_params, hints) + end + + attr_reader :prototype + + def name_as_sym + @name.nil? ? nil : @name.to_sym + end + + def name + @name + end + + def has_parameter?(param) + @prototype.has_parameter?(param) + end + + def instantiate(value = nil, parent = nil) + @prototype.instantiate(value, parent) + end + end + #---------------------------------------------------------------------------- + + class SanitizedFields < SanitizedParameter + include Enumerable + + def initialize(hints, base_fields = nil) + @hints = hints + if base_fields + @fields = base_fields.raw_fields + else + @fields = [] + end + end + + def add_field(type, name, params) + name = nil if name == "" + + @fields << SanitizedField.new(name, type, params, @hints) + end + + def raw_fields + @fields.dup + end + + def [](idx) + @fields[idx] + end + + def empty? + @fields.empty? + end + + def length + @fields.length + end + + def each(&block) + @fields.each(&block) + end + + def field_names + @fields.collect(&:name_as_sym) + end + + def field_name?(name) + @fields.detect { |f| f.name_as_sym == name.to_sym } + end + + def all_field_names_blank? + @fields.all? { |f| f.name.nil? } + end + + def no_field_names_blank? + @fields.all? { |f| f.name != nil } + end + + def any_field_has_parameter?(parameter) + @fields.any? { |f| f.has_parameter?(parameter) } + end + end + #---------------------------------------------------------------------------- + + class SanitizedChoices < SanitizedParameter + def initialize(choices, hints) + @choices = {} + choices.each_pair do |key, val| + if SanitizedParameter === val + prototype = val + else + type, param = val + prototype = SanitizedPrototype.new(type, param, hints) + end + + if key == :default + @choices.default = prototype + else + @choices[key] = prototype + end + end + end + + def [](key) + @choices[key] + end + end + #---------------------------------------------------------------------------- + + class SanitizedBigEndian < SanitizedParameter + def endian + :big + end + end + + class SanitizedLittleEndian < SanitizedParameter + def endian + :little + end + end + #---------------------------------------------------------------------------- + + # BinData objects are instantiated with parameters to determine their + # behaviour. These parameters must be sanitized to ensure their values + # are valid. When instantiating many objects with identical parameters, + # such as an array of records, there is much duplicated sanitizing. + # + # The purpose of the sanitizing code is to eliminate the duplicated + # validation. + # + # SanitizedParameters is a hash-like collection of parameters. Its purpose + # is to recursively sanitize the parameters of an entire BinData object chain + # at a single time. + class SanitizedParameters < Hash + + # Memoized constants + BIG_ENDIAN = SanitizedBigEndian.new + LITTLE_ENDIAN = SanitizedLittleEndian.new + + class << self + def sanitize(parameters, the_class) + if SanitizedParameters === parameters + parameters + else + SanitizedParameters.new(parameters, the_class, {}) + end + end + end + + def initialize(parameters, the_class, hints) + parameters.each_pair { |key, value| self[key.to_sym] = value } + + @the_class = the_class + + if hints[:endian] + self[:endian] ||= hints[:endian] + end + + if hints[:search_prefix] && !hints[:search_prefix].empty? + self[:search_prefix] = Array(self[:search_prefix]).concat(Array(hints[:search_prefix])) + end + + sanitize! + end + + alias_method :has_parameter?, :key? + + def has_at_least_one_of?(*keys) + keys.each do |key| + return true if has_parameter?(key) + end + + false + end + + def warn_replacement_parameter(bad_key, suggested_key) + if has_parameter?(bad_key) + Kernel.warn ":#{bad_key} is not used with #{@the_class}. " \ + "You probably want to change this to :#{suggested_key}" + end + end + +# def warn_renamed_parameter(old_key, new_key) +# val = delete(old_key) +# if val +# self[new_key] = val +# Kernel.warn ":#{old_key} has been renamed to :#{new_key} in #{@the_class}. " \ +# "Using :#{old_key} is now deprecated and will be removed in the future" +# end +# end + + def must_be_integer(*keys) + keys.each do |key| + if has_parameter?(key) + parameter = self[key] + unless Symbol === parameter || + parameter.respond_to?(:arity) || + parameter.respond_to?(:to_int) + raise ArgumentError, "parameter '#{key}' in #{@the_class} must " \ + "evaluate to an integer, got #{parameter.class}" + end + end + end + end + + def rename_parameter(old_key, new_key) + if has_parameter?(old_key) + self[new_key] = delete(old_key) + end + end + + def sanitize_object_prototype(key) + sanitize(key) { |obj_type, obj_params| create_sanitized_object_prototype(obj_type, obj_params) } + end + + def sanitize_fields(key, &block) + sanitize(key) do |fields| + sanitized_fields = create_sanitized_fields + yield(fields, sanitized_fields) + sanitized_fields + end + end + + def sanitize_choices(key, &block) + sanitize(key) do |obj| + create_sanitized_choices(yield(obj)) + end + end + + def sanitize_endian(key) + sanitize(key) { |endian| create_sanitized_endian(endian) } + end + + def sanitize(key, &block) + if needs_sanitizing?(key) + self[key] = yield(self[key]) + end + end + + def create_sanitized_params(params, the_class) + SanitizedParameters.new(params, the_class, hints) + end + + def hints + { endian: self[:endian], search_prefix: self[:search_prefix] } + end + + #--------------- + private + + def sanitize! + ensure_no_nil_values + merge_default_parameters! + + @the_class.arg_processor.sanitize_parameters!(@the_class, self) + + ensure_mandatory_parameters_exist + ensure_mutual_exclusion_of_parameters + end + + def needs_sanitizing?(key) + has_key?(key) && ! self[key].is_a?(SanitizedParameter) + end + + def ensure_no_nil_values + each do |key, value| + if value.nil? + raise ArgumentError, + "parameter '#{key}' has nil value in #{@the_class}" + end + end + end + + def merge_default_parameters! + @the_class.default_parameters.each do |key, value| + self[key] = value unless has_key?(key) + end + end + + def ensure_mandatory_parameters_exist + @the_class.mandatory_parameters.each do |key| + unless has_parameter?(key) + raise ArgumentError, + "parameter '#{key}' must be specified in #{@the_class}" + end + end + end + + def ensure_mutual_exclusion_of_parameters + return if length < 2 + + @the_class.mutually_exclusive_parameters.each do |key1, key2| + if has_parameter?(key1) && has_parameter?(key2) + raise ArgumentError, "params '#{key1}' and '#{key2}' " \ + "are mutually exclusive in #{@the_class}" + end + end + end + + def create_sanitized_endian(endian) + if endian == :big + BIG_ENDIAN + elsif endian == :little + LITTLE_ENDIAN + elsif endian == :big_and_little + raise ArgumentError, "endian: :big or endian: :little is required" + else + raise ArgumentError, "unknown value for endian '#{endian}'" + end + end + + def create_sanitized_choices(choices) + SanitizedChoices.new(choices, hints) + end + + def create_sanitized_fields + SanitizedFields.new(hints) + end + + def create_sanitized_object_prototype(obj_type, obj_params) + SanitizedPrototype.new(obj_type, obj_params, hints) + end + end + #---------------------------------------------------------------------------- +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/skip.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/skip.rb new file mode 100644 index 0000000000..40d4fe940a --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/skip.rb @@ -0,0 +1,133 @@ +require "bindata/base_primitive" + +module BinData + # Skip will skip over bytes from the input stream. If the stream is not + # seekable, then the bytes are consumed and discarded. + # + # When writing, skip will write the appropriate number of zero bytes. + # + # require 'bindata' + # + # class A < BinData::Record + # skip length: 5 + # string :a, read_length: 5 + # end + # + # obj = A.read("abcdefghij") + # obj.a #=> "fghij" + # + # + # class B < BinData::Record + # skip until_valid: [:string, {read_length: 2, assert: "ef"} ] + # string :b, read_length: 5 + # end + # + # obj = B.read("abcdefghij") + # obj.b #=> "efghi" + # + # + # == Parameters + # + # Skip objects accept all the params that BinData::BasePrimitive + # does, as well as the following: + # + # :length:: The number of bytes to skip. + # :to_abs_offset:: Skips to the given absolute offset. + # :until_valid:: Skips untils a given byte pattern is matched. + # This parameter contains a type that will raise + # a BinData::ValidityError unless an acceptable byte + # sequence is found. The type is represented by a + # Symbol, or if the type is to have params # + # passed to it, then it should be provided as # + # [type_symbol, hash_params]. + # + class Skip < BinData::BasePrimitive + arg_processor :skip + + optional_parameters :length, :to_abs_offset, :until_valid + mutually_exclusive_parameters :length, :to_abs_offset, :until_valid + + def initialize_shared_instance + extend SkipLengthPlugin if has_parameter?(:length) + extend SkipToAbsOffsetPlugin if has_parameter?(:to_abs_offset) + extend SkipUntilValidPlugin if has_parameter?(:until_valid) + super + end + + #--------------- + private + + def value_to_binary_string(val) + len = skip_length + if len < 0 + raise ValidityError, "#{debug_name} attempted to seek backwards by #{len.abs} bytes" + end + + "\000" * skip_length + end + + def read_and_return_value(io) + len = skip_length + if len < 0 + raise ValidityError, "#{debug_name} attempted to seek backwards by #{len.abs} bytes" + end + + io.seekbytes(len) + "" + end + + def sensible_default + "" + end + end + + class SkipArgProcessor < BaseArgProcessor + def sanitize_parameters!(obj_class, params) + unless params.has_at_least_one_of?(:length, :to_abs_offset, :until_valid) + raise ArgumentError, + "#{obj_class} requires either :length, :to_abs_offset or :until_valid" + end + params.must_be_integer(:to_abs_offset, :length) + params.sanitize_object_prototype(:until_valid) + end + end + + # Logic for the :length parameter + module SkipLengthPlugin + def skip_length + eval_parameter(:length) + end + end + + # Logic for the :to_abs_offset parameter + module SkipToAbsOffsetPlugin + def skip_length + eval_parameter(:to_abs_offset) - abs_offset + end + end + + # Logic for the :until_valid parameter + module SkipUntilValidPlugin + def skip_length + # no skipping when writing + 0 + end + + def read_and_return_value(io) + prototype = get_parameter(:until_valid) + validator = prototype.instantiate(nil, self) + + valid = false + until valid + begin + io.with_readahead do + validator.read(io) + valid = true + end + rescue ValidityError + io.readbytes(1) + end + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/string.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/string.rb new file mode 100644 index 0000000000..cf744ae2df --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/string.rb @@ -0,0 +1,153 @@ +require "bindata/base_primitive" + +module BinData + # A String is a sequence of bytes. This is the same as strings in Ruby 1.8. + # The issue of character encoding is ignored by this class. + # + # require 'bindata' + # + # data = "abcdefghij" + # + # obj = BinData::String.new(read_length: 5) + # obj.read(data) + # obj #=> "abcde" + # + # obj = BinData::String.new(length: 6) + # obj.read(data) + # obj #=> "abcdef" + # obj.assign("abcdefghij") + # obj #=> "abcdef" + # obj.assign("abcd") + # obj #=> "abcd\000\000" + # + # obj = BinData::String.new(length: 6, trim_padding: true) + # obj.assign("abcd") + # obj #=> "abcd" + # obj.to_binary_s #=> "abcd\000\000" + # + # obj = BinData::String.new(length: 6, pad_byte: 'A') + # obj.assign("abcd") + # obj #=> "abcdAA" + # obj.to_binary_s #=> "abcdAA" + # + # == Parameters + # + # String objects accept all the params that BinData::BasePrimitive + # does, as well as the following: + # + # :read_length:: The length in bytes to use when reading a value. + # :length:: The fixed length of the string. If a shorter + # string is set, it will be padded to this length. + # :pad_byte:: The byte to use when padding a string to a + # set length. Valid values are Integers and + # Strings of length 1. "\0" is the default. + # :pad_front:: Signifies that the padding occurs at the front + # of the string rather than the end. Default + # is false. + # :trim_padding:: Boolean, default false. If set, #value will + # return the value with all pad_bytes trimmed + # from the end of the string. The value will + # not be trimmed when writing. + class String < BinData::BasePrimitive + arg_processor :string + + optional_parameters :read_length, :length, :trim_padding, :pad_front, :pad_left + default_parameters pad_byte: "\0" + mutually_exclusive_parameters :read_length, :length + mutually_exclusive_parameters :length, :value + + def initialize_shared_instance + if (has_parameter?(:value) || has_parameter?(:asserted_value)) && + !has_parameter?(:read_length) + extend WarnNoReadLengthPlugin + end + super + end + + def assign(val) + super(binary_string(val)) + end + + def snapshot + # override to trim padding + snap = super + snap = clamp_to_length(snap) + + if get_parameter(:trim_padding) + trim_padding(snap) + else + snap + end + end + + #--------------- + private + + def clamp_to_length(str) + str = binary_string(str) + + len = eval_parameter(:length) || str.length + if str.length == len + str + elsif str.length > len + str.slice(0, len) + else + padding = (eval_parameter(:pad_byte) * (len - str.length)) + if get_parameter(:pad_front) + padding + str + else + str + padding + end + end + end + + def trim_padding(str) + if get_parameter(:pad_front) + str.sub(/\A#{eval_parameter(:pad_byte)}*/, "") + else + str.sub(/#{eval_parameter(:pad_byte)}*\z/, "") + end + end + + def value_to_binary_string(val) + clamp_to_length(val) + end + + def read_and_return_value(io) + len = eval_parameter(:read_length) || eval_parameter(:length) || 0 + io.readbytes(len) + end + + def sensible_default + "" + end + end + + class StringArgProcessor < BaseArgProcessor + def sanitize_parameters!(obj_class, params) + params.warn_replacement_parameter(:initial_length, :read_length) + params.must_be_integer(:read_length, :length) + params.rename_parameter(:pad_left, :pad_front) + params.sanitize(:pad_byte) { |byte| sanitized_pad_byte(byte) } + end + + #------------- + private + + def sanitized_pad_byte(byte) + pad_byte = byte.is_a?(Integer) ? byte.chr : byte.to_s + if pad_byte.bytesize > 1 + raise ArgumentError, ":pad_byte must not contain more than 1 byte" + end + pad_byte + end + end + + # Warns when reading if :value && no :read_length + module WarnNoReadLengthPlugin + def read_and_return_value(io) + warn "#{debug_name} does not have a :read_length parameter - returning empty string" + "" + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/stringz.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/stringz.rb new file mode 100644 index 0000000000..ff047fca85 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/stringz.rb @@ -0,0 +1,96 @@ +require "bindata/base_primitive" + +module BinData + # A BinData::Stringz object is a container for a zero ("\0") terminated + # string. + # + # For convenience, the zero terminator is not necessary when setting the + # value. Likewise, the returned value will not be zero terminated. + # + # require 'bindata' + # + # data = "abcd\x00efgh" + # + # obj = BinData::Stringz.new + # obj.read(data) + # obj.snapshot #=> "abcd" + # obj.num_bytes #=> 5 + # obj.to_binary_s #=> "abcd\000" + # + # == Parameters + # + # Stringz objects accept all the params that BinData::BasePrimitive + # does, as well as the following: + # + # :max_length:: The maximum length of the string including the zero + # byte. + class Stringz < BinData::BasePrimitive + + optional_parameters :max_length + + def assign(val) + super(binary_string(val)) + end + + def snapshot + # override to always remove trailing zero bytes + result = super + trim_and_zero_terminate(result).chomp("\0") + end + + #--------------- + private + + def value_to_binary_string(val) + trim_and_zero_terminate(val) + end + + def read_and_return_value(io) + max_length = eval_parameter(:max_length) + str = "" + i = 0 + ch = nil + + # read until zero byte or we have read in the max number of bytes + while ch != "\0" && i != max_length + ch = io.readbytes(1) + str += ch + i += 1 + end + + trim_and_zero_terminate(str) + end + + def sensible_default + "" + end + + def trim_and_zero_terminate(str) + result = binary_string(str) + truncate_after_first_zero_byte!(result) + trim_to!(result, eval_parameter(:max_length)) + append_zero_byte_if_needed!(result) + result + end + + def truncate_after_first_zero_byte!(str) + str.sub!(/([^\0]*\0).*/, '\1') + end + + def trim_to!(str, max_length = nil) + if max_length + max_length = 1 if max_length < 1 + str.slice!(max_length..-1) + if str.length == max_length && str[-1, 1] != "\0" + str[-1, 1] = "\0" + end + end + end + + def append_zero_byte_if_needed!(str) + if str.length == 0 || str[-1, 1] != "\0" + str << "\0" + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/struct.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/struct.rb new file mode 100644 index 0000000000..f990036e1b --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/struct.rb @@ -0,0 +1,422 @@ +require 'bindata/base' +require 'bindata/delayed_io' + +module BinData + + class Base + optional_parameter :onlyif, :byte_align # Used by Struct + end + + # A Struct is an ordered collection of named data objects. + # + # require 'bindata' + # + # class Tuple < BinData::Record + # int8 :x + # int8 :y + # int8 :z + # end + # + # obj = BinData::Struct.new(hide: :a, + # fields: [ [:int32le, :a], + # [:int16le, :b], + # [:tuple, :s] ]) + # obj.field_names =># [:b, :s] + # + # + # == Parameters + # + # Parameters may be provided at initialisation to control the behaviour of + # an object. These params are: + # + # :fields:: An array specifying the fields for this struct. + # Each element of the array is of the form [type, name, + # params]. Type is a symbol representing a registered + # type. Name is the name of this field. Params is an + # optional hash of parameters to pass to this field + # when instantiating it. If name is "" or nil, then + # that field is anonymous and behaves as a hidden field. + # :hide:: A list of the names of fields that are to be hidden + # from the outside world. Hidden fields don't appear + # in #snapshot or #field_names but are still accessible + # by name. + # :endian:: Either :little or :big. This specifies the default + # endian of any numerics in this struct, or in any + # nested data objects. + # :search_prefix:: Allows abbreviated type names. If a type is + # unrecognised, then each prefix is applied until + # a match is found. + # + # == Field Parameters + # + # Fields may have have extra parameters as listed below: + # + # [:onlyif] Used to indicate a data object is optional. + # if +false+, this object will not be included in any + # calls to #read, #write, #num_bytes or #snapshot. + # [:byte_align] This field's rel_offset must be a multiple of + # :byte_align. + class Struct < BinData::Base + arg_processor :struct + + mandatory_parameter :fields + optional_parameters :endian, :search_prefix, :hide + + # These reserved words may not be used as field names + RESERVED = + Hash[* + (Hash.instance_methods + + %w{alias and begin break case class def defined do else elsif + end ensure false for if in module next nil not or redo + rescue retry return self super then true undef unless until + when while yield} + + %w{array element index value} + + %w{type initial_length read_until} + + %w{fields endian search_prefix hide only_if byte_align} + + %w{choices selection copy_on_change} + + %w{read_abs_offset struct_params}).collect(&:to_sym). + uniq.collect { |key| [key, true] }.flatten + ] + + def initialize_shared_instance + fields = get_parameter(:fields) + @field_names = fields.field_names.freeze + extend ByteAlignPlugin if fields.any_field_has_parameter?(:byte_align) + define_field_accessors + super + end + + def initialize_instance + @field_objs = [] + end + + def clear #:nodoc: + @field_objs.each { |f| f.clear unless f.nil? } + end + + def clear? #:nodoc: + @field_objs.all? { |f| f.nil? || f.clear? } + end + + def assign(val) + clear + assign_fields(val) + end + + def snapshot + snapshot = Snapshot.new + field_names.each do |name| + obj = find_obj_for_name(name) + snapshot[name] = obj.snapshot if include_obj?(obj) + end + snapshot + end + + # Returns a list of the names of all fields accessible through this + # object. +include_hidden+ specifies whether to include hidden names + # in the listing. + def field_names(include_hidden = false) + if include_hidden + @field_names.compact + else + hidden = get_parameter(:hide) || [] + @field_names.compact - hidden + end + end + + def debug_name_of(child) #:nodoc: + field_name = @field_names[find_index_of(child)] + "#{debug_name}.#{field_name}" + end + + def offset_of(child) #:nodoc: + instantiate_all_objs + sum = sum_num_bytes_below_index(find_index_of(child)) + child.bit_aligned? ? sum.floor : sum.ceil + end + + def do_read(io) #:nodoc: + instantiate_all_objs + @field_objs.each { |f| f.do_read(io) if include_obj_for_io?(f) } + end + + def do_write(io) #:nodoc + instantiate_all_objs + @field_objs.each { |f| f.do_write(io) if include_obj_for_io?(f) } + end + + def do_num_bytes #:nodoc: + instantiate_all_objs + sum_num_bytes_for_all_fields + end + + def [](key) + find_obj_for_name(key) + end + + def []=(key, value) + obj = find_obj_for_name(key) + if obj + obj.assign(value) + end + end + + def key?(key) + @field_names.index(base_field_name(key)) + end + + def each_pair + @field_names.compact.each do |name| + yield [name, find_obj_for_name(name)] + end + end + + #--------------- + private + + def define_field_accessors + get_parameter(:fields).each_with_index do |field, i| + name = field.name_as_sym + define_field_accessors_for(name, i) if name + end + end + + def define_field_accessors_for(name, index) + define_singleton_method(name) do + instantiate_obj_at(index) if @field_objs[index].nil? + @field_objs[index] + end + define_singleton_method("#{name}=") do |*vals| + instantiate_obj_at(index) if @field_objs[index].nil? + @field_objs[index].assign(*vals) + end + define_singleton_method("#{name}?") do + instantiate_obj_at(index) if @field_objs[index].nil? + include_obj?(@field_objs[index]) + end + end + + def find_index_of(obj) + @field_objs.index { |el| el.equal?(obj) } + end + + def find_obj_for_name(name) + index = @field_names.index(base_field_name(name)) + if index + instantiate_obj_at(index) + @field_objs[index] + else + nil + end + end + + def base_field_name(name) + name.to_s.sub(/(=|\?)\z/, "").to_sym + end + + def instantiate_all_objs + @field_names.each_index { |i| instantiate_obj_at(i) } + end + + def instantiate_obj_at(index) + if @field_objs[index].nil? + field = get_parameter(:fields)[index] + @field_objs[index] = field.instantiate(nil, self) + end + end + + def assign_fields(val) + src = as_stringified_hash(val) + + @field_names.compact.each do |name| + obj = find_obj_for_name(name) + if obj && src.key?(name) + obj.assign(src[name]) + end + end + end + + def as_stringified_hash(val) + if BinData::Struct === val + val + elsif val.nil? + {} + else + hash = Snapshot.new + val.each_pair { |k,v| hash[k] = v } + hash + end + end + + def sum_num_bytes_for_all_fields + sum_num_bytes_below_index(@field_objs.length) + end + + def sum_num_bytes_below_index(index) + (0...index).inject(0) do |sum, i| + obj = @field_objs[i] + if include_obj?(obj) + nbytes = obj.do_num_bytes + (nbytes.is_a?(Integer) ? sum.ceil : sum) + nbytes + else + sum + end + end + end + + def include_obj_for_io?(obj) + # Used by #do_read and #do_write, to ensure the stream is passed to + # DelayedIO objects for delayed processing. + include_obj?(obj) || DelayedIO === obj + end + + def include_obj?(obj) + !obj.has_parameter?(:onlyif) || obj.eval_parameter(:onlyif) + end + + # A hash that can be accessed via attributes. + class Snapshot < ::Hash #:nodoc: + def []=(key, value) + super unless value.nil? + end + + def respond_to?(symbol, include_private = false) + key?(symbol) || super + end + + def method_missing(symbol, *args) + key?(symbol) ? self[symbol] : super + end + end + end + + # Align fields to a multiple of :byte_align + module ByteAlignPlugin + def do_read(io) + initial_offset = io.offset + instantiate_all_objs + @field_objs.each do |f| + if include_obj?(f) + if align_obj?(f) + io.seekbytes(bytes_to_align(f, io.offset - initial_offset)) + end + f.do_read(io) + end + end + end + + def do_write(io) + initial_offset = io.offset + instantiate_all_objs + @field_objs.each do |f| + if include_obj?(f) + if align_obj?(f) + io.writebytes("\x00" * bytes_to_align(f, io.offset - initial_offset)) + end + f.do_write(io) + end + end + end + + def sum_num_bytes_below_index(index) + sum = 0 + (0...@field_objs.length).each do |i| + obj = @field_objs[i] + if include_obj?(obj) + sum = sum.ceil + bytes_to_align(obj, sum.ceil) if align_obj?(obj) + + break if i >= index + + nbytes = obj.do_num_bytes + sum = (nbytes.is_a?(Integer) ? sum.ceil : sum) + nbytes + end + end + + sum + end + + def bytes_to_align(obj, rel_offset) + align = obj.eval_parameter(:byte_align) + (align - (rel_offset % align)) % align + end + + def align_obj?(obj) + obj.has_parameter?(:byte_align) + end + end + + class StructArgProcessor < BaseArgProcessor + def sanitize_parameters!(obj_class, params) + sanitize_endian(params) + sanitize_search_prefix(params) + sanitize_fields(obj_class, params) + sanitize_hide(params) + end + + #------------- + private + + def sanitize_endian(params) + params.sanitize_endian(:endian) + end + + def sanitize_search_prefix(params) + params.sanitize(:search_prefix) do |sprefix| + search_prefix = [] + Array(sprefix).each do |prefix| + prefix = prefix.to_s.chomp("_") + search_prefix << prefix if prefix != "" + end + + search_prefix + end + end + + def sanitize_fields(obj_class, params) + params.sanitize_fields(:fields) do |fields, sanitized_fields| + fields.each do |ftype, fname, fparams| + sanitized_fields.add_field(ftype, fname, fparams) + end + + field_names = sanitized_field_names(sanitized_fields) + ensure_field_names_are_valid(obj_class, field_names) + end + end + + def sanitize_hide(params) + params.sanitize(:hide) do |hidden| + field_names = sanitized_field_names(params[:fields]) + hfield_names = hidden_field_names(hidden) + + hfield_names & field_names + end + end + + def sanitized_field_names(sanitized_fields) + sanitized_fields.field_names.compact + end + + def hidden_field_names(hidden) + (hidden || []).collect(&:to_sym) + end + + def ensure_field_names_are_valid(obj_class, field_names) + reserved_names = BinData::Struct::RESERVED + + field_names.each do |name| + if obj_class.method_defined?(name) + raise NameError.new("Rename field '#{name}' in #{obj_class}, " \ + "as it shadows an existing method.", name) + end + if reserved_names.include?(name) + raise NameError.new("Rename field '#{name}' in #{obj_class}, " \ + "as it is a reserved name.", name) + end + if field_names.count(name) != 1 + raise NameError.new("field '#{name}' in #{obj_class}, " \ + "is defined multiple times.", name) + end + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/trace.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/trace.rb new file mode 100644 index 0000000000..4e4f9ba59c --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/trace.rb @@ -0,0 +1,95 @@ +module BinData + # reference to the current tracer + @tracer ||= nil + + class Tracer #:nodoc: + def initialize(io) + @trace_io = io + end + + def trace(msg) + @trace_io.puts(msg) + end + + def trace_obj(obj_name, val) + if val.length > 30 + val = val.slice(0..30) + "..." + end + + trace "#{obj_name} => #{val}" + end + end + + # Turn on trace information when reading a BinData object. + # If +block+ is given then the tracing only occurs for that block. + # This is useful for debugging a BinData declaration. + def trace_reading(io = STDERR) + @tracer = Tracer.new(io) + [BasePrimitive, Choice].each(&:turn_on_tracing) + + if block_given? + begin + yield + ensure + [BasePrimitive, Choice].each(&:turn_off_tracing) + @tracer = nil + end + end + end + + def trace_message #:nodoc: + yield @tracer if @tracer + end + + module_function :trace_reading, :trace_message + + class BasePrimitive < BinData::Base + class << self + def turn_on_tracing + alias_method :do_read_without_hook, :do_read + alias_method :do_read, :do_read_with_hook + end + + def turn_off_tracing + alias_method :do_read, :do_read_without_hook + end + end + + def do_read_with_hook(io) + do_read_without_hook(io) + trace_value + end + + def trace_value + BinData.trace_message do |tracer| + value_string = _value.inspect + tracer.trace_obj(debug_name, value_string) + end + end + end + + class Choice < BinData::Base + class << self + def turn_on_tracing + alias_method :do_read_without_hook, :do_read + alias_method :do_read, :do_read_with_hook + end + + def turn_off_tracing + alias_method :do_read, :do_read_without_hook + end + end + + def do_read_with_hook(io) + trace_selection + do_read_without_hook(io) + end + + def trace_selection + BinData.trace_message do |tracer| + selection_string = eval_parameter(:selection).inspect + tracer.trace_obj("#{debug_name}-selection-", selection_string) + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/uint8_array.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/uint8_array.rb new file mode 100644 index 0000000000..72816611e8 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/uint8_array.rb @@ -0,0 +1,62 @@ +require "bindata/base_primitive" + +module BinData + # Uint8Array is a specialised type of array that only contains + # bytes (Uint8). It is a faster and more memory efficient version + # of `BinData::Array.new(:type => :uint8)`. + # + # require 'bindata' + # + # obj = BinData::Uint8Array.new(initial_length: 5) + # obj.read("abcdefg") #=> [97, 98, 99, 100, 101] + # obj[2] #=> 99 + # obj.collect { |x| x.chr }.join #=> "abcde" + # + # == Parameters + # + # Parameters may be provided at initialisation to control the behaviour of + # an object. These params are: + # + # :initial_length:: The initial length of the array. + # :read_until:: May only have a value of `:eof`. This parameter + # instructs the array to read as much data from + # the stream as possible. + class Uint8Array < BinData::BasePrimitive + optional_parameters :initial_length, :read_until + mutually_exclusive_parameters :initial_length, :read_until + arg_processor :uint8_array + + #--------------- + private + + def value_to_binary_string(val) + val.pack("C*") + end + + def read_and_return_value(io) + if has_parameter?(:initial_length) + data = io.readbytes(eval_parameter(:initial_length)) + else + data = io.read_all_bytes + end + + data.unpack("C*") + end + + def sensible_default + [] + end + end + + class Uint8ArrayArgProcessor < BaseArgProcessor + def sanitize_parameters!(obj_class, params) #:nodoc: + # ensure one of :initial_length and :read_until exists + unless params.has_at_least_one_of?(:initial_length, :read_until) + params[:initial_length] = 0 + end + + msg = "Parameter :read_until must have a value of :eof" + params.sanitize(:read_until) { |val| raise ArgumentError, msg unless val == :eof } + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/version.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/version.rb new file mode 100644 index 0000000000..a127d6cb11 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/version.rb @@ -0,0 +1,3 @@ +module BinData + VERSION = "2.4.15" +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/virtual.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/virtual.rb new file mode 100644 index 0000000000..1a7205f74b --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/virtual.rb @@ -0,0 +1,47 @@ +require "bindata/base" + +module BinData + # A virtual field is one that is neither read, written nor occupies space in + # the data stream. It is used to make assertions or as a convenient label + # for determining offsets or storing values. + # + # require 'bindata' + # + # class A < BinData::Record + # string :a, read_length: 5 + # string :b, read_length: 5 + # virtual :c, assert: -> { a == b } + # end + # + # obj = A.read("abcdeabcde") + # obj.a #=> "abcde" + # obj.c.offset #=> 10 + # + # obj = A.read("abcdeABCDE") #=> BinData::ValidityError: assertion failed for obj.c + # + # == Parameters + # + # Parameters may be provided at initialisation to control the behaviour of + # an object. These params include those for BinData::Base as well as: + # + # [:assert] Raise an error when reading or assigning if the value + # of this evaluated parameter is false. + # [:value] The virtual object will always have this value. + # + class Virtual < BinData::BasePrimitive + + def do_read(io) + end + + def do_write(io) + end + + def do_num_bytes + 0.0 + end + + def sensible_default + nil + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/warnings.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/warnings.rb new file mode 100644 index 0000000000..3d1cfe728b --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/bindata-2.4.15/lib/bindata/warnings.rb @@ -0,0 +1,36 @@ +module BinData + class Base + # Don't override initialize. If you are defining a new kind of datatype + # (list, array, choice etc) then put your initialization code in + # #initialize_instance. BinData objects might be initialized as prototypes + # and your initialization code may not be called. + # + # If you're subclassing BinData::Record, you are definitely doing the wrong + # thing. Read the documentation on how to use BinData. + # http://github.com/dmendel/bindata/wiki/Records + alias_method :initialize_without_warning, :initialize + def initialize_with_warning(*args) + owner = method(:initialize).owner + if owner != BinData::Base + msg = "Don't override #initialize on #{owner}." + if %w(BinData::Base BinData::BasePrimitive).include? self.class.superclass.name + msg += "\nrename #initialize to #initialize_instance." + end + fail msg + end + initialize_without_warning(*args) + end + alias initialize initialize_with_warning + + def initialize_instance(*args) + unless args.empty? + fail "#{caller[0]} remove the call to super in #initialize_instance" + end + end + end + + class Struct + # has_key? is deprecated + alias has_key? key? + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools.rb new file mode 100644 index 0000000000..2b16c7ef8c --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +require 'elftools/constants' +require 'elftools/elf_file' +require 'elftools/version' + +# The ELF parsing tools! +# Main entry point is {ELFTools::ELFFile}, see it +# for more information. +module ELFTools +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/constants.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/constants.rb new file mode 100644 index 0000000000..2e2f77da2b --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/constants.rb @@ -0,0 +1,722 @@ +# frozen_string_literal: true + +module ELFTools + # Define constants from elf.h. + # Mostly refer from https://github.com/torvalds/linux/blob/master/include/uapi/linux/elf.h + # and binutils/elfcpp/elfcpp.h. + module Constants + # ELF magic header + ELFMAG = "\x7FELF" + + # Values of `d_un.d_val' in the DT_FLAGS and DT_FLAGS_1 entry. + module DF + DF_ORIGIN = 0x00000001 # Object may use DF_ORIGIN + DF_SYMBOLIC = 0x00000002 # Symbol resolutions starts here + DF_TEXTREL = 0x00000004 # Object contains text relocations + DF_BIND_NOW = 0x00000008 # No lazy binding for this object + DF_STATIC_TLS = 0x00000010 # Module uses the static TLS model + + DF_1_NOW = 0x00000001 # Set RTLD_NOW for this object. + DF_1_GLOBAL = 0x00000002 # Set RTLD_GLOBAL for this object. + DF_1_GROUP = 0x00000004 # Set RTLD_GROUP for this object. + DF_1_NODELETE = 0x00000008 # Set RTLD_NODELETE for this object. + DF_1_LOADFLTR = 0x00000010 # Trigger filtee loading at runtime. + DF_1_INITFIRST = 0x00000020 # Set RTLD_INITFIRST for this object + DF_1_NOOPEN = 0x00000040 # Set RTLD_NOOPEN for this object. + DF_1_ORIGIN = 0x00000080 # $ORIGIN must be handled. + DF_1_DIRECT = 0x00000100 # Direct binding enabled. + DF_1_TRANS = 0x00000200 # :nodoc: + DF_1_INTERPOSE = 0x00000400 # Object is used to interpose. + DF_1_NODEFLIB = 0x00000800 # Ignore default lib search path. + DF_1_NODUMP = 0x00001000 # Object can't be dldump'ed. + DF_1_CONFALT = 0x00002000 # Configuration alternative created. + DF_1_ENDFILTEE = 0x00004000 # Filtee terminates filters search. + DF_1_DISPRELDNE = 0x00008000 # Disp reloc applied at build time. + DF_1_DISPRELPND = 0x00010000 # Disp reloc applied at run-time. + DF_1_NODIRECT = 0x00020000 # Object has no-direct binding. + DF_1_IGNMULDEF = 0x00040000 # :nodoc: + DF_1_NOKSYMS = 0x00080000 # :nodoc: + DF_1_NOHDR = 0x00100000 # :nodoc: + DF_1_EDITED = 0x00200000 # Object is modified after built. + DF_1_NORELOC = 0x00400000 # :nodoc: + DF_1_SYMINTPOSE = 0x00800000 # Object has individual interposers. + DF_1_GLOBAUDIT = 0x01000000 # Global auditing required. + DF_1_SINGLETON = 0x02000000 # Singleton symbols are used. + DF_1_STUB = 0x04000000 # :nodoc: + DF_1_PIE = 0x08000000 # Object is a position-independent executable. + DF_1_KMOD = 0x10000000 # :nodoc: + DF_1_WEAKFILTER = 0x20000000 # :nodoc: + DF_1_NOCOMMON = 0x40000000 # :nodoc: + end + include DF + + # Dynamic table types, records in +d_tag+. + module DT + DT_NULL = 0 # marks the end of the _DYNAMIC array + DT_NEEDED = 1 # libraries need to be linked by loader + DT_PLTRELSZ = 2 # total size of relocation entries + DT_PLTGOT = 3 # address of procedure linkage table or global offset table + DT_HASH = 4 # address of symbol hash table + DT_STRTAB = 5 # address of string table + DT_SYMTAB = 6 # address of symbol table + DT_RELA = 7 # address of a relocation table + DT_RELASZ = 8 # total size of the {DT_RELA} table + DT_RELAENT = 9 # size of each entry in the {DT_RELA} table + DT_STRSZ = 10 # total size of {DT_STRTAB} + DT_SYMENT = 11 # size of each entry in {DT_SYMTAB} + DT_INIT = 12 # where the initialization function is + DT_FINI = 13 # where the termination function is + DT_SONAME = 14 # the shared object name + DT_RPATH = 15 # has been superseded by {DT_RUNPATH} + DT_SYMBOLIC = 16 # has been superseded by the DF_SYMBOLIC flag + DT_REL = 17 # similar to {DT_RELA} + DT_RELSZ = 18 # total size of the {DT_REL} table + DT_RELENT = 19 # size of each entry in the {DT_REL} table + DT_PLTREL = 20 # type of relocation entry, either {DT_REL} or {DT_RELA} + DT_DEBUG = 21 # for debugging + DT_TEXTREL = 22 # has been superseded by the DF_TEXTREL flag + DT_JMPREL = 23 # address of relocation entries associated solely with procedure linkage table + DT_BIND_NOW = 24 # if the loader needs to do relocate now, superseded by the DF_BIND_NOW flag + DT_INIT_ARRAY = 25 # address init array + DT_FINI_ARRAY = 26 # address of fini array + DT_INIT_ARRAYSZ = 27 # total size of init array + DT_FINI_ARRAYSZ = 28 # total size of fini array + DT_RUNPATH = 29 # path of libraries for searching + DT_FLAGS = 30 # flags + DT_ENCODING = 32 # just a lower bound + DT_PREINIT_ARRAY = 32 # pre-initialization functions array + DT_PREINIT_ARRAYSZ = 33 # pre-initialization functions array size (bytes) + DT_SYMTAB_SHNDX = 34 # address of the +SHT_SYMTAB_SHNDX+ section associated with {DT_SYMTAB} table + DT_RELRSZ = 35 # :nodoc: + DT_RELR = 36 # :nodoc: + DT_RELRENT = 37 # :nodoc: + + # Values between {DT_LOOS} and {DT_HIOS} are reserved for operating system-specific semantics. + DT_LOOS = 0x6000000d + DT_HIOS = 0x6ffff000 # see {DT_LOOS} + + # Values between {DT_VALRNGLO} and {DT_VALRNGHI} use the +d_un.d_val+ field of the dynamic structure. + DT_VALRNGLO = 0x6ffffd00 + DT_VALRNGHI = 0x6ffffdff # see {DT_VALRNGLO} + + # Values between {DT_ADDRRNGLO} and {DT_ADDRRNGHI} use the +d_un.d_ptr+ field of the dynamic structure. + DT_ADDRRNGLO = 0x6ffffe00 + DT_GNU_HASH = 0x6ffffef5 # the gnu hash + DT_TLSDESC_PLT = 0x6ffffef6 # :nodoc: + DT_TLSDESC_GOT = 0x6ffffef7 # :nodoc: + DT_GNU_CONFLICT = 0x6ffffef8 # :nodoc: + DT_GNU_LIBLIST = 0x6ffffef9 # :nodoc: + DT_CONFIG = 0x6ffffefa # :nodoc: + DT_DEPAUDIT = 0x6ffffefb # :nodoc: + DT_AUDIT = 0x6ffffefc # :nodoc: + DT_PLTPAD = 0x6ffffefd # :nodoc: + DT_MOVETAB = 0x6ffffefe # :nodoc: + DT_SYMINFO = 0x6ffffeff # :nodoc: + DT_ADDRRNGHI = 0x6ffffeff # see {DT_ADDRRNGLO} + + DT_VERSYM = 0x6ffffff0 # section address of .gnu.version + DT_RELACOUNT = 0x6ffffff9 # relative relocation count + DT_RELCOUNT = 0x6ffffffa # relative relocation count + DT_FLAGS_1 = 0x6ffffffb # flags + DT_VERDEF = 0x6ffffffc # address of version definition table + DT_VERDEFNUM = 0x6ffffffd # number of entries in {DT_VERDEF} + DT_VERNEED = 0x6ffffffe # address of version dependency table + DT_VERNEEDNUM = 0x6fffffff # number of entries in {DT_VERNEED} + + # Values between {DT_LOPROC} and {DT_HIPROC} are reserved for processor-specific semantics. + DT_LOPROC = 0x70000000 + + DT_PPC_GOT = 0x70000000 # global offset table + DT_PPC_OPT = 0x70000001 # whether various optimisations are possible + + DT_PPC64_GLINK = 0x70000000 # start of the .glink section + DT_PPC64_OPD = 0x70000001 # start of the .opd section + DT_PPC64_OPDSZ = 0x70000002 # size of the .opd section + DT_PPC64_OPT = 0x70000003 # whether various optimisations are possible + + DT_SPARC_REGISTER = 0x70000000 # index of an +STT_SPARC_REGISTER+ symbol within the {DT_SYMTAB} table + + DT_MIPS_RLD_VERSION = 0x70000001 # 32 bit version number for runtime linker interface + DT_MIPS_TIME_STAMP = 0x70000002 # time stamp + DT_MIPS_ICHECKSUM = 0x70000003 # checksum of external strings and common sizes + DT_MIPS_IVERSION = 0x70000004 # index of version string in string table + DT_MIPS_FLAGS = 0x70000005 # 32 bits of flags + DT_MIPS_BASE_ADDRESS = 0x70000006 # base address of the segment + DT_MIPS_MSYM = 0x70000007 # :nodoc: + DT_MIPS_CONFLICT = 0x70000008 # address of +.conflict+ section + DT_MIPS_LIBLIST = 0x70000009 # address of +.liblist+ section + DT_MIPS_LOCAL_GOTNO = 0x7000000a # number of local global offset table entries + DT_MIPS_CONFLICTNO = 0x7000000b # number of entries in the +.conflict+ section + DT_MIPS_LIBLISTNO = 0x70000010 # number of entries in the +.liblist+ section + DT_MIPS_SYMTABNO = 0x70000011 # number of entries in the +.dynsym+ section + DT_MIPS_UNREFEXTNO = 0x70000012 # index of first external dynamic symbol not referenced locally + DT_MIPS_GOTSYM = 0x70000013 # index of first dynamic symbol in global offset table + DT_MIPS_HIPAGENO = 0x70000014 # number of page table entries in global offset table + DT_MIPS_RLD_MAP = 0x70000016 # address of run time loader map, used for debugging + DT_MIPS_DELTA_CLASS = 0x70000017 # delta C++ class definition + DT_MIPS_DELTA_CLASS_NO = 0x70000018 # number of entries in {DT_MIPS_DELTA_CLASS} + DT_MIPS_DELTA_INSTANCE = 0x70000019 # delta C++ class instances + DT_MIPS_DELTA_INSTANCE_NO = 0x7000001a # number of entries in {DT_MIPS_DELTA_INSTANCE} + DT_MIPS_DELTA_RELOC = 0x7000001b # delta relocations + DT_MIPS_DELTA_RELOC_NO = 0x7000001c # number of entries in {DT_MIPS_DELTA_RELOC} + DT_MIPS_DELTA_SYM = 0x7000001d # delta symbols that Delta relocations refer to + DT_MIPS_DELTA_SYM_NO = 0x7000001e # number of entries in {DT_MIPS_DELTA_SYM} + DT_MIPS_DELTA_CLASSSYM = 0x70000020 # delta symbols that hold class declarations + DT_MIPS_DELTA_CLASSSYM_NO = 0x70000021 # number of entries in {DT_MIPS_DELTA_CLASSSYM} + DT_MIPS_CXX_FLAGS = 0x70000022 # flags indicating information about C++ flavor + DT_MIPS_PIXIE_INIT = 0x70000023 # :nodoc: + DT_MIPS_SYMBOL_LIB = 0x70000024 # address of +.MIPS.symlib+ + DT_MIPS_LOCALPAGE_GOTIDX = 0x70000025 # GOT index of the first PTE for a segment + DT_MIPS_LOCAL_GOTIDX = 0x70000026 # GOT index of the first PTE for a local symbol + DT_MIPS_HIDDEN_GOTIDX = 0x70000027 # GOT index of the first PTE for a hidden symbol + DT_MIPS_PROTECTED_GOTIDX = 0x70000028 # GOT index of the first PTE for a protected symbol + DT_MIPS_OPTIONS = 0x70000029 # address of +.MIPS.options+ + DT_MIPS_INTERFACE = 0x7000002a # address of +.interface+ + DT_MIPS_DYNSTR_ALIGN = 0x7000002b # :nodoc: + DT_MIPS_INTERFACE_SIZE = 0x7000002c # size of the +.interface+ section + DT_MIPS_RLD_TEXT_RESOLVE_ADDR = 0x7000002d # size of +rld_text_resolve+ function stored in the GOT + DT_MIPS_PERF_SUFFIX = 0x7000002e # default suffix of DSO to be added by rld on +dlopen()+ calls + DT_MIPS_COMPACT_SIZE = 0x7000002f # size of compact relocation section (O32) + DT_MIPS_GP_VALUE = 0x70000030 # GP value for auxiliary GOTs + DT_MIPS_AUX_DYNAMIC = 0x70000031 # address of auxiliary +.dynamic+ + DT_MIPS_PLTGOT = 0x70000032 # address of the base of the PLTGOT + DT_MIPS_RWPLT = 0x70000034 # base of a writable PLT + DT_MIPS_RLD_MAP_REL = 0x70000035 # relative offset of run time loader map + DT_MIPS_XHASH = 0x70000036 # GNU-style hash table with xlat + + DT_AUXILIARY = 0x7ffffffd # :nodoc: + DT_USED = 0x7ffffffe # :nodoc: + DT_FILTER = 0x7ffffffe # :nodoc: + + DT_HIPROC = 0x7fffffff # see {DT_LOPROC} + end + include DT + + # These constants define the various ELF target machines. + module EM + EM_NONE = 0 # none + EM_M32 = 1 # AT&T WE 32100 + EM_SPARC = 2 # SPARC + EM_386 = 3 # Intel 80386 + EM_68K = 4 # Motorola 68000 + EM_88K = 5 # Motorola 88000 + EM_486 = 6 # Intel 80486 + EM_860 = 7 # Intel 80860 + EM_MIPS = 8 # MIPS R3000 (officially, big-endian only) + EM_S370 = 9 # IBM System/370 + + # Next two are historical and binaries and + # modules of these types will be rejected by Linux. + EM_MIPS_RS3_LE = 10 # MIPS R3000 little-endian + EM_MIPS_RS4_BE = 10 # MIPS R4000 big-endian + + EM_PARISC = 15 # HPPA + EM_VPP500 = 17 # Fujitsu VPP500 (also some older versions of PowerPC) + EM_SPARC32PLUS = 18 # Sun's "v8plus" + EM_960 = 19 # Intel 80960 + EM_PPC = 20 # PowerPC + EM_PPC64 = 21 # PowerPC64 + EM_S390 = 22 # IBM S/390 + EM_SPU = 23 # Cell BE SPU + EM_V800 = 36 # NEC V800 series + EM_FR20 = 37 # Fujitsu FR20 + EM_RH32 = 38 # TRW RH32 + EM_RCE = 39 # Motorola M*Core + EM_ARM = 40 # ARM 32 bit + EM_SH = 42 # SuperH + EM_SPARCV9 = 43 # SPARC v9 64-bit + EM_TRICORE = 44 # Siemens Tricore embedded processor + EM_ARC = 45 # ARC Cores + EM_H8_300 = 46 # Renesas H8/300 + EM_H8_300H = 47 # Renesas H8/300H + EM_H8S = 48 # Renesas H8S + EM_H8_500 = 49 # Renesas H8/500H + EM_IA_64 = 50 # HP/Intel IA-64 + EM_MIPS_X = 51 # Stanford MIPS-X + EM_COLDFIRE = 52 # Motorola Coldfire + EM_68HC12 = 53 # Motorola M68HC12 + EM_MMA = 54 # Fujitsu Multimedia Accelerator + EM_PCP = 55 # Siemens PCP + EM_NCPU = 56 # Sony nCPU embedded RISC processor + EM_NDR1 = 57 # Denso NDR1 microprocessor + EM_STARCORE = 58 # Motorola Star*Core processor + EM_ME16 = 59 # Toyota ME16 processor + EM_ST100 = 60 # STMicroelectronics ST100 processor + EM_TINYJ = 61 # Advanced Logic Corp. TinyJ embedded processor + EM_X86_64 = 62 # AMD x86-64 + EM_PDSP = 63 # Sony DSP Processor + EM_PDP10 = 64 # Digital Equipment Corp. PDP-10 + EM_PDP11 = 65 # Digital Equipment Corp. PDP-11 + EM_FX66 = 66 # Siemens FX66 microcontroller + EM_ST9PLUS = 67 # STMicroelectronics ST9+ 8/16 bit microcontroller + EM_ST7 = 68 # STMicroelectronics ST7 8-bit microcontroller + EM_68HC16 = 69 # Motorola MC68HC16 Microcontroller + EM_68HC11 = 70 # Motorola MC68HC11 Microcontroller + EM_68HC08 = 71 # Motorola MC68HC08 Microcontroller + EM_68HC05 = 72 # Motorola MC68HC05 Microcontroller + EM_SVX = 73 # Silicon Graphics SVx + EM_ST19 = 74 # STMicroelectronics ST19 8-bit cpu + EM_VAX = 75 # Digital VAX + EM_CRIS = 76 # Axis Communications 32-bit embedded processor + EM_JAVELIN = 77 # Infineon Technologies 32-bit embedded cpu + EM_FIREPATH = 78 # Element 14 64-bit DSP processor + EM_ZSP = 79 # LSI Logic's 16-bit DSP processor + EM_MMIX = 80 # Donald Knuth's educational 64-bit processor + EM_HUANY = 81 # Harvard's machine-independent format + EM_PRISM = 82 # SiTera Prism + EM_AVR = 83 # Atmel AVR 8-bit microcontroller + EM_FR30 = 84 # Fujitsu FR30 + EM_D10V = 85 # Mitsubishi D10V + EM_D30V = 86 # Mitsubishi D30V + EM_V850 = 87 # Renesas V850 + EM_M32R = 88 # Renesas M32R + EM_MN10300 = 89 # Matsushita MN10300 + EM_MN10200 = 90 # Matsushita MN10200 + EM_PJ = 91 # picoJava + EM_OPENRISC = 92 # OpenRISC 32-bit embedded processor + EM_ARC_COMPACT = 93 # ARC International ARCompact processor + EM_XTENSA = 94 # Tensilica Xtensa Architecture + EM_VIDEOCORE = 95 # Alphamosaic VideoCore processor + EM_TMM_GPP = 96 # Thompson Multimedia General Purpose Processor + EM_NS32K = 97 # National Semiconductor 32000 series + EM_TPC = 98 # Tenor Network TPC processor + EM_SNP1K = 99 # Trebia SNP 1000 processor + EM_ST200 = 100 # STMicroelectronics ST200 microcontroller + EM_IP2K = 101 # Ubicom IP2022 micro controller + EM_MAX = 102 # MAX Processor + EM_CR = 103 # National Semiconductor CompactRISC + EM_F2MC16 = 104 # Fujitsu F2MC16 + EM_MSP430 = 105 # TI msp430 micro controller + EM_BLACKFIN = 106 # ADI Blackfin Processor + EM_SE_C33 = 107 # S1C33 Family of Seiko Epson processors + EM_SEP = 108 # Sharp embedded microprocessor + EM_ARCA = 109 # Arca RISC Microprocessor + EM_UNICORE = 110 # Microprocessor series from PKU-Unity Ltd. and MPRC of Peking University + EM_EXCESS = 111 # eXcess: 16/32/64-bit configurable embedded CPU + EM_DXP = 112 # Icera Semiconductor Inc. Deep Execution Processor + EM_ALTERA_NIOS2 = 113 # Altera Nios II soft-core processor + EM_CRX = 114 # National Semiconductor CRX + EM_XGATE = 115 # Motorola XGATE embedded processor + EM_C116 = 116 # Infineon C16x/XC16x processor + EM_M16C = 117 # Renesas M16C series microprocessors + EM_DSPIC30F = 118 # Microchip Technology dsPIC30F Digital Signal Controller + EM_CE = 119 # Freescale Communication Engine RISC core + EM_M32C = 120 # Freescale Communication Engine RISC core + EM_TSK3000 = 131 # Altium TSK3000 core + EM_RS08 = 132 # Freescale RS08 embedded processor + EM_SHARC = 133 # Analog Devices SHARC family of 32-bit DSP processors + EM_ECOG2 = 134 # Cyan Technology eCOG2 microprocessor + EM_SCORE7 = 135 # Sunplus S+core7 RISC processor + EM_DSP24 = 136 # New Japan Radio (NJR) 24-bit DSP Processor + EM_VIDEOCORE3 = 137 # Broadcom VideoCore III processor + EM_LATTICEMICO32 = 138 # RISC processor for Lattice FPGA architecture + EM_SE_C17 = 139 # Seiko Epson C17 family + EM_TI_C6000 = 140 # The Texas Instruments TMS320C6000 DSP family + EM_TI_C2000 = 141 # The Texas Instruments TMS320C2000 DSP family + EM_TI_C5500 = 142 # The Texas Instruments TMS320C55x DSP family + EM_TI_ARP32 = 143 # Texas Instruments Application Specific RISC Processor, 32bit fetch + EM_TI_PRU = 144 # Texas Instruments Programmable Realtime Unit + EM_MMDSP_PLUS = 160 # STMicroelectronics 64bit VLIW Data Signal Processor + EM_CYPRESS_M8C = 161 # Cypress M8C microprocessor + EM_R32C = 162 # Renesas R32C series microprocessors + EM_TRIMEDIA = 163 # NXP Semiconductors TriMedia architecture family + EM_QDSP6 = 164 # QUALCOMM DSP6 Processor + EM_8051 = 165 # Intel 8051 and variants + EM_STXP7X = 166 # STMicroelectronics STxP7x family + EM_NDS32 = 167 # Andes Technology compact code size embedded RISC processor family + EM_ECOG1 = 168 # Cyan Technology eCOG1X family + EM_ECOG1X = 168 # Cyan Technology eCOG1X family + EM_MAXQ30 = 169 # Dallas Semiconductor MAXQ30 Core Micro-controllers + EM_XIMO16 = 170 # New Japan Radio (NJR) 16-bit DSP Processor + EM_MANIK = 171 # M2000 Reconfigurable RISC Microprocessor + EM_CRAYNV2 = 172 # Cray Inc. NV2 vector architecture + EM_RX = 173 # Renesas RX family + EM_METAG = 174 # Imagination Technologies Meta processor architecture + EM_MCST_ELBRUS = 175 # MCST Elbrus general purpose hardware architecture + EM_ECOG16 = 176 # Cyan Technology eCOG16 family + EM_CR16 = 177 # National Semiconductor CompactRISC 16-bit processor + EM_ETPU = 178 # Freescale Extended Time Processing Unit + EM_SLE9X = 179 # Infineon Technologies SLE9X core + EM_L1OM = 180 # Intel L1OM + EM_K1OM = 181 # Intel K1OM + EM_AARCH64 = 183 # ARM 64 bit + EM_AVR32 = 185 # Atmel Corporation 32-bit microprocessor family + EM_STM8 = 186 # STMicroeletronics STM8 8-bit microcontroller + EM_TILE64 = 187 # Tilera TILE64 multicore architecture family + EM_TILEPRO = 188 # Tilera TILEPro + EM_MICROBLAZE = 189 # Xilinx MicroBlaze + EM_CUDA = 190 # NVIDIA CUDA architecture + EM_TILEGX = 191 # Tilera TILE-Gx + EM_CLOUDSHIELD = 192 # CloudShield architecture family + EM_COREA_1ST = 193 # KIPO-KAIST Core-A 1st generation processor family + EM_COREA_2ND = 194 # KIPO-KAIST Core-A 2nd generation processor family + EM_ARC_COMPACT2 = 195 # Synopsys ARCompact V2 + EM_OPEN8 = 196 # Open8 8-bit RISC soft processor core + EM_RL78 = 197 # Renesas RL78 family + EM_VIDEOCORE5 = 198 # Broadcom VideoCore V processor + EM_78K0R = 199 # Renesas 78K0R + EM_56800EX = 200 # Freescale 56800EX Digital Signal Controller (DSC) + EM_BA1 = 201 # Beyond BA1 CPU architecture + EM_BA2 = 202 # Beyond BA2 CPU architecture + EM_XCORE = 203 # XMOS xCORE processor family + EM_MCHP_PIC = 204 # Microchip 8-bit PIC(r) family + EM_INTELGT = 205 # Intel Graphics Technology + EM_KM32 = 210 # KM211 KM32 32-bit processor + EM_KMX32 = 211 # KM211 KMX32 32-bit processor + EM_KMX16 = 212 # KM211 KMX16 16-bit processor + EM_KMX8 = 213 # KM211 KMX8 8-bit processor + EM_KVARC = 214 # KM211 KVARC processor + EM_CDP = 215 # Paneve CDP architecture family + EM_COGE = 216 # Cognitive Smart Memory Processor + EM_COOL = 217 # Bluechip Systems CoolEngine + EM_NORC = 218 # Nanoradio Optimized RISC + EM_CSR_KALIMBA = 219 # CSR Kalimba architecture family + EM_Z80 = 220 # Zilog Z80 + EM_VISIUM = 221 # Controls and Data Services VISIUMcore processor + EM_FT32 = 222 # FTDI Chip FT32 high performance 32-bit RISC architecture + EM_MOXIE = 223 # Moxie processor family + EM_AMDGPU = 224 # AMD GPU architecture + EM_LANAI = 244 # Lanai 32-bit processor + EM_CEVA = 245 # CEVA Processor Architecture Family + EM_CEVA_X2 = 246 # CEVA X2 Processor Family + EM_BPF = 247 # Linux BPF - in-kernel virtual machine + EM_GRAPHCORE_IPU = 248 # Graphcore Intelligent Processing Unit + EM_IMG1 = 249 # Imagination Technologies + EM_NFP = 250 # Netronome Flow Processor (NFP) + EM_VE = 251 # NEC Vector Engine + EM_CSKY = 252 # C-SKY processor family + EM_ARC_COMPACT3_64 = 253 # Synopsys ARCv2.3 64-bit + EM_MCS6502 = 254 # MOS Technology MCS 6502 processor + EM_ARC_COMPACT3 = 255 # Synopsys ARCv2.3 32-bit + EM_KVX = 256 # Kalray VLIW core of the MPPA processor family + EM_65816 = 257 # WDC 65816/65C816 + EM_LOONGARCH = 258 # LoongArch + EM_KF32 = 259 # ChipON KungFu32 + EM_U16_U8CORE = 260 # LAPIS nX-U16/U8 + EM_TACHYUM = 261 # Tachyum + EM_56800EF = 262 # NXP 56800EF Digital Signal Controller (DSC) + + EM_FRV = 0x5441 # Fujitsu FR-V + + # This is an interim value that we will use until the committee comes up with a final number. + EM_ALPHA = 0x9026 + + # Bogus old m32r magic number, used by old tools. + EM_CYGNUS_M32R = 0x9041 + # This is the old interim value for S/390 architecture + EM_S390_OLD = 0xA390 + # Also Panasonic/MEI MN10300, AM33 + EM_CYGNUS_MN10300 = 0xbeef + + # Return the architecture name according to +val+. + # Used by {ELFTools::ELFFile#machine}. + # + # Only supports famous archs. + # @param [Integer] val Value of +e_machine+. + # @return [String] + # Name of architecture. + # @example + # mapping(3) + # #=> 'Intel 80386' + # mapping(6) + # #=> 'Intel 80386' + # mapping(62) + # #=> 'Advanced Micro Devices X86-64' + # mapping(1337) + # #=> ': 0x539' + def self.mapping(val) + case val + when EM_NONE then 'None' + when EM_386, EM_486 then 'Intel 80386' + when EM_860 then 'Intel 80860' + when EM_MIPS then 'MIPS R3000' + when EM_PPC then 'PowerPC' + when EM_PPC64 then 'PowerPC64' + when EM_ARM then 'ARM' + when EM_IA_64 then 'Intel IA-64' + when EM_AARCH64 then 'AArch64' + when EM_X86_64 then 'Advanced Micro Devices X86-64' + else format(': 0x%x', val) + end + end + end + include EM + + # This module defines ELF file types. + module ET + ET_NONE = 0 # no file type + ET_REL = 1 # relocatable file + ET_EXEC = 2 # executable file + ET_DYN = 3 # shared object + ET_CORE = 4 # core file + # Return the type name according to +e_type+ in ELF file header. + # @return [String] Type in string format. + def self.mapping(type) + case type + when Constants::ET_NONE then 'NONE' + when Constants::ET_REL then 'REL' + when Constants::ET_EXEC then 'EXEC' + when Constants::ET_DYN then 'DYN' + when Constants::ET_CORE then 'CORE' + else '' + end + end + end + include ET + + # Program header permission flags, records bitwise OR value in +p_flags+. + module PF + PF_X = 1 # executable + PF_W = 2 # writable + PF_R = 4 # readable + end + include PF + + # Program header types, records in +p_type+. + module PT + PT_NULL = 0 # null segment + PT_LOAD = 1 # segment to be load + PT_DYNAMIC = 2 # dynamic tags + PT_INTERP = 3 # interpreter, same as .interp section + PT_NOTE = 4 # same as .note* section + PT_SHLIB = 5 # reserved + PT_PHDR = 6 # where program header starts + PT_TLS = 7 # thread local storage segment + + PT_LOOS = 0x60000000 # OS-specific + PT_GNU_EH_FRAME = 0x6474e550 # for exception handler + PT_GNU_STACK = 0x6474e551 # permission of stack + PT_GNU_RELRO = 0x6474e552 # read only after relocation + PT_GNU_PROPERTY = 0x6474e553 # GNU property + PT_GNU_MBIND_HI = 0x6474f554 # Mbind segments (upper bound) + PT_GNU_MBIND_LO = 0x6474e555 # Mbind segments (lower bound) + PT_OPENBSD_RANDOMIZE = 0x65a3dbe6 # Fill with random data + PT_OPENBSD_WXNEEDED = 0x65a3dbe7 # Program does W^X violations + PT_OPENBSD_BOOTDATA = 0x65a41be6 # Section for boot arguments + PT_HIOS = 0x6fffffff # OS-specific + + # Values between {PT_LOPROC} and {PT_HIPROC} are reserved for processor-specific semantics. + PT_LOPROC = 0x70000000 + + PT_ARM_ARCHEXT = 0x70000000 # platform architecture compatibility information + PT_ARM_EXIDX = 0x70000001 # exception unwind tables + + PT_MIPS_REGINFO = 0x70000000 # register usage information + PT_MIPS_RTPROC = 0x70000001 # runtime procedure table + PT_MIPS_OPTIONS = 0x70000002 # +.MIPS.options+ section + PT_MIPS_ABIFLAGS = 0x70000003 # +.MIPS.abiflags+ section + + PT_AARCH64_ARCHEXT = 0x70000000 # platform architecture compatibility information + PT_AARCH64_UNWIND = 0x70000001 # exception unwind tables + + PT_S390_PGSTE = 0x70000000 # 4k page table size + + PT_HIPROC = 0x7fffffff # see {PT_LOPROC} + end + include PT + + # Special indices to section. These are used when there is no valid index to section header. + # The meaning of these values is left upto the embedding header. + module SHN + SHN_UNDEF = 0 # undefined section + SHN_LORESERVE = 0xff00 # start of reserved indices + + # Values between {SHN_LOPROC} and {SHN_HIPROC} are reserved for processor-specific semantics. + SHN_LOPROC = 0xff00 + + SHN_MIPS_ACOMMON = 0xff00 # defined and allocated common symbol + SHN_MIPS_TEXT = 0xff01 # defined and allocated text symbol + SHN_MIPS_DATA = 0xff02 # defined and allocated data symbol + SHN_MIPS_SCOMMON = 0xff03 # small common symbol + SHN_MIPS_SUNDEFINED = 0xff04 # small undefined symbol + + SHN_X86_64_LCOMMON = 0xff02 # large common symbol + + SHN_HIPROC = 0xff1f # see {SHN_LOPROC} + + # Values between {SHN_LOOS} and {SHN_HIOS} are reserved for operating system-specific semantics. + SHN_LOOS = 0xff20 + SHN_HIOS = 0xff3f # see {SHN_LOOS} + SHN_ABS = 0xfff1 # specifies absolute values for the corresponding reference + SHN_COMMON = 0xfff2 # symbols defined relative to this section are common symbols + SHN_XINDEX = 0xffff # escape value indicating that the actual section header index is too large to fit + SHN_HIRESERVE = 0xffff # end of reserved indices + end + include SHN + + # Section flag mask types, records in +sh_flag+. + module SHF + SHF_WRITE = (1 << 0) # Writable + SHF_ALLOC = (1 << 1) # Occupies memory during execution + SHF_EXECINSTR = (1 << 2) # Executable + SHF_MERGE = (1 << 4) # Might be merged + SHF_STRINGS = (1 << 5) # Contains nul-terminated strings + SHF_INFO_LINK = (1 << 6) # `sh_info' contains SHT index + SHF_LINK_ORDER = (1 << 7) # Preserve order after combining + SHF_OS_NONCONFORMING = (1 << 8) # Non-standard OS specific handling required + SHF_GROUP = (1 << 9) # Section is member of a group. + SHF_TLS = (1 << 10) # Section hold thread-local data. + SHF_COMPRESSED = (1 << 11) # Section with compressed data. + SHF_MASKOS = 0x0ff00000 # OS-specific. + SHF_MASKPROC = 0xf0000000 # Processor-specific + SHF_GNU_RETAIN = (1 << 21) # Not to be GCed by linker. + SHF_GNU_MBIND = (1 << 24) # Mbind section + SHF_ORDERED = (1 << 30) # Special ordering requirement + SHF_EXCLUDE = (1 << 31) # Section is excluded unless referenced or allocated (Solaris). + end + include SHF + + # Section header types, records in +sh_type+. + module SHT + SHT_NULL = 0 # null section + SHT_PROGBITS = 1 # information defined by program itself + SHT_SYMTAB = 2 # symbol table section + SHT_STRTAB = 3 # string table section + SHT_RELA = 4 # relocation with addends + SHT_HASH = 5 # symbol hash table + SHT_DYNAMIC = 6 # information of dynamic linking + SHT_NOTE = 7 # section for notes + SHT_NOBITS = 8 # section occupies no space + SHT_REL = 9 # relocation + SHT_SHLIB = 10 # reserved + SHT_DYNSYM = 11 # symbols for dynamic + SHT_INIT_ARRAY = 14 # array of initialization functions + SHT_FINI_ARRAY = 15 # array of termination functions + SHT_PREINIT_ARRAY = 16 # array of functions that are invoked before all other initialization functions + SHT_GROUP = 17 # section group + SHT_SYMTAB_SHNDX = 18 # indices for SHN_XINDEX entries + SHT_RELR = 19 # RELR relative relocations + + # Values between {SHT_LOOS} and {SHT_HIOS} are reserved for operating system-specific semantics. + SHT_LOOS = 0x60000000 + SHT_GNU_INCREMENTAL_INPUTS = 0x6fff4700 # incremental build data + SHT_GNU_INCREMENTAL_SYMTAB = 0x6fff4701 # incremental build data + SHT_GNU_INCREMENTAL_RELOCS = 0x6fff4702 # incremental build data + SHT_GNU_INCREMENTAL_GOT_PLT = 0x6fff4703 # incremental build data + SHT_GNU_ATTRIBUTES = 0x6ffffff5 # object attributes + SHT_GNU_HASH = 0x6ffffff6 # GNU style symbol hash table + SHT_GNU_LIBLIST = 0x6ffffff7 # list of prelink dependencies + SHT_SUNW_verdef = 0x6ffffffd # versions defined by file + SHT_GNU_verdef = 0x6ffffffd # versions defined by file + SHT_SUNW_verneed = 0x6ffffffe # versions needed by file + SHT_GNU_verneed = 0x6ffffffe # versions needed by file + SHT_SUNW_versym = 0x6fffffff # symbol versions + SHT_GNU_versym = 0x6fffffff # symbol versions + SHT_HIOS = 0x6fffffff # see {SHT_LOOS} + + # Values between {SHT_LOPROC} and {SHT_HIPROC} are reserved for processor-specific semantics. + SHT_LOPROC = 0x70000000 + + SHT_SPARC_GOTDATA = 0x70000000 # :nodoc: + + SHT_ARM_EXIDX = 0x70000001 # exception index table + SHT_ARM_PREEMPTMAP = 0x70000002 # BPABI DLL dynamic linking pre-emption map + SHT_ARM_ATTRIBUTES = 0x70000003 # object file compatibility attributes + SHT_ARM_DEBUGOVERLAY = 0x70000004 # support for debugging overlaid programs + SHT_ARM_OVERLAYSECTION = 0x70000005 # support for debugging overlaid programs + + SHT_X86_64_UNWIND = 0x70000001 # x86_64 unwind information + + SHT_MIPS_LIBLIST = 0x70000000 # set of dynamic shared objects + SHT_MIPS_MSYM = 0x70000001 # :nodoc: + SHT_MIPS_CONFLICT = 0x70000002 # list of symbols whose definitions conflict with shared objects + SHT_MIPS_GPTAB = 0x70000003 # global pointer table + SHT_MIPS_UCODE = 0x70000004 # microcode information + SHT_MIPS_DEBUG = 0x70000005 # register usage information + SHT_MIPS_REGINFO = 0x70000006 # section contains register usage information + SHT_MIPS_PACKAGE = 0x70000007 # :nodoc: + SHT_MIPS_PACKSYM = 0x70000008 # :nodoc: + SHT_MIPS_RELD = 0x70000009 # :nodoc: + SHT_MIPS_IFACE = 0x7000000b # interface information + SHT_MIPS_CONTENT = 0x7000000c # description of contents of another section + SHT_MIPS_OPTIONS = 0x7000000d # miscellaneous options + SHT_MIPS_SHDR = 0x70000010 # :nodoc: + SHT_MIPS_FDESC = 0x70000011 # :nodoc: + SHT_MIPS_EXTSYM = 0x70000012 # :nodoc: + SHT_MIPS_DENSE = 0x70000013 # :nodoc: + SHT_MIPS_PDESC = 0x70000014 # :nodoc: + SHT_MIPS_LOCSYM = 0x70000015 # :nodoc: + SHT_MIPS_AUXSYM = 0x70000016 # :nodoc: + SHT_MIPS_OPTSYM = 0x70000017 # :nodoc: + SHT_MIPS_LOCSTR = 0x70000018 # :nodoc: + SHT_MIPS_LINE = 0x70000019 # :nodoc: + SHT_MIPS_RFDESC = 0x7000001a # :nodoc: + SHT_MIPS_DELTASYM = 0x7000001b # delta C++ symbol table + SHT_MIPS_DELTAINST = 0x7000001c # delta C++ instance table + SHT_MIPS_DELTACLASS = 0x7000001d # delta C++ class table + SHT_MIPS_DWARF = 0x7000001e # DWARF debugging section + SHT_MIPS_DELTADECL = 0x7000001f # delta C++ declarations + SHT_MIPS_SYMBOL_LIB = 0x70000020 # list of libraries the binary depends on + SHT_MIPS_EVENTS = 0x70000021 # events section + SHT_MIPS_TRANSLATE = 0x70000022 # :nodoc: + SHT_MIPS_PIXIE = 0x70000023 # :nodoc: + SHT_MIPS_XLATE = 0x70000024 # address translation table + SHT_MIPS_XLATE_DEBUG = 0x70000025 # SGI internal address translation table + SHT_MIPS_WHIRL = 0x70000026 # intermediate code + SHT_MIPS_EH_REGION = 0x70000027 # C++ exception handling region info + SHT_MIPS_PDR_EXCEPTION = 0x70000029 # runtime procedure descriptor table exception information + SHT_MIPS_ABIFLAGS = 0x7000002a # ABI related flags + SHT_MIPS_XHASH = 0x7000002b # GNU style symbol hash table with xlat + + SHT_AARCH64_ATTRIBUTES = 0x70000003 # :nodoc: + + SHT_CSKY_ATTRIBUTES = 0x70000001 # object file compatibility attributes + + SHT_ORDERED = 0x7fffffff # :nodoc: + + SHT_HIPROC = 0x7fffffff # see {SHT_LOPROC} + + # Values between {SHT_LOUSER} and {SHT_HIUSER} are reserved for application programs. + SHT_LOUSER = 0x80000000 + SHT_HIUSER = 0xffffffff # see {SHT_LOUSER} + end + include SHT + + # Symbol binding from Sym st_info field. + module STB + STB_LOCAL = 0 # Local symbol + STB_GLOBAL = 1 # Global symbol + STB_WEAK = 2 # Weak symbol + STB_NUM = 3 # Number of defined types. + STB_LOOS = 10 # Start of OS-specific + STB_GNU_UNIQUE = 10 # Unique symbol. + STB_HIOS = 12 # End of OS-specific + STB_LOPROC = 13 # Start of processor-specific + STB_HIPROC = 15 # End of processor-specific + end + include STB + + # Symbol types from Sym st_info field. + module STT + STT_NOTYPE = 0 # Symbol type is unspecified + STT_OBJECT = 1 # Symbol is a data object + STT_FUNC = 2 # Symbol is a code object + STT_SECTION = 3 # Symbol associated with a section + STT_FILE = 4 # Symbol's name is file name + STT_COMMON = 5 # Symbol is a common data object + STT_TLS = 6 # Symbol is thread-local data object + STT_NUM = 7 # Deprecated. + STT_RELC = 8 # Complex relocation expression + STT_SRELC = 9 # Signed Complex relocation expression + + # GNU extension: symbol value points to a function which is called + # at runtime to determine the final value of the symbol. + STT_GNU_IFUNC = 10 + + STT_LOOS = 10 # Start of OS-specific + STT_HIOS = 12 # End of OS-specific + STT_LOPROC = 13 # Start of processor-specific + STT_HIPROC = 15 # End of processor-specific + + # The section type that must be used for register symbols on + # Sparc. These symbols initialize a global register. + STT_SPARC_REGISTER = 13 + + # ARM: a THUMB function. This is not defined in ARM ELF Specification but + # used by the GNU tool-chain. + STT_ARM_TFUNC = 13 + STT_ARM_16BIT = 15 # ARM: a THUMB label. + end + include STT + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/dynamic.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/dynamic.rb new file mode 100644 index 0000000000..3295504cb5 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/dynamic.rb @@ -0,0 +1,178 @@ +# frozen_string_literal: true + +module ELFTools + # Define common methods for dynamic sections and dynamic segments. + # + # @note + # This module can only be included by {ELFTools::Sections::DynamicSection} + # and {ELFTools::Segments::DynamicSegment} because methods here assume some + # attributes exist. + module Dynamic + # Iterate all tags. + # + # @note + # This method assume the following methods already exist: + # header + # tag_start + # @yieldparam [ELFTools::Dynamic::Tag] tag + # @return [Enumerator, Array] + # If block is not given, an enumerator will be returned. + # Otherwise, return array of tags. + def each_tags(&block) + return enum_for(:each_tags) unless block_given? + + arr = [] + 0.step do |i| + tag = tag_at(i).tap(&block) + arr << tag + break if tag.header.d_tag == ELFTools::Constants::DT_NULL + end + arr + end + + # Use {#tags} to get all tags. + # @return [Array] + # Array of tags. + def tags + @tags ||= each_tags.to_a + end + + # Get a tag of specific type. + # @param [Integer, Symbol, String] type + # Constant value, symbol, or string of type + # is acceptable. See examples for more information. + # @return [ELFTools::Dynamic::Tag] The desired tag. + # @example + # dynamic = elf.segment_by_type(:dynamic) + # # type as integer + # dynamic.tag_by_type(0) # the null tag + # #=> #0, :d_val=>0}> + # dynamic.tag_by_type(ELFTools::Constants::DT_NULL) + # #=> #0, :d_val=>0}> + # + # # symbol + # dynamic.tag_by_type(:null) + # #=> #0, :d_val=>0}> + # dynamic.tag_by_type(:pltgot) + # #=> #3, :d_val=>6295552}> + # + # # string + # dynamic.tag_by_type('null') + # #=> #0, :d_val=>0}> + # dynamic.tag_by_type('DT_PLTGOT') + # #=> #3, :d_val=>6295552}> + def tag_by_type(type) + type = Util.to_constant(Constants::DT, type) + each_tags.find { |tag| tag.header.d_tag == type } + end + + # Get tags of specific type. + # @param [Integer, Symbol, String] type + # Constant value, symbol, or string of type + # is acceptable. See examples for more information. + # @return [Array] The desired tags. + # + # @see #tag_by_type + def tags_by_type(type) + type = Util.to_constant(Constants::DT, type) + each_tags.select { |tag| tag.header.d_tag == type } + end + + # Get the +n+-th tag. + # + # Tags are lazy loaded. + # @note + # This method assume the following methods already exist: + # header + # tag_start + # @note + # We cannot do bound checking of +n+ here since the only way to get size + # of tags is calling +tags.size+. + # @param [Integer] n The index. + # @return [ELFTools::Dynamic::Tag] The desired tag. + def tag_at(n) + return if n.negative? + + @tag_at_map ||= {} + return @tag_at_map[n] if @tag_at_map[n] + + dyn = Structs::ELF_Dyn.new(endian: endian) + dyn.elf_class = header.elf_class + stream.pos = tag_start + n * dyn.num_bytes + dyn.offset = stream.pos + @tag_at_map[n] = Tag.new(dyn.read(stream), stream, method(:str_offset)) + end + + private + + def endian + header.class.self_endian + end + + # Get the DT_STRTAB's +d_val+ offset related to file. + def str_offset + # TODO: handle DT_STRTAB not exitsts. + @str_offset ||= @offset_from_vma.call(tag_by_type(:strtab).header.d_val.to_i) + end + + # A tag class. + class Tag + attr_reader :header # @return [ELFTools::Structs::ELF_Dyn] The dynamic tag header. + attr_reader :stream # @return [#pos=, #read] Streaming object. + + # Instantiate a {ELFTools::Dynamic::Tag} object. + # @param [ELF_Dyn] header The dynamic tag header. + # @param [#pos=, #read] stream Streaming object. + # @param [Method] str_offset + # Call this method to get the string offset related + # to file. + def initialize(header, stream, str_offset) + @header = header + @stream = stream + @str_offset = str_offset + end + + # Some dynamic have name. + TYPE_WITH_NAME = [Constants::DT_NEEDED, + Constants::DT_SONAME, + Constants::DT_RPATH, + Constants::DT_RUNPATH].freeze + # Return the content of this tag records. + # + # For normal tags, this method just return + # +header.d_val+. For tags with +header.d_val+ + # in meaning of string offset (e.g. DT_NEEDED), this method would + # return the string it specified. + # Tags with type in {TYPE_WITH_NAME} are those tags with name. + # @return [Integer, String] The content this tag records. + # @example + # dynamic = elf.segment_by_type(:dynamic) + # dynamic.tag_by_type(:init).value + # #=> 4195600 # 0x400510 + # dynamic.tag_by_type(:needed).value + # #=> 'libc.so.6' + def value + name || header.d_val.to_i + end + + # Is this tag has a name? + # + # The criteria here is if this tag's type is in {TYPE_WITH_NAME}. + # @return [Boolean] Is this tag has a name. + def name? + TYPE_WITH_NAME.include?(header.d_tag) + end + + # Return the name of this tag. + # + # Only tags with name would return a name. + # Others would return +nil+. + # @return [String, nil] The name. + def name + return nil unless name? + + Util.cstring(stream, @str_offset.call + header.d_val.to_i) + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/elf_file.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/elf_file.rb new file mode 100644 index 0000000000..3170b998ba --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/elf_file.rb @@ -0,0 +1,377 @@ +# frozen_string_literal: true + +require 'elftools/constants' +require 'elftools/exceptions' +require 'elftools/lazy_array' +require 'elftools/sections/sections' +require 'elftools/segments/segments' +require 'elftools/structs' + +module ELFTools + # The main class for using elftools. + class ELFFile + attr_reader :stream # @return [#pos=, #read] The +File+ object. + attr_reader :elf_class # @return [Integer] 32 or 64. + attr_reader :endian # @return [Symbol] +:little+ or +:big+. + + # Instantiate an {ELFFile} object. + # + # @param [#pos=, #read] stream + # The +File+ object to be fetch information from. + # @example + # ELFFile.new(File.open('/bin/cat')) + # #=> #> + def initialize(stream) + @stream = stream + # always set binmode if stream is an IO object. + @stream.binmode if @stream.respond_to?(:binmode) + identify # fetch the most basic information + end + + # Return the file header. + # + # Lazy loading. + # @return [ELFTools::Structs::ELF_Ehdr] The header. + def header + return @header if defined?(@header) + + stream.pos = 0 + @header = Structs::ELF_Ehdr.new(endian: endian, offset: stream.pos) + @header.elf_class = elf_class + @header.read(stream) + end + + # Return the BuildID of ELF. + # @return [String, nil] + # BuildID in hex form will be returned. + # +nil+ is returned if the .note.gnu.build-id section + # is not found. + # @example + # elf.build_id + # #=> '73ab62cb7bc9959ce053c2b711322158708cdc07' + def build_id + section = section_by_name('.note.gnu.build-id') + return nil if section.nil? + + note = section.notes.first + return nil if note.nil? + + note.desc.unpack1('H*') + end + + # Get machine architecture. + # + # Mappings of architecture can be found + # in {ELFTools::Constants::EM.mapping}. + # @return [String] + # Name of architecture. + # @example + # elf.machine + # #=> 'Advanced Micro Devices X86-64' + def machine + ELFTools::Constants::EM.mapping(header.e_machine) + end + + # Return the ELF type according to +e_type+. + # @return [String] Type in string format. + # @example + # ELFFile.new(File.open('spec/files/libc.so.6')).elf_type + # #=> 'DYN' + # ELFFile.new(File.open('spec/files/amd64.elf')).elf_type + # #=> 'EXEC' + def elf_type + ELFTools::Constants::ET.mapping(header.e_type) + end + + #========= method about sections + + # Number of sections in this file. + # @return [Integer] The desired number. + # @example + # elf.num_sections + # #=> 29 + def num_sections + header.e_shnum + end + + # Acquire the section named as +name+. + # @param [String] name The desired section name. + # @return [ELFTools::Sections::Section, nil] The target section. + # @example + # elf.section_by_name('.note.gnu.build-id') + # #=> # + # elf.section_by_name('') + # #=> # + # elf.section_by_name('no such section') + # #=> nil + def section_by_name(name) + each_sections.find { |sec| sec.name == name } + end + + # Iterate all sections. + # + # All sections are lazy loading, the section + # only be created whenever accessing it. + # This method is useful for {#section_by_name} + # since not all sections need to be created. + # @yieldparam [ELFTools::Sections::Section] section A section. + # @yieldreturn [void] + # @return [Enumerator, Array] + # As +Array#each+, if block is not given, a enumerator will be returned, + # otherwise, the whole sections will be returned. + def each_sections(&block) + return enum_for(:each_sections) unless block_given? + + Array.new(num_sections) do |i| + section_at(i).tap(&block) + end + end + + # Simply use {#sections} to get all sections. + # @return [Array] + # Whole sections. + def sections + each_sections.to_a + end + + # Acquire the +n+-th section, 0-based. + # + # Sections are lazy loaded. + # @param [Integer] n The index. + # @return [ELFTools::Sections::Section, nil] + # The target section. + # If +n+ is out of bound, +nil+ is returned. + def section_at(n) + @sections ||= LazyArray.new(num_sections, &method(:create_section)) + @sections[n] + end + + # Fetch all sections with specific type. + # + # The available types are listed in {ELFTools::Constants::PT}. + # This method accept giving block. + # @param [Integer, Symbol, String] type + # The type needed, similar format as {#segment_by_type}. + # @yieldparam [ELFTools::Sections::Section] section A section in specific type. + # @yieldreturn [void] + # @return [Array] The target sections. + # @example + # elf = ELFTools::ELFFile.new(File.open('spec/files/amd64.elf')) + # elf.sections_by_type(:rela) + # #=> [#, + # # #] + def sections_by_type(type, &block) + type = Util.to_constant(Constants::SHT, type) + Util.select_by_type(each_sections, type, &block) + end + + # Get the string table section. + # + # This section is acquired by using the +e_shstrndx+ + # in ELF header. + # @return [ELFTools::Sections::StrTabSection] The desired section. + def strtab_section + section_at(header.e_shstrndx) + end + + #========= method about segments + + # Number of segments in this file. + # @return [Integer] The desited number. + def num_segments + header.e_phnum + end + + # Iterate all segments. + # + # All segments are lazy loading, the segment + # only be created whenever accessing it. + # This method is useful for {#segment_by_type} + # since not all segments need to be created. + # @yieldparam [ELFTools::Segments::Segment] segment A segment. + # @yieldreturn [void] + # @return [Array] + # Whole segments will be returned. + def each_segments(&block) + return enum_for(:each_segments) unless block_given? + + Array.new(num_segments) do |i| + segment_at(i).tap(&block) + end + end + + # Simply use {#segments} to get all segments. + # @return [Array] + # Whole segments. + def segments + each_segments.to_a + end + + # Get the first segment with +p_type=type+. + # The available types are listed in {ELFTools::Constants::PT}. + # + # @note + # This method will return the first segment found, + # to found all segments with specific type you can use {#segments_by_type}. + # @param [Integer, Symbol, String] type + # See examples for clear usage. + # @return [ELFTools::Segments::Segment] The target segment. + # @example + # # type as an integer + # elf.segment_by_type(ELFTools::Constants::PT_NOTE) + # #=> # + # + # elf.segment_by_type(4) # PT_NOTE + # #=> # + # + # # type as a symbol + # elf.segment_by_type(:PT_NOTE) + # #=> # + # + # # you can do this + # elf.segment_by_type(:note) # will be transformed into `PT_NOTE` + # #=> # + # + # # type as a string + # elf.segment_by_type('PT_NOTE') + # #=> # + # + # # this is ok + # elf.segment_by_type('note') # will be tranformed into `PT_NOTE` + # #=> # + # @example + # elf.segment_by_type(1337) + # # ArgumentError: No constants in Constants::PT is 1337 + # + # elf.segment_by_type('oao') + # # ArgumentError: No constants in Constants::PT named "PT_OAO" + # @example + # elf.segment_by_type(0) + # #=> nil # no such segment exists + def segment_by_type(type) + type = Util.to_constant(Constants::PT, type) + each_segments.find { |seg| seg.header.p_type == type } + end + + # Fetch all segments with specific type. + # + # If you want to find only one segment, + # use {#segment_by_type} instead. + # This method accept giving block. + # @param [Integer, Symbol, String] type + # The type needed, same format as {#segment_by_type}. + # @yieldparam [ELFTools::Segments::Segment] segment A segment in specific type. + # @yieldreturn [void] + # @return [Array] The target segments. + def segments_by_type(type, &block) + type = Util.to_constant(Constants::PT, type) + Util.select_by_type(each_segments, type, &block) + end + + # Acquire the +n+-th segment, 0-based. + # + # Segments are lazy loaded. + # @param [Integer] n The index. + # @return [ELFTools::Segments::Segment, nil] + # The target segment. + # If +n+ is out of bound, +nil+ is returned. + def segment_at(n) + @segments ||= LazyArray.new(num_segments, &method(:create_segment)) + @segments[n] + end + + # Get the offset related to file, given virtual memory address. + # + # This method should work no matter ELF is a PIE or not. + # This method refers from (actually equals to) binutils/readelf.c#offset_from_vma. + # @param [Integer] vma The virtual address to be queried. + # @return [Integer] Related file offset. + # @example + # elf = ELFTools::ELFFile.new(File.open('/bin/cat')) + # elf.offset_from_vma(0x401337) + # #=> 4919 # 0x1337 + def offset_from_vma(vma, size = 0) + segments_by_type(:load) do |seg| + return seg.vma_to_offset(vma) if seg.vma_in?(vma, size) + end + end + + # The patch status. + # @return [Hash{Integer => String}] + def patches + patch = {} + loaded_headers.each do |header| + header.patches.each do |key, val| + patch[key + header.offset] = val + end + end + patch + end + + # Apply patches and save as +filename+. + # + # @param [String] filename + # @return [void] + def save(filename) + stream.pos = 0 + all = stream.read.force_encoding('ascii-8bit') + patches.each do |pos, val| + all[pos, val.size] = val + end + File.binwrite(filename, all) + end + + private + + # bad idea.. + def loaded_headers + explore = lambda do |obj| + return obj if obj.is_a?(::ELFTools::Structs::ELFStruct) + return obj.map(&explore) if obj.is_a?(Array) + + obj.instance_variables.map do |s| + explore.call(obj.instance_variable_get(s)) + end + end + explore.call(self).flatten + end + + def identify + stream.pos = 0 + magic = stream.read(4) + raise ELFMagicError, "Invalid magic number #{magic.inspect}" unless magic == Constants::ELFMAG + + ei_class = stream.read(1).ord + @elf_class = { + 1 => 32, + 2 => 64 + }[ei_class] + raise ELFClassError, format('Invalid EI_CLASS "\x%02x"', ei_class) if elf_class.nil? + + ei_data = stream.read(1).ord + @endian = { + 1 => :little, + 2 => :big + }[ei_data] + raise ELFDataError, format('Invalid EI_DATA "\x%02x"', ei_data) if endian.nil? + end + + def create_section(n) + stream.pos = header.e_shoff + n * header.e_shentsize + shdr = Structs::ELF_Shdr.new(endian: endian, offset: stream.pos) + shdr.elf_class = elf_class + shdr.read(stream) + Sections::Section.create(shdr, stream, + offset_from_vma: method(:offset_from_vma), + strtab: method(:strtab_section), + section_at: method(:section_at)) + end + + def create_segment(n) + stream.pos = header.e_phoff + n * header.e_phentsize + phdr = Structs::ELF_Phdr[elf_class].new(endian: endian, offset: stream.pos) + phdr.elf_class = elf_class + Segments::Segment.create(phdr.read(stream), stream, offset_from_vma: method(:offset_from_vma)) + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/exceptions.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/exceptions.rb new file mode 100644 index 0000000000..1d516ff22b --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/exceptions.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +module ELFTools + # Being raised when parsing error. + class ELFError < StandardError; end + + # Raised on invalid ELF magic. + class ELFMagicError < ELFError; end + + # Raised on invalid ELF class (EI_CLASS). + class ELFClassError < ELFError; end + + # Raised on invalid ELF data encoding (EI_DATA). + class ELFDataError < ELFError; end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/lazy_array.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/lazy_array.rb new file mode 100644 index 0000000000..ecb300d9bb --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/lazy_array.rb @@ -0,0 +1,49 @@ +# frozen_string_literal: true + +require 'delegate' + +module ELFTools + # A helper class for {ELFTools} easy to implement + # 'lazy loading' objects. + # Mainly used when loading sections, segments, and + # symbols. + class LazyArray < SimpleDelegator + # Instantiate a {LazyArray} object. + # @param [Integer] size + # The size of array. + # @yieldparam [Integer] i + # Needs the +i+-th element. + # @yieldreturn [Object] + # Value of the +i+-th element. + # @example + # arr = LazyArray.new(10) { |i| p "calc #{i}"; i * i } + # p arr[2] + # # "calc 2" + # # 4 + # + # p arr[3] + # # "calc 3" + # # 9 + # + # p arr[3] + # # 9 + def initialize(size, &block) + super(Array.new(size)) + @block = block + end + + # To access elements like a normal array. + # + # Elements are lazy loaded at the first time + # access it. + # @return [Object] + # The element, returned type is the + # return type of block given in {#initialize}. + def [](i) + # XXX: support negative index? + return nil unless i.between?(0, __getobj__.size - 1) + + __getobj__[i] ||= @block.call(i) + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/note.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/note.rb new file mode 100644 index 0000000000..5eae0338f7 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/note.rb @@ -0,0 +1,125 @@ +# frozen_string_literal: true + +require 'elftools/structs' +require 'elftools/util' + +module ELFTools + # Since both note sections and note segments refer to notes, this module + # defines common methods for {ELFTools::Sections::NoteSection} and + # {ELFTools::Segments::NoteSegment}. + # + # @note + # This module can only be included in {ELFTools::Sections::NoteSection} and + # {ELFTools::Segments::NoteSegment} since some methods here assume some + # attributes already exist. + module Note + # Since size of {ELFTools::Structs::ELF_Nhdr} will not change no matter in + # what endian and what arch, we can do this here. This value should equal + # to 12. + SIZE_OF_NHDR = Structs::ELF_Nhdr.new(endian: :little).num_bytes + + # Iterate all notes in a note section or segment. + # + # Structure of notes are: + # +---------------+ + # | Note 1 header | + # +---------------+ + # | Note 1 name | + # +---------------+ + # | Note 1 desc | + # +---------------+ + # | Note 2 header | + # +---------------+ + # | ... | + # +---------------+ + # + # @note + # This method assume following methods exist: + # stream + # note_start + # note_total_size + # @return [Enumerator, Array] + # If block is not given, an enumerator will be returned. + # Otherwise, return the array of notes. + def each_notes + return enum_for(:each_notes) unless block_given? + + @notes_offset_map ||= {} + cur = note_start + notes = [] + while cur < note_start + note_total_size + stream.pos = cur + @notes_offset_map[cur] ||= create_note(cur) + note = @notes_offset_map[cur] + # name and desc size needs to be 4-bytes align + name_size = Util.align(note.header.n_namesz, 2) + desc_size = Util.align(note.header.n_descsz, 2) + cur += SIZE_OF_NHDR + name_size + desc_size + notes << note + yield note + end + notes + end + + # Simply +#notes+ to get all notes. + # @return [Array] + # Whole notes. + def notes + each_notes.to_a + end + + private + + # Get the endian. + # + # @note This method assume method +header+ exists. + # @return [Symbol] +:little+ or +:big+. + def endian + header.class.self_endian + end + + def create_note(cur) + nhdr = Structs::ELF_Nhdr.new(endian: endian, offset: stream.pos).read(stream) + ELFTools::Note::Note.new(nhdr, stream, cur) + end + + # Class of a note. + class Note + attr_reader :header # @return [ELFTools::Structs::ELF_Nhdr] Note header. + attr_reader :stream # @return [#pos=, #read] Streaming object. + attr_reader :offset # @return [Integer] Address of this note start, includes note header. + + # Instantiate a {ELFTools::Note::Note} object. + # @param [ELF_Nhdr] header The note header. + # @param [#pos=, #read] stream Streaming object. + # @param [Integer] offset + # Start address of this note, includes the header. + def initialize(header, stream, offset) + @header = header + @stream = stream + @offset = offset + end + + # Name of this note. + # @return [String] The name. + def name + return @name if defined?(@name) + + stream.pos = @offset + SIZE_OF_NHDR + @name = stream.read(header.n_namesz)[0..-2] + end + + # Description of this note. + # @return [String] The description. + def desc + return @desc if instance_variable_defined?(:@desc) + + stream.pos = @offset + SIZE_OF_NHDR + Util.align(header.n_namesz, 2) + @desc = stream.read(header.n_descsz) + end + + # If someone likes to use full name. + alias description desc + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/sections/dynamic_section.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/sections/dynamic_section.rb new file mode 100644 index 0000000000..d38b04b353 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/sections/dynamic_section.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +require 'elftools/dynamic' +require 'elftools/sections/section' + +module ELFTools + module Sections + # Class for dynamic table section. + # + # This section should always be named .dynamic. + # This class knows how to get the list of dynamic tags. + class DynamicSection < Section + include ELFTools::Dynamic + + # Get the start address of tags. + # @return [Integer] Start address of tags. + def tag_start + header.sh_offset + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/sections/note_section.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/sections/note_section.rb new file mode 100644 index 0000000000..111708ef80 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/sections/note_section.rb @@ -0,0 +1,27 @@ +# frozen_string_literal: true + +require 'elftools/note' +require 'elftools/sections/section' + +module ELFTools + module Sections + # Class of note section. + # Note section records notes + class NoteSection < Section + # Load note related methods. + include ELFTools::Note + + # Address offset of notes start. + # @return [Integer] The offset. + def note_start + header.sh_offset + end + + # The total size of notes in this section. + # @return [Integer] The size. + def note_total_size + header.sh_size + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/sections/null_section.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/sections/null_section.rb new file mode 100644 index 0000000000..e71172a2be --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/sections/null_section.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true + +require 'elftools/sections/section' + +module ELFTools + module Sections + # Class of null section. + # Null section is for specific the end + # of linked list (+sh_link+) between sections. + class NullSection < Section + # Is this a null section? + # @return [Boolean] Yes it is. + def null? + true + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/sections/relocation_section.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/sections/relocation_section.rb new file mode 100644 index 0000000000..a87780bddf --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/sections/relocation_section.rb @@ -0,0 +1,109 @@ +# frozen_string_literal: true + +require 'elftools/constants' +require 'elftools/sections/section' +require 'elftools/structs' + +module ELFTools + module Sections + # Class of note section. + # Note section records notes + class RelocationSection < Section + # Is this relocation a RELA or REL type. + # @return [Boolean] If is RELA. + def rela? + header.sh_type == Constants::SHT_RELA + end + + # Number of relocations in this section. + # @return [Integer] The number. + def num_relocations + header.sh_size / header.sh_entsize + end + + # Acquire the +n+-th relocation, 0-based. + # + # relocations are lazy loaded. + # @param [Integer] n The index. + # @return [ELFTools::Relocation, nil] + # The target relocation. + # If +n+ is out of bound, +nil+ is returned. + def relocation_at(n) + @relocations ||= LazyArray.new(num_relocations, &method(:create_relocation)) + @relocations[n] + end + + # Iterate all relocations. + # + # All relocations are lazy loading, the relocation + # only be created whenever accessing it. + # @yieldparam [ELFTools::Relocation] rel A relocation object. + # @yieldreturn [void] + # @return [Enumerator, Array] + # If block is not given, an enumerator will be returned. + # Otherwise, the whole relocations will be returned. + def each_relocations(&block) + return enum_for(:each_relocations) unless block_given? + + Array.new(num_relocations) do |i| + relocation_at(i).tap(&block) + end + end + + # Simply use {#relocations} to get all relocations. + # @return [Array] + # Whole relocations. + def relocations + each_relocations.to_a + end + + private + + def create_relocation(n) + stream.pos = header.sh_offset + n * header.sh_entsize + klass = rela? ? Structs::ELF_Rela : Structs::ELF_Rel + rel = klass.new(endian: header.class.self_endian, offset: stream.pos) + rel.elf_class = header.elf_class + rel.read(stream) + Relocation.new(rel, stream) + end + end + end + + # A relocation entry. + # + # Can be either a REL or RELA relocation. + # XXX: move this to an independent file? + class Relocation + attr_reader :header # @return [ELFTools::Structs::ELF_Rel, ELFTools::Structs::ELF_Rela] Rel(a) header. + attr_reader :stream # @return [#pos=, #read] Streaming object. + + # Instantiate a {Relocation} object. + def initialize(header, stream) + @header = header + @stream = stream + end + + # +r_info+ contains sym and type, use two methods + # to access them easier. + # @return [Integer] sym infor. + def r_info_sym + header.r_info >> mask_bit + end + alias symbol_index r_info_sym + + # +r_info+ contains sym and type, use two methods + # to access them easier. + # @return [Integer] type infor. + def r_info_type + header.r_info & ((1 << mask_bit) - 1) + end + alias type r_info_type + + private + + def mask_bit + header.elf_class == 32 ? 8 : 32 + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/sections/section.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/sections/section.rb new file mode 100644 index 0000000000..b0a835cde4 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/sections/section.rb @@ -0,0 +1,56 @@ +# frozen_string_literal: true + +require 'elftools/constants' +module ELFTools + module Sections + # Base class of sections. + class Section + attr_reader :header # @return [ELFTools::Structs::ELF_Shdr] Section header. + attr_reader :stream # @return [#pos=, #read] Streaming object. + + # Instantiate a {Section} object. + # @param [ELFTools::Structs::ELF_Shdr] header + # The section header object. + # @param [#pos=, #read] stream + # The streaming object for further dump. + # @param [ELFTools::Sections::StrTabSection, Proc] strtab + # The string table object. For fetching section names. + # If +Proc+ if given, it will call at the first + # time access +#name+. + # @param [Method] offset_from_vma + # The method to get offset of file, given virtual memory address. + def initialize(header, stream, offset_from_vma: nil, strtab: nil, **_kwargs) + @header = header + @stream = stream + @strtab = strtab + @offset_from_vma = offset_from_vma + end + + # Return +header.sh_type+ in a simplier way. + # @return [Integer] + # The type, meaning of types are defined in {Constants::SHT}. + def type + header.sh_type.to_i + end + + # Get name of this section. + # @return [String] The name. + def name + @name ||= @strtab.call.name_at(header.sh_name) + end + + # Fetch data of this section. + # @return [String] Data. + def data + stream.pos = header.sh_offset + stream.read(header.sh_size) + end + + # Is this a null section? + # @return [Boolean] No it's not. + def null? + false + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/sections/sections.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/sections/sections.rb new file mode 100644 index 0000000000..969bf4c909 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/sections/sections.rb @@ -0,0 +1,38 @@ +# frozen_string_literal: true + +# Require this file to load all sections classes. + +require 'elftools/sections/section' + +require 'elftools/sections/dynamic_section' +require 'elftools/sections/note_section' +require 'elftools/sections/null_section' +require 'elftools/sections/relocation_section' +require 'elftools/sections/str_tab_section' +require 'elftools/sections/sym_tab_section' + +module ELFTools + # Defines different types of sections in this module. + module Sections + # Class methods of {Sections::Section}. + class << Section + # Use different class according to +header.sh_type+. + # @param [ELFTools::Structs::ELF_Shdr] header Section header. + # @param [#pos=, #read] stream Streaming object. + # @return [ELFTools::Sections::Section] + # Return object dependes on +header.sh_type+. + def create(header, stream, *args, **kwargs) + klass = case header.sh_type + when Constants::SHT_DYNAMIC then DynamicSection + when Constants::SHT_NULL then NullSection + when Constants::SHT_NOTE then NoteSection + when Constants::SHT_RELA, Constants::SHT_REL then RelocationSection + when Constants::SHT_STRTAB then StrTabSection + when Constants::SHT_SYMTAB, Constants::SHT_DYNSYM then SymTabSection + else Section + end + klass.new(header, stream, *args, **kwargs) + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/sections/str_tab_section.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/sections/str_tab_section.rb new file mode 100644 index 0000000000..95736190aa --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/sections/str_tab_section.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +require 'elftools/sections/section' +require 'elftools/util' + +module ELFTools + module Sections + # Class of string table section. + # Usually for section .strtab and .dynstr, + # which record names. + class StrTabSection < Section + # Return the section or symbol name. + # @param [Integer] offset + # Usually from +shdr.sh_name+ or +sym.st_name+. + # @return [String] The name without null bytes. + def name_at(offset) + Util.cstring(stream, header.sh_offset + offset) + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/sections/sym_tab_section.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/sections/sym_tab_section.rb new file mode 100644 index 0000000000..9c5fea04bb --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/sections/sym_tab_section.rb @@ -0,0 +1,127 @@ +# frozen_string_literal: true + +require 'elftools/sections/section' + +module ELFTools + module Sections + # Class of symbol table section. + # Usually for section .symtab and .dynsym, + # which will refer to symbols in ELF file. + class SymTabSection < Section + # Instantiate a {SymTabSection} object. + # There's a +section_at+ lambda for {SymTabSection} + # to easily fetch other sections. + # @param [ELFTools::Structs::ELF_Shdr] header + # See {Section#initialize} for more information. + # @param [#pos=, #read] stream + # See {Section#initialize} for more information. + # @param [Proc] section_at + # The method for fetching other sections by index. + # This lambda should be {ELFTools::ELFFile#section_at}. + def initialize(header, stream, section_at: nil, **_kwargs) + @section_at = section_at + # For faster #symbol_by_name + super + end + + # Number of symbols. + # @return [Integer] The number. + # @example + # symtab.num_symbols + # #=> 75 + def num_symbols + header.sh_size / header.sh_entsize + end + + # Acquire the +n+-th symbol, 0-based. + # + # Symbols are lazy loaded. + # @param [Integer] n The index. + # @return [ELFTools::Sections::Symbol, nil] + # The target symbol. + # If +n+ is out of bound, +nil+ is returned. + def symbol_at(n) + @symbols ||= LazyArray.new(num_symbols, &method(:create_symbol)) + @symbols[n] + end + + # Iterate all symbols. + # + # All symbols are lazy loading, the symbol + # only be created whenever accessing it. + # This method is useful for {#symbol_by_name} + # since not all symbols need to be created. + # @yieldparam [ELFTools::Sections::Symbol] sym A symbol object. + # @yieldreturn [void] + # @return [Enumerator, Array] + # If block is not given, an enumerator will be returned. + # Otherwise return array of symbols. + def each_symbols(&block) + return enum_for(:each_symbols) unless block_given? + + Array.new(num_symbols) do |i| + symbol_at(i).tap(&block) + end + end + + # Simply use {#symbols} to get all symbols. + # @return [Array] + # The whole symbols. + def symbols + each_symbols.to_a + end + + # Get symbol by its name. + # @param [String] name + # The name of symbol. + # @return [ELFTools::Sections::Symbol] Desired symbol. + def symbol_by_name(name) + each_symbols.find { |symbol| symbol.name == name } + end + + # Return the symbol string section. + # Lazy loaded. + # @return [ELFTools::Sections::StrTabSection] The string table section. + def symstr + @symstr ||= @section_at.call(header.sh_link) + end + + private + + def create_symbol(n) + stream.pos = header.sh_offset + n * header.sh_entsize + sym = Structs::ELF_sym[header.elf_class].new(endian: header.class.self_endian, offset: stream.pos) + sym.read(stream) + Symbol.new(sym, stream, symstr: method(:symstr)) + end + end + + # Class of symbol. + # + # XXX: Should this class be defined in an independent file? + class Symbol + attr_reader :header # @return [ELFTools::Structs::ELF32_sym, ELFTools::Structs::ELF64_sym] Section header. + attr_reader :stream # @return [#pos=, #read] Streaming object. + + # Instantiate a {ELFTools::Sections::Symbol} object. + # @param [ELFTools::Structs::ELF32_sym, ELFTools::Structs::ELF64_sym] header + # The symbol header. + # @param [#pos=, #read] stream The streaming object. + # @param [ELFTools::Sections::StrTabSection, Proc] symstr + # The symbol string section. + # If +Proc+ is given, it will be called at the first time + # access {Symbol#name}. + def initialize(header, stream, symstr: nil) + @header = header + @stream = stream + @symstr = symstr + end + + # Return the symbol name. + # @return [String] The name. + def name + @name ||= @symstr.call.name_at(header.st_name) + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/segments/dynamic_segment.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/segments/dynamic_segment.rb new file mode 100644 index 0000000000..cdec0f8e9d --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/segments/dynamic_segment.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +require 'elftools/segments/segment' +require 'elftools/dynamic' + +module ELFTools + module Segments + # Class for dynamic table segment. + # + # This class knows how to get the list of dynamic tags. + class DynamicSegment < Segment + include Dynamic # rock! + # Get the start address of tags. + # @return [Integer] Start address of tags. + def tag_start + header.p_offset + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/segments/interp_segment.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/segments/interp_segment.rb new file mode 100644 index 0000000000..c45a0be7a2 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/segments/interp_segment.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +require 'elftools/segments/segment' + +module ELFTools + module Segments + # For DT_INTERP segment, knows how to get path of + # ELF interpreter. + class InterpSegment < Segment + # Get the path of interpreter. + # @return [String] Path to the interpreter. + # @example + # interp_segment.interp_name + # #=> '/lib64/ld-linux-x86-64.so.2' + def interp_name + data[0..-2] # remove last null byte + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/segments/load_segment.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/segments/load_segment.rb new file mode 100644 index 0000000000..ab41752d15 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/segments/load_segment.rb @@ -0,0 +1,91 @@ +# frozen_string_literal: true + +require 'elftools/segments/segment' + +module ELFTools + module Segments + # For DT_LOAD segment. + # Able to query between file offset and virtual memory address. + class LoadSegment < Segment + # Returns the start of this segment. + # @return [Integer] + # The file offset. + def file_head + header.p_offset.to_i + end + + # Returns size in file. + # @return [Integer] + # The size. + def size + header.p_filesz.to_i + end + + # Returns the end of this segment. + # @return [Integer] + # The file offset. + def file_tail + file_head + size + end + + # Returns the start virtual address of this segment. + # @return [Integer] + # The vma. + def mem_head + header.p_vaddr.to_i + end + + # Returns size in memory. + # @return [Integer] + # The size. + def mem_size + header.p_memsz.to_i + end + + # Returns the end virtual address of this segment. + # @return [Integer] + # The vma. + def mem_tail + mem_head + mem_size + end + + # Query if the given file offset located in this segment. + # @param [Integer] offset + # File offset. + # @param [Integer] size + # Size. + # @return [Boolean] + def offset_in?(offset, size = 0) + file_head <= offset && offset + size < file_tail + end + + # Convert file offset into virtual memory address. + # @param [Integer] offset + # File offset. + # @return [Integer] + def offset_to_vma(offset) + # XXX: What if file_head is not aligned with p_vaddr (which is invalid according to ELF spec)? + offset - file_head + header.p_vaddr + end + + # Query if the given virtual memory address located in this segment. + # @param [Integer] vma + # Virtual memory address. + # @param [Integer] size + # Size. + # @return [Boolean] + def vma_in?(vma, size = 0) + vma >= (header.p_vaddr & -header.p_align) && + vma + size <= mem_tail + end + + # Convert virtual memory address into file offset. + # @param [Integer] vma + # Virtual memory address. + # @return [Integer] + def vma_to_offset(vma) + vma - header.p_vaddr + header.p_offset + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/segments/note_segment.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/segments/note_segment.rb new file mode 100644 index 0000000000..1581bf33c5 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/segments/note_segment.rb @@ -0,0 +1,26 @@ +# frozen_string_literal: true + +require 'elftools/note' +require 'elftools/segments/segment' + +module ELFTools + module Segments + # Class of note segment. + class NoteSegment < Segment + # Load note related methods. + include ELFTools::Note + + # Address offset of notes start. + # @return [Integer] The offset. + def note_start + header.p_offset + end + + # The total size of notes in this segment. + # @return [Integer] The size. + def note_total_size + header.p_filesz + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/segments/segment.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/segments/segment.rb new file mode 100644 index 0000000000..b575e31cc9 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/segments/segment.rb @@ -0,0 +1,56 @@ +# frozen_string_literal: true + +module ELFTools + module Segments + # Base class of segments. + class Segment + attr_reader :header # @return [ELFTools::Structs::ELF32_Phdr, ELFTools::Structs::ELF64_Phdr] Program header. + attr_reader :stream # @return [#pos=, #read] Streaming object. + + # Instantiate a {Segment} object. + # @param [ELFTools::Structs::ELF32_Phdr, ELFTools::Structs::ELF64_Phdr] header + # Program header. + # @param [#pos=, #read] stream + # Streaming object. + # @param [Method] offset_from_vma + # The method to get offset of file, given virtual memory address. + def initialize(header, stream, offset_from_vma: nil) + @header = header + @stream = stream + @offset_from_vma = offset_from_vma + end + + # Return +header.p_type+ in a simplier way. + # @return [Integer] + # The type, meaning of types are defined in {Constants::PT}. + def type + header.p_type + end + + # The content in this segment. + # @return [String] The content. + def data + stream.pos = header.p_offset + stream.read(header.p_filesz) + end + + # Is this segment readable? + # @return [Boolean] Ture or false. + def readable? + (header.p_flags & 4) == 4 + end + + # Is this segment writable? + # @return [Boolean] Ture or false. + def writable? + (header.p_flags & 2) == 2 + end + + # Is this segment executable? + # @return [Boolean] Ture or false. + def executable? + (header.p_flags & 1) == 1 + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/segments/segments.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/segments/segments.rb new file mode 100644 index 0000000000..7ca65d9054 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/segments/segments.rb @@ -0,0 +1,34 @@ +# frozen_string_literal: true + +# Require this file to load all segment classes. + +require 'elftools/segments/segment' + +require 'elftools/segments/dynamic_segment' +require 'elftools/segments/interp_segment' +require 'elftools/segments/load_segment' +require 'elftools/segments/note_segment' + +module ELFTools + # Module for defining different types of segments. + module Segments + # Class methods of {Segments::Segment}. + class << Segment + # Use different class according to +header.p_type+. + # @param [ELFTools::Structs::ELF32_Phdr, ELFTools::Structs::ELF64_Phdr] header Program header of a segment. + # @param [#pos=, #read] stream Streaming object. + # @return [ELFTools::Segments::Segment] + # Return object dependes on +header.p_type+. + def create(header, stream, *args, **kwargs) + klass = case header.p_type + when Constants::PT_DYNAMIC then DynamicSegment + when Constants::PT_INTERP then InterpSegment + when Constants::PT_LOAD then LoadSegment + when Constants::PT_NOTE then NoteSegment + else Segment + end + klass.new(header, stream, *args, **kwargs) + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/structs.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/structs.rb new file mode 100644 index 0000000000..6ac7803204 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/structs.rb @@ -0,0 +1,219 @@ +# frozen_string_literal: true + +require 'bindata' + +module ELFTools + # Define ELF related structures in this module. + # + # Structures are fetched from https://github.com/torvalds/linux/blob/master/include/uapi/linux/elf.h. + # Use gem +bindata+ to have these structures support 32/64 bits and little/big endian simultaneously. + module Structs + # The base structure to define common methods. + class ELFStruct < BinData::Record + # DRY. Many fields have different type in different arch. + CHOICE_SIZE_T = proc do |t = 'uint'| + { selection: :elf_class, choices: { 32 => :"#{t}32", 64 => :"#{t}64" }, copy_on_change: true } + end + + attr_accessor :elf_class # @return [Integer] 32 or 64. + attr_accessor :offset # @return [Integer] The file offset of this header. + + # Records which fields have been patched. + # @return [Hash{Integer => Integer}] Patches. + def patches + @patches ||= {} + end + + # BinData hash(Snapshot) that behaves like HashWithIndifferentAccess + alias to_h snapshot + + class << self + # Hooks the constructor. + # + # +BinData::Record+ doesn't allow us to override +#initialize+, so we hack +new+ here. + def new(*args) + # XXX: The better implementation is +new(*args, **kwargs)+, but we can't do this unless bindata changed + # lib/bindata/dsl.rb#override_new_in_class to invoke +new+ with both +args+ and +kwargs+. + kwargs = args.last.is_a?(Hash) ? args.last : {} + offset = kwargs.delete(:offset) + super.tap do |obj| + obj.offset = offset + obj.field_names.each do |f| + m = "#{f}=".to_sym + old_method = obj.singleton_method(m) + obj.singleton_class.send(:undef_method, m) + obj.define_singleton_method(m) do |val| + org = obj.send(f) + obj.patches[org.abs_offset] = ELFStruct.pack(val, org.num_bytes) + old_method.call(val) + end + end + end + end + + # Gets the endianness of current class. + # @return [:little, :big] The endianness. + def self_endian + bindata_name[-2..] == 'be' ? :big : :little + end + + # Packs an integer to string. + # @param [Integer] val + # @param [Integer] bytes + # @return [String] + def pack(val, bytes) + raise ArgumentError, "Not supported assign type #{val.class}" unless val.is_a?(Integer) + + number = val & ((1 << (8 * bytes)) - 1) + out = [] + bytes.times do + out << (number & 0xff) + number >>= 8 + end + out = out.pack('C*') + self_endian == :little ? out : out.reverse + end + end + end + + # ELF header structure. + class ELF_Ehdr < ELFStruct + endian :big_and_little + struct :e_ident do + string :magic, read_length: 4 + int8 :ei_class + int8 :ei_data + int8 :ei_version + int8 :ei_osabi + int8 :ei_abiversion + string :ei_padding, read_length: 7 # no use + end + uint16 :e_type + uint16 :e_machine + uint32 :e_version + # entry point + choice :e_entry, **CHOICE_SIZE_T['uint'] + choice :e_phoff, **CHOICE_SIZE_T['uint'] + choice :e_shoff, **CHOICE_SIZE_T['uint'] + uint32 :e_flags + uint16 :e_ehsize # size of this header + uint16 :e_phentsize # size of each segment + uint16 :e_phnum # number of segments + uint16 :e_shentsize # size of each section + uint16 :e_shnum # number of sections + uint16 :e_shstrndx # index of string table section + end + + # Section header structure. + class ELF_Shdr < ELFStruct + endian :big_and_little + uint32 :sh_name + uint32 :sh_type + choice :sh_flags, **CHOICE_SIZE_T['uint'] + choice :sh_addr, **CHOICE_SIZE_T['uint'] + choice :sh_offset, **CHOICE_SIZE_T['uint'] + choice :sh_size, **CHOICE_SIZE_T['uint'] + uint32 :sh_link + uint32 :sh_info + choice :sh_addralign, **CHOICE_SIZE_T['uint'] + choice :sh_entsize, **CHOICE_SIZE_T['uint'] + end + + # Program header structure for 32-bit. + class ELF32_Phdr < ELFStruct + endian :big_and_little + uint32 :p_type + uint32 :p_offset + uint32 :p_vaddr + uint32 :p_paddr + uint32 :p_filesz + uint32 :p_memsz + uint32 :p_flags + uint32 :p_align + end + + # Program header structure for 64-bit. + class ELF64_Phdr < ELFStruct + endian :big_and_little + uint32 :p_type + uint32 :p_flags + uint64 :p_offset + uint64 :p_vaddr + uint64 :p_paddr + uint64 :p_filesz + uint64 :p_memsz + uint64 :p_align + end + + # Gets the class of program header according to bits. + ELF_Phdr = { + 32 => ELF32_Phdr, + 64 => ELF64_Phdr + }.freeze + + # Symbol structure for 32-bit. + class ELF32_sym < ELFStruct + endian :big_and_little + uint32 :st_name + uint32 :st_value + uint32 :st_size + uint8 :st_info + uint8 :st_other + uint16 :st_shndx + end + + # Symbol structure for 64-bit. + class ELF64_sym < ELFStruct + endian :big_and_little + uint32 :st_name # Symbol name, index in string tbl + uint8 :st_info # Type and binding attributes + uint8 :st_other # No defined meaning, 0 + uint16 :st_shndx # Associated section index + uint64 :st_value # Value of the symbol + uint64 :st_size # Associated symbol size + end + + # Get symbol header class according to bits. + ELF_sym = { + 32 => ELF32_sym, + 64 => ELF64_sym + }.freeze + + # Note header. + class ELF_Nhdr < ELFStruct + endian :big_and_little + uint32 :n_namesz # Name size + uint32 :n_descsz # Content size + uint32 :n_type # Content type + end + + # Dynamic tag header. + class ELF_Dyn < ELFStruct + endian :big_and_little + choice :d_tag, **CHOICE_SIZE_T['int'] + # This is an union type named +d_un+ in original source, + # simplify it to be +d_val+ here. + choice :d_val, **CHOICE_SIZE_T['uint'] + end + + # Rel header in .rel section. + class ELF_Rel < ELFStruct + endian :big_and_little + choice :r_offset, **CHOICE_SIZE_T['uint'] + choice :r_info, **CHOICE_SIZE_T['uint'] + + # Compatibility with ELF_Rela, both can be used interchangeably + def r_addend + nil + end + end + + # Rela header in .rela section. + class ELF_Rela < ELFStruct + endian :big_and_little + choice :r_offset, **CHOICE_SIZE_T['uint'] + choice :r_info, **CHOICE_SIZE_T['uint'] + choice :r_addend, **CHOICE_SIZE_T['int'] + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/util.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/util.rb new file mode 100644 index 0000000000..152d210fca --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/util.rb @@ -0,0 +1,99 @@ +# frozen_string_literal: true + +module ELFTools + # Define some util methods. + module Util + # Class methods. + module ClassMethods + # Round up the number to be mulitple of + # +2**bit+. + # @param [Integer] num Number to be rounded-up. + # @param [Integer] bit How many bit to be aligned. + # @return [Integer] See examples. + # @example + # align(10, 1) #=> 10 + # align(10, 2) #=> 12 + # align(10, 3) #=> 16 + # align(10, 4) #=> 16 + # align(10, 5) #=> 32 + def align(num, bit) + n = 2**bit + return num if (num % n).zero? + + (num + n) & ~(n - 1) + end + + # Fetch the correct value from module +mod+. + # + # See {ELFTools::ELFFile#segment_by_type} for how to + # use this method. + # @param [Module] mod The module defined constant numbers. + # @param [Integer, Symbol, String] val + # Desired value. + # @return [Integer] + # Currently this method always return a value + # from {ELFTools::Constants}. + def to_constant(mod, val) + # Ignore the outest name. + module_name = mod.name.sub('ELFTools::', '') + # if val is an integer, check if exists in mod + if val.is_a?(Integer) + return val if mod.constants.any? { |c| mod.const_get(c) == val } + + raise ArgumentError, "No constants in #{module_name} is #{val}" + end + val = val.to_s.upcase + prefix = module_name.split('::')[-1] + val = "#{prefix}_#{val}" unless val.start_with?(prefix) + val = val.to_sym + raise ArgumentError, "No constants in #{module_name} named \"#{val}\"" unless mod.const_defined?(val) + + mod.const_get(val) + end + + # Read from stream until reach a null-byte. + # @param [#pos=, #read] stream Streaming object + # @param [Integer] offset Start from here. + # @return [String] Result string will never contain null byte. + # @example + # Util.cstring(File.open('/bin/cat'), 0) + # #=> "\x7FELF\x02\x01\x01" + def cstring(stream, offset) + stream.pos = offset + # read until "\x00" + ret = '' + loop do + c = stream.read(1) + return nil if c.nil? # reach EOF + break if c == "\x00" + + ret += c + end + ret + end + + # Select objects from enumerator with +.type+ property + # equals to +type+. + # + # Different from naive +Array#select+ is this method + # will yield block whenever find a desired object. + # + # This method is used to simplify the same logic in methods + # {ELFFile#sections_by_type}, {ELFFile#segments_by_type}, etc. + # @param [Enumerator] enum An enumerator for further select. + # @param [Object] type The type you want. + # @return [Array] + # The return value will be objects in +enum+ with attribute + # +.type+ equals to +type+. + def select_by_type(enum, type) + enum.select do |obj| + if obj.type == type + yield obj if block_given? + true + end + end + end + end + extend ClassMethods + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/version.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/version.rb new file mode 100644 index 0000000000..111fae9406 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/elftools-1.2.0/lib/elftools/version.rb @@ -0,0 +1,6 @@ +# frozen_string_literal: true + +module ELFTools + # Current gem version + VERSION = '1.2.0' +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/patchelf-1.4.0/lib/patchelf.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/patchelf-1.4.0/lib/patchelf.rb new file mode 100644 index 0000000000..1cb237433a --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/patchelf-1.4.0/lib/patchelf.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: true + +# Main module of patchelf. +# +# @author david942j +module PatchELF +end + +require 'patchelf/patcher' +require 'patchelf/version' diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/patchelf-1.4.0/lib/patchelf/alt_saver.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/patchelf-1.4.0/lib/patchelf/alt_saver.rb new file mode 100644 index 0000000000..430eee12f4 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/patchelf-1.4.0/lib/patchelf/alt_saver.rb @@ -0,0 +1,1052 @@ +# frozen_string_literal: true + +require 'elftools/constants' +require 'elftools/elf_file' +require 'elftools/structs' +require 'elftools/util' +require 'fileutils' + +require 'patchelf/helper' + +# :nodoc: +module PatchELF + # TODO: refactor buf_* methods here + # TODO: move all refinements into a separate file / helper file. + # refinements for cleaner syntax / speed / memory optimizations + module Refinements + refine StringIO do + # behaves like C memset. Equivalent to calling stream.write(char * nbytes) + # the benefit of preferring this over `stream.write(char * nbytes)` is only when data to be written is large. + # @param [String] char + # @param [Integer] nbytes + # @return[void] + def fill(char, nbytes) + at_once = Helper.page_size + pending = nbytes + + if pending > at_once + to_write = char * at_once + while pending >= at_once + write(to_write) + pending -= at_once + end + end + write(char * pending) if pending.positive? + end + end + end + using Refinements + + # Internal use only. + # alternative to +Saver+, that aims to be byte to byte equivalent with NixOS/patchelf. + # + # *DISCLAIMER*: This differs from +Saver+ in number of ways. No lazy reading, + # inconsistent use of existing internal API(e.g: manual reading of data instead of calling +section.data+) + # @private + class AltSaver + attr_reader :in_file # @return [String] Input filename. + attr_reader :out_file # @return [String] Output filename. + + # Instantiate a {AltSaver} object. + # the params passed are the same as the ones passed to +Saver+ + # @param [String] in_file + # @param [String] out_file + # @param [{Symbol => String, Array}] set + def initialize(in_file, out_file, set) + @in_file = in_file + @out_file = out_file + @set = set + + f = File.open(in_file, 'rb') + # the +@buffer+ and +@elf+ both could work on same +StringIO+ stream, + # the updating of @buffer in place blocks us from looking up old values. + # TODO: cache the values needed later, use same stream for +@buffer+ and +@elf+. + # also be sure to update the stream offset passed to Segments::Segment. + @elf = ELFTools::ELFFile.new(f) + @buffer = StringIO.new(f.tap(&:rewind).read) # StringIO makes easier to work with Bindata + + @ehdr = @elf.header + @endian = @elf.endian + @elf_class = @elf.elf_class + + @segments = @elf.segments # usage similar to phdrs + @sections = @elf.sections # usage similar to shdrs + update_section_idx! + + # {String => String} + # section name to its data mapping + @replaced_sections = {} + @section_alignment = ehdr.e_phoff.num_bytes + + # using the same environment flag as patchelf, makes it easier for debugging + Logger.level = ::Logger.const_get(ENV['PATCHELF_DEBUG'] ? :DEBUG : :WARN) + end + + # @return [void] + def save! + @set.each { |mtd, val| send(:"modify_#{mtd}") if val } + rewrite_sections + + FileUtils.cp(in_file, out_file) if out_file != in_file + patch_out + # Let output file have the same permission as input. + FileUtils.chmod(File.stat(in_file).mode, out_file) + end + + private + + attr_reader :ehdr, :endian, :elf_class + + def old_sections + @old_sections ||= @elf.sections + end + + def buf_cstr(off) + cstr = [] + with_buf_at(off) do |buf| + loop do + c = buf.read 1 + break if c.nil? || c == "\x00" + + cstr.push c + end + end + cstr.join + end + + def buf_move!(dst_idx, src_idx, n_bytes) + with_buf_at(src_idx) do |buf| + to_write = buf.read(n_bytes) + buf.seek dst_idx + buf.write to_write + end + end + + def dynstr + find_section '.dynstr' + end + + # yields dynamic tag, and offset in buffer + def each_dynamic_tags + return unless block_given? + + sec = find_section '.dynamic' + return unless sec + + return if sec.header.sh_type == ELFTools::Constants::SHT_NOBITS + + shdr = sec.header + with_buf_at(shdr.sh_offset) do |buf| + dyn = ELFTools::Structs::ELF_Dyn.new(elf_class: elf_class, endian: endian) + loop do + buf_dyn_offset = buf.tell + dyn.clear + dyn.read(buf) + break if dyn.d_tag == ELFTools::Constants::DT_NULL + + yield dyn, buf_dyn_offset + # there's a possibility for caller to modify @buffer.pos, seek to avoid such issues + buf.seek buf_dyn_offset + dyn.num_bytes + end + end + end + + # the idea of uniquely identifying section by its name has its problems + # but this is how patchelf operates and is prone to bugs. + # e.g: https://github.com/NixOS/patchelf/issues/197 + def find_section(sec_name) + idx = find_section_idx sec_name + return unless idx + + @sections[idx] + end + + def find_section_idx(sec_name) + @section_idx_by_name[sec_name] + end + + def buf_grow!(newsz) + bufsz = @buffer.size + return if newsz <= bufsz + + @buffer.truncate newsz + end + + def modify_interpreter + @replaced_sections['.interp'] = "#{@set[:interpreter]}\x00" + end + + def modify_needed + # due to gsoc time constraints only implmenting features used by brew. + raise NotImplementedError + end + + # not checking for nil as modify_rpath is only called if @set[:rpath] + def modify_rpath + modify_rpath_helper @set[:rpath], force_rpath: true + end + + # not checking for nil as modify_runpath is only called if @set[:runpath] + def modify_runpath + modify_rpath_helper @set[:runpath] + end + + def collect_runpath_tags + tags = {} + each_dynamic_tags do |dyn, off| + case dyn.d_tag + when ELFTools::Constants::DT_RPATH + tag_type = :rpath + when ELFTools::Constants::DT_RUNPATH + tag_type = :runpath + else + next + end + + # clone does shallow copy, and for some reason d_tag and d_val can't be pass as argument + dyn_rpath = ELFTools::Structs::ELF_Dyn.new(endian: endian, elf_class: elf_class) + dyn_rpath.assign({ d_tag: dyn.d_tag.to_i, d_val: dyn.d_val.to_i }) + tags[tag_type] = { offset: off, header: dyn_rpath } + end + tags + end + + def resolve_rpath_tag_conflict(dyn_tags, force_rpath: false) + dyn_runpath, dyn_rpath = dyn_tags.values_at(:runpath, :rpath) + + update_sym = + if !force_rpath && dyn_rpath && dyn_runpath.nil? + :runpath + elsif force_rpath && dyn_runpath + :rpath + end + return unless update_sym + + delete_sym, = %i[rpath runpath] - [update_sym] + dyn_tag = dyn_tags[update_sym] = dyn_tags[delete_sym] + dyn = dyn_tag[:header] + dyn.d_tag = ELFTools::Constants.const_get("DT_#{update_sym.upcase}") + with_buf_at(dyn_tag[:offset]) { |buf| dyn.write(buf) } + dyn_tags.delete(delete_sym) + end + + def modify_rpath_helper(new_rpath, force_rpath: false) + shdr_dynstr = dynstr.header + + dyn_tags = collect_runpath_tags + resolve_rpath_tag_conflict(dyn_tags, force_rpath: force_rpath) + # (:runpath, :rpath) order_matters. + resolved_rpath_dyn = dyn_tags.values_at(:runpath, :rpath).compact.first + + old_rpath = '' + rpath_off = nil + if resolved_rpath_dyn + rpath_off = shdr_dynstr.sh_offset + resolved_rpath_dyn[:header].d_val + old_rpath = buf_cstr(rpath_off) + end + return if old_rpath == new_rpath + + with_buf_at(rpath_off) { |b| b.write('X' * old_rpath.size) } if rpath_off + if new_rpath.size <= old_rpath.size + with_buf_at(rpath_off) { |b| b.write "#{new_rpath}\x00" } + return + end + + Logger.debug 'rpath is too long, resizing...' + new_dynstr = replace_section '.dynstr', shdr_dynstr.sh_size + new_rpath.size + 1 + new_rpath_strtab_idx = shdr_dynstr.sh_size.to_i + new_dynstr[new_rpath_strtab_idx..(new_rpath_strtab_idx + new_rpath.size)] = "#{new_rpath}\x00" + + dyn_tags.each do |_, dyn| + dyn[:header].d_val = new_rpath_strtab_idx + with_buf_at(dyn[:offset]) { |b| dyn[:header].write(b) } + end + + return unless dyn_tags.empty? + + add_dt_rpath!( + d_tag: force_rpath ? ELFTools::Constants::DT_RPATH : ELFTools::Constants::DT_RUNPATH, + d_val: new_rpath_strtab_idx + ) + end + + def modify_soname + return unless ehdr.e_type == ELFTools::Constants::ET_DYN + + # due to gsoc time constraints only implmenting features used by brew. + raise NotImplementedError + end + + def add_segment!(**phdr_vals) + new_phdr = ELFTools::Structs::ELF_Phdr[elf_class].new(endian: endian, **phdr_vals) + # nil = no reference to stream; we only want @segments[i].header + new_segment = ELFTools::Segments::Segment.new(new_phdr, nil) + @segments.push new_segment + ehdr.e_phnum += 1 + nil + end + + def add_dt_rpath!(d_tag: nil, d_val: nil) + dyn_num_bytes = nil + dt_null_idx = 0 + each_dynamic_tags do |dyn| + dyn_num_bytes ||= dyn.num_bytes + dt_null_idx += 1 + end + + if dyn_num_bytes.nil? + Logger.error 'no dynamic tags' + return + end + + # allot for new dt_runpath + shdr_dynamic = find_section('.dynamic').header + new_dynamic_data = replace_section '.dynamic', shdr_dynamic.sh_size + dyn_num_bytes + + # consider DT_NULL when copying + replacement_size = (dt_null_idx + 1) * dyn_num_bytes + + # make space for dt_runpath tag at the top, shift data by one tag positon + new_dynamic_data[dyn_num_bytes..(replacement_size + dyn_num_bytes)] = new_dynamic_data[0..replacement_size] + + dyn_rpath = ELFTools::Structs::ELF_Dyn.new endian: endian, elf_class: elf_class + dyn_rpath.d_tag = d_tag + dyn_rpath.d_val = d_val + + zi = StringIO.new + dyn_rpath.write zi + zi.rewind + new_dynamic_data[0...dyn_num_bytes] = zi.read + end + + # given a index into old_sections table + # returns the corresponding section index in @sections + # + # raises ArgumentError if old_shndx can't be found in old_sections + # TODO: handle case of non existing section in (new) @sections. + def new_section_idx(old_shndx) + return if old_shndx == ELFTools::Constants::SHN_UNDEF || old_shndx >= ELFTools::Constants::SHN_LORESERVE + + raise ArgumentError if old_shndx >= old_sections.count + + old_sec = old_sections[old_shndx] + raise PatchError, "old_sections[#{shndx}] is nil" if old_sec.nil? + + # TODO: handle case of non existing section in (new) @sections. + find_section_idx(old_sec.name) + end + + def page_size + Helper.page_size(ehdr.e_machine) + end + + def patch_out + with_buf_at(0) { |b| ehdr.write(b) } + + File.open(out_file, 'wb') do |f| + @buffer.rewind + f.write @buffer.read + end + end + + # size includes NUL byte + def replace_section(section_name, size) + data = @replaced_sections[section_name] + unless data + shdr = find_section(section_name).header + # avoid calling +section.data+ as the @buffer contents may vary from + # the stream provided to section at initialization. + # ideally, calling section.data should work, however avoiding it to prevent + # future traps. + with_buf_at(shdr.sh_offset) { |b| data = b.read shdr.sh_size } + end + rep_data = if data.size == size + data + elsif data.size < size + data.ljust(size, "\x00") + else + "#{data[0...size]}\x00" + end + @replaced_sections[section_name] = rep_data + end + + def write_phdrs_to_buf! + sort_phdrs! + with_buf_at(ehdr.e_phoff) do |buf| + @segments.each { |seg| seg.header.write(buf) } + end + end + + def write_shdrs_to_buf! + raise PatchError, 'ehdr.e_shnum != @sections.count' if ehdr.e_shnum != @sections.count + + sort_shdrs! + with_buf_at(ehdr.e_shoff) do |buf| + @sections.each { |section| section.header.write(buf) } + end + sync_dyn_tags! + end + + # data for manual packing and unpacking of symbols in symtab sections. + def meta_sym_pack + return @meta_sym_pack if @meta_sym_pack + + # resort to manual packing and unpacking of data, + # as using bindata is painfully slow :( + if elf_class == 32 + sym_num_bytes = 16 # u32 u32 u32 u8 u8 u16 + pack_code = endian == :little ? 'VVVCCv' : 'NNNCCn' + pack_st_info = 3 + pack_st_shndx = 5 + pack_st_value = 1 + else # 64 + sym_num_bytes = 24 # u32 u8 u8 u16 u64 u64 + pack_code = endian == :little ? 'VCCvQQ>' + pack_st_info = 1 + pack_st_shndx = 3 + pack_st_value = 4 + end + + @meta_sym_pack = { + num_bytes: sym_num_bytes, code: pack_code, + st_info: pack_st_info, st_shndx: pack_st_shndx, st_value: pack_st_value + } + end + + # yields +symbol+, +entry+ + def each_symbol(shdr) + return unless [ELFTools::Constants::SHT_SYMTAB, ELFTools::Constants::SHT_DYNSYM].include?(shdr.sh_type) + + pack_code, sym_num_bytes = meta_sym_pack.values_at(:code, :num_bytes) + + with_buf_at(shdr.sh_offset) do |buf| + num_symbols = shdr.sh_size / sym_num_bytes + num_symbols.times do |entry| + sym = buf.read(sym_num_bytes).unpack(pack_code) + sym_modified = yield sym, entry + + if sym_modified + buf.seek buf.tell - sym_num_bytes + buf.write sym.pack(pack_code) + end + end + end + end + + def rewrite_headers(phdr_address) + # there can only be a single program header table according to ELF spec + @segments.find { |seg| seg.header.p_type == ELFTools::Constants::PT_PHDR }&.tap do |seg| + phdr = seg.header + phdr.p_offset = ehdr.e_phoff.to_i + phdr.p_vaddr = phdr.p_paddr = phdr_address.to_i + phdr.p_filesz = phdr.p_memsz = phdr.num_bytes * @segments.count # e_phentsize * e_phnum + end + write_phdrs_to_buf! + write_shdrs_to_buf! + + pack = meta_sym_pack + @sections.each do |sec| + each_symbol(sec.header) do |sym, entry| + old_shndx = sym[pack[:st_shndx]] + + begin + new_index = new_section_idx(old_shndx) + next unless new_index + rescue ArgumentError + Logger.warn "entry #{entry} in symbol table refers to a non existing section, skipping" + end + + sym[pack[:st_shndx]] = new_index + + # right 4 bits in the st_info field is st_type + if (sym[pack[:st_info]] & 0xF) == ELFTools::Constants::STT_SECTION + sym[pack[:st_value]] = @sections[new_index].header.sh_addr.to_i + end + true + end + end + end + + def rewrite_sections + return if @replaced_sections.empty? + + case ehdr.e_type + when ELFTools::Constants::ET_DYN + rewrite_sections_library + when ELFTools::Constants::ET_EXEC + rewrite_sections_executable + else + raise PatchError, 'unknown ELF type' + end + end + + def replaced_section_indices + return enum_for(:replaced_section_indices) unless block_given? + + last_replaced = 0 + @sections.each_with_index do |sec, idx| + if @replaced_sections[sec.name] + last_replaced = idx + yield last_replaced + end + end + raise PatchError, 'last_replaced = 0' if last_replaced.zero? + raise PatchError, 'last_replaced + 1 >= @sections.size' if last_replaced + 1 >= @sections.size + end + + def start_replacement_shdr + last_replaced = replaced_section_indices.max + start_replacement_hdr = @sections[last_replaced + 1].header + + prev_sec_name = '' + (1..last_replaced).each do |idx| + sec = @sections[idx] + shdr = sec.header + if (sec.type == ELFTools::Constants::SHT_PROGBITS && sec.name != '.interp') || prev_sec_name == '.dynstr' + start_replacement_hdr = shdr + break + elsif @replaced_sections[sec.name].nil? + Logger.debug " replacing section #{sec.name} which is in the way" + replace_section(sec.name, shdr.sh_size) + end + prev_sec_name = sec.name + end + + start_replacement_hdr + end + + def copy_shdrs_to_eof + shoff_new = @buffer.size + # honestly idk why `ehdr.e_shoff` is considered when we are only moving shdrs. + sh_size = ehdr.e_shoff + (ehdr.e_shnum * ehdr.e_shentsize) + buf_grow! @buffer.size + sh_size + ehdr.e_shoff = shoff_new + raise PatchError, 'ehdr.e_shnum != @sections.size' if ehdr.e_shnum != @sections.size + + with_buf_at(ehdr.e_shoff + @sections.first.header.num_bytes) do |buf| # skip writing to NULL section + @sections.each_with_index do |sec, idx| + next if idx.zero? + + sec.header.write buf + end + end + end + + def rewrite_sections_executable + sort_shdrs! + shdr = start_replacement_shdr + start_offset = shdr.sh_offset.to_i + start_addr = shdr.sh_addr.to_i + first_page = start_addr - start_offset + + Logger.debug "first reserved offset/addr is 0x#{start_offset.to_s 16}/0x#{start_addr.to_s 16}" + + unless start_addr % page_size == start_offset % page_size + raise PatchError, 'start_addr != start_offset (mod PAGE_SIZE)' + end + + Logger.debug "first page is 0x#{first_page.to_i.to_s 16}" + + copy_shdrs_to_eof if ehdr.e_shoff < start_offset + + normalize_note_segments + + seg_num_bytes = @segments.first.header.num_bytes + needed_space = ( + ehdr.num_bytes + + (@segments.count * seg_num_bytes) + + @replaced_sections.sum { |_, str| Helper.alignup(str.size, @section_alignment) } + ) + + if needed_space > start_offset + needed_space += seg_num_bytes # new load segment is required + + needed_pages = Helper.alignup(needed_space - start_offset, page_size) / page_size + Logger.debug "needed pages is #{needed_pages}" + raise PatchError, 'virtual address space underrun' if needed_pages * page_size > first_page + + shift_file(needed_pages, start_offset) + + first_page -= needed_pages * page_size + start_offset += needed_pages * page_size + end + Logger.debug "needed space is #{needed_space}" + + cur_off = ehdr.num_bytes + (@segments.count * seg_num_bytes) + Logger.debug "clearing first #{start_offset - cur_off} bytes" + with_buf_at(cur_off) { |buf| buf.fill("\x00", (start_offset - cur_off)) } + + cur_off = write_replaced_sections cur_off, first_page, 0 + raise PatchError, "cur_off(#{cur_off}) != needed_space" if cur_off != needed_space + + rewrite_headers first_page + ehdr.e_phoff + end + + def replace_sections_in_the_way_of_phdr! + num_notes = @sections.count { |sec| sec.type == ELFTools::Constants::SHT_NOTE } + pht_size = ehdr.num_bytes + ((@segments.count + num_notes + 1) * @segments.first.header.num_bytes) + + # replace sections that may overlap with expanded program header table + @sections.each_with_index do |sec, idx| + shdr = sec.header + next if idx.zero? || @replaced_sections[sec.name] + break if shdr.sh_offset > pht_size + + replace_section sec.name, shdr.sh_size + end + end + + def rewrite_sections_library + start_page = 0 + first_page = 0 + @segments.each do |seg| + phdr = seg.header + this_page = Helper.alignup(phdr.p_vaddr + phdr.p_memsz, page_size) + start_page = [start_page, this_page].max + first_page = phdr.p_vaddr - phdr.p_offset if phdr.p_type == ELFTools::Constants::PT_PHDR + end + + Logger.debug "Last page is 0x#{start_page.to_s 16}" + Logger.debug "First page is 0x#{first_page.to_s 16}" + replace_sections_in_the_way_of_phdr! + needed_space = @replaced_sections.sum { |_, str| Helper.alignup(str.size, @section_alignment) } + Logger.debug "needed space = #{needed_space}" + + start_offset = Helper.alignup(@buffer.size, page_size) + buf_grow! start_offset + needed_space + + # executable shared object + if start_offset > start_page && @segments.any? { |seg| seg.header.p_type == ELFTools::Constants::PT_INTERP } + Logger.debug( + "shifting new PT_LOAD segment by #{start_offset - start_page} bytes to work around a Linux kernel bug" + ) + start_page = start_offset + end + + ehdr.e_phoff = ehdr.num_bytes + add_segment!( + p_type: ELFTools::Constants::PT_LOAD, + p_offset: start_offset, + p_vaddr: start_page, + p_paddr: start_page, + p_filesz: needed_space, + p_memsz: needed_space, + p_flags: ELFTools::Constants::PF_R | ELFTools::Constants::PF_W, + p_align: page_size + ) + + normalize_note_segments + + cur_off = write_replaced_sections start_offset, start_page, start_offset + raise PatchError, 'cur_off != start_offset + needed_space' if cur_off != start_offset + needed_space + + rewrite_headers(first_page + ehdr.e_phoff) + end + + def normalize_note_segments + return if @replaced_sections.none? do |rsec_name, _| + find_section(rsec_name)&.type == ELFTools::Constants::SHT_NOTE + end + + new_phdrs = [] + + phdrs_by_type(ELFTools::Constants::PT_NOTE) do |phdr| + # Binaries produced by older patchelf versions may contain empty PT_NOTE segments. + next if @sections.none? do |sec| + sec.header.sh_offset >= phdr.p_offset && sec.header.sh_offset < phdr.p_offset + phdr.p_filesz + end + + new_phdrs += normalize_note_segment(phdr) + end + + new_phdrs.each { |phdr| add_segment!(**phdr.snapshot) } + end + + def normalize_note_segment(phdr) + start_off = phdr.p_offset.to_i + curr_off = start_off + end_off = start_off + phdr.p_filesz + + new_phdrs = [] + + while curr_off < end_off + size = 0 + sections_at_aligned_offset(curr_off) do |sec| + next if sec.type != ELFTools::Constants::SHT_NOTE + + size = sec.header.sh_size.to_i + curr_off = sec.header.sh_offset.to_i + break + end + + raise PatchError, 'cannot normalize PT_NOTE segment: non-contiguous SHT_NOTE sections' if size.zero? + + if curr_off + size > end_off + raise PatchError, 'cannot normalize PT_NOTE segment: partially mapped SHT_NOTE section' + end + + new_phdr = ELFTools::Structs::ELF_Phdr[elf_class].new(endian: endian, **phdr.snapshot) + new_phdr.p_offset = curr_off + new_phdr.p_vaddr = phdr.p_vaddr + (curr_off - start_off) + new_phdr.p_paddr = phdr.p_paddr + (curr_off - start_off) + new_phdr.p_filesz = size + new_phdr.p_memsz = size + + if curr_off == start_off + phdr.assign(new_phdr) + else + new_phdrs << new_phdr + end + + curr_off += size + end + + new_phdrs + end + + def sections_at_aligned_offset(offset) + @sections.each do |sec| + shdr = sec.header + + aligned_offset = Helper.alignup(offset, shdr.sh_addralign) + next if shdr.sh_offset != aligned_offset + + yield sec + end + end + + def shift_sections(shift, start_offset) + ehdr.e_shoff += shift if ehdr.e_shoff >= start_offset + + @sections.each_with_index do |sec, i| + next if i.zero? # dont touch NULL section + + shdr = sec.header + next if shdr.sh_offset < start_offset + + shdr.sh_offset += shift + end + end + + def shift_segment_offset(phdr, shift) + phdr.p_offset += shift + phdr.p_align = page_size if phdr.p_align != 0 && (phdr.p_vaddr - phdr.p_offset) % phdr.p_align != 0 + end + + def shift_segment_virtual_address(phdr, shift) + phdr.p_paddr -= shift if phdr.p_paddr > shift + phdr.p_vaddr -= shift if phdr.p_vaddr > shift + end + + # rubocop:disable Metrics/PerceivedComplexity + def shift_segments(shift, start_offset) + split_index = -1 + split_shift = 0 + + @segments.each_with_index do |seg, idx| + phdr = seg.header + p_start = phdr.p_offset + + if p_start <= start_offset && p_start + phdr.p_filesz > start_offset && + phdr.p_type == ELFTools::Constants::PT_LOAD + raise PatchError, "split_index(#{split_index}) != -1" if split_index != -1 + + split_index = idx + split_shift = start_offset - p_start + + phdr.p_offset = start_offset + phdr.p_memsz -= split_shift + phdr.p_filesz -= split_shift + phdr.p_paddr += split_shift + phdr.p_vaddr += split_shift + + p_start = start_offset + end + + if p_start >= start_offset + shift_segment_offset(phdr, shift) + else + shift_segment_virtual_address(phdr, shift) + end + end + + raise PatchError, "split_index(#{split_index}) == -1" if split_index == -1 + + [split_index, split_shift] + end + # rubocop:enable Metrics/PerceivedComplexity + + def shift_file(extra_pages, start_offset) + raise PatchError, "start_offset(#{start_offset}) < ehdr.num_bytes" if start_offset < ehdr.num_bytes + + oldsz = @buffer.size + raise PatchError, "oldsz <= start_offset(#{start_offset})" if oldsz <= start_offset + + shift = extra_pages * page_size + buf_grow!(oldsz + shift) + buf_move!(start_offset + shift, start_offset, oldsz - start_offset) + with_buf_at(start_offset) { |buf| buf.write "\x00" * shift } + + ehdr.e_phoff = ehdr.num_bytes + + shift_sections(shift, start_offset) + + split_index, split_shift = shift_segments(shift, start_offset) + + split_phdr = @segments[split_index].header + add_segment!( + p_type: ELFTools::Constants::PT_LOAD, + p_offset: split_phdr.p_offset - split_shift - shift, + p_vaddr: split_phdr.p_vaddr - split_shift - shift, + p_paddr: split_phdr.p_paddr - split_shift - shift, + p_filesz: split_shift + shift, + p_memsz: split_shift + shift, + p_flags: ELFTools::Constants::PF_R | ELFTools::Constants::PF_W, + p_align: page_size + ) + end + + def sort_phdrs! + pt_phdr = ELFTools::Constants::PT_PHDR + @segments.sort! do |me, you| + next 1 if you.header.p_type == pt_phdr + next -1 if me.header.p_type == pt_phdr + + me.header.p_paddr.to_i <=> you.header.p_paddr.to_i + end + end + + # section headers may contain sh_info and sh_link values that are + # references to another section + def collect_section_to_section_refs + rel_syms = [ELFTools::Constants::SHT_REL, ELFTools::Constants::SHT_RELA] + # Translate sh_link, sh_info mappings to section names. + @sections.each_with_object({ linkage: {}, info: {} }) do |s, collected| + hdr = s.header + collected[:linkage][s.name] = @sections[hdr.sh_link].name if hdr.sh_link.nonzero? + collected[:info][s.name] = @sections[hdr.sh_info].name if hdr.sh_info.nonzero? && rel_syms.include?(hdr.sh_type) + end + end + + # @param collected + # this must be the value returned by +collect_section_to_section_refs+ + def restore_section_to_section_refs!(collected) + rel_syms = [ELFTools::Constants::SHT_REL, ELFTools::Constants::SHT_RELA] + linkage, info = collected.values_at(:linkage, :info) + @sections.each do |sec| + hdr = sec.header + hdr.sh_link = find_section_idx(linkage[sec.name]) if hdr.sh_link.nonzero? + hdr.sh_info = find_section_idx(info[sec.name]) if hdr.sh_info.nonzero? && rel_syms.include?(hdr.sh_type) + end + end + + def sort_shdrs! + return if @sections.empty? + + section_dep_values = collect_section_to_section_refs + shstrtab = @sections[ehdr.e_shstrndx].header + @sections.sort! { |me, you| me.header.sh_offset.to_i <=> you.header.sh_offset.to_i } + update_section_idx! + restore_section_to_section_refs!(section_dep_values) + @sections.each_with_index do |sec, idx| + ehdr.e_shstrndx = idx if sec.header.sh_offset == shstrtab.sh_offset + end + end + + def jmprel_section_name + sec_name = %w[.rel.plt .rela.plt .rela.IA_64.pltoff].find { |s| find_section(s) } + raise PatchError, 'cannot find section corresponding to DT_JMPREL' unless sec_name + + sec_name + end + + # given a +dyn.d_tag+, returns the section name it must be synced to. + # it may return nil, when given tag maps to no section, + # or when its okay to skip if section is not found. + def dyn_tag_to_section_name(d_tag) + case d_tag + when ELFTools::Constants::DT_STRTAB, ELFTools::Constants::DT_STRSZ + '.dynstr' + when ELFTools::Constants::DT_SYMTAB + '.dynsym' + when ELFTools::Constants::DT_HASH + '.hash' + when ELFTools::Constants::DT_GNU_HASH + # return nil if not found, patchelf claims no problem in skipping + find_section('.gnu.hash')&.name + when ELFTools::Constants::DT_MIPS_XHASH + return if ehdr.e_machine != ELFTools::Constants::EM_MIPS + + '.MIPS.xhash' + when ELFTools::Constants::DT_JMPREL + jmprel_section_name + when ELFTools::Constants::DT_REL + # regarding .rel.got, NixOS/patchelf says + # "no idea if this makes sense, but it was needed for some program" + # + # return nil if not found, patchelf claims no problem in skipping + %w[.rel.dyn .rel.got].find { |s| find_section(s) } + when ELFTools::Constants::DT_RELA + # return nil if not found, patchelf claims no problem in skipping + find_section('.rela.dyn')&.name + when ELFTools::Constants::DT_VERNEED + '.gnu.version_r' + when ELFTools::Constants::DT_VERSYM + '.gnu.version' + end + end + + # updates dyn tags by syncing it with @section values + def sync_dyn_tags! + dyn_table_offset = nil + each_dynamic_tags do |dyn, buf_off| + dyn_table_offset ||= buf_off + + sec_name = dyn_tag_to_section_name(dyn.d_tag) + + unless sec_name + if dyn.d_tag == ELFTools::Constants::DT_MIPS_RLD_MAP_REL && ehdr.e_machine == ELFTools::Constants::EM_MIPS + rld_map = find_section('.rld_map') + dyn.d_val = if rld_map + rld_map.header.sh_addr.to_i - (buf_off - dyn_table_offset) - + find_section('.dynamic').header.sh_addr.to_i + else + Logger.warn 'DT_MIPS_RLD_MAP_REL entry is present, but .rld_map section is not' + 0 + end + end + + next + end + + shdr = find_section(sec_name).header + dyn.d_val = dyn.d_tag == ELFTools::Constants::DT_STRSZ ? shdr.sh_size.to_i : shdr.sh_addr.to_i + + with_buf_at(buf_off) { |wbuf| dyn.write(wbuf) } + end + end + + def update_section_idx! + @section_idx_by_name = @sections.map.with_index { |sec, idx| [sec.name, idx] }.to_h + end + + def with_buf_at(pos) + return unless block_given? + + opos = @buffer.tell + @buffer.seek pos + yield @buffer + @buffer.seek opos + nil + end + + def sync_sec_to_seg(shdr, phdr) + phdr.p_offset = shdr.sh_offset.to_i + phdr.p_vaddr = phdr.p_paddr = shdr.sh_addr.to_i + phdr.p_filesz = phdr.p_memsz = shdr.sh_size.to_i + end + + def phdrs_by_type(seg_type) + return unless seg_type + + @segments.each_with_index do |seg, idx| + next unless (phdr = seg.header).p_type == seg_type + + yield phdr, idx + end + end + + # Returns a blank shdr if the section doesn't exist. + def find_or_create_section_header(rsec_name) + shdr = find_section(rsec_name)&.header + shdr ||= ELFTools::Structs::ELF_Shdr.new(endian: endian, elf_class: elf_class) + shdr + end + + def overwrite_replaced_sections + # the original source says this has to be done separately to + # prevent clobbering the previously written section contents. + @replaced_sections.each do |rsec_name, _| + shdr = find_section(rsec_name)&.header + next unless shdr + + next if shdr.sh_type == ELFTools::Constants::SHT_NOBITS + + with_buf_at(shdr.sh_offset) { |b| b.fill('X', shdr.sh_size) } + end + end + + def write_section_aligment(shdr) + return if shdr.sh_type == ELFTools::Constants::SHT_NOTE && shdr.sh_addralign <= @section_alignment + + shdr.sh_addralign = @section_alignment + end + + def section_bounds_within_segment?(s_start, s_end, p_start, p_end) + (s_start >= p_start && s_start < p_end) || (s_end > p_start && s_end <= p_end) + end + + def write_replaced_sections(cur_off, start_addr, start_offset) + overwrite_replaced_sections + + noted_phdrs = Set.new + + # the sort is necessary, the strategy in ruby and Cpp to iterate map/hash + # is different, patchelf v0.10 iterates the replaced_sections sorted by + # keys. + @replaced_sections.sort.each do |rsec_name, rsec_data| + shdr = find_or_create_section_header(rsec_name) + + Logger.debug <<~DEBUG + rewriting section '#{rsec_name}' + from offset 0x#{shdr.sh_offset.to_i.to_s 16}(size #{shdr.sh_size}) + to offset 0x#{cur_off.to_i.to_s 16}(size #{rsec_data.size}) + DEBUG + + with_buf_at(cur_off) { |b| b.write rsec_data } + + orig_sh_offset = shdr.sh_offset.to_i + orig_sh_size = shdr.sh_size.to_i + + shdr.sh_offset = cur_off + shdr.sh_addr = start_addr + (cur_off - start_offset) + shdr.sh_size = rsec_data.size + + write_section_aligment(shdr) + + seg_type = { + '.interp' => ELFTools::Constants::PT_INTERP, + '.dynamic' => ELFTools::Constants::PT_DYNAMIC, + '.MIPS.abiflags' => ELFTools::Constants::PT_MIPS_ABIFLAGS, + '.note.gnu.property' => ELFTools::Constants::PT_GNU_PROPERTY + }[rsec_name] + + phdrs_by_type(seg_type) { |phdr| sync_sec_to_seg(shdr, phdr) } + + if shdr.sh_type == ELFTools::Constants::SHT_NOTE + phdrs_by_type(ELFTools::Constants::PT_NOTE) do |phdr, idx| + next if noted_phdrs.include?(idx) + + s_start = orig_sh_offset + s_end = s_start + orig_sh_size + p_start = phdr.p_offset + p_end = p_start + phdr.p_filesz + + next unless section_bounds_within_segment?(s_start, s_end, p_start, p_end) + + raise PatchError, 'unsupported overlap of SHT_NOTE and PT_NOTE' if p_start != s_start || p_end != s_end + + sync_sec_to_seg(shdr, phdr) + + noted_phdrs << idx + end + end + + cur_off += Helper.alignup(rsec_data.size, @section_alignment) + end + @replaced_sections.clear + + cur_off + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/patchelf-1.4.0/lib/patchelf/cli.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/patchelf-1.4.0/lib/patchelf/cli.rb new file mode 100644 index 0000000000..877406885c --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/patchelf-1.4.0/lib/patchelf/cli.rb @@ -0,0 +1,148 @@ +# frozen_string_literal: true + +require 'optparse' + +require 'patchelf/patcher' +require 'patchelf/version' + +module PatchELF + # For command line interface to parsing arguments. + module CLI + # Name of binary. + SCRIPT_NAME = 'patchelf.rb'.freeze + # CLI usage string. + USAGE = format('Usage: %s FILENAME [OUTPUT_FILE]', SCRIPT_NAME).freeze + + module_function + + # Main method of CLI. + # @param [Array] argv + # Command line arguments. + # @return [void] + # @example + # PatchELF::CLI.work(%w[--help]) + # # usage message to stdout + # PatchELF::CLI.work(%w[--version]) + # # version message to stdout + def work(argv) + @options = { + set: {}, + print: [], + needed: [] + } + return $stdout.puts "PatchELF Version #{PatchELF::VERSION}" if argv.include?('--version') + return $stdout.puts option_parser unless parse(argv) + + # Now the options are (hopefully) valid, let's process the ELF file. + begin + @patcher = PatchELF::Patcher.new(@options[:in_file]) + rescue ELFTools::ELFError, Errno::ENOENT => e + return PatchELF::Logger.error(e.message) + end + patcher.use_rpath! if @options[:force_rpath] + readonly + patch_requests + patcher.save(@options[:out_file]) + end + + private + + def patcher + @patcher + end + + def readonly + @options[:print].uniq.each do |s| + content = patcher.__send__(s) + next if content.nil? + + s = :rpath if @options[:force_rpath] && s == :runpath + $stdout.puts "#{s}: #{Array(content).join(' ')}" + end + end + + def patch_requests + @options[:set].each do |sym, val| + patcher.__send__("#{sym}=".to_sym, val) + end + + @options[:needed].each do |type, val| + patcher.__send__("#{type}_needed".to_sym, *val) + end + end + + def parse(argv) + remain = option_parser.permute(argv) + return false if remain.first.nil? + + @options[:in_file] = remain.first + @options[:out_file] = remain[1] # can be nil + true + end + + def option_parser + @option_parser ||= OptionParser.new do |opts| + opts.banner = USAGE + + opts.on('--print-interpreter', '--pi', 'Show interpreter\'s name.') do + @options[:print] << :interpreter + end + + opts.on('--print-needed', '--pn', 'Show needed libraries specified in DT_NEEDED.') do + @options[:print] << :needed + end + + opts.on('--print-runpath', '--pr', 'Show the path specified in DT_RUNPATH.') do + @options[:print] << :runpath + end + + opts.on('--print-soname', '--ps', 'Show soname specified in DT_SONAME.') do + @options[:print] << :soname + end + + opts.on('--set-interpreter INTERP', '--interp INTERP', 'Set interpreter\'s name.') do |interp| + @options[:set][:interpreter] = interp + end + + opts.on('--set-needed LIB1,LIB2,LIB3', '--needed LIB1,LIB2,LIB3', Array, + 'Set needed libraries, this will remove all existent needed libraries.') do |needs| + @options[:set][:needed] = needs + end + + opts.on('--add-needed LIB', 'Append a new needed library.') do |lib| + @options[:needed] << [:add, lib] + end + + opts.on('--remove-needed LIB', 'Remove a needed library.') do |lib| + @options[:needed] << [:remove, lib] + end + + opts.on('--replace-needed LIB1,LIB2', Array, 'Replace needed library LIB1 as LIB2.') do |libs| + @options[:needed] << [:replace, libs] + end + + opts.on('--set-runpath PATH', '--runpath PATH', 'Set the path of runpath.') do |path| + @options[:set][:runpath] = path + end + + opts.on( + '--force-rpath', + 'According to the ld.so docs, DT_RPATH is obsolete,', + "#{SCRIPT_NAME} will always try to get/set DT_RUNPATH first.", + 'Use this option to force every operations related to runpath (e.g. --runpath)', + 'to consider \'DT_RPATH\' instead of \'DT_RUNPATH\'.' + ) do + @options[:force_rpath] = true + end + + opts.on('--set-soname SONAME', '--so SONAME', 'Set name of a shared library.') do |soname| + @options[:set][:soname] = soname + end + + opts.on('--version', 'Show current gem\'s version.') + end + end + + extend self + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/patchelf-1.4.0/lib/patchelf/exceptions.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/patchelf-1.4.0/lib/patchelf/exceptions.rb new file mode 100644 index 0000000000..3a7b69614f --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/patchelf-1.4.0/lib/patchelf/exceptions.rb @@ -0,0 +1,15 @@ +# encoding: ascii-8bit +# frozen_string_literal: true + +require 'elftools/exceptions' + +module PatchELF + # Raised on an error during ELF modification. + class PatchError < ELFTools::ELFError; end + + # Raised when Dynamic Tag is missing + class MissingTagError < PatchError; end + + # Raised on missing Program Header(segment) + class MissingSegmentError < PatchError; end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/patchelf-1.4.0/lib/patchelf/helper.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/patchelf-1.4.0/lib/patchelf/helper.rb new file mode 100644 index 0000000000..10b740d833 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/patchelf-1.4.0/lib/patchelf/helper.rb @@ -0,0 +1,84 @@ +# frozen_string_literal: true + +module PatchELF + # Helper methods for internal usage. + module Helper + module_function + + # Color codes for pretty print. + COLOR_CODE = { + esc_m: "\e[0m", + info: "\e[38;5;82m", # light green + warn: "\e[38;5;230m", # light yellow + error: "\e[38;5;196m" # heavy red + }.freeze + + # The size of one page. + def page_size(e_machine = nil) + # Different architectures have different minimum section alignments. + case e_machine + when ELFTools::Constants::EM_SPARC, + ELFTools::Constants::EM_MIPS, + ELFTools::Constants::EM_PPC, + ELFTools::Constants::EM_PPC64, + ELFTools::Constants::EM_AARCH64, + ELFTools::Constants::EM_TILEGX, + ELFTools::Constants::EM_LOONGARCH + 0x10000 + else + 0x1000 + end + end + + # For wrapping string with color codes for prettier inspect. + # @param [String] str + # Content to colorize. + # @param [Symbol] type + # Specify which kind of color to use, valid symbols are defined in {.COLOR_CODE}. + # @return [String] + # String that wrapped with color codes. + def colorize(str, type) + return str unless color_enabled? + + cc = COLOR_CODE + color = cc.key?(type) ? cc[type] : '' + "#{color}#{str.sub(COLOR_CODE[:esc_m], color)}#{cc[:esc_m]}" + end + + # For {#colorize} to decide if need add color codes. + # @return [Boolean] + def color_enabled? + $stderr.tty? + end + + # @param [Integer] val + # @param [Integer] align + # @return [Integer] + # Aligned result. + # @example + # aligndown(0x1234) + # #=> 4096 + # aligndown(0x33, 0x20) + # #=> 32 + # aligndown(0x10, 0x8) + # #=> 16 + def aligndown(val, align = page_size) + val - (val & (align - 1)) + end + + # @param [Integer] val + # @param [Integer] align + # @return [Integer] + # Aligned result. + # @example + # alignup(0x1234) + # #=> 8192 + # alignup(0x33, 0x20) + # #=> 64 + # alignup(0x10, 0x8) + # #=> 16 + def alignup(val, align = page_size) + (val & (align - 1)).zero? ? val : (aligndown(val, align) + align) + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/patchelf-1.4.0/lib/patchelf/logger.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/patchelf-1.4.0/lib/patchelf/logger.rb new file mode 100644 index 0000000000..f5a4a1c9ff --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/patchelf-1.4.0/lib/patchelf/logger.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +require 'logger' + +require 'patchelf/helper' + +module PatchELF + # A logger for internal usage. + module Logger + module_function + + @logger = ::Logger.new($stderr).tap do |log| + log.formatter = proc do |severity, _datetime, _progname, msg| + "[#{PatchELF::Helper.colorize(severity, severity.downcase.to_sym)}] #{msg}\n" + end + end + + %i[debug info warn error level=].each do |sym| + define_method(sym) do |msg| + @logger.__send__(sym, msg) + nil + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/patchelf-1.4.0/lib/patchelf/mm.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/patchelf-1.4.0/lib/patchelf/mm.rb new file mode 100644 index 0000000000..ec2b1ea081 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/patchelf-1.4.0/lib/patchelf/mm.rb @@ -0,0 +1,186 @@ +# frozen_string_literal: true + +require 'patchelf/helper' + +module PatchELF + # Memory management, provides malloc/free to allocate LOAD segments. + # @private + class MM + attr_reader :extend_size # @return [Integer] The size extended. + attr_reader :threshold # @return [Integer] Where the file start to be extended. + + # Instantiate a {MM} object. + # @param [ELFTools::ELFFile] elf + def initialize(elf) + @elf = elf + @request = [] + end + + # @param [Integer] size + # @return [void] + # @yieldparam [Integer] off + # @yieldparam [Integer] vaddr + # @yieldreturn [void] + # One can only do the following things in the block: + # 1. Set ELF headers' attributes (with ELFTools) + # 2. Invoke {Saver#inline_patch} + def malloc(size, &block) + raise ArgumentError, 'malloc\'s size most be positive.' if size <= 0 + + @request << [size, block] + end + + # Let the malloc / free requests be effective. + # @return [void] + def dispatch! + return if @request.empty? + + @request_size = @request.map(&:first).inject(0, :+) + # The malloc-ed area must be 'rw-' since the dynamic table will be modified during runtime. + # Find all LOADs and calculate their f-gaps and m-gaps. + # We prefer f-gap since it doesn't need move the whole binaries. + # 1. Find if any f-gap has enough size, and one of the LOAD next to it is 'rw-'. + # - expand (forwardlly), only need to change the attribute of LOAD. + # 2. Do 1. again but consider m-gaps instead. + # - expand (forwardlly), need to modify all section headers. + # 3. We have to create a new LOAD, now we need to expand the first LOAD for putting new segment header. + + # First of all we check if there're less than two LOADs. + abnormal_elf('No LOAD segment found, not an executable.') if load_segments.empty? + # TODO: Handle only one LOAD. (be careful if memsz > filesz) + + fgap_method || mgap_method || new_load_method + end + + # Query if extended. + # @return [Boolean] + def extended? + defined?(@threshold) + end + + # Get correct offset after the extension. + # + # @param [Integer] off + # @return [Integer] + # Shifted offset. + def extended_offset(off) + return off unless defined?(@threshold) + return off if off < @threshold + + off + @extend_size + end + + private + + def fgap_method + idx = find_gap { |prv, nxt| nxt.file_head - prv.file_tail } + return false if idx.nil? + + loads = load_segments + # prefer extend backwardly + return extend_backward(loads[idx - 1]) if writable?(loads[idx - 1]) + + extend_forward(loads[idx]) + end + + def extend_backward(seg, size = @request_size) + invoke_callbacks(seg, seg.file_tail) + seg.header.p_filesz += size + seg.header.p_memsz += size + true + end + + def extend_forward(seg, size = @request_size) + seg.header.p_offset -= size + seg.header.p_vaddr -= size + seg.header.p_filesz += size + seg.header.p_memsz += size + invoke_callbacks(seg, seg.file_head) + true + end + + def mgap_method + # | 1 | | 2 | + # | 1 | | 2 | + #=> + # | 1 | | 2 | + # | 1 | | 2 | + idx = find_gap(check_sz: false) { |prv, nxt| PatchELF::Helper.aligndown(nxt.mem_head) - prv.mem_tail } + return false if idx.nil? + + loads = load_segments + @threshold = loads[idx].file_head + @extend_size = PatchELF::Helper.alignup(@request_size) + shift_attributes + # prefer backward than forward + return extend_backward(loads[idx - 1]) if writable?(loads[idx - 1]) + + # NOTE: loads[idx].file_head has been changed in shift_attributes + extend_forward(loads[idx], @extend_size) + end + + def find_gap(check_sz: true) + loads = load_segments + loads.each_with_index do |l, i| + next if i.zero? + next unless writable?(l) || writable?(loads[i - 1]) + + sz = yield(loads[i - 1], l) + abnormal_elf('LOAD segments are out of order.') if check_sz && sz.negative? + next unless sz >= @request_size + + return i + end + nil + end + + # TODO + def new_load_method + raise NotImplementedError + end + + def writable?(seg) + seg.readable? && seg.writable? + end + + # For all attributes >= threshold, += offset + def shift_attributes + # ELFHeader->section_header + # Sections: + # all + # Segments: + # all + # XXX: will be buggy if someday the number of segments can be changed. + + # Bottom-up + @elf.each_sections do |sec| + sec.header.sh_offset += extend_size if sec.header.sh_offset >= threshold + end + @elf.each_segments do |seg| + next unless seg.header.p_offset >= threshold + + seg.header.p_offset += extend_size + # We have to change align of LOAD segment since ld.so checks it. + seg.header.p_align = Helper.page_size if seg.is_a?(ELFTools::Segments::LoadSegment) + end + + @elf.header.e_shoff += extend_size if @elf.header.e_shoff >= threshold + end + + def load_segments + @elf.segments_by_type(:load) + end + + def invoke_callbacks(seg, start) + cur = start + @request.each do |sz, block| + block.call(cur, seg.offset_to_vma(cur)) + cur += sz + end + end + + def abnormal_elf(msg) + raise ArgumentError, msg + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/patchelf-1.4.0/lib/patchelf/patcher.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/patchelf-1.4.0/lib/patchelf/patcher.rb new file mode 100644 index 0000000000..94da26822b --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/patchelf-1.4.0/lib/patchelf/patcher.rb @@ -0,0 +1,250 @@ +# encoding: ascii-8bit +# frozen_string_literal: true + +require 'elftools/elf_file' + +require 'patchelf/exceptions' +require 'patchelf/logger' +require 'patchelf/saver' + +module PatchELF + # Class to handle all patching things. + class Patcher + # @!macro [new] note_apply + # @note This setting will be saved after {#save} being invoked. + + attr_reader :elf # @return [ELFTools::ELFFile] ELF parser object. + + # Instantiate a {Patcher} object. + # @param [String] filename + # Filename of input ELF. + # @param [Boolean] logging + # *deprecated*: use +on_error+ instead + # @param [:log, :silent, :exception] on_error + # action when the desired segment/tag field isn't present + # :log = logs to stderr + # :exception = raise exception related to the error + # :silent = ignore the errors + def initialize(filename, on_error: :log, logging: true) + @in_file = filename + @elf = ELFTools::ELFFile.new(File.open(filename)) + @set = {} + @rpath_sym = :runpath + @on_error = logging ? on_error : :exception + + on_error_syms = %i[exception log silent] + raise ArgumentError, "on_error must be one of #{on_error_syms}" unless on_error_syms.include?(@on_error) + end + + # @return [String?] + # Get interpreter's name. + # @example + # PatchELF::Patcher.new('/bin/ls').interpreter + # #=> "/lib64/ld-linux-x86-64.so.2" + def interpreter + @set[:interpreter] || interpreter_ + end + + # Set interpreter's name. + # + # If the input ELF has no existent interpreter, + # this method will show a warning and has no effect. + # @param [String] interp + # @macro note_apply + def interpreter=(interp) + return if interpreter_.nil? # will also show warning if there's no interp segment. + + @set[:interpreter] = interp + end + + # Get needed libraries. + # @return [Array] + # @example + # patcher = PatchELF::Patcher.new('/bin/ls') + # patcher.needed + # #=> ["libselinux.so.1", "libc.so.6"] + def needed + @set[:needed] || needed_ + end + + # Set needed libraries. + # @param [Array] needs + # @macro note_apply + def needed=(needs) + @set[:needed] = needs + end + + # Add the needed library. + # @param [String] need + # @return [void] + # @macro note_apply + def add_needed(need) + @set[:needed] ||= needed_ + @set[:needed] << need + end + + # Remove the needed library. + # @param [String] need + # @return [void] + # @macro note_apply + def remove_needed(need) + @set[:needed] ||= needed_ + @set[:needed].delete(need) + end + + # Replace needed library +src+ with +tar+. + # + # @param [String] src + # Library to be replaced. + # @param [String] tar + # Library replace with. + # @return [void] + # @macro note_apply + def replace_needed(src, tar) + @set[:needed] ||= needed_ + @set[:needed].map! { |v| v == src ? tar : v } + end + + # Get the soname of a shared library. + # @return [String?] The name. + # @example + # patcher = PatchELF::Patcher.new('/bin/ls') + # patcher.soname + # # [WARN] Entry DT_SONAME not found, not a shared library? + # #=> nil + # @example + # PatchELF::Patcher.new('/lib/x86_64-linux-gnu/libc.so.6').soname + # #=> "libc.so.6" + def soname + @set[:soname] || soname_ + end + + # Set soname. + # + # If the input ELF is not a shared library with a soname, + # this method will show a warning and has no effect. + # @param [String] name + # @macro note_apply + def soname=(name) + return if soname_.nil? + + @set[:soname] = name + end + + # Get runpath. + # @return [String?] + def runpath + @set[@rpath_sym] || runpath_(@rpath_sym) + end + + # Get rpath + # return [String?] + def rpath + @set[:rpath] || runpath_(:rpath) + end + + # Set rpath + # + # Modify / set DT_RPATH of the given ELF. + # similar to runpath= except DT_RPATH is modifed/created in DYNAMIC segment. + # @param [String] rpath + # @macro note_apply + def rpath=(rpath) + @set[:rpath] = rpath + end + + # Set runpath. + # + # If DT_RUNPATH is not presented in the input ELF, + # a new DT_RUNPATH attribute will be inserted into the DYNAMIC segment. + # @param [String] runpath + # @macro note_apply + def runpath=(runpath) + @set[@rpath_sym] = runpath + end + + # Set all operations related to DT_RUNPATH to use DT_RPATH. + # @return [self] + def use_rpath! + @rpath_sym = :rpath + self + end + + # Save the patched ELF as +out_file+. + # @param [String?] out_file + # If +out_file+ is +nil+, the original input file will be modified. + # @param [Boolean] patchelf_compatible + # When +patchelf_compatible+ is true, tries to produce same ELF as the one produced by NixOS/patchelf. + # @return [void] + def save(out_file = nil, patchelf_compatible: false) + # If nothing is modified, return directly. + return if out_file.nil? && !dirty? + + out_file ||= @in_file + saver = if patchelf_compatible + require 'patchelf/alt_saver' + PatchELF::AltSaver.new(@in_file, out_file, @set) + else + PatchELF::Saver.new(@in_file, out_file, @set) + end + + saver.save! + end + + private + + def log_or_raise(msg, exception = PatchELF::PatchError) + raise exception, msg if @on_error == :exception + + PatchELF::Logger.warn(msg) if @on_error == :log + end + + def interpreter_ + segment = @elf.segment_by_type(:interp) + return log_or_raise 'No interpreter found.', PatchELF::MissingSegmentError if segment.nil? + + segment.interp_name + end + + # @return [Array] + def needed_ + segment = dynamic_or_log + return if segment.nil? + + segment.tags_by_type(:needed).map(&:name) + end + + # @return [String?] + def runpath_(rpath_sym = :runpath) + tag_name_or_log(rpath_sym, "Entry DT_#{rpath_sym.to_s.upcase} not found.") + end + + # @return [String?] + def soname_ + tag_name_or_log(:soname, 'Entry DT_SONAME not found, not a shared library?') + end + + # @return [Boolean] + def dirty? + @set.any? + end + + def tag_name_or_log(type, log_msg) + segment = dynamic_or_log + return if segment.nil? + + tag = segment.tag_by_type(type) + return log_or_raise log_msg, PatchELF::MissingTagError if tag.nil? + + tag.name + end + + def dynamic_or_log + @elf.segment_by_type(:dynamic).tap do |s| + if s.nil? + log_or_raise 'DYNAMIC segment not found, might be a statically-linked ELF?', PatchELF::MissingSegmentError + end + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/patchelf-1.4.0/lib/patchelf/saver.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/patchelf-1.4.0/lib/patchelf/saver.rb new file mode 100644 index 0000000000..0da2b11e17 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/patchelf-1.4.0/lib/patchelf/saver.rb @@ -0,0 +1,282 @@ +# frozen_string_literal: true + +require 'elftools/constants' +require 'elftools/elf_file' +require 'elftools/structs' +require 'elftools/util' +require 'fileutils' + +require 'patchelf/mm' + +module PatchELF + # Internal use only. + # + # For {Patcher} to do patching things and save to file. + # @private + class Saver + attr_reader :in_file # @return [String] Input filename. + attr_reader :out_file # @return [String] Output filename. + + # Instantiate a {Saver} object. + # @param [String] in_file + # @param [String] out_file + # @param [{Symbol => String, Array}] set + def initialize(in_file, out_file, set) + @in_file = in_file + @out_file = out_file + @set = set + # [{Integer => String}] + @inline_patch = {} + @elf = ELFTools::ELFFile.new(File.open(in_file)) + @mm = PatchELF::MM.new(@elf) + @strtab_extend_requests = [] + @append_dyn = [] + end + + # @return [void] + def save! + # In this method we assume all attributes that should exist do exist. + # e.g. DT_INTERP, DT_DYNAMIC. These should have been checked in the patcher. + patch_interpreter + patch_dynamic + + @mm.dispatch! + + FileUtils.cp(in_file, out_file) if out_file != in_file + patch_out(@out_file) + # Let output file have the same permission as input. + FileUtils.chmod(File.stat(in_file).mode, out_file) + end + + private + + def patch_interpreter + return if @set[:interpreter].nil? + + new_interp = "#{@set[:interpreter]}\x00" + old_interp = "#{@elf.segment_by_type(:interp).interp_name}\x00" + return if old_interp == new_interp + + # These headers must be found here but not in the proc. + seg_header = @elf.segment_by_type(:interp).header + sec_header = section_header('.interp') + + patch = proc do |off, vaddr| + # Register an inline patching + inline_patch(off, new_interp) + + # The patching feature of ELFTools + seg_header.p_offset = off + seg_header.p_vaddr = seg_header.p_paddr = vaddr + seg_header.p_filesz = seg_header.p_memsz = new_interp.size + + if sec_header + sec_header.sh_offset = off + sec_header.sh_size = new_interp.size + end + end + + if new_interp.size <= old_interp.size + # easy case + patch.call(seg_header.p_offset.to_i, seg_header.p_vaddr.to_i) + else + # hard case, we have to request a new LOAD area + @mm.malloc(new_interp.size, &patch) + end + end + + def patch_dynamic + # We never do inline patching on strtab's string. + # 1. Search if there's useful string exists + # - only need header patching + # 2. Append a new string to the strtab. + # - register strtab extension + dynamic.tags # HACK, force @tags to be defined + patch_soname if @set[:soname] + patch_runpath if @set[:runpath] + patch_runpath(:rpath) if @set[:rpath] + patch_needed if @set[:needed] + malloc_strtab! + expand_dynamic! + end + + def patch_soname + # The tag must exist. + so_tag = dynamic.tag_by_type(:soname) + reg_str_table(@set[:soname]) do |idx| + so_tag.header.d_val = idx + end + end + + def patch_runpath(sym = :runpath) + tag = dynamic.tag_by_type(sym) + tag = tag.nil? ? lazy_dyn(sym) : tag.header + reg_str_table(@set[sym]) do |idx| + tag.d_val = idx + end + end + + # To mark a not-using tag + IGNORE = ELFTools::Constants::DT_LOOS + def patch_needed + original_needs = dynamic.tags_by_type(:needed) + @set[:needed].uniq! + + original = original_needs.map(&:name) + replace = @set[:needed] + + # 3 sets: + # 1. in original and in needs - remain unchanged + # 2. in original but not in needs - remove + # 3. not in original and in needs - append + append = replace - original + remove = original - replace + + ignored_dyns = remove.each_with_object([]) do |name, ignored| + dyn = original_needs.find { |n| n.name == name }.header + dyn.d_tag = IGNORE + ignored << dyn + end + + append.zip(ignored_dyns) do |name, ignored_dyn| + dyn = ignored_dyn || lazy_dyn(:needed) + dyn.d_tag = ELFTools::Constants::DT_NEEDED + reg_str_table(name) { |idx| dyn.d_val = idx } + end + end + + # Create a temp tag header. + # @return [ELFTools::Structs::ELF_Dyn] + def lazy_dyn(sym) + ELFTools::Structs::ELF_Dyn.new(endian: @elf.endian).tap do |dyn| + @append_dyn << dyn + dyn.elf_class = @elf.elf_class + dyn.d_tag = ELFTools::Util.to_constant(ELFTools::Constants::DT, sym) + end + end + + def expand_dynamic! + return if @append_dyn.empty? + + dyn_sec = section_header('.dynamic') + total = dynamic.tags.map(&:header) + # the last must be a null-tag + total = total[0..-2] + @append_dyn + [total.last] + bytes = total.first.num_bytes * total.size + @mm.malloc(bytes) do |off, vaddr| + inline_patch(off, total.map(&:to_binary_s).join) + dynamic.header.p_offset = off + dynamic.header.p_vaddr = dynamic.header.p_paddr = vaddr + dynamic.header.p_filesz = dynamic.header.p_memsz = bytes + if dyn_sec + dyn_sec.sh_offset = off + dyn_sec.sh_addr = vaddr + dyn_sec.sh_size = bytes + end + end + end + + def malloc_strtab! + return if @strtab_extend_requests.empty? + + strtab = dynamic.tag_by_type(:strtab) + # Process registered requests + need_size = strtab_string.size + @strtab_extend_requests.reduce(0) { |sum, (str, _)| sum + str.size + 1 } + dynstr = section_header('.dynstr') + @mm.malloc(need_size) do |off, vaddr| + new_str = "#{strtab_string}#{@strtab_extend_requests.map(&:first).join("\x00")}\x00" + inline_patch(off, new_str) + cur = strtab_string.size + @strtab_extend_requests.each do |str, block| + block.call(cur) + cur += str.size + 1 + end + # Now patching strtab header + strtab.header.d_val = vaddr + # We also need to patch dynstr to let readelf have correct output. + if dynstr + dynstr.sh_size = new_str.size + dynstr.sh_offset = off + dynstr.sh_addr = vaddr + end + end + end + + # @param [String] str + # @yieldparam [Integer] idx + # @yieldreturn [void] + def reg_str_table(str, &block) + idx = strtab_string.index("#{str}\x00") + # Request string is already exist + return yield idx if idx + + # Record the request + @strtab_extend_requests << [str, block] + end + + def strtab_string + return @strtab_string if defined?(@strtab_string) + + # TODO: handle no strtab exists.. + offset = @elf.offset_from_vma(dynamic.tag_by_type(:strtab).value) + # This is a little tricky since no length information is stored in the tag. + # We first get the file offset of the string then 'guess' where the end is. + @elf.stream.pos = offset + @strtab_string = +'' + loop do + c = @elf.stream.read(1) + break unless c =~ /\x00|[[:print:]]/ + + @strtab_string << c + end + @strtab_string + end + + # This can only be used for patching interpreter's name + # or set strings in a malloc-ed area. + # i.e. NEVER intend to change the string defined in strtab + def inline_patch(off, str) + @inline_patch[off] = str + end + + # Modify the out_file according to registered patches. + def patch_out(out_file) + File.open(out_file, 'r+') do |f| + if @mm.extended? + original_head = @mm.threshold + extra = {} + # Copy all data after the second load + @elf.stream.pos = original_head + extra[original_head + @mm.extend_size] = @elf.stream.read # read to end + # zero out the 'gap' we created + extra[original_head] = "\x00" * @mm.extend_size + extra.each do |pos, str| + f.pos = pos + f.write(str) + end + end + @elf.patches.each do |pos, str| + f.pos = @mm.extended_offset(pos) + f.write(str) + end + + @inline_patch.each do |pos, str| + f.pos = pos + f.write(str) + end + end + end + + # @return [ELFTools::Sections::Section?] + def section_header(name) + sec = @elf.section_by_name(name) + return if sec.nil? + + sec.header + end + + def dynamic + @dynamic ||= @elf.segment_by_type(:dynamic) + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/patchelf-1.4.0/lib/patchelf/version.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/patchelf-1.4.0/lib/patchelf/version.rb new file mode 100644 index 0000000000..fb223bc4fa --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/patchelf-1.4.0/lib/patchelf/version.rb @@ -0,0 +1,6 @@ +# frozen_string_literal: true + +module PatchELF + # Current gem version. + VERSION = '1.4.0'.freeze +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/plist-3.7.0/LICENSE.txt b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/plist-3.7.0/LICENSE.txt new file mode 100644 index 0000000000..0ccffe7bf3 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/plist-3.7.0/LICENSE.txt @@ -0,0 +1,20 @@ +Copyright (c) 2006-2010, Ben Bleything and Patrick May + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/plist-3.7.0/lib/plist.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/plist-3.7.0/lib/plist.rb new file mode 100644 index 0000000000..2304992dfa --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/plist-3.7.0/lib/plist.rb @@ -0,0 +1,18 @@ +# encoding: utf-8 + +# = plist +# +# This is the main file for plist. Everything interesting happens in +# Plist and Plist::Emit. +# +# Copyright 2006-2010 Ben Bleything and Patrick May +# Distributed under the MIT License +# + +require 'base64' +require 'cgi' +require 'stringio' + +require_relative 'plist/generator' +require_relative 'plist/parser' +require_relative 'plist/version' diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/plist-3.7.0/lib/plist/generator.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/plist-3.7.0/lib/plist/generator.rb new file mode 100644 index 0000000000..0b8af54b3f --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/plist-3.7.0/lib/plist/generator.rb @@ -0,0 +1,180 @@ +# encoding: utf-8 + +# = plist +# +# Copyright 2006-2010 Ben Bleything and Patrick May +# Distributed under the MIT License +# + +module Plist + # === Create a plist + # You can dump an object to a plist in one of two ways: + # + # * Plist::Emit.dump(obj) + # * obj.to_plist + # * This requires that you mixin the Plist::Emit module, which is already done for +Array+ and +Hash+. + # + # The following Ruby classes are converted into native plist types: + # Array, Bignum, Date, DateTime, Fixnum, Float, Hash, Integer, String, Symbol, Time, true, false + # * +Array+ and +Hash+ are both recursive; their elements will be converted into plist nodes inside the and containers (respectively). + # * +IO+ (and its descendants) and +StringIO+ objects are read from and their contents placed in a element. + # * User classes may implement +to_plist_node+ to dictate how they should be serialized; otherwise the object will be passed to Marshal.dump and the result placed in a element. + # + # For detailed usage instructions, refer to USAGE[link:files/docs/USAGE.html] and the methods documented below. + module Emit + DEFAULT_INDENT = "\t" + + # Helper method for injecting into classes. Calls Plist::Emit.dump with +self+. + def to_plist(envelope = true, options = {}) + Plist::Emit.dump(self, envelope, options) + end + + # Helper method for injecting into classes. Calls Plist::Emit.save_plist with +self+. + def save_plist(filename, options = {}) + Plist::Emit.save_plist(self, filename, options) + end + + # The following Ruby classes are converted into native plist types: + # Array, Bignum, Date, DateTime, Fixnum, Float, Hash, Integer, String, Symbol, Time + # + # Write us (via RubyForge) if you think another class can be coerced safely into one of the expected plist classes. + # + # +IO+ and +StringIO+ objects are encoded and placed in elements; other objects are Marshal.dump'ed unless they implement +to_plist_node+. + # + # The +envelope+ parameters dictates whether or not the resultant plist fragment is wrapped in the normal XML/plist header and footer. Set it to false if you only want the fragment. + def self.dump(obj, envelope = true, options = {}) + options = { :indent => DEFAULT_INDENT }.merge(options) + + output = PlistBuilder.new(options[:indent]).build(obj) + output = wrap(output) if envelope + + output + end + + # Writes the serialized object's plist to the specified filename. + def self.save_plist(obj, filename, options = {}) + File.open(filename, 'wb') do |f| + f.write(obj.to_plist(true, options)) + end + end + + private + + class PlistBuilder + def initialize(indent_str) + @indent_str = indent_str.to_s + end + + def build(element, level=0) + if element.respond_to? :to_plist_node + element.to_plist_node + else + case element + when Array + if element.empty? + tag('array', nil, level) + else + tag('array', nil, level) { + element.collect {|e| build(e, level + 1) }.join + } + end + when Hash + if element.empty? + tag('dict', nil, level) + else + tag('dict', '', level) do + element.sort_by{|k,v| k.to_s }.collect do |k,v| + tag('key', CGI.escapeHTML(k.to_s), level + 1) + + build(v, level + 1) + end.join + end + end + when true, false + tag(element, nil, level) + when Time + tag('date', element.utc.strftime('%Y-%m-%dT%H:%M:%SZ'), level) + when Date # also catches DateTime + tag('date', element.strftime('%Y-%m-%dT%H:%M:%SZ'), level) + when String, Symbol, Integer, Float + tag(element_type(element), CGI.escapeHTML(element.to_s), level) + when IO, StringIO + data = element.tap(&:rewind).read + data_tag(data, level) + else + data = Marshal.dump(element) + comment_tag('The element below contains a Ruby object which has been serialized with Marshal.dump.') + + data_tag(data, level) + end + end + end + + private + + def tag(type, contents, level, &block) + if block_given? + indent("<#{type}>\n", level) + + block.call + + indent("\n", level) + elsif contents.to_s.empty? + indent("<#{type}/>\n", level) + else + indent("<#{type}>#{contents.to_s}\n", level) + end + end + + def data_tag(data, level) + # note that apple plists are wrapped at a different length then + # what ruby's base64 wraps by default. + # I used #encode64 instead of #b64encode (which allows a length arg) + # because b64encode is b0rked and ignores the length arg. + tag('data', nil, level) do + Base64.encode64(data) + .gsub(/\s+/, '') + .scan(/.{1,68}/o) + .collect { |line| indent(line, level) } + .join("\n") + .concat("\n") + end + end + + def indent(str, level) + @indent_str.to_s * level + str + end + + def element_type(item) + case item + when String, Symbol + 'string' + when Integer + 'integer' + when Float + 'real' + else + raise "Don't know about this data type... something must be wrong!" + end + end + + def comment_tag(content) + return "\n" + end + end + + def self.wrap(contents) + output = '' + "\n" + output << '' + "\n" + output << '' + "\n" + output << contents + output << '' + "\n" + + output + end + end +end + +class Array #:nodoc: + include Plist::Emit +end + +class Hash #:nodoc: + include Plist::Emit +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/plist-3.7.0/lib/plist/parser.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/plist-3.7.0/lib/plist/parser.rb new file mode 100755 index 0000000000..6b83ed42ed --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/plist-3.7.0/lib/plist/parser.rb @@ -0,0 +1,263 @@ +# encoding: utf-8 + +# = plist +# +# Copyright 2006-2010 Ben Bleything and Patrick May +# Distributed under the MIT License +# + +# Plist parses Mac OS X xml property list files into ruby data structures. +# +# === Load a plist file +# This is the main point of the library: +# +# r = Plist.parse_xml(filename_or_xml) +module Plist + # Raised when an element is not implemented + class UnimplementedElementError < RuntimeError; end + + # Note that I don't use these two elements much: + # + # + Date elements are returned as DateTime objects. + # + Data elements are implemented as Tempfiles + # + # Plist.parse_xml will blow up if it encounters a Date element. + # If you encounter such an error, or if you have a Date element which + # can't be parsed into a Time object, please create an issue + # attaching your plist file at https://github.com/patsplat/plist/issues + # so folks can implement the proper support. + # + # By default, will be assumed to be a marshaled Ruby object and + # interpreted with Marshal.load. Pass marshal: false + # to disable this behavior and return the raw binary data as an IO + # object instead. + def self.parse_xml(filename_or_xml, options={}) + listener = Listener.new(options) + # parser = REXML::Parsers::StreamParser.new(File.new(filename), listener) + parser = StreamParser.new(filename_or_xml, listener) + parser.parse + listener.result + end + + class Listener + # include REXML::StreamListener + + attr_accessor :result, :open + + def initialize(options={}) + @result = nil + @open = [] + @options = { :marshal => true }.merge(options).freeze + end + + def tag_start(name, attributes) + @open.push PTag.mappings[name].new(@options) + end + + def text(contents) + if @open.last + @open.last.text ||= '' + @open.last.text.concat(contents) + end + end + + def tag_end(name) + last = @open.pop + if @open.empty? + @result = last.to_ruby + else + @open.last.children.push last + end + end + end + + class StreamParser + def initialize(plist_data_or_file, listener) + if plist_data_or_file.respond_to? :read + @xml = plist_data_or_file.read + elsif File.exist? plist_data_or_file + @xml = File.read(plist_data_or_file) + else + @xml = plist_data_or_file + end + + @listener = listener + end + + TEXT = /([^<]+)/ + CDATA = // + XMLDECL_PATTERN = /<\?xml\s+(.*?)\?>*/m + DOCTYPE_PATTERN = /\s*)/m + COMMENT_START = /\A/m + UNIMPLEMENTED_ERROR = 'Unimplemented element. ' \ + 'Consider reporting via https://github.com/patsplat/plist/issues' + + def parse + plist_tags = PTag.mappings.keys.join('|') + start_tag = /<(#{plist_tags})([^>]*)>/i + end_tag = /<\/(#{plist_tags})[^>]*>/i + + require 'strscan' + + @scanner = StringScanner.new(@xml) + until @scanner.eos? + if @scanner.scan(COMMENT_START) + @scanner.scan(COMMENT_END) + elsif @scanner.scan(XMLDECL_PATTERN) + encoding = parse_encoding_from_xml_declaration(@scanner[1]) + next if encoding.nil? + + # use the specified encoding for the rest of the file + next unless String.method_defined?(:force_encoding) + @scanner.string = @scanner.rest.force_encoding(encoding) + elsif @scanner.scan(DOCTYPE_PATTERN) + next + elsif @scanner.scan(start_tag) + @listener.tag_start(@scanner[1], nil) + if (@scanner[2] =~ /\/$/) + @listener.tag_end(@scanner[1]) + end + elsif @scanner.scan(TEXT) + @listener.text(@scanner[1]) + elsif @scanner.scan(CDATA) + @listener.text(@scanner[1]) + elsif @scanner.scan(end_tag) + @listener.tag_end(@scanner[1]) + else + raise UnimplementedElementError.new(UNIMPLEMENTED_ERROR) + end + end + end + + private + + def parse_encoding_from_xml_declaration(xml_declaration) + return unless defined?(Encoding) + + xml_encoding = xml_declaration.match(/(?:\A|\s)encoding=(?:"(.*?)"|'(.*?)')(?:\s|\Z)/) + + return if xml_encoding.nil? + + begin + Encoding.find(xml_encoding[1]) + rescue ArgumentError + nil + end + end + end + + class PTag + def self.mappings + @mappings ||= {} + end + + def self.inherited(sub_class) + key = sub_class.to_s.downcase + key.gsub!(/^plist::/, '') + key.gsub!(/^p/, '') unless key == "plist" + + mappings[key] = sub_class + end + + attr_accessor :text, :children, :options + def initialize(options) + @children = [] + @options = options + end + + def to_ruby + raise "Unimplemented: " + self.class.to_s + "#to_ruby on #{self.inspect}" + end + end + + class PList < PTag + def to_ruby + children.first.to_ruby if children.first + end + end + + class PDict < PTag + def to_ruby + dict = {} + key = nil + + children.each do |c| + if key.nil? + key = c.to_ruby + else + dict[key] = c.to_ruby + key = nil + end + end + + dict + end + end + + class PKey < PTag + def to_ruby + CGI.unescapeHTML(text || '') + end + end + + class PString < PTag + def to_ruby + CGI.unescapeHTML(text || '') + end + end + + class PArray < PTag + def to_ruby + children.collect do |c| + c.to_ruby + end + end + end + + class PInteger < PTag + def to_ruby + text.to_i + end + end + + class PTrue < PTag + def to_ruby + true + end + end + + class PFalse < PTag + def to_ruby + false + end + end + + class PReal < PTag + def to_ruby + text.to_f + end + end + + require 'date' + class PDate < PTag + def to_ruby + DateTime.parse(text) + end + end + + require 'base64' + class PData < PTag + def to_ruby + data = Base64.decode64(text.gsub(/\s+/, '')) unless text.nil? + begin + return Marshal.load(data) if options[:marshal] + rescue Exception + end + io = StringIO.new + io.write data + io.rewind + io + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/plist-3.7.0/lib/plist/version.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/plist-3.7.0/lib/plist/version.rb new file mode 100644 index 0000000000..4d1d5685f6 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/plist-3.7.0/lib/plist/version.rb @@ -0,0 +1,5 @@ +# encoding: utf-8 + +module Plist + VERSION = '3.7.0'.freeze +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/public_suffix-5.0.4/LICENSE.txt b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/public_suffix-5.0.4/LICENSE.txt new file mode 100644 index 0000000000..0909dd4133 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/public_suffix-5.0.4/LICENSE.txt @@ -0,0 +1,22 @@ +Copyright (c) 2009-2023 Simone Carletti + +MIT License + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/public_suffix-5.0.4/data/list.txt b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/public_suffix-5.0.4/data/list.txt new file mode 100644 index 0000000000..fff6e9a494 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/public_suffix-5.0.4/data/list.txt @@ -0,0 +1,15431 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +// Please pull this list from, and only from https://publicsuffix.org/list/public_suffix_list.dat, +// rather than any other VCS sites. Pulling from any other URL is not guaranteed to be supported. + +// Instructions on pulling and using this list can be found at https://publicsuffix.org/list/. + +// ===BEGIN ICANN DOMAINS=== + +// ac : http://nic.ac/rules.htm +ac +com.ac +edu.ac +gov.ac +net.ac +mil.ac +org.ac + +// ad : https://en.wikipedia.org/wiki/.ad +ad +nom.ad + +// ae : https://tdra.gov.ae/en/aeda/ae-policies +ae +co.ae +net.ae +org.ae +sch.ae +ac.ae +gov.ae +mil.ae + +// aero : see https://www.information.aero/index.php?id=66 +aero +accident-investigation.aero +accident-prevention.aero +aerobatic.aero +aeroclub.aero +aerodrome.aero +agents.aero +aircraft.aero +airline.aero +airport.aero +air-surveillance.aero +airtraffic.aero +air-traffic-control.aero +ambulance.aero +amusement.aero +association.aero +author.aero +ballooning.aero +broker.aero +caa.aero +cargo.aero +catering.aero +certification.aero +championship.aero +charter.aero +civilaviation.aero +club.aero +conference.aero +consultant.aero +consulting.aero +control.aero +council.aero +crew.aero +design.aero +dgca.aero +educator.aero +emergency.aero +engine.aero +engineer.aero +entertainment.aero +equipment.aero +exchange.aero +express.aero +federation.aero +flight.aero +fuel.aero +gliding.aero +government.aero +groundhandling.aero +group.aero +hanggliding.aero +homebuilt.aero +insurance.aero +journal.aero +journalist.aero +leasing.aero +logistics.aero +magazine.aero +maintenance.aero +media.aero +microlight.aero +modelling.aero +navigation.aero +parachuting.aero +paragliding.aero +passenger-association.aero +pilot.aero +press.aero +production.aero +recreation.aero +repbody.aero +res.aero +research.aero +rotorcraft.aero +safety.aero +scientist.aero +services.aero +show.aero +skydiving.aero +software.aero +student.aero +trader.aero +trading.aero +trainer.aero +union.aero +workinggroup.aero +works.aero + +// af : http://www.nic.af/help.jsp +af +gov.af +com.af +org.af +net.af +edu.af + +// ag : http://www.nic.ag/prices.htm +ag +com.ag +org.ag +net.ag +co.ag +nom.ag + +// ai : http://nic.com.ai/ +ai +off.ai +com.ai +net.ai +org.ai + +// al : http://www.ert.gov.al/ert_alb/faq_det.html?Id=31 +al +com.al +edu.al +gov.al +mil.al +net.al +org.al + +// am : https://www.amnic.net/policy/en/Policy_EN.pdf +am +co.am +com.am +commune.am +net.am +org.am + +// ao : https://en.wikipedia.org/wiki/.ao +// http://www.dns.ao/REGISTR.DOC +ao +ed.ao +gv.ao +og.ao +co.ao +pb.ao +it.ao + +// aq : https://en.wikipedia.org/wiki/.aq +aq + +// ar : https://nic.ar/es/nic-argentina/normativa +ar +bet.ar +com.ar +coop.ar +edu.ar +gob.ar +gov.ar +int.ar +mil.ar +musica.ar +mutual.ar +net.ar +org.ar +senasa.ar +tur.ar + +// arpa : https://en.wikipedia.org/wiki/.arpa +// Confirmed by registry 2008-06-18 +arpa +e164.arpa +in-addr.arpa +ip6.arpa +iris.arpa +uri.arpa +urn.arpa + +// as : https://en.wikipedia.org/wiki/.as +as +gov.as + +// asia : https://en.wikipedia.org/wiki/.asia +asia + +// at : https://en.wikipedia.org/wiki/.at +// Confirmed by registry 2008-06-17 +at +ac.at +co.at +gv.at +or.at +sth.ac.at + +// au : https://en.wikipedia.org/wiki/.au +// http://www.auda.org.au/ +au +// 2LDs +com.au +net.au +org.au +edu.au +gov.au +asn.au +id.au +// Historic 2LDs (closed to new registration, but sites still exist) +info.au +conf.au +oz.au +// CGDNs - http://www.cgdn.org.au/ +act.au +nsw.au +nt.au +qld.au +sa.au +tas.au +vic.au +wa.au +// 3LDs +act.edu.au +catholic.edu.au +// eq.edu.au - Removed at the request of the Queensland Department of Education +nsw.edu.au +nt.edu.au +qld.edu.au +sa.edu.au +tas.edu.au +vic.edu.au +wa.edu.au +// act.gov.au Bug 984824 - Removed at request of Greg Tankard +// nsw.gov.au Bug 547985 - Removed at request of +// nt.gov.au Bug 940478 - Removed at request of Greg Connors +qld.gov.au +sa.gov.au +tas.gov.au +vic.gov.au +wa.gov.au +// 4LDs +// education.tas.edu.au - Removed at the request of the Department of Education Tasmania +schools.nsw.edu.au + +// aw : https://en.wikipedia.org/wiki/.aw +aw +com.aw + +// ax : https://en.wikipedia.org/wiki/.ax +ax + +// az : https://en.wikipedia.org/wiki/.az +az +com.az +net.az +int.az +gov.az +org.az +edu.az +info.az +pp.az +mil.az +name.az +pro.az +biz.az + +// ba : http://nic.ba/users_data/files/pravilnik_o_registraciji.pdf +ba +com.ba +edu.ba +gov.ba +mil.ba +net.ba +org.ba + +// bb : https://en.wikipedia.org/wiki/.bb +bb +biz.bb +co.bb +com.bb +edu.bb +gov.bb +info.bb +net.bb +org.bb +store.bb +tv.bb + +// bd : https://en.wikipedia.org/wiki/.bd +*.bd + +// be : https://en.wikipedia.org/wiki/.be +// Confirmed by registry 2008-06-08 +be +ac.be + +// bf : https://en.wikipedia.org/wiki/.bf +bf +gov.bf + +// bg : https://en.wikipedia.org/wiki/.bg +// https://www.register.bg/user/static/rules/en/index.html +bg +a.bg +b.bg +c.bg +d.bg +e.bg +f.bg +g.bg +h.bg +i.bg +j.bg +k.bg +l.bg +m.bg +n.bg +o.bg +p.bg +q.bg +r.bg +s.bg +t.bg +u.bg +v.bg +w.bg +x.bg +y.bg +z.bg +0.bg +1.bg +2.bg +3.bg +4.bg +5.bg +6.bg +7.bg +8.bg +9.bg + +// bh : https://en.wikipedia.org/wiki/.bh +bh +com.bh +edu.bh +net.bh +org.bh +gov.bh + +// bi : https://en.wikipedia.org/wiki/.bi +// http://whois.nic.bi/ +bi +co.bi +com.bi +edu.bi +or.bi +org.bi + +// biz : https://en.wikipedia.org/wiki/.biz +biz + +// bj : https://nic.bj/bj-suffixes.txt +// submitted by registry +bj +africa.bj +agro.bj +architectes.bj +assur.bj +avocats.bj +co.bj +com.bj +eco.bj +econo.bj +edu.bj +info.bj +loisirs.bj +money.bj +net.bj +org.bj +ote.bj +resto.bj +restaurant.bj +tourism.bj +univ.bj + +// bm : http://www.bermudanic.bm/dnr-text.txt +bm +com.bm +edu.bm +gov.bm +net.bm +org.bm + +// bn : http://www.bnnic.bn/faqs +bn +com.bn +edu.bn +gov.bn +net.bn +org.bn + +// bo : https://nic.bo/delegacion2015.php#h-1.10 +bo +com.bo +edu.bo +gob.bo +int.bo +org.bo +net.bo +mil.bo +tv.bo +web.bo +// Social Domains +academia.bo +agro.bo +arte.bo +blog.bo +bolivia.bo +ciencia.bo +cooperativa.bo +democracia.bo +deporte.bo +ecologia.bo +economia.bo +empresa.bo +indigena.bo +industria.bo +info.bo +medicina.bo +movimiento.bo +musica.bo +natural.bo +nombre.bo +noticias.bo +patria.bo +politica.bo +profesional.bo +plurinacional.bo +pueblo.bo +revista.bo +salud.bo +tecnologia.bo +tksat.bo +transporte.bo +wiki.bo + +// br : http://registro.br/dominio/categoria.html +// Submitted by registry +br +9guacu.br +abc.br +adm.br +adv.br +agr.br +aju.br +am.br +anani.br +aparecida.br +app.br +arq.br +art.br +ato.br +b.br +barueri.br +belem.br +bhz.br +bib.br +bio.br +blog.br +bmd.br +boavista.br +bsb.br +campinagrande.br +campinas.br +caxias.br +cim.br +cng.br +cnt.br +com.br +contagem.br +coop.br +coz.br +cri.br +cuiaba.br +curitiba.br +def.br +des.br +det.br +dev.br +ecn.br +eco.br +edu.br +emp.br +enf.br +eng.br +esp.br +etc.br +eti.br +far.br +feira.br +flog.br +floripa.br +fm.br +fnd.br +fortal.br +fot.br +foz.br +fst.br +g12.br +geo.br +ggf.br +goiania.br +gov.br +// gov.br 26 states + df https://en.wikipedia.org/wiki/States_of_Brazil +ac.gov.br +al.gov.br +am.gov.br +ap.gov.br +ba.gov.br +ce.gov.br +df.gov.br +es.gov.br +go.gov.br +ma.gov.br +mg.gov.br +ms.gov.br +mt.gov.br +pa.gov.br +pb.gov.br +pe.gov.br +pi.gov.br +pr.gov.br +rj.gov.br +rn.gov.br +ro.gov.br +rr.gov.br +rs.gov.br +sc.gov.br +se.gov.br +sp.gov.br +to.gov.br +gru.br +imb.br +ind.br +inf.br +jab.br +jampa.br +jdf.br +joinville.br +jor.br +jus.br +leg.br +lel.br +log.br +londrina.br +macapa.br +maceio.br +manaus.br +maringa.br +mat.br +med.br +mil.br +morena.br +mp.br +mus.br +natal.br +net.br +niteroi.br +*.nom.br +not.br +ntr.br +odo.br +ong.br +org.br +osasco.br +palmas.br +poa.br +ppg.br +pro.br +psc.br +psi.br +pvh.br +qsl.br +radio.br +rec.br +recife.br +rep.br +ribeirao.br +rio.br +riobranco.br +riopreto.br +salvador.br +sampa.br +santamaria.br +santoandre.br +saobernardo.br +saogonca.br +seg.br +sjc.br +slg.br +slz.br +sorocaba.br +srv.br +taxi.br +tc.br +tec.br +teo.br +the.br +tmp.br +trd.br +tur.br +tv.br +udi.br +vet.br +vix.br +vlog.br +wiki.br +zlg.br + +// bs : http://www.nic.bs/rules.html +bs +com.bs +net.bs +org.bs +edu.bs +gov.bs + +// bt : https://en.wikipedia.org/wiki/.bt +bt +com.bt +edu.bt +gov.bt +net.bt +org.bt + +// bv : No registrations at this time. +// Submitted by registry +bv + +// bw : https://en.wikipedia.org/wiki/.bw +// http://www.gobin.info/domainname/bw.doc +// list of other 2nd level tlds ? +bw +co.bw +org.bw + +// by : https://en.wikipedia.org/wiki/.by +// http://tld.by/rules_2006_en.html +// list of other 2nd level tlds ? +by +gov.by +mil.by +// Official information does not indicate that com.by is a reserved +// second-level domain, but it's being used as one (see www.google.com.by and +// www.yahoo.com.by, for example), so we list it here for safety's sake. +com.by + +// http://hoster.by/ +of.by + +// bz : https://en.wikipedia.org/wiki/.bz +// http://www.belizenic.bz/ +bz +com.bz +net.bz +org.bz +edu.bz +gov.bz + +// ca : https://en.wikipedia.org/wiki/.ca +ca +// ca geographical names +ab.ca +bc.ca +mb.ca +nb.ca +nf.ca +nl.ca +ns.ca +nt.ca +nu.ca +on.ca +pe.ca +qc.ca +sk.ca +yk.ca +// gc.ca: https://en.wikipedia.org/wiki/.gc.ca +// see also: http://registry.gc.ca/en/SubdomainFAQ +gc.ca + +// cat : https://en.wikipedia.org/wiki/.cat +cat + +// cc : https://en.wikipedia.org/wiki/.cc +cc + +// cd : https://en.wikipedia.org/wiki/.cd +// see also: https://www.nic.cd/domain/insertDomain_2.jsp?act=1 +cd +gov.cd + +// cf : https://en.wikipedia.org/wiki/.cf +cf + +// cg : https://en.wikipedia.org/wiki/.cg +cg + +// ch : https://en.wikipedia.org/wiki/.ch +ch + +// ci : https://en.wikipedia.org/wiki/.ci +// http://www.nic.ci/index.php?page=charte +ci +org.ci +or.ci +com.ci +co.ci +edu.ci +ed.ci +ac.ci +net.ci +go.ci +asso.ci +aéroport.ci +int.ci +presse.ci +md.ci +gouv.ci + +// ck : https://en.wikipedia.org/wiki/.ck +*.ck +!www.ck + +// cl : https://www.nic.cl +// Confirmed by .CL registry +cl +co.cl +gob.cl +gov.cl +mil.cl + +// cm : https://en.wikipedia.org/wiki/.cm plus bug 981927 +cm +co.cm +com.cm +gov.cm +net.cm + +// cn : https://en.wikipedia.org/wiki/.cn +// Submitted by registry +cn +ac.cn +com.cn +edu.cn +gov.cn +net.cn +org.cn +mil.cn +公司.cn +网络.cn +網絡.cn +// cn geographic names +ah.cn +bj.cn +cq.cn +fj.cn +gd.cn +gs.cn +gz.cn +gx.cn +ha.cn +hb.cn +he.cn +hi.cn +hl.cn +hn.cn +jl.cn +js.cn +jx.cn +ln.cn +nm.cn +nx.cn +qh.cn +sc.cn +sd.cn +sh.cn +sn.cn +sx.cn +tj.cn +xj.cn +xz.cn +yn.cn +zj.cn +hk.cn +mo.cn +tw.cn + +// co : https://en.wikipedia.org/wiki/.co +// Submitted by registry +co +arts.co +com.co +edu.co +firm.co +gov.co +info.co +int.co +mil.co +net.co +nom.co +org.co +rec.co +web.co + +// com : https://en.wikipedia.org/wiki/.com +com + +// coop : https://en.wikipedia.org/wiki/.coop +coop + +// cr : http://www.nic.cr/niccr_publico/showRegistroDominiosScreen.do +cr +ac.cr +co.cr +ed.cr +fi.cr +go.cr +or.cr +sa.cr + +// cu : https://en.wikipedia.org/wiki/.cu +cu +com.cu +edu.cu +org.cu +net.cu +gov.cu +inf.cu + +// cv : https://en.wikipedia.org/wiki/.cv +// cv : http://www.dns.cv/tldcv_portal/do?com=DS;5446457100;111;+PAGE(4000018)+K-CAT-CODIGO(RDOM)+RCNT(100); <- registration rules +cv +com.cv +edu.cv +int.cv +nome.cv +org.cv + +// cw : http://www.una.cw/cw_registry/ +// Confirmed by registry 2013-03-26 +cw +com.cw +edu.cw +net.cw +org.cw + +// cx : https://en.wikipedia.org/wiki/.cx +// list of other 2nd level tlds ? +cx +gov.cx + +// cy : http://www.nic.cy/ +// Submitted by registry Panayiotou Fotia +// namespace policies URL https://www.nic.cy/portal//sites/default/files/symfonia_gia_eggrafi.pdf +cy +ac.cy +biz.cy +com.cy +ekloges.cy +gov.cy +ltd.cy +mil.cy +net.cy +org.cy +press.cy +pro.cy +tm.cy + +// cz : https://en.wikipedia.org/wiki/.cz +cz + +// de : https://en.wikipedia.org/wiki/.de +// Confirmed by registry (with technical +// reservations) 2008-07-01 +de + +// dj : https://en.wikipedia.org/wiki/.dj +dj + +// dk : https://en.wikipedia.org/wiki/.dk +// Confirmed by registry 2008-06-17 +dk + +// dm : https://en.wikipedia.org/wiki/.dm +dm +com.dm +net.dm +org.dm +edu.dm +gov.dm + +// do : https://en.wikipedia.org/wiki/.do +do +art.do +com.do +edu.do +gob.do +gov.do +mil.do +net.do +org.do +sld.do +web.do + +// dz : http://www.nic.dz/images/pdf_nic/charte.pdf +dz +art.dz +asso.dz +com.dz +edu.dz +gov.dz +org.dz +net.dz +pol.dz +soc.dz +tm.dz + +// ec : http://www.nic.ec/reg/paso1.asp +// Submitted by registry +ec +com.ec +info.ec +net.ec +fin.ec +k12.ec +med.ec +pro.ec +org.ec +edu.ec +gov.ec +gob.ec +mil.ec + +// edu : https://en.wikipedia.org/wiki/.edu +edu + +// ee : http://www.eenet.ee/EENet/dom_reeglid.html#lisa_B +ee +edu.ee +gov.ee +riik.ee +lib.ee +med.ee +com.ee +pri.ee +aip.ee +org.ee +fie.ee + +// eg : https://en.wikipedia.org/wiki/.eg +eg +com.eg +edu.eg +eun.eg +gov.eg +mil.eg +name.eg +net.eg +org.eg +sci.eg + +// er : https://en.wikipedia.org/wiki/.er +*.er + +// es : https://www.nic.es/site_ingles/ingles/dominios/index.html +es +com.es +nom.es +org.es +gob.es +edu.es + +// et : https://en.wikipedia.org/wiki/.et +et +com.et +gov.et +org.et +edu.et +biz.et +name.et +info.et +net.et + +// eu : https://en.wikipedia.org/wiki/.eu +eu + +// fi : https://en.wikipedia.org/wiki/.fi +fi +// aland.fi : https://en.wikipedia.org/wiki/.ax +// This domain is being phased out in favor of .ax. As there are still many +// domains under aland.fi, we still keep it on the list until aland.fi is +// completely removed. +// TODO: Check for updates (expected to be phased out around Q1/2009) +aland.fi + +// fj : http://domains.fj/ +// Submitted by registry 2020-02-11 +fj +ac.fj +biz.fj +com.fj +gov.fj +info.fj +mil.fj +name.fj +net.fj +org.fj +pro.fj + +// fk : https://en.wikipedia.org/wiki/.fk +*.fk + +// fm : https://en.wikipedia.org/wiki/.fm +com.fm +edu.fm +net.fm +org.fm +fm + +// fo : https://en.wikipedia.org/wiki/.fo +fo + +// fr : https://www.afnic.fr/ https://www.afnic.fr/wp-media/uploads/2022/12/afnic-naming-policy-2023-01-01.pdf +fr +asso.fr +com.fr +gouv.fr +nom.fr +prd.fr +tm.fr +// Other SLDs now selfmanaged out of AFNIC range. Former "domaines sectoriels", still registration suffixes +avoues.fr +cci.fr +greta.fr +huissier-justice.fr + +// ga : https://en.wikipedia.org/wiki/.ga +ga + +// gb : This registry is effectively dormant +// Submitted by registry +gb + +// gd : https://en.wikipedia.org/wiki/.gd +edu.gd +gov.gd +gd + +// ge : http://www.nic.net.ge/policy_en.pdf +ge +com.ge +edu.ge +gov.ge +org.ge +mil.ge +net.ge +pvt.ge + +// gf : https://en.wikipedia.org/wiki/.gf +gf + +// gg : http://www.channelisles.net/register-domains/ +// Confirmed by registry 2013-11-28 +gg +co.gg +net.gg +org.gg + +// gh : https://en.wikipedia.org/wiki/.gh +// see also: http://www.nic.gh/reg_now.php +// Although domains directly at second level are not possible at the moment, +// they have been possible for some time and may come back. +gh +com.gh +edu.gh +gov.gh +org.gh +mil.gh + +// gi : http://www.nic.gi/rules.html +gi +com.gi +ltd.gi +gov.gi +mod.gi +edu.gi +org.gi + +// gl : https://en.wikipedia.org/wiki/.gl +// http://nic.gl +gl +co.gl +com.gl +edu.gl +net.gl +org.gl + +// gm : http://www.nic.gm/htmlpages%5Cgm-policy.htm +gm + +// gn : http://psg.com/dns/gn/gn.txt +// Submitted by registry +gn +ac.gn +com.gn +edu.gn +gov.gn +org.gn +net.gn + +// gov : https://en.wikipedia.org/wiki/.gov +gov + +// gp : http://www.nic.gp/index.php?lang=en +gp +com.gp +net.gp +mobi.gp +edu.gp +org.gp +asso.gp + +// gq : https://en.wikipedia.org/wiki/.gq +gq + +// gr : https://grweb.ics.forth.gr/english/1617-B-2005.html +// Submitted by registry +gr +com.gr +edu.gr +net.gr +org.gr +gov.gr + +// gs : https://en.wikipedia.org/wiki/.gs +gs + +// gt : https://www.gt/sitio/registration_policy.php?lang=en +gt +com.gt +edu.gt +gob.gt +ind.gt +mil.gt +net.gt +org.gt + +// gu : http://gadao.gov.gu/register.html +// University of Guam : https://www.uog.edu +// Submitted by uognoc@triton.uog.edu +gu +com.gu +edu.gu +gov.gu +guam.gu +info.gu +net.gu +org.gu +web.gu + +// gw : https://en.wikipedia.org/wiki/.gw +// gw : https://nic.gw/regras/ +gw + +// gy : https://en.wikipedia.org/wiki/.gy +// http://registry.gy/ +gy +co.gy +com.gy +edu.gy +gov.gy +net.gy +org.gy + +// hk : https://www.hkirc.hk +// Submitted by registry +hk +com.hk +edu.hk +gov.hk +idv.hk +net.hk +org.hk +公司.hk +教育.hk +敎育.hk +政府.hk +個人.hk +个人.hk +箇人.hk +網络.hk +网络.hk +组織.hk +網絡.hk +网絡.hk +组织.hk +組織.hk +組织.hk + +// hm : https://en.wikipedia.org/wiki/.hm +hm + +// hn : http://www.nic.hn/politicas/ps02,,05.html +hn +com.hn +edu.hn +org.hn +net.hn +mil.hn +gob.hn + +// hr : http://www.dns.hr/documents/pdf/HRTLD-regulations.pdf +hr +iz.hr +from.hr +name.hr +com.hr + +// ht : http://www.nic.ht/info/charte.cfm +ht +com.ht +shop.ht +firm.ht +info.ht +adult.ht +net.ht +pro.ht +org.ht +med.ht +art.ht +coop.ht +pol.ht +asso.ht +edu.ht +rel.ht +gouv.ht +perso.ht + +// hu : http://www.domain.hu/domain/English/sld.html +// Confirmed by registry 2008-06-12 +hu +co.hu +info.hu +org.hu +priv.hu +sport.hu +tm.hu +2000.hu +agrar.hu +bolt.hu +casino.hu +city.hu +erotica.hu +erotika.hu +film.hu +forum.hu +games.hu +hotel.hu +ingatlan.hu +jogasz.hu +konyvelo.hu +lakas.hu +media.hu +news.hu +reklam.hu +sex.hu +shop.hu +suli.hu +szex.hu +tozsde.hu +utazas.hu +video.hu + +// id : https://pandi.id/en/domain/registration-requirements/ +id +ac.id +biz.id +co.id +desa.id +go.id +mil.id +my.id +net.id +or.id +ponpes.id +sch.id +web.id + +// ie : https://en.wikipedia.org/wiki/.ie +ie +gov.ie + +// il : http://www.isoc.org.il/domains/ +// see also: https://en.isoc.org.il/il-cctld/registration-rules +// ISOC-IL (operated by .il Registry) +il +ac.il +co.il +gov.il +idf.il +k12.il +muni.il +net.il +org.il +// xn--4dbrk0ce ("Israel", Hebrew) : IL +ישראל +// xn--4dbgdty6c.xn--4dbrk0ce. +אקדמיה.ישראל +// xn--5dbhl8d.xn--4dbrk0ce. +ישוב.ישראל +// xn--8dbq2a.xn--4dbrk0ce. +צהל.ישראל +// xn--hebda8b.xn--4dbrk0ce. +ממשל.ישראל + +// im : https://www.nic.im/ +// Submitted by registry +im +ac.im +co.im +com.im +ltd.co.im +net.im +org.im +plc.co.im +tt.im +tv.im + +// in : https://en.wikipedia.org/wiki/.in +// see also: https://registry.in/policies +// Please note, that nic.in is not an official eTLD, but used by most +// government institutions. +in +5g.in +6g.in +ac.in +ai.in +am.in +bihar.in +biz.in +business.in +ca.in +cn.in +co.in +com.in +coop.in +cs.in +delhi.in +dr.in +edu.in +er.in +firm.in +gen.in +gov.in +gujarat.in +ind.in +info.in +int.in +internet.in +io.in +me.in +mil.in +net.in +nic.in +org.in +pg.in +post.in +pro.in +res.in +travel.in +tv.in +uk.in +up.in +us.in + +// info : https://en.wikipedia.org/wiki/.info +info + +// int : https://en.wikipedia.org/wiki/.int +// Confirmed by registry 2008-06-18 +int +eu.int + +// io : http://www.nic.io/rules.htm +// list of other 2nd level tlds ? +io +com.io + +// iq : http://www.cmc.iq/english/iq/iqregister1.htm +iq +gov.iq +edu.iq +mil.iq +com.iq +org.iq +net.iq + +// ir : http://www.nic.ir/Terms_and_Conditions_ir,_Appendix_1_Domain_Rules +// Also see http://www.nic.ir/Internationalized_Domain_Names +// Two .ir entries added at request of , 2010-04-16 +ir +ac.ir +co.ir +gov.ir +id.ir +net.ir +org.ir +sch.ir +// xn--mgba3a4f16a.ir (.ir, Persian YEH) +ایران.ir +// xn--mgba3a4fra.ir (.ir, Arabic YEH) +ايران.ir + +// is : http://www.isnic.is/domain/rules.php +// Confirmed by registry 2008-12-06 +is +net.is +com.is +edu.is +gov.is +org.is +int.is + +// it : https://en.wikipedia.org/wiki/.it +it +gov.it +edu.it +// Reserved geo-names (regions and provinces): +// https://www.nic.it/sites/default/files/archivio/docs/Regulation_assignation_v7.1.pdf +// Regions +abr.it +abruzzo.it +aosta-valley.it +aostavalley.it +bas.it +basilicata.it +cal.it +calabria.it +cam.it +campania.it +emilia-romagna.it +emiliaromagna.it +emr.it +friuli-v-giulia.it +friuli-ve-giulia.it +friuli-vegiulia.it +friuli-venezia-giulia.it +friuli-veneziagiulia.it +friuli-vgiulia.it +friuliv-giulia.it +friulive-giulia.it +friulivegiulia.it +friulivenezia-giulia.it +friuliveneziagiulia.it +friulivgiulia.it +fvg.it +laz.it +lazio.it +lig.it +liguria.it +lom.it +lombardia.it +lombardy.it +lucania.it +mar.it +marche.it +mol.it +molise.it +piedmont.it +piemonte.it +pmn.it +pug.it +puglia.it +sar.it +sardegna.it +sardinia.it +sic.it +sicilia.it +sicily.it +taa.it +tos.it +toscana.it +trentin-sud-tirol.it +trentin-süd-tirol.it +trentin-sudtirol.it +trentin-südtirol.it +trentin-sued-tirol.it +trentin-suedtirol.it +trentino-a-adige.it +trentino-aadige.it +trentino-alto-adige.it +trentino-altoadige.it +trentino-s-tirol.it +trentino-stirol.it +trentino-sud-tirol.it +trentino-süd-tirol.it +trentino-sudtirol.it +trentino-südtirol.it +trentino-sued-tirol.it +trentino-suedtirol.it +trentino.it +trentinoa-adige.it +trentinoaadige.it +trentinoalto-adige.it +trentinoaltoadige.it +trentinos-tirol.it +trentinostirol.it +trentinosud-tirol.it +trentinosüd-tirol.it +trentinosudtirol.it +trentinosüdtirol.it +trentinosued-tirol.it +trentinosuedtirol.it +trentinsud-tirol.it +trentinsüd-tirol.it +trentinsudtirol.it +trentinsüdtirol.it +trentinsued-tirol.it +trentinsuedtirol.it +tuscany.it +umb.it +umbria.it +val-d-aosta.it +val-daosta.it +vald-aosta.it +valdaosta.it +valle-aosta.it +valle-d-aosta.it +valle-daosta.it +valleaosta.it +valled-aosta.it +valledaosta.it +vallee-aoste.it +vallée-aoste.it +vallee-d-aoste.it +vallée-d-aoste.it +valleeaoste.it +valléeaoste.it +valleedaoste.it +valléedaoste.it +vao.it +vda.it +ven.it +veneto.it +// Provinces +ag.it +agrigento.it +al.it +alessandria.it +alto-adige.it +altoadige.it +an.it +ancona.it +andria-barletta-trani.it +andria-trani-barletta.it +andriabarlettatrani.it +andriatranibarletta.it +ao.it +aosta.it +aoste.it +ap.it +aq.it +aquila.it +ar.it +arezzo.it +ascoli-piceno.it +ascolipiceno.it +asti.it +at.it +av.it +avellino.it +ba.it +balsan-sudtirol.it +balsan-südtirol.it +balsan-suedtirol.it +balsan.it +bari.it +barletta-trani-andria.it +barlettatraniandria.it +belluno.it +benevento.it +bergamo.it +bg.it +bi.it +biella.it +bl.it +bn.it +bo.it +bologna.it +bolzano-altoadige.it +bolzano.it +bozen-sudtirol.it +bozen-südtirol.it +bozen-suedtirol.it +bozen.it +br.it +brescia.it +brindisi.it +bs.it +bt.it +bulsan-sudtirol.it +bulsan-südtirol.it +bulsan-suedtirol.it +bulsan.it +bz.it +ca.it +cagliari.it +caltanissetta.it +campidano-medio.it +campidanomedio.it +campobasso.it +carbonia-iglesias.it +carboniaiglesias.it +carrara-massa.it +carraramassa.it +caserta.it +catania.it +catanzaro.it +cb.it +ce.it +cesena-forli.it +cesena-forlì.it +cesenaforli.it +cesenaforlì.it +ch.it +chieti.it +ci.it +cl.it +cn.it +co.it +como.it +cosenza.it +cr.it +cremona.it +crotone.it +cs.it +ct.it +cuneo.it +cz.it +dell-ogliastra.it +dellogliastra.it +en.it +enna.it +fc.it +fe.it +fermo.it +ferrara.it +fg.it +fi.it +firenze.it +florence.it +fm.it +foggia.it +forli-cesena.it +forlì-cesena.it +forlicesena.it +forlìcesena.it +fr.it +frosinone.it +ge.it +genoa.it +genova.it +go.it +gorizia.it +gr.it +grosseto.it +iglesias-carbonia.it +iglesiascarbonia.it +im.it +imperia.it +is.it +isernia.it +kr.it +la-spezia.it +laquila.it +laspezia.it +latina.it +lc.it +le.it +lecce.it +lecco.it +li.it +livorno.it +lo.it +lodi.it +lt.it +lu.it +lucca.it +macerata.it +mantova.it +massa-carrara.it +massacarrara.it +matera.it +mb.it +mc.it +me.it +medio-campidano.it +mediocampidano.it +messina.it +mi.it +milan.it +milano.it +mn.it +mo.it +modena.it +monza-brianza.it +monza-e-della-brianza.it +monza.it +monzabrianza.it +monzaebrianza.it +monzaedellabrianza.it +ms.it +mt.it +na.it +naples.it +napoli.it +no.it +novara.it +nu.it +nuoro.it +og.it +ogliastra.it +olbia-tempio.it +olbiatempio.it +or.it +oristano.it +ot.it +pa.it +padova.it +padua.it +palermo.it +parma.it +pavia.it +pc.it +pd.it +pe.it +perugia.it +pesaro-urbino.it +pesarourbino.it +pescara.it +pg.it +pi.it +piacenza.it +pisa.it +pistoia.it +pn.it +po.it +pordenone.it +potenza.it +pr.it +prato.it +pt.it +pu.it +pv.it +pz.it +ra.it +ragusa.it +ravenna.it +rc.it +re.it +reggio-calabria.it +reggio-emilia.it +reggiocalabria.it +reggioemilia.it +rg.it +ri.it +rieti.it +rimini.it +rm.it +rn.it +ro.it +roma.it +rome.it +rovigo.it +sa.it +salerno.it +sassari.it +savona.it +si.it +siena.it +siracusa.it +so.it +sondrio.it +sp.it +sr.it +ss.it +suedtirol.it +südtirol.it +sv.it +ta.it +taranto.it +te.it +tempio-olbia.it +tempioolbia.it +teramo.it +terni.it +tn.it +to.it +torino.it +tp.it +tr.it +trani-andria-barletta.it +trani-barletta-andria.it +traniandriabarletta.it +tranibarlettaandria.it +trapani.it +trento.it +treviso.it +trieste.it +ts.it +turin.it +tv.it +ud.it +udine.it +urbino-pesaro.it +urbinopesaro.it +va.it +varese.it +vb.it +vc.it +ve.it +venezia.it +venice.it +verbania.it +vercelli.it +verona.it +vi.it +vibo-valentia.it +vibovalentia.it +vicenza.it +viterbo.it +vr.it +vs.it +vt.it +vv.it + +// je : http://www.channelisles.net/register-domains/ +// Confirmed by registry 2013-11-28 +je +co.je +net.je +org.je + +// jm : http://www.com.jm/register.html +*.jm + +// jo : http://www.dns.jo/Registration_policy.aspx +jo +com.jo +org.jo +net.jo +edu.jo +sch.jo +gov.jo +mil.jo +name.jo + +// jobs : https://en.wikipedia.org/wiki/.jobs +jobs + +// jp : https://en.wikipedia.org/wiki/.jp +// http://jprs.co.jp/en/jpdomain.html +// Submitted by registry +jp +// jp organizational type names +ac.jp +ad.jp +co.jp +ed.jp +go.jp +gr.jp +lg.jp +ne.jp +or.jp +// jp prefecture type names +aichi.jp +akita.jp +aomori.jp +chiba.jp +ehime.jp +fukui.jp +fukuoka.jp +fukushima.jp +gifu.jp +gunma.jp +hiroshima.jp +hokkaido.jp +hyogo.jp +ibaraki.jp +ishikawa.jp +iwate.jp +kagawa.jp +kagoshima.jp +kanagawa.jp +kochi.jp +kumamoto.jp +kyoto.jp +mie.jp +miyagi.jp +miyazaki.jp +nagano.jp +nagasaki.jp +nara.jp +niigata.jp +oita.jp +okayama.jp +okinawa.jp +osaka.jp +saga.jp +saitama.jp +shiga.jp +shimane.jp +shizuoka.jp +tochigi.jp +tokushima.jp +tokyo.jp +tottori.jp +toyama.jp +wakayama.jp +yamagata.jp +yamaguchi.jp +yamanashi.jp +栃木.jp +愛知.jp +愛媛.jp +兵庫.jp +熊本.jp +茨城.jp +北海道.jp +千葉.jp +和歌山.jp +長崎.jp +長野.jp +新潟.jp +青森.jp +静岡.jp +東京.jp +石川.jp +埼玉.jp +三重.jp +京都.jp +佐賀.jp +大分.jp +大阪.jp +奈良.jp +宮城.jp +宮崎.jp +富山.jp +山口.jp +山形.jp +山梨.jp +岩手.jp +岐阜.jp +岡山.jp +島根.jp +広島.jp +徳島.jp +沖縄.jp +滋賀.jp +神奈川.jp +福井.jp +福岡.jp +福島.jp +秋田.jp +群馬.jp +香川.jp +高知.jp +鳥取.jp +鹿児島.jp +// jp geographic type names +// http://jprs.jp/doc/rule/saisoku-1.html +*.kawasaki.jp +*.kitakyushu.jp +*.kobe.jp +*.nagoya.jp +*.sapporo.jp +*.sendai.jp +*.yokohama.jp +!city.kawasaki.jp +!city.kitakyushu.jp +!city.kobe.jp +!city.nagoya.jp +!city.sapporo.jp +!city.sendai.jp +!city.yokohama.jp +// 4th level registration +aisai.aichi.jp +ama.aichi.jp +anjo.aichi.jp +asuke.aichi.jp +chiryu.aichi.jp +chita.aichi.jp +fuso.aichi.jp +gamagori.aichi.jp +handa.aichi.jp +hazu.aichi.jp +hekinan.aichi.jp +higashiura.aichi.jp +ichinomiya.aichi.jp +inazawa.aichi.jp +inuyama.aichi.jp +isshiki.aichi.jp +iwakura.aichi.jp +kanie.aichi.jp +kariya.aichi.jp +kasugai.aichi.jp +kira.aichi.jp +kiyosu.aichi.jp +komaki.aichi.jp +konan.aichi.jp +kota.aichi.jp +mihama.aichi.jp +miyoshi.aichi.jp +nishio.aichi.jp +nisshin.aichi.jp +obu.aichi.jp +oguchi.aichi.jp +oharu.aichi.jp +okazaki.aichi.jp +owariasahi.aichi.jp +seto.aichi.jp +shikatsu.aichi.jp +shinshiro.aichi.jp +shitara.aichi.jp +tahara.aichi.jp +takahama.aichi.jp +tobishima.aichi.jp +toei.aichi.jp +togo.aichi.jp +tokai.aichi.jp +tokoname.aichi.jp +toyoake.aichi.jp +toyohashi.aichi.jp +toyokawa.aichi.jp +toyone.aichi.jp +toyota.aichi.jp +tsushima.aichi.jp +yatomi.aichi.jp +akita.akita.jp +daisen.akita.jp +fujisato.akita.jp +gojome.akita.jp +hachirogata.akita.jp +happou.akita.jp +higashinaruse.akita.jp +honjo.akita.jp +honjyo.akita.jp +ikawa.akita.jp +kamikoani.akita.jp +kamioka.akita.jp +katagami.akita.jp +kazuno.akita.jp +kitaakita.akita.jp +kosaka.akita.jp +kyowa.akita.jp +misato.akita.jp +mitane.akita.jp +moriyoshi.akita.jp +nikaho.akita.jp +noshiro.akita.jp +odate.akita.jp +oga.akita.jp +ogata.akita.jp +semboku.akita.jp +yokote.akita.jp +yurihonjo.akita.jp +aomori.aomori.jp +gonohe.aomori.jp +hachinohe.aomori.jp +hashikami.aomori.jp +hiranai.aomori.jp +hirosaki.aomori.jp +itayanagi.aomori.jp +kuroishi.aomori.jp +misawa.aomori.jp +mutsu.aomori.jp +nakadomari.aomori.jp +noheji.aomori.jp +oirase.aomori.jp +owani.aomori.jp +rokunohe.aomori.jp +sannohe.aomori.jp +shichinohe.aomori.jp +shingo.aomori.jp +takko.aomori.jp +towada.aomori.jp +tsugaru.aomori.jp +tsuruta.aomori.jp +abiko.chiba.jp +asahi.chiba.jp +chonan.chiba.jp +chosei.chiba.jp +choshi.chiba.jp +chuo.chiba.jp +funabashi.chiba.jp +futtsu.chiba.jp +hanamigawa.chiba.jp +ichihara.chiba.jp +ichikawa.chiba.jp +ichinomiya.chiba.jp +inzai.chiba.jp +isumi.chiba.jp +kamagaya.chiba.jp +kamogawa.chiba.jp +kashiwa.chiba.jp +katori.chiba.jp +katsuura.chiba.jp +kimitsu.chiba.jp +kisarazu.chiba.jp +kozaki.chiba.jp +kujukuri.chiba.jp +kyonan.chiba.jp +matsudo.chiba.jp +midori.chiba.jp +mihama.chiba.jp +minamiboso.chiba.jp +mobara.chiba.jp +mutsuzawa.chiba.jp +nagara.chiba.jp +nagareyama.chiba.jp +narashino.chiba.jp +narita.chiba.jp +noda.chiba.jp +oamishirasato.chiba.jp +omigawa.chiba.jp +onjuku.chiba.jp +otaki.chiba.jp +sakae.chiba.jp +sakura.chiba.jp +shimofusa.chiba.jp +shirako.chiba.jp +shiroi.chiba.jp +shisui.chiba.jp +sodegaura.chiba.jp +sosa.chiba.jp +tako.chiba.jp +tateyama.chiba.jp +togane.chiba.jp +tohnosho.chiba.jp +tomisato.chiba.jp +urayasu.chiba.jp +yachimata.chiba.jp +yachiyo.chiba.jp +yokaichiba.chiba.jp +yokoshibahikari.chiba.jp +yotsukaido.chiba.jp +ainan.ehime.jp +honai.ehime.jp +ikata.ehime.jp +imabari.ehime.jp +iyo.ehime.jp +kamijima.ehime.jp +kihoku.ehime.jp +kumakogen.ehime.jp +masaki.ehime.jp +matsuno.ehime.jp +matsuyama.ehime.jp +namikata.ehime.jp +niihama.ehime.jp +ozu.ehime.jp +saijo.ehime.jp +seiyo.ehime.jp +shikokuchuo.ehime.jp +tobe.ehime.jp +toon.ehime.jp +uchiko.ehime.jp +uwajima.ehime.jp +yawatahama.ehime.jp +echizen.fukui.jp +eiheiji.fukui.jp +fukui.fukui.jp +ikeda.fukui.jp +katsuyama.fukui.jp +mihama.fukui.jp +minamiechizen.fukui.jp +obama.fukui.jp +ohi.fukui.jp +ono.fukui.jp +sabae.fukui.jp +sakai.fukui.jp +takahama.fukui.jp +tsuruga.fukui.jp +wakasa.fukui.jp +ashiya.fukuoka.jp +buzen.fukuoka.jp +chikugo.fukuoka.jp +chikuho.fukuoka.jp +chikujo.fukuoka.jp +chikushino.fukuoka.jp +chikuzen.fukuoka.jp +chuo.fukuoka.jp +dazaifu.fukuoka.jp +fukuchi.fukuoka.jp +hakata.fukuoka.jp +higashi.fukuoka.jp +hirokawa.fukuoka.jp +hisayama.fukuoka.jp +iizuka.fukuoka.jp +inatsuki.fukuoka.jp +kaho.fukuoka.jp +kasuga.fukuoka.jp +kasuya.fukuoka.jp +kawara.fukuoka.jp +keisen.fukuoka.jp +koga.fukuoka.jp +kurate.fukuoka.jp +kurogi.fukuoka.jp +kurume.fukuoka.jp +minami.fukuoka.jp +miyako.fukuoka.jp +miyama.fukuoka.jp +miyawaka.fukuoka.jp +mizumaki.fukuoka.jp +munakata.fukuoka.jp +nakagawa.fukuoka.jp +nakama.fukuoka.jp +nishi.fukuoka.jp +nogata.fukuoka.jp +ogori.fukuoka.jp +okagaki.fukuoka.jp +okawa.fukuoka.jp +oki.fukuoka.jp +omuta.fukuoka.jp +onga.fukuoka.jp +onojo.fukuoka.jp +oto.fukuoka.jp +saigawa.fukuoka.jp +sasaguri.fukuoka.jp +shingu.fukuoka.jp +shinyoshitomi.fukuoka.jp +shonai.fukuoka.jp +soeda.fukuoka.jp +sue.fukuoka.jp +tachiarai.fukuoka.jp +tagawa.fukuoka.jp +takata.fukuoka.jp +toho.fukuoka.jp +toyotsu.fukuoka.jp +tsuiki.fukuoka.jp +ukiha.fukuoka.jp +umi.fukuoka.jp +usui.fukuoka.jp +yamada.fukuoka.jp +yame.fukuoka.jp +yanagawa.fukuoka.jp +yukuhashi.fukuoka.jp +aizubange.fukushima.jp +aizumisato.fukushima.jp +aizuwakamatsu.fukushima.jp +asakawa.fukushima.jp +bandai.fukushima.jp +date.fukushima.jp +fukushima.fukushima.jp +furudono.fukushima.jp +futaba.fukushima.jp +hanawa.fukushima.jp +higashi.fukushima.jp +hirata.fukushima.jp +hirono.fukushima.jp +iitate.fukushima.jp +inawashiro.fukushima.jp +ishikawa.fukushima.jp +iwaki.fukushima.jp +izumizaki.fukushima.jp +kagamiishi.fukushima.jp +kaneyama.fukushima.jp +kawamata.fukushima.jp +kitakata.fukushima.jp +kitashiobara.fukushima.jp +koori.fukushima.jp +koriyama.fukushima.jp +kunimi.fukushima.jp +miharu.fukushima.jp +mishima.fukushima.jp +namie.fukushima.jp +nango.fukushima.jp +nishiaizu.fukushima.jp +nishigo.fukushima.jp +okuma.fukushima.jp +omotego.fukushima.jp +ono.fukushima.jp +otama.fukushima.jp +samegawa.fukushima.jp +shimogo.fukushima.jp +shirakawa.fukushima.jp +showa.fukushima.jp +soma.fukushima.jp +sukagawa.fukushima.jp +taishin.fukushima.jp +tamakawa.fukushima.jp +tanagura.fukushima.jp +tenei.fukushima.jp +yabuki.fukushima.jp +yamato.fukushima.jp +yamatsuri.fukushima.jp +yanaizu.fukushima.jp +yugawa.fukushima.jp +anpachi.gifu.jp +ena.gifu.jp +gifu.gifu.jp +ginan.gifu.jp +godo.gifu.jp +gujo.gifu.jp +hashima.gifu.jp +hichiso.gifu.jp +hida.gifu.jp +higashishirakawa.gifu.jp +ibigawa.gifu.jp +ikeda.gifu.jp +kakamigahara.gifu.jp +kani.gifu.jp +kasahara.gifu.jp +kasamatsu.gifu.jp +kawaue.gifu.jp +kitagata.gifu.jp +mino.gifu.jp +minokamo.gifu.jp +mitake.gifu.jp +mizunami.gifu.jp +motosu.gifu.jp +nakatsugawa.gifu.jp +ogaki.gifu.jp +sakahogi.gifu.jp +seki.gifu.jp +sekigahara.gifu.jp +shirakawa.gifu.jp +tajimi.gifu.jp +takayama.gifu.jp +tarui.gifu.jp +toki.gifu.jp +tomika.gifu.jp +wanouchi.gifu.jp +yamagata.gifu.jp +yaotsu.gifu.jp +yoro.gifu.jp +annaka.gunma.jp +chiyoda.gunma.jp +fujioka.gunma.jp +higashiagatsuma.gunma.jp +isesaki.gunma.jp +itakura.gunma.jp +kanna.gunma.jp +kanra.gunma.jp +katashina.gunma.jp +kawaba.gunma.jp +kiryu.gunma.jp +kusatsu.gunma.jp +maebashi.gunma.jp +meiwa.gunma.jp +midori.gunma.jp +minakami.gunma.jp +naganohara.gunma.jp +nakanojo.gunma.jp +nanmoku.gunma.jp +numata.gunma.jp +oizumi.gunma.jp +ora.gunma.jp +ota.gunma.jp +shibukawa.gunma.jp +shimonita.gunma.jp +shinto.gunma.jp +showa.gunma.jp +takasaki.gunma.jp +takayama.gunma.jp +tamamura.gunma.jp +tatebayashi.gunma.jp +tomioka.gunma.jp +tsukiyono.gunma.jp +tsumagoi.gunma.jp +ueno.gunma.jp +yoshioka.gunma.jp +asaminami.hiroshima.jp +daiwa.hiroshima.jp +etajima.hiroshima.jp +fuchu.hiroshima.jp +fukuyama.hiroshima.jp +hatsukaichi.hiroshima.jp +higashihiroshima.hiroshima.jp +hongo.hiroshima.jp +jinsekikogen.hiroshima.jp +kaita.hiroshima.jp +kui.hiroshima.jp +kumano.hiroshima.jp +kure.hiroshima.jp +mihara.hiroshima.jp +miyoshi.hiroshima.jp +naka.hiroshima.jp +onomichi.hiroshima.jp +osakikamijima.hiroshima.jp +otake.hiroshima.jp +saka.hiroshima.jp +sera.hiroshima.jp +seranishi.hiroshima.jp +shinichi.hiroshima.jp +shobara.hiroshima.jp +takehara.hiroshima.jp +abashiri.hokkaido.jp +abira.hokkaido.jp +aibetsu.hokkaido.jp +akabira.hokkaido.jp +akkeshi.hokkaido.jp +asahikawa.hokkaido.jp +ashibetsu.hokkaido.jp +ashoro.hokkaido.jp +assabu.hokkaido.jp +atsuma.hokkaido.jp +bibai.hokkaido.jp +biei.hokkaido.jp +bifuka.hokkaido.jp +bihoro.hokkaido.jp +biratori.hokkaido.jp +chippubetsu.hokkaido.jp +chitose.hokkaido.jp +date.hokkaido.jp +ebetsu.hokkaido.jp +embetsu.hokkaido.jp +eniwa.hokkaido.jp +erimo.hokkaido.jp +esan.hokkaido.jp +esashi.hokkaido.jp +fukagawa.hokkaido.jp +fukushima.hokkaido.jp +furano.hokkaido.jp +furubira.hokkaido.jp +haboro.hokkaido.jp +hakodate.hokkaido.jp +hamatonbetsu.hokkaido.jp +hidaka.hokkaido.jp +higashikagura.hokkaido.jp +higashikawa.hokkaido.jp +hiroo.hokkaido.jp +hokuryu.hokkaido.jp +hokuto.hokkaido.jp +honbetsu.hokkaido.jp +horokanai.hokkaido.jp +horonobe.hokkaido.jp +ikeda.hokkaido.jp +imakane.hokkaido.jp +ishikari.hokkaido.jp +iwamizawa.hokkaido.jp +iwanai.hokkaido.jp +kamifurano.hokkaido.jp +kamikawa.hokkaido.jp +kamishihoro.hokkaido.jp +kamisunagawa.hokkaido.jp +kamoenai.hokkaido.jp +kayabe.hokkaido.jp +kembuchi.hokkaido.jp +kikonai.hokkaido.jp +kimobetsu.hokkaido.jp +kitahiroshima.hokkaido.jp +kitami.hokkaido.jp +kiyosato.hokkaido.jp +koshimizu.hokkaido.jp +kunneppu.hokkaido.jp +kuriyama.hokkaido.jp +kuromatsunai.hokkaido.jp +kushiro.hokkaido.jp +kutchan.hokkaido.jp +kyowa.hokkaido.jp +mashike.hokkaido.jp +matsumae.hokkaido.jp +mikasa.hokkaido.jp +minamifurano.hokkaido.jp +mombetsu.hokkaido.jp +moseushi.hokkaido.jp +mukawa.hokkaido.jp +muroran.hokkaido.jp +naie.hokkaido.jp +nakagawa.hokkaido.jp +nakasatsunai.hokkaido.jp +nakatombetsu.hokkaido.jp +nanae.hokkaido.jp +nanporo.hokkaido.jp +nayoro.hokkaido.jp +nemuro.hokkaido.jp +niikappu.hokkaido.jp +niki.hokkaido.jp +nishiokoppe.hokkaido.jp +noboribetsu.hokkaido.jp +numata.hokkaido.jp +obihiro.hokkaido.jp +obira.hokkaido.jp +oketo.hokkaido.jp +okoppe.hokkaido.jp +otaru.hokkaido.jp +otobe.hokkaido.jp +otofuke.hokkaido.jp +otoineppu.hokkaido.jp +oumu.hokkaido.jp +ozora.hokkaido.jp +pippu.hokkaido.jp +rankoshi.hokkaido.jp +rebun.hokkaido.jp +rikubetsu.hokkaido.jp +rishiri.hokkaido.jp +rishirifuji.hokkaido.jp +saroma.hokkaido.jp +sarufutsu.hokkaido.jp +shakotan.hokkaido.jp +shari.hokkaido.jp +shibecha.hokkaido.jp +shibetsu.hokkaido.jp +shikabe.hokkaido.jp +shikaoi.hokkaido.jp +shimamaki.hokkaido.jp +shimizu.hokkaido.jp +shimokawa.hokkaido.jp +shinshinotsu.hokkaido.jp +shintoku.hokkaido.jp +shiranuka.hokkaido.jp +shiraoi.hokkaido.jp +shiriuchi.hokkaido.jp +sobetsu.hokkaido.jp +sunagawa.hokkaido.jp +taiki.hokkaido.jp +takasu.hokkaido.jp +takikawa.hokkaido.jp +takinoue.hokkaido.jp +teshikaga.hokkaido.jp +tobetsu.hokkaido.jp +tohma.hokkaido.jp +tomakomai.hokkaido.jp +tomari.hokkaido.jp +toya.hokkaido.jp +toyako.hokkaido.jp +toyotomi.hokkaido.jp +toyoura.hokkaido.jp +tsubetsu.hokkaido.jp +tsukigata.hokkaido.jp +urakawa.hokkaido.jp +urausu.hokkaido.jp +uryu.hokkaido.jp +utashinai.hokkaido.jp +wakkanai.hokkaido.jp +wassamu.hokkaido.jp +yakumo.hokkaido.jp +yoichi.hokkaido.jp +aioi.hyogo.jp +akashi.hyogo.jp +ako.hyogo.jp +amagasaki.hyogo.jp +aogaki.hyogo.jp +asago.hyogo.jp +ashiya.hyogo.jp +awaji.hyogo.jp +fukusaki.hyogo.jp +goshiki.hyogo.jp +harima.hyogo.jp +himeji.hyogo.jp +ichikawa.hyogo.jp +inagawa.hyogo.jp +itami.hyogo.jp +kakogawa.hyogo.jp +kamigori.hyogo.jp +kamikawa.hyogo.jp +kasai.hyogo.jp +kasuga.hyogo.jp +kawanishi.hyogo.jp +miki.hyogo.jp +minamiawaji.hyogo.jp +nishinomiya.hyogo.jp +nishiwaki.hyogo.jp +ono.hyogo.jp +sanda.hyogo.jp +sannan.hyogo.jp +sasayama.hyogo.jp +sayo.hyogo.jp +shingu.hyogo.jp +shinonsen.hyogo.jp +shiso.hyogo.jp +sumoto.hyogo.jp +taishi.hyogo.jp +taka.hyogo.jp +takarazuka.hyogo.jp +takasago.hyogo.jp +takino.hyogo.jp +tamba.hyogo.jp +tatsuno.hyogo.jp +toyooka.hyogo.jp +yabu.hyogo.jp +yashiro.hyogo.jp +yoka.hyogo.jp +yokawa.hyogo.jp +ami.ibaraki.jp +asahi.ibaraki.jp +bando.ibaraki.jp +chikusei.ibaraki.jp +daigo.ibaraki.jp +fujishiro.ibaraki.jp +hitachi.ibaraki.jp +hitachinaka.ibaraki.jp +hitachiomiya.ibaraki.jp +hitachiota.ibaraki.jp +ibaraki.ibaraki.jp +ina.ibaraki.jp +inashiki.ibaraki.jp +itako.ibaraki.jp +iwama.ibaraki.jp +joso.ibaraki.jp +kamisu.ibaraki.jp +kasama.ibaraki.jp +kashima.ibaraki.jp +kasumigaura.ibaraki.jp +koga.ibaraki.jp +miho.ibaraki.jp +mito.ibaraki.jp +moriya.ibaraki.jp +naka.ibaraki.jp +namegata.ibaraki.jp +oarai.ibaraki.jp +ogawa.ibaraki.jp +omitama.ibaraki.jp +ryugasaki.ibaraki.jp +sakai.ibaraki.jp +sakuragawa.ibaraki.jp +shimodate.ibaraki.jp +shimotsuma.ibaraki.jp +shirosato.ibaraki.jp +sowa.ibaraki.jp +suifu.ibaraki.jp +takahagi.ibaraki.jp +tamatsukuri.ibaraki.jp +tokai.ibaraki.jp +tomobe.ibaraki.jp +tone.ibaraki.jp +toride.ibaraki.jp +tsuchiura.ibaraki.jp +tsukuba.ibaraki.jp +uchihara.ibaraki.jp +ushiku.ibaraki.jp +yachiyo.ibaraki.jp +yamagata.ibaraki.jp +yawara.ibaraki.jp +yuki.ibaraki.jp +anamizu.ishikawa.jp +hakui.ishikawa.jp +hakusan.ishikawa.jp +kaga.ishikawa.jp +kahoku.ishikawa.jp +kanazawa.ishikawa.jp +kawakita.ishikawa.jp +komatsu.ishikawa.jp +nakanoto.ishikawa.jp +nanao.ishikawa.jp +nomi.ishikawa.jp +nonoichi.ishikawa.jp +noto.ishikawa.jp +shika.ishikawa.jp +suzu.ishikawa.jp +tsubata.ishikawa.jp +tsurugi.ishikawa.jp +uchinada.ishikawa.jp +wajima.ishikawa.jp +fudai.iwate.jp +fujisawa.iwate.jp +hanamaki.iwate.jp +hiraizumi.iwate.jp +hirono.iwate.jp +ichinohe.iwate.jp +ichinoseki.iwate.jp +iwaizumi.iwate.jp +iwate.iwate.jp +joboji.iwate.jp +kamaishi.iwate.jp +kanegasaki.iwate.jp +karumai.iwate.jp +kawai.iwate.jp +kitakami.iwate.jp +kuji.iwate.jp +kunohe.iwate.jp +kuzumaki.iwate.jp +miyako.iwate.jp +mizusawa.iwate.jp +morioka.iwate.jp +ninohe.iwate.jp +noda.iwate.jp +ofunato.iwate.jp +oshu.iwate.jp +otsuchi.iwate.jp +rikuzentakata.iwate.jp +shiwa.iwate.jp +shizukuishi.iwate.jp +sumita.iwate.jp +tanohata.iwate.jp +tono.iwate.jp +yahaba.iwate.jp +yamada.iwate.jp +ayagawa.kagawa.jp +higashikagawa.kagawa.jp +kanonji.kagawa.jp +kotohira.kagawa.jp +manno.kagawa.jp +marugame.kagawa.jp +mitoyo.kagawa.jp +naoshima.kagawa.jp +sanuki.kagawa.jp +tadotsu.kagawa.jp +takamatsu.kagawa.jp +tonosho.kagawa.jp +uchinomi.kagawa.jp +utazu.kagawa.jp +zentsuji.kagawa.jp +akune.kagoshima.jp +amami.kagoshima.jp +hioki.kagoshima.jp +isa.kagoshima.jp +isen.kagoshima.jp +izumi.kagoshima.jp +kagoshima.kagoshima.jp +kanoya.kagoshima.jp +kawanabe.kagoshima.jp +kinko.kagoshima.jp +kouyama.kagoshima.jp +makurazaki.kagoshima.jp +matsumoto.kagoshima.jp +minamitane.kagoshima.jp +nakatane.kagoshima.jp +nishinoomote.kagoshima.jp +satsumasendai.kagoshima.jp +soo.kagoshima.jp +tarumizu.kagoshima.jp +yusui.kagoshima.jp +aikawa.kanagawa.jp +atsugi.kanagawa.jp +ayase.kanagawa.jp +chigasaki.kanagawa.jp +ebina.kanagawa.jp +fujisawa.kanagawa.jp +hadano.kanagawa.jp +hakone.kanagawa.jp +hiratsuka.kanagawa.jp +isehara.kanagawa.jp +kaisei.kanagawa.jp +kamakura.kanagawa.jp +kiyokawa.kanagawa.jp +matsuda.kanagawa.jp +minamiashigara.kanagawa.jp +miura.kanagawa.jp +nakai.kanagawa.jp +ninomiya.kanagawa.jp +odawara.kanagawa.jp +oi.kanagawa.jp +oiso.kanagawa.jp +sagamihara.kanagawa.jp +samukawa.kanagawa.jp +tsukui.kanagawa.jp +yamakita.kanagawa.jp +yamato.kanagawa.jp +yokosuka.kanagawa.jp +yugawara.kanagawa.jp +zama.kanagawa.jp +zushi.kanagawa.jp +aki.kochi.jp +geisei.kochi.jp +hidaka.kochi.jp +higashitsuno.kochi.jp +ino.kochi.jp +kagami.kochi.jp +kami.kochi.jp +kitagawa.kochi.jp +kochi.kochi.jp +mihara.kochi.jp +motoyama.kochi.jp +muroto.kochi.jp +nahari.kochi.jp +nakamura.kochi.jp +nankoku.kochi.jp +nishitosa.kochi.jp +niyodogawa.kochi.jp +ochi.kochi.jp +okawa.kochi.jp +otoyo.kochi.jp +otsuki.kochi.jp +sakawa.kochi.jp +sukumo.kochi.jp +susaki.kochi.jp +tosa.kochi.jp +tosashimizu.kochi.jp +toyo.kochi.jp +tsuno.kochi.jp +umaji.kochi.jp +yasuda.kochi.jp +yusuhara.kochi.jp +amakusa.kumamoto.jp +arao.kumamoto.jp +aso.kumamoto.jp +choyo.kumamoto.jp +gyokuto.kumamoto.jp +kamiamakusa.kumamoto.jp +kikuchi.kumamoto.jp +kumamoto.kumamoto.jp +mashiki.kumamoto.jp +mifune.kumamoto.jp +minamata.kumamoto.jp +minamioguni.kumamoto.jp +nagasu.kumamoto.jp +nishihara.kumamoto.jp +oguni.kumamoto.jp +ozu.kumamoto.jp +sumoto.kumamoto.jp +takamori.kumamoto.jp +uki.kumamoto.jp +uto.kumamoto.jp +yamaga.kumamoto.jp +yamato.kumamoto.jp +yatsushiro.kumamoto.jp +ayabe.kyoto.jp +fukuchiyama.kyoto.jp +higashiyama.kyoto.jp +ide.kyoto.jp +ine.kyoto.jp +joyo.kyoto.jp +kameoka.kyoto.jp +kamo.kyoto.jp +kita.kyoto.jp +kizu.kyoto.jp +kumiyama.kyoto.jp +kyotamba.kyoto.jp +kyotanabe.kyoto.jp +kyotango.kyoto.jp +maizuru.kyoto.jp +minami.kyoto.jp +minamiyamashiro.kyoto.jp +miyazu.kyoto.jp +muko.kyoto.jp +nagaokakyo.kyoto.jp +nakagyo.kyoto.jp +nantan.kyoto.jp +oyamazaki.kyoto.jp +sakyo.kyoto.jp +seika.kyoto.jp +tanabe.kyoto.jp +uji.kyoto.jp +ujitawara.kyoto.jp +wazuka.kyoto.jp +yamashina.kyoto.jp +yawata.kyoto.jp +asahi.mie.jp +inabe.mie.jp +ise.mie.jp +kameyama.mie.jp +kawagoe.mie.jp +kiho.mie.jp +kisosaki.mie.jp +kiwa.mie.jp +komono.mie.jp +kumano.mie.jp +kuwana.mie.jp +matsusaka.mie.jp +meiwa.mie.jp +mihama.mie.jp +minamiise.mie.jp +misugi.mie.jp +miyama.mie.jp +nabari.mie.jp +shima.mie.jp +suzuka.mie.jp +tado.mie.jp +taiki.mie.jp +taki.mie.jp +tamaki.mie.jp +toba.mie.jp +tsu.mie.jp +udono.mie.jp +ureshino.mie.jp +watarai.mie.jp +yokkaichi.mie.jp +furukawa.miyagi.jp +higashimatsushima.miyagi.jp +ishinomaki.miyagi.jp +iwanuma.miyagi.jp +kakuda.miyagi.jp +kami.miyagi.jp +kawasaki.miyagi.jp +marumori.miyagi.jp +matsushima.miyagi.jp +minamisanriku.miyagi.jp +misato.miyagi.jp +murata.miyagi.jp +natori.miyagi.jp +ogawara.miyagi.jp +ohira.miyagi.jp +onagawa.miyagi.jp +osaki.miyagi.jp +rifu.miyagi.jp +semine.miyagi.jp +shibata.miyagi.jp +shichikashuku.miyagi.jp +shikama.miyagi.jp +shiogama.miyagi.jp +shiroishi.miyagi.jp +tagajo.miyagi.jp +taiwa.miyagi.jp +tome.miyagi.jp +tomiya.miyagi.jp +wakuya.miyagi.jp +watari.miyagi.jp +yamamoto.miyagi.jp +zao.miyagi.jp +aya.miyazaki.jp +ebino.miyazaki.jp +gokase.miyazaki.jp +hyuga.miyazaki.jp +kadogawa.miyazaki.jp +kawaminami.miyazaki.jp +kijo.miyazaki.jp +kitagawa.miyazaki.jp +kitakata.miyazaki.jp +kitaura.miyazaki.jp +kobayashi.miyazaki.jp +kunitomi.miyazaki.jp +kushima.miyazaki.jp +mimata.miyazaki.jp +miyakonojo.miyazaki.jp +miyazaki.miyazaki.jp +morotsuka.miyazaki.jp +nichinan.miyazaki.jp +nishimera.miyazaki.jp +nobeoka.miyazaki.jp +saito.miyazaki.jp +shiiba.miyazaki.jp +shintomi.miyazaki.jp +takaharu.miyazaki.jp +takanabe.miyazaki.jp +takazaki.miyazaki.jp +tsuno.miyazaki.jp +achi.nagano.jp +agematsu.nagano.jp +anan.nagano.jp +aoki.nagano.jp +asahi.nagano.jp +azumino.nagano.jp +chikuhoku.nagano.jp +chikuma.nagano.jp +chino.nagano.jp +fujimi.nagano.jp +hakuba.nagano.jp +hara.nagano.jp +hiraya.nagano.jp +iida.nagano.jp +iijima.nagano.jp +iiyama.nagano.jp +iizuna.nagano.jp +ikeda.nagano.jp +ikusaka.nagano.jp +ina.nagano.jp +karuizawa.nagano.jp +kawakami.nagano.jp +kiso.nagano.jp +kisofukushima.nagano.jp +kitaaiki.nagano.jp +komagane.nagano.jp +komoro.nagano.jp +matsukawa.nagano.jp +matsumoto.nagano.jp +miasa.nagano.jp +minamiaiki.nagano.jp +minamimaki.nagano.jp +minamiminowa.nagano.jp +minowa.nagano.jp +miyada.nagano.jp +miyota.nagano.jp +mochizuki.nagano.jp +nagano.nagano.jp +nagawa.nagano.jp +nagiso.nagano.jp +nakagawa.nagano.jp +nakano.nagano.jp +nozawaonsen.nagano.jp +obuse.nagano.jp +ogawa.nagano.jp +okaya.nagano.jp +omachi.nagano.jp +omi.nagano.jp +ookuwa.nagano.jp +ooshika.nagano.jp +otaki.nagano.jp +otari.nagano.jp +sakae.nagano.jp +sakaki.nagano.jp +saku.nagano.jp +sakuho.nagano.jp +shimosuwa.nagano.jp +shinanomachi.nagano.jp +shiojiri.nagano.jp +suwa.nagano.jp +suzaka.nagano.jp +takagi.nagano.jp +takamori.nagano.jp +takayama.nagano.jp +tateshina.nagano.jp +tatsuno.nagano.jp +togakushi.nagano.jp +togura.nagano.jp +tomi.nagano.jp +ueda.nagano.jp +wada.nagano.jp +yamagata.nagano.jp +yamanouchi.nagano.jp +yasaka.nagano.jp +yasuoka.nagano.jp +chijiwa.nagasaki.jp +futsu.nagasaki.jp +goto.nagasaki.jp +hasami.nagasaki.jp +hirado.nagasaki.jp +iki.nagasaki.jp +isahaya.nagasaki.jp +kawatana.nagasaki.jp +kuchinotsu.nagasaki.jp +matsuura.nagasaki.jp +nagasaki.nagasaki.jp +obama.nagasaki.jp +omura.nagasaki.jp +oseto.nagasaki.jp +saikai.nagasaki.jp +sasebo.nagasaki.jp +seihi.nagasaki.jp +shimabara.nagasaki.jp +shinkamigoto.nagasaki.jp +togitsu.nagasaki.jp +tsushima.nagasaki.jp +unzen.nagasaki.jp +ando.nara.jp +gose.nara.jp +heguri.nara.jp +higashiyoshino.nara.jp +ikaruga.nara.jp +ikoma.nara.jp +kamikitayama.nara.jp +kanmaki.nara.jp +kashiba.nara.jp +kashihara.nara.jp +katsuragi.nara.jp +kawai.nara.jp +kawakami.nara.jp +kawanishi.nara.jp +koryo.nara.jp +kurotaki.nara.jp +mitsue.nara.jp +miyake.nara.jp +nara.nara.jp +nosegawa.nara.jp +oji.nara.jp +ouda.nara.jp +oyodo.nara.jp +sakurai.nara.jp +sango.nara.jp +shimoichi.nara.jp +shimokitayama.nara.jp +shinjo.nara.jp +soni.nara.jp +takatori.nara.jp +tawaramoto.nara.jp +tenkawa.nara.jp +tenri.nara.jp +uda.nara.jp +yamatokoriyama.nara.jp +yamatotakada.nara.jp +yamazoe.nara.jp +yoshino.nara.jp +aga.niigata.jp +agano.niigata.jp +gosen.niigata.jp +itoigawa.niigata.jp +izumozaki.niigata.jp +joetsu.niigata.jp +kamo.niigata.jp +kariwa.niigata.jp +kashiwazaki.niigata.jp +minamiuonuma.niigata.jp +mitsuke.niigata.jp +muika.niigata.jp +murakami.niigata.jp +myoko.niigata.jp +nagaoka.niigata.jp +niigata.niigata.jp +ojiya.niigata.jp +omi.niigata.jp +sado.niigata.jp +sanjo.niigata.jp +seiro.niigata.jp +seirou.niigata.jp +sekikawa.niigata.jp +shibata.niigata.jp +tagami.niigata.jp +tainai.niigata.jp +tochio.niigata.jp +tokamachi.niigata.jp +tsubame.niigata.jp +tsunan.niigata.jp +uonuma.niigata.jp +yahiko.niigata.jp +yoita.niigata.jp +yuzawa.niigata.jp +beppu.oita.jp +bungoono.oita.jp +bungotakada.oita.jp +hasama.oita.jp +hiji.oita.jp +himeshima.oita.jp +hita.oita.jp +kamitsue.oita.jp +kokonoe.oita.jp +kuju.oita.jp +kunisaki.oita.jp +kusu.oita.jp +oita.oita.jp +saiki.oita.jp +taketa.oita.jp +tsukumi.oita.jp +usa.oita.jp +usuki.oita.jp +yufu.oita.jp +akaiwa.okayama.jp +asakuchi.okayama.jp +bizen.okayama.jp +hayashima.okayama.jp +ibara.okayama.jp +kagamino.okayama.jp +kasaoka.okayama.jp +kibichuo.okayama.jp +kumenan.okayama.jp +kurashiki.okayama.jp +maniwa.okayama.jp +misaki.okayama.jp +nagi.okayama.jp +niimi.okayama.jp +nishiawakura.okayama.jp +okayama.okayama.jp +satosho.okayama.jp +setouchi.okayama.jp +shinjo.okayama.jp +shoo.okayama.jp +soja.okayama.jp +takahashi.okayama.jp +tamano.okayama.jp +tsuyama.okayama.jp +wake.okayama.jp +yakage.okayama.jp +aguni.okinawa.jp +ginowan.okinawa.jp +ginoza.okinawa.jp +gushikami.okinawa.jp +haebaru.okinawa.jp +higashi.okinawa.jp +hirara.okinawa.jp +iheya.okinawa.jp +ishigaki.okinawa.jp +ishikawa.okinawa.jp +itoman.okinawa.jp +izena.okinawa.jp +kadena.okinawa.jp +kin.okinawa.jp +kitadaito.okinawa.jp +kitanakagusuku.okinawa.jp +kumejima.okinawa.jp +kunigami.okinawa.jp +minamidaito.okinawa.jp +motobu.okinawa.jp +nago.okinawa.jp +naha.okinawa.jp +nakagusuku.okinawa.jp +nakijin.okinawa.jp +nanjo.okinawa.jp +nishihara.okinawa.jp +ogimi.okinawa.jp +okinawa.okinawa.jp +onna.okinawa.jp +shimoji.okinawa.jp +taketomi.okinawa.jp +tarama.okinawa.jp +tokashiki.okinawa.jp +tomigusuku.okinawa.jp +tonaki.okinawa.jp +urasoe.okinawa.jp +uruma.okinawa.jp +yaese.okinawa.jp +yomitan.okinawa.jp +yonabaru.okinawa.jp +yonaguni.okinawa.jp +zamami.okinawa.jp +abeno.osaka.jp +chihayaakasaka.osaka.jp +chuo.osaka.jp +daito.osaka.jp +fujiidera.osaka.jp +habikino.osaka.jp +hannan.osaka.jp +higashiosaka.osaka.jp +higashisumiyoshi.osaka.jp +higashiyodogawa.osaka.jp +hirakata.osaka.jp +ibaraki.osaka.jp +ikeda.osaka.jp +izumi.osaka.jp +izumiotsu.osaka.jp +izumisano.osaka.jp +kadoma.osaka.jp +kaizuka.osaka.jp +kanan.osaka.jp +kashiwara.osaka.jp +katano.osaka.jp +kawachinagano.osaka.jp +kishiwada.osaka.jp +kita.osaka.jp +kumatori.osaka.jp +matsubara.osaka.jp +minato.osaka.jp +minoh.osaka.jp +misaki.osaka.jp +moriguchi.osaka.jp +neyagawa.osaka.jp +nishi.osaka.jp +nose.osaka.jp +osakasayama.osaka.jp +sakai.osaka.jp +sayama.osaka.jp +sennan.osaka.jp +settsu.osaka.jp +shijonawate.osaka.jp +shimamoto.osaka.jp +suita.osaka.jp +tadaoka.osaka.jp +taishi.osaka.jp +tajiri.osaka.jp +takaishi.osaka.jp +takatsuki.osaka.jp +tondabayashi.osaka.jp +toyonaka.osaka.jp +toyono.osaka.jp +yao.osaka.jp +ariake.saga.jp +arita.saga.jp +fukudomi.saga.jp +genkai.saga.jp +hamatama.saga.jp +hizen.saga.jp +imari.saga.jp +kamimine.saga.jp +kanzaki.saga.jp +karatsu.saga.jp +kashima.saga.jp +kitagata.saga.jp +kitahata.saga.jp +kiyama.saga.jp +kouhoku.saga.jp +kyuragi.saga.jp +nishiarita.saga.jp +ogi.saga.jp +omachi.saga.jp +ouchi.saga.jp +saga.saga.jp +shiroishi.saga.jp +taku.saga.jp +tara.saga.jp +tosu.saga.jp +yoshinogari.saga.jp +arakawa.saitama.jp +asaka.saitama.jp +chichibu.saitama.jp +fujimi.saitama.jp +fujimino.saitama.jp +fukaya.saitama.jp +hanno.saitama.jp +hanyu.saitama.jp +hasuda.saitama.jp +hatogaya.saitama.jp +hatoyama.saitama.jp +hidaka.saitama.jp +higashichichibu.saitama.jp +higashimatsuyama.saitama.jp +honjo.saitama.jp +ina.saitama.jp +iruma.saitama.jp +iwatsuki.saitama.jp +kamiizumi.saitama.jp +kamikawa.saitama.jp +kamisato.saitama.jp +kasukabe.saitama.jp +kawagoe.saitama.jp +kawaguchi.saitama.jp +kawajima.saitama.jp +kazo.saitama.jp +kitamoto.saitama.jp +koshigaya.saitama.jp +kounosu.saitama.jp +kuki.saitama.jp +kumagaya.saitama.jp +matsubushi.saitama.jp +minano.saitama.jp +misato.saitama.jp +miyashiro.saitama.jp +miyoshi.saitama.jp +moroyama.saitama.jp +nagatoro.saitama.jp +namegawa.saitama.jp +niiza.saitama.jp +ogano.saitama.jp +ogawa.saitama.jp +ogose.saitama.jp +okegawa.saitama.jp +omiya.saitama.jp +otaki.saitama.jp +ranzan.saitama.jp +ryokami.saitama.jp +saitama.saitama.jp +sakado.saitama.jp +satte.saitama.jp +sayama.saitama.jp +shiki.saitama.jp +shiraoka.saitama.jp +soka.saitama.jp +sugito.saitama.jp +toda.saitama.jp +tokigawa.saitama.jp +tokorozawa.saitama.jp +tsurugashima.saitama.jp +urawa.saitama.jp +warabi.saitama.jp +yashio.saitama.jp +yokoze.saitama.jp +yono.saitama.jp +yorii.saitama.jp +yoshida.saitama.jp +yoshikawa.saitama.jp +yoshimi.saitama.jp +aisho.shiga.jp +gamo.shiga.jp +higashiomi.shiga.jp +hikone.shiga.jp +koka.shiga.jp +konan.shiga.jp +kosei.shiga.jp +koto.shiga.jp +kusatsu.shiga.jp +maibara.shiga.jp +moriyama.shiga.jp +nagahama.shiga.jp +nishiazai.shiga.jp +notogawa.shiga.jp +omihachiman.shiga.jp +otsu.shiga.jp +ritto.shiga.jp +ryuoh.shiga.jp +takashima.shiga.jp +takatsuki.shiga.jp +torahime.shiga.jp +toyosato.shiga.jp +yasu.shiga.jp +akagi.shimane.jp +ama.shimane.jp +gotsu.shimane.jp +hamada.shimane.jp +higashiizumo.shimane.jp +hikawa.shimane.jp +hikimi.shimane.jp +izumo.shimane.jp +kakinoki.shimane.jp +masuda.shimane.jp +matsue.shimane.jp +misato.shimane.jp +nishinoshima.shimane.jp +ohda.shimane.jp +okinoshima.shimane.jp +okuizumo.shimane.jp +shimane.shimane.jp +tamayu.shimane.jp +tsuwano.shimane.jp +unnan.shimane.jp +yakumo.shimane.jp +yasugi.shimane.jp +yatsuka.shimane.jp +arai.shizuoka.jp +atami.shizuoka.jp +fuji.shizuoka.jp +fujieda.shizuoka.jp +fujikawa.shizuoka.jp +fujinomiya.shizuoka.jp +fukuroi.shizuoka.jp +gotemba.shizuoka.jp +haibara.shizuoka.jp +hamamatsu.shizuoka.jp +higashiizu.shizuoka.jp +ito.shizuoka.jp +iwata.shizuoka.jp +izu.shizuoka.jp +izunokuni.shizuoka.jp +kakegawa.shizuoka.jp +kannami.shizuoka.jp +kawanehon.shizuoka.jp +kawazu.shizuoka.jp +kikugawa.shizuoka.jp +kosai.shizuoka.jp +makinohara.shizuoka.jp +matsuzaki.shizuoka.jp +minamiizu.shizuoka.jp +mishima.shizuoka.jp +morimachi.shizuoka.jp +nishiizu.shizuoka.jp +numazu.shizuoka.jp +omaezaki.shizuoka.jp +shimada.shizuoka.jp +shimizu.shizuoka.jp +shimoda.shizuoka.jp +shizuoka.shizuoka.jp +susono.shizuoka.jp +yaizu.shizuoka.jp +yoshida.shizuoka.jp +ashikaga.tochigi.jp +bato.tochigi.jp +haga.tochigi.jp +ichikai.tochigi.jp +iwafune.tochigi.jp +kaminokawa.tochigi.jp +kanuma.tochigi.jp +karasuyama.tochigi.jp +kuroiso.tochigi.jp +mashiko.tochigi.jp +mibu.tochigi.jp +moka.tochigi.jp +motegi.tochigi.jp +nasu.tochigi.jp +nasushiobara.tochigi.jp +nikko.tochigi.jp +nishikata.tochigi.jp +nogi.tochigi.jp +ohira.tochigi.jp +ohtawara.tochigi.jp +oyama.tochigi.jp +sakura.tochigi.jp +sano.tochigi.jp +shimotsuke.tochigi.jp +shioya.tochigi.jp +takanezawa.tochigi.jp +tochigi.tochigi.jp +tsuga.tochigi.jp +ujiie.tochigi.jp +utsunomiya.tochigi.jp +yaita.tochigi.jp +aizumi.tokushima.jp +anan.tokushima.jp +ichiba.tokushima.jp +itano.tokushima.jp +kainan.tokushima.jp +komatsushima.tokushima.jp +matsushige.tokushima.jp +mima.tokushima.jp +minami.tokushima.jp +miyoshi.tokushima.jp +mugi.tokushima.jp +nakagawa.tokushima.jp +naruto.tokushima.jp +sanagochi.tokushima.jp +shishikui.tokushima.jp +tokushima.tokushima.jp +wajiki.tokushima.jp +adachi.tokyo.jp +akiruno.tokyo.jp +akishima.tokyo.jp +aogashima.tokyo.jp +arakawa.tokyo.jp +bunkyo.tokyo.jp +chiyoda.tokyo.jp +chofu.tokyo.jp +chuo.tokyo.jp +edogawa.tokyo.jp +fuchu.tokyo.jp +fussa.tokyo.jp +hachijo.tokyo.jp +hachioji.tokyo.jp +hamura.tokyo.jp +higashikurume.tokyo.jp +higashimurayama.tokyo.jp +higashiyamato.tokyo.jp +hino.tokyo.jp +hinode.tokyo.jp +hinohara.tokyo.jp +inagi.tokyo.jp +itabashi.tokyo.jp +katsushika.tokyo.jp +kita.tokyo.jp +kiyose.tokyo.jp +kodaira.tokyo.jp +koganei.tokyo.jp +kokubunji.tokyo.jp +komae.tokyo.jp +koto.tokyo.jp +kouzushima.tokyo.jp +kunitachi.tokyo.jp +machida.tokyo.jp +meguro.tokyo.jp +minato.tokyo.jp +mitaka.tokyo.jp +mizuho.tokyo.jp +musashimurayama.tokyo.jp +musashino.tokyo.jp +nakano.tokyo.jp +nerima.tokyo.jp +ogasawara.tokyo.jp +okutama.tokyo.jp +ome.tokyo.jp +oshima.tokyo.jp +ota.tokyo.jp +setagaya.tokyo.jp +shibuya.tokyo.jp +shinagawa.tokyo.jp +shinjuku.tokyo.jp +suginami.tokyo.jp +sumida.tokyo.jp +tachikawa.tokyo.jp +taito.tokyo.jp +tama.tokyo.jp +toshima.tokyo.jp +chizu.tottori.jp +hino.tottori.jp +kawahara.tottori.jp +koge.tottori.jp +kotoura.tottori.jp +misasa.tottori.jp +nanbu.tottori.jp +nichinan.tottori.jp +sakaiminato.tottori.jp +tottori.tottori.jp +wakasa.tottori.jp +yazu.tottori.jp +yonago.tottori.jp +asahi.toyama.jp +fuchu.toyama.jp +fukumitsu.toyama.jp +funahashi.toyama.jp +himi.toyama.jp +imizu.toyama.jp +inami.toyama.jp +johana.toyama.jp +kamiichi.toyama.jp +kurobe.toyama.jp +nakaniikawa.toyama.jp +namerikawa.toyama.jp +nanto.toyama.jp +nyuzen.toyama.jp +oyabe.toyama.jp +taira.toyama.jp +takaoka.toyama.jp +tateyama.toyama.jp +toga.toyama.jp +tonami.toyama.jp +toyama.toyama.jp +unazuki.toyama.jp +uozu.toyama.jp +yamada.toyama.jp +arida.wakayama.jp +aridagawa.wakayama.jp +gobo.wakayama.jp +hashimoto.wakayama.jp +hidaka.wakayama.jp +hirogawa.wakayama.jp +inami.wakayama.jp +iwade.wakayama.jp +kainan.wakayama.jp +kamitonda.wakayama.jp +katsuragi.wakayama.jp +kimino.wakayama.jp +kinokawa.wakayama.jp +kitayama.wakayama.jp +koya.wakayama.jp +koza.wakayama.jp +kozagawa.wakayama.jp +kudoyama.wakayama.jp +kushimoto.wakayama.jp +mihama.wakayama.jp +misato.wakayama.jp +nachikatsuura.wakayama.jp +shingu.wakayama.jp +shirahama.wakayama.jp +taiji.wakayama.jp +tanabe.wakayama.jp +wakayama.wakayama.jp +yuasa.wakayama.jp +yura.wakayama.jp +asahi.yamagata.jp +funagata.yamagata.jp +higashine.yamagata.jp +iide.yamagata.jp +kahoku.yamagata.jp +kaminoyama.yamagata.jp +kaneyama.yamagata.jp +kawanishi.yamagata.jp +mamurogawa.yamagata.jp +mikawa.yamagata.jp +murayama.yamagata.jp +nagai.yamagata.jp +nakayama.yamagata.jp +nanyo.yamagata.jp +nishikawa.yamagata.jp +obanazawa.yamagata.jp +oe.yamagata.jp +oguni.yamagata.jp +ohkura.yamagata.jp +oishida.yamagata.jp +sagae.yamagata.jp +sakata.yamagata.jp +sakegawa.yamagata.jp +shinjo.yamagata.jp +shirataka.yamagata.jp +shonai.yamagata.jp +takahata.yamagata.jp +tendo.yamagata.jp +tozawa.yamagata.jp +tsuruoka.yamagata.jp +yamagata.yamagata.jp +yamanobe.yamagata.jp +yonezawa.yamagata.jp +yuza.yamagata.jp +abu.yamaguchi.jp +hagi.yamaguchi.jp +hikari.yamaguchi.jp +hofu.yamaguchi.jp +iwakuni.yamaguchi.jp +kudamatsu.yamaguchi.jp +mitou.yamaguchi.jp +nagato.yamaguchi.jp +oshima.yamaguchi.jp +shimonoseki.yamaguchi.jp +shunan.yamaguchi.jp +tabuse.yamaguchi.jp +tokuyama.yamaguchi.jp +toyota.yamaguchi.jp +ube.yamaguchi.jp +yuu.yamaguchi.jp +chuo.yamanashi.jp +doshi.yamanashi.jp +fuefuki.yamanashi.jp +fujikawa.yamanashi.jp +fujikawaguchiko.yamanashi.jp +fujiyoshida.yamanashi.jp +hayakawa.yamanashi.jp +hokuto.yamanashi.jp +ichikawamisato.yamanashi.jp +kai.yamanashi.jp +kofu.yamanashi.jp +koshu.yamanashi.jp +kosuge.yamanashi.jp +minami-alps.yamanashi.jp +minobu.yamanashi.jp +nakamichi.yamanashi.jp +nanbu.yamanashi.jp +narusawa.yamanashi.jp +nirasaki.yamanashi.jp +nishikatsura.yamanashi.jp +oshino.yamanashi.jp +otsuki.yamanashi.jp +showa.yamanashi.jp +tabayama.yamanashi.jp +tsuru.yamanashi.jp +uenohara.yamanashi.jp +yamanakako.yamanashi.jp +yamanashi.yamanashi.jp + +// ke : http://www.kenic.or.ke/index.php/en/ke-domains/ke-domains +ke +ac.ke +co.ke +go.ke +info.ke +me.ke +mobi.ke +ne.ke +or.ke +sc.ke + +// kg : http://www.domain.kg/dmn_n.html +kg +org.kg +net.kg +com.kg +edu.kg +gov.kg +mil.kg + +// kh : http://www.mptc.gov.kh/dns_registration.htm +*.kh + +// ki : http://www.ki/dns/index.html +ki +edu.ki +biz.ki +net.ki +org.ki +gov.ki +info.ki +com.ki + +// km : https://en.wikipedia.org/wiki/.km +// http://www.domaine.km/documents/charte.doc +km +org.km +nom.km +gov.km +prd.km +tm.km +edu.km +mil.km +ass.km +com.km +// These are only mentioned as proposed suggestions at domaine.km, but +// https://en.wikipedia.org/wiki/.km says they're available for registration: +coop.km +asso.km +presse.km +medecin.km +notaires.km +pharmaciens.km +veterinaire.km +gouv.km + +// kn : https://en.wikipedia.org/wiki/.kn +// http://www.dot.kn/domainRules.html +kn +net.kn +org.kn +edu.kn +gov.kn + +// kp : http://www.kcce.kp/en_index.php +kp +com.kp +edu.kp +gov.kp +org.kp +rep.kp +tra.kp + +// kr : https://en.wikipedia.org/wiki/.kr +// see also: http://domain.nida.or.kr/eng/registration.jsp +kr +ac.kr +co.kr +es.kr +go.kr +hs.kr +kg.kr +mil.kr +ms.kr +ne.kr +or.kr +pe.kr +re.kr +sc.kr +// kr geographical names +busan.kr +chungbuk.kr +chungnam.kr +daegu.kr +daejeon.kr +gangwon.kr +gwangju.kr +gyeongbuk.kr +gyeonggi.kr +gyeongnam.kr +incheon.kr +jeju.kr +jeonbuk.kr +jeonnam.kr +seoul.kr +ulsan.kr + +// kw : https://www.nic.kw/policies/ +// Confirmed by registry +kw +com.kw +edu.kw +emb.kw +gov.kw +ind.kw +net.kw +org.kw + +// ky : http://www.icta.ky/da_ky_reg_dom.php +// Confirmed by registry 2008-06-17 +ky +com.ky +edu.ky +net.ky +org.ky + +// kz : https://en.wikipedia.org/wiki/.kz +// see also: http://www.nic.kz/rules/index.jsp +kz +org.kz +edu.kz +net.kz +gov.kz +mil.kz +com.kz + +// la : https://en.wikipedia.org/wiki/.la +// Submitted by registry +la +int.la +net.la +info.la +edu.la +gov.la +per.la +com.la +org.la + +// lb : https://en.wikipedia.org/wiki/.lb +// Submitted by registry +lb +com.lb +edu.lb +gov.lb +net.lb +org.lb + +// lc : https://en.wikipedia.org/wiki/.lc +// see also: http://www.nic.lc/rules.htm +lc +com.lc +net.lc +co.lc +org.lc +edu.lc +gov.lc + +// li : https://en.wikipedia.org/wiki/.li +li + +// lk : https://www.nic.lk/index.php/domain-registration/lk-domain-naming-structure +lk +gov.lk +sch.lk +net.lk +int.lk +com.lk +org.lk +edu.lk +ngo.lk +soc.lk +web.lk +ltd.lk +assn.lk +grp.lk +hotel.lk +ac.lk + +// lr : http://psg.com/dns/lr/lr.txt +// Submitted by registry +lr +com.lr +edu.lr +gov.lr +org.lr +net.lr + +// ls : http://www.nic.ls/ +// Confirmed by registry +ls +ac.ls +biz.ls +co.ls +edu.ls +gov.ls +info.ls +net.ls +org.ls +sc.ls + +// lt : https://en.wikipedia.org/wiki/.lt +lt +// gov.lt : http://www.gov.lt/index_en.php +gov.lt + +// lu : http://www.dns.lu/en/ +lu + +// lv : http://www.nic.lv/DNS/En/generic.php +lv +com.lv +edu.lv +gov.lv +org.lv +mil.lv +id.lv +net.lv +asn.lv +conf.lv + +// ly : http://www.nic.ly/regulations.php +ly +com.ly +net.ly +gov.ly +plc.ly +edu.ly +sch.ly +med.ly +org.ly +id.ly + +// ma : https://en.wikipedia.org/wiki/.ma +// http://www.anrt.ma/fr/admin/download/upload/file_fr782.pdf +ma +co.ma +net.ma +gov.ma +org.ma +ac.ma +press.ma + +// mc : http://www.nic.mc/ +mc +tm.mc +asso.mc + +// md : https://en.wikipedia.org/wiki/.md +md + +// me : https://en.wikipedia.org/wiki/.me +me +co.me +net.me +org.me +edu.me +ac.me +gov.me +its.me +priv.me + +// mg : http://nic.mg/nicmg/?page_id=39 +mg +org.mg +nom.mg +gov.mg +prd.mg +tm.mg +edu.mg +mil.mg +com.mg +co.mg + +// mh : https://en.wikipedia.org/wiki/.mh +mh + +// mil : https://en.wikipedia.org/wiki/.mil +mil + +// mk : https://en.wikipedia.org/wiki/.mk +// see also: http://dns.marnet.net.mk/postapka.php +mk +com.mk +org.mk +net.mk +edu.mk +gov.mk +inf.mk +name.mk + +// ml : http://www.gobin.info/domainname/ml-template.doc +// see also: https://en.wikipedia.org/wiki/.ml +ml +com.ml +edu.ml +gouv.ml +gov.ml +net.ml +org.ml +presse.ml + +// mm : https://en.wikipedia.org/wiki/.mm +*.mm + +// mn : https://en.wikipedia.org/wiki/.mn +mn +gov.mn +edu.mn +org.mn + +// mo : http://www.monic.net.mo/ +mo +com.mo +net.mo +org.mo +edu.mo +gov.mo + +// mobi : https://en.wikipedia.org/wiki/.mobi +mobi + +// mp : http://www.dot.mp/ +// Confirmed by registry 2008-06-17 +mp + +// mq : https://en.wikipedia.org/wiki/.mq +mq + +// mr : https://en.wikipedia.org/wiki/.mr +mr +gov.mr + +// ms : http://www.nic.ms/pdf/MS_Domain_Name_Rules.pdf +ms +com.ms +edu.ms +gov.ms +net.ms +org.ms + +// mt : https://www.nic.org.mt/go/policy +// Submitted by registry +mt +com.mt +edu.mt +net.mt +org.mt + +// mu : https://en.wikipedia.org/wiki/.mu +mu +com.mu +net.mu +org.mu +gov.mu +ac.mu +co.mu +or.mu + +// museum : https://welcome.museum/wp-content/uploads/2018/05/20180525-Registration-Policy-MUSEUM-EN_VF-2.pdf https://welcome.museum/buy-your-dot-museum-2/ +museum + +// mv : https://en.wikipedia.org/wiki/.mv +// "mv" included because, contra Wikipedia, google.mv exists. +mv +aero.mv +biz.mv +com.mv +coop.mv +edu.mv +gov.mv +info.mv +int.mv +mil.mv +museum.mv +name.mv +net.mv +org.mv +pro.mv + +// mw : http://www.registrar.mw/ +mw +ac.mw +biz.mw +co.mw +com.mw +coop.mw +edu.mw +gov.mw +int.mw +museum.mw +net.mw +org.mw + +// mx : http://www.nic.mx/ +// Submitted by registry +mx +com.mx +org.mx +gob.mx +edu.mx +net.mx + +// my : http://www.mynic.my/ +// Available strings: https://mynic.my/resources/domains/buying-a-domain/ +my +biz.my +com.my +edu.my +gov.my +mil.my +name.my +net.my +org.my + +// mz : http://www.uem.mz/ +// Submitted by registry +mz +ac.mz +adv.mz +co.mz +edu.mz +gov.mz +mil.mz +net.mz +org.mz + +// na : http://www.na-nic.com.na/ +// http://www.info.na/domain/ +na +info.na +pro.na +name.na +school.na +or.na +dr.na +us.na +mx.na +ca.na +in.na +cc.na +tv.na +ws.na +mobi.na +co.na +com.na +org.na + +// name : has 2nd-level tlds, but there's no list of them +name + +// nc : http://www.cctld.nc/ +nc +asso.nc +nom.nc + +// ne : https://en.wikipedia.org/wiki/.ne +ne + +// net : https://en.wikipedia.org/wiki/.net +net + +// nf : https://en.wikipedia.org/wiki/.nf +nf +com.nf +net.nf +per.nf +rec.nf +web.nf +arts.nf +firm.nf +info.nf +other.nf +store.nf + +// ng : http://www.nira.org.ng/index.php/join-us/register-ng-domain/189-nira-slds +ng +com.ng +edu.ng +gov.ng +i.ng +mil.ng +mobi.ng +name.ng +net.ng +org.ng +sch.ng + +// ni : http://www.nic.ni/ +ni +ac.ni +biz.ni +co.ni +com.ni +edu.ni +gob.ni +in.ni +info.ni +int.ni +mil.ni +net.ni +nom.ni +org.ni +web.ni + +// nl : https://en.wikipedia.org/wiki/.nl +// https://www.sidn.nl/ +// ccTLD for the Netherlands +nl + +// no : https://www.norid.no/en/om-domenenavn/regelverk-for-no/ +// Norid geographical second level domains : https://www.norid.no/en/om-domenenavn/regelverk-for-no/vedlegg-b/ +// Norid category second level domains : https://www.norid.no/en/om-domenenavn/regelverk-for-no/vedlegg-c/ +// Norid category second-level domains managed by parties other than Norid : https://www.norid.no/en/om-domenenavn/regelverk-for-no/vedlegg-d/ +// RSS feed: https://teknisk.norid.no/en/feed/ +no +// Norid category second level domains : https://www.norid.no/en/om-domenenavn/regelverk-for-no/vedlegg-c/ +fhs.no +vgs.no +fylkesbibl.no +folkebibl.no +museum.no +idrett.no +priv.no +// Norid category second-level domains managed by parties other than Norid : https://www.norid.no/en/om-domenenavn/regelverk-for-no/vedlegg-d/ +mil.no +stat.no +dep.no +kommune.no +herad.no +// Norid geographical second level domains : https://www.norid.no/en/om-domenenavn/regelverk-for-no/vedlegg-b/ +// counties +aa.no +ah.no +bu.no +fm.no +hl.no +hm.no +jan-mayen.no +mr.no +nl.no +nt.no +of.no +ol.no +oslo.no +rl.no +sf.no +st.no +svalbard.no +tm.no +tr.no +va.no +vf.no +// primary and lower secondary schools per county +gs.aa.no +gs.ah.no +gs.bu.no +gs.fm.no +gs.hl.no +gs.hm.no +gs.jan-mayen.no +gs.mr.no +gs.nl.no +gs.nt.no +gs.of.no +gs.ol.no +gs.oslo.no +gs.rl.no +gs.sf.no +gs.st.no +gs.svalbard.no +gs.tm.no +gs.tr.no +gs.va.no +gs.vf.no +// cities +akrehamn.no +åkrehamn.no +algard.no +ålgård.no +arna.no +brumunddal.no +bryne.no +bronnoysund.no +brønnøysund.no +drobak.no +drøbak.no +egersund.no +fetsund.no +floro.no +florø.no +fredrikstad.no +hokksund.no +honefoss.no +hønefoss.no +jessheim.no +jorpeland.no +jørpeland.no +kirkenes.no +kopervik.no +krokstadelva.no +langevag.no +langevåg.no +leirvik.no +mjondalen.no +mjøndalen.no +mo-i-rana.no +mosjoen.no +mosjøen.no +nesoddtangen.no +orkanger.no +osoyro.no +osøyro.no +raholt.no +råholt.no +sandnessjoen.no +sandnessjøen.no +skedsmokorset.no +slattum.no +spjelkavik.no +stathelle.no +stavern.no +stjordalshalsen.no +stjørdalshalsen.no +tananger.no +tranby.no +vossevangen.no +// communities +afjord.no +åfjord.no +agdenes.no +al.no +ål.no +alesund.no +ålesund.no +alstahaug.no +alta.no +áltá.no +alaheadju.no +álaheadju.no +alvdal.no +amli.no +åmli.no +amot.no +åmot.no +andebu.no +andoy.no +andøy.no +andasuolo.no +ardal.no +årdal.no +aremark.no +arendal.no +ås.no +aseral.no +åseral.no +asker.no +askim.no +askvoll.no +askoy.no +askøy.no +asnes.no +åsnes.no +audnedaln.no +aukra.no +aure.no +aurland.no +aurskog-holand.no +aurskog-høland.no +austevoll.no +austrheim.no +averoy.no +averøy.no +balestrand.no +ballangen.no +balat.no +bálát.no +balsfjord.no +bahccavuotna.no +báhccavuotna.no +bamble.no +bardu.no +beardu.no +beiarn.no +bajddar.no +bájddar.no +baidar.no +báidár.no +berg.no +bergen.no +berlevag.no +berlevåg.no +bearalvahki.no +bearalváhki.no +bindal.no +birkenes.no +bjarkoy.no +bjarkøy.no +bjerkreim.no +bjugn.no +bodo.no +bodø.no +badaddja.no +bådåddjå.no +budejju.no +bokn.no +bremanger.no +bronnoy.no +brønnøy.no +bygland.no +bykle.no +barum.no +bærum.no +bo.telemark.no +bø.telemark.no +bo.nordland.no +bø.nordland.no +bievat.no +bievát.no +bomlo.no +bømlo.no +batsfjord.no +båtsfjord.no +bahcavuotna.no +báhcavuotna.no +dovre.no +drammen.no +drangedal.no +dyroy.no +dyrøy.no +donna.no +dønna.no +eid.no +eidfjord.no +eidsberg.no +eidskog.no +eidsvoll.no +eigersund.no +elverum.no +enebakk.no +engerdal.no +etne.no +etnedal.no +evenes.no +evenassi.no +evenášši.no +evje-og-hornnes.no +farsund.no +fauske.no +fuossko.no +fuoisku.no +fedje.no +fet.no +finnoy.no +finnøy.no +fitjar.no +fjaler.no +fjell.no +flakstad.no +flatanger.no +flekkefjord.no +flesberg.no +flora.no +fla.no +flå.no +folldal.no +forsand.no +fosnes.no +frei.no +frogn.no +froland.no +frosta.no +frana.no +fræna.no +froya.no +frøya.no +fusa.no +fyresdal.no +forde.no +førde.no +gamvik.no +gangaviika.no +gáŋgaviika.no +gaular.no +gausdal.no +gildeskal.no +gildeskål.no +giske.no +gjemnes.no +gjerdrum.no +gjerstad.no +gjesdal.no +gjovik.no +gjøvik.no +gloppen.no +gol.no +gran.no +grane.no +granvin.no +gratangen.no +grimstad.no +grong.no +kraanghke.no +kråanghke.no +grue.no +gulen.no +hadsel.no +halden.no +halsa.no +hamar.no +hamaroy.no +habmer.no +hábmer.no +hapmir.no +hápmir.no +hammerfest.no +hammarfeasta.no +hámmárfeasta.no +haram.no +hareid.no +harstad.no +hasvik.no +aknoluokta.no +ákŋoluokta.no +hattfjelldal.no +aarborte.no +haugesund.no +hemne.no +hemnes.no +hemsedal.no +heroy.more-og-romsdal.no +herøy.møre-og-romsdal.no +heroy.nordland.no +herøy.nordland.no +hitra.no +hjartdal.no +hjelmeland.no +hobol.no +hobøl.no +hof.no +hol.no +hole.no +holmestrand.no +holtalen.no +holtålen.no +hornindal.no +horten.no +hurdal.no +hurum.no +hvaler.no +hyllestad.no +hagebostad.no +hægebostad.no +hoyanger.no +høyanger.no +hoylandet.no +høylandet.no +ha.no +hå.no +ibestad.no +inderoy.no +inderøy.no +iveland.no +jevnaker.no +jondal.no +jolster.no +jølster.no +karasjok.no +karasjohka.no +kárášjohka.no +karlsoy.no +galsa.no +gálsá.no +karmoy.no +karmøy.no +kautokeino.no +guovdageaidnu.no +klepp.no +klabu.no +klæbu.no +kongsberg.no +kongsvinger.no +kragero.no +kragerø.no +kristiansand.no +kristiansund.no +krodsherad.no +krødsherad.no +kvalsund.no +rahkkeravju.no +ráhkkerávju.no +kvam.no +kvinesdal.no +kvinnherad.no +kviteseid.no +kvitsoy.no +kvitsøy.no +kvafjord.no +kvæfjord.no +giehtavuoatna.no +kvanangen.no +kvænangen.no +navuotna.no +návuotna.no +kafjord.no +kåfjord.no +gaivuotna.no +gáivuotna.no +larvik.no +lavangen.no +lavagis.no +loabat.no +loabát.no +lebesby.no +davvesiida.no +leikanger.no +leirfjord.no +leka.no +leksvik.no +lenvik.no +leangaviika.no +leaŋgaviika.no +lesja.no +levanger.no +lier.no +lierne.no +lillehammer.no +lillesand.no +lindesnes.no +lindas.no +lindås.no +lom.no +loppa.no +lahppi.no +láhppi.no +lund.no +lunner.no +luroy.no +lurøy.no +luster.no +lyngdal.no +lyngen.no +ivgu.no +lardal.no +lerdal.no +lærdal.no +lodingen.no +lødingen.no +lorenskog.no +lørenskog.no +loten.no +løten.no +malvik.no +masoy.no +måsøy.no +muosat.no +muosát.no +mandal.no +marker.no +marnardal.no +masfjorden.no +meland.no +meldal.no +melhus.no +meloy.no +meløy.no +meraker.no +meråker.no +moareke.no +moåreke.no +midsund.no +midtre-gauldal.no +modalen.no +modum.no +molde.no +moskenes.no +moss.no +mosvik.no +malselv.no +målselv.no +malatvuopmi.no +málatvuopmi.no +namdalseid.no +aejrie.no +namsos.no +namsskogan.no +naamesjevuemie.no +nååmesjevuemie.no +laakesvuemie.no +nannestad.no +narvik.no +narviika.no +naustdal.no +nedre-eiker.no +nes.akershus.no +nes.buskerud.no +nesna.no +nesodden.no +nesseby.no +unjarga.no +unjárga.no +nesset.no +nissedal.no +nittedal.no +nord-aurdal.no +nord-fron.no +nord-odal.no +norddal.no +nordkapp.no +davvenjarga.no +davvenjárga.no +nordre-land.no +nordreisa.no +raisa.no +ráisa.no +nore-og-uvdal.no +notodden.no +naroy.no +nærøy.no +notteroy.no +nøtterøy.no +odda.no +oksnes.no +øksnes.no +oppdal.no +oppegard.no +oppegård.no +orkdal.no +orland.no +ørland.no +orskog.no +ørskog.no +orsta.no +ørsta.no +os.hedmark.no +os.hordaland.no +osen.no +osteroy.no +osterøy.no +ostre-toten.no +østre-toten.no +overhalla.no +ovre-eiker.no +øvre-eiker.no +oyer.no +øyer.no +oygarden.no +øygarden.no +oystre-slidre.no +øystre-slidre.no +porsanger.no +porsangu.no +porsáŋgu.no +porsgrunn.no +radoy.no +radøy.no +rakkestad.no +rana.no +ruovat.no +randaberg.no +rauma.no +rendalen.no +rennebu.no +rennesoy.no +rennesøy.no +rindal.no +ringebu.no +ringerike.no +ringsaker.no +rissa.no +risor.no +risør.no +roan.no +rollag.no +rygge.no +ralingen.no +rælingen.no +rodoy.no +rødøy.no +romskog.no +rømskog.no +roros.no +røros.no +rost.no +røst.no +royken.no +røyken.no +royrvik.no +røyrvik.no +rade.no +råde.no +salangen.no +siellak.no +saltdal.no +salat.no +sálát.no +sálat.no +samnanger.no +sande.more-og-romsdal.no +sande.møre-og-romsdal.no +sande.vestfold.no +sandefjord.no +sandnes.no +sandoy.no +sandøy.no +sarpsborg.no +sauda.no +sauherad.no +sel.no +selbu.no +selje.no +seljord.no +sigdal.no +siljan.no +sirdal.no +skaun.no +skedsmo.no +ski.no +skien.no +skiptvet.no +skjervoy.no +skjervøy.no +skierva.no +skiervá.no +skjak.no +skjåk.no +skodje.no +skanland.no +skånland.no +skanit.no +skánit.no +smola.no +smøla.no +snillfjord.no +snasa.no +snåsa.no +snoasa.no +snaase.no +snåase.no +sogndal.no +sokndal.no +sola.no +solund.no +songdalen.no +sortland.no +spydeberg.no +stange.no +stavanger.no +steigen.no +steinkjer.no +stjordal.no +stjørdal.no +stokke.no +stor-elvdal.no +stord.no +stordal.no +storfjord.no +omasvuotna.no +strand.no +stranda.no +stryn.no +sula.no +suldal.no +sund.no +sunndal.no +surnadal.no +sveio.no +svelvik.no +sykkylven.no +sogne.no +søgne.no +somna.no +sømna.no +sondre-land.no +søndre-land.no +sor-aurdal.no +sør-aurdal.no +sor-fron.no +sør-fron.no +sor-odal.no +sør-odal.no +sor-varanger.no +sør-varanger.no +matta-varjjat.no +mátta-várjjat.no +sorfold.no +sørfold.no +sorreisa.no +sørreisa.no +sorum.no +sørum.no +tana.no +deatnu.no +time.no +tingvoll.no +tinn.no +tjeldsund.no +dielddanuorri.no +tjome.no +tjøme.no +tokke.no +tolga.no +torsken.no +tranoy.no +tranøy.no +tromso.no +tromsø.no +tromsa.no +romsa.no +trondheim.no +troandin.no +trysil.no +trana.no +træna.no +trogstad.no +trøgstad.no +tvedestrand.no +tydal.no +tynset.no +tysfjord.no +divtasvuodna.no +divttasvuotna.no +tysnes.no +tysvar.no +tysvær.no +tonsberg.no +tønsberg.no +ullensaker.no +ullensvang.no +ulvik.no +utsira.no +vadso.no +vadsø.no +cahcesuolo.no +čáhcesuolo.no +vaksdal.no +valle.no +vang.no +vanylven.no +vardo.no +vardø.no +varggat.no +várggát.no +vefsn.no +vaapste.no +vega.no +vegarshei.no +vegårshei.no +vennesla.no +verdal.no +verran.no +vestby.no +vestnes.no +vestre-slidre.no +vestre-toten.no +vestvagoy.no +vestvågøy.no +vevelstad.no +vik.no +vikna.no +vindafjord.no +volda.no +voss.no +varoy.no +værøy.no +vagan.no +vågan.no +voagat.no +vagsoy.no +vågsøy.no +vaga.no +vågå.no +valer.ostfold.no +våler.østfold.no +valer.hedmark.no +våler.hedmark.no + +// np : http://www.mos.com.np/register.html +*.np + +// nr : http://cenpac.net.nr/dns/index.html +// Submitted by registry +nr +biz.nr +info.nr +gov.nr +edu.nr +org.nr +net.nr +com.nr + +// nu : https://en.wikipedia.org/wiki/.nu +nu + +// nz : https://en.wikipedia.org/wiki/.nz +// Submitted by registry +nz +ac.nz +co.nz +cri.nz +geek.nz +gen.nz +govt.nz +health.nz +iwi.nz +kiwi.nz +maori.nz +mil.nz +māori.nz +net.nz +org.nz +parliament.nz +school.nz + +// om : https://en.wikipedia.org/wiki/.om +om +co.om +com.om +edu.om +gov.om +med.om +museum.om +net.om +org.om +pro.om + +// onion : https://tools.ietf.org/html/rfc7686 +onion + +// org : https://en.wikipedia.org/wiki/.org +org + +// pa : http://www.nic.pa/ +// Some additional second level "domains" resolve directly as hostnames, such as +// pannet.pa, so we add a rule for "pa". +pa +ac.pa +gob.pa +com.pa +org.pa +sld.pa +edu.pa +net.pa +ing.pa +abo.pa +med.pa +nom.pa + +// pe : https://www.nic.pe/InformeFinalComision.pdf +pe +edu.pe +gob.pe +nom.pe +mil.pe +org.pe +com.pe +net.pe + +// pf : http://www.gobin.info/domainname/formulaire-pf.pdf +pf +com.pf +org.pf +edu.pf + +// pg : https://en.wikipedia.org/wiki/.pg +*.pg + +// ph : http://www.domains.ph/FAQ2.asp +// Submitted by registry +ph +com.ph +net.ph +org.ph +gov.ph +edu.ph +ngo.ph +mil.ph +i.ph + +// pk : http://pk5.pknic.net.pk/pk5/msgNamepk.PK +pk +com.pk +net.pk +edu.pk +org.pk +fam.pk +biz.pk +web.pk +gov.pk +gob.pk +gok.pk +gon.pk +gop.pk +gos.pk +info.pk + +// pl http://www.dns.pl/english/index.html +// Submitted by registry +pl +com.pl +net.pl +org.pl +// pl functional domains (http://www.dns.pl/english/index.html) +aid.pl +agro.pl +atm.pl +auto.pl +biz.pl +edu.pl +gmina.pl +gsm.pl +info.pl +mail.pl +miasta.pl +media.pl +mil.pl +nieruchomosci.pl +nom.pl +pc.pl +powiat.pl +priv.pl +realestate.pl +rel.pl +sex.pl +shop.pl +sklep.pl +sos.pl +szkola.pl +targi.pl +tm.pl +tourism.pl +travel.pl +turystyka.pl +// Government domains +gov.pl +ap.gov.pl +griw.gov.pl +ic.gov.pl +is.gov.pl +kmpsp.gov.pl +konsulat.gov.pl +kppsp.gov.pl +kwp.gov.pl +kwpsp.gov.pl +mup.gov.pl +mw.gov.pl +oia.gov.pl +oirm.gov.pl +oke.gov.pl +oow.gov.pl +oschr.gov.pl +oum.gov.pl +pa.gov.pl +pinb.gov.pl +piw.gov.pl +po.gov.pl +pr.gov.pl +psp.gov.pl +psse.gov.pl +pup.gov.pl +rzgw.gov.pl +sa.gov.pl +sdn.gov.pl +sko.gov.pl +so.gov.pl +sr.gov.pl +starostwo.gov.pl +ug.gov.pl +ugim.gov.pl +um.gov.pl +umig.gov.pl +upow.gov.pl +uppo.gov.pl +us.gov.pl +uw.gov.pl +uzs.gov.pl +wif.gov.pl +wiih.gov.pl +winb.gov.pl +wios.gov.pl +witd.gov.pl +wiw.gov.pl +wkz.gov.pl +wsa.gov.pl +wskr.gov.pl +wsse.gov.pl +wuoz.gov.pl +wzmiuw.gov.pl +zp.gov.pl +zpisdn.gov.pl +// pl regional domains (http://www.dns.pl/english/index.html) +augustow.pl +babia-gora.pl +bedzin.pl +beskidy.pl +bialowieza.pl +bialystok.pl +bielawa.pl +bieszczady.pl +boleslawiec.pl +bydgoszcz.pl +bytom.pl +cieszyn.pl +czeladz.pl +czest.pl +dlugoleka.pl +elblag.pl +elk.pl +glogow.pl +gniezno.pl +gorlice.pl +grajewo.pl +ilawa.pl +jaworzno.pl +jelenia-gora.pl +jgora.pl +kalisz.pl +kazimierz-dolny.pl +karpacz.pl +kartuzy.pl +kaszuby.pl +katowice.pl +kepno.pl +ketrzyn.pl +klodzko.pl +kobierzyce.pl +kolobrzeg.pl +konin.pl +konskowola.pl +kutno.pl +lapy.pl +lebork.pl +legnica.pl +lezajsk.pl +limanowa.pl +lomza.pl +lowicz.pl +lubin.pl +lukow.pl +malbork.pl +malopolska.pl +mazowsze.pl +mazury.pl +mielec.pl +mielno.pl +mragowo.pl +naklo.pl +nowaruda.pl +nysa.pl +olawa.pl +olecko.pl +olkusz.pl +olsztyn.pl +opoczno.pl +opole.pl +ostroda.pl +ostroleka.pl +ostrowiec.pl +ostrowwlkp.pl +pila.pl +pisz.pl +podhale.pl +podlasie.pl +polkowice.pl +pomorze.pl +pomorskie.pl +prochowice.pl +pruszkow.pl +przeworsk.pl +pulawy.pl +radom.pl +rawa-maz.pl +rybnik.pl +rzeszow.pl +sanok.pl +sejny.pl +slask.pl +slupsk.pl +sosnowiec.pl +stalowa-wola.pl +skoczow.pl +starachowice.pl +stargard.pl +suwalki.pl +swidnica.pl +swiebodzin.pl +swinoujscie.pl +szczecin.pl +szczytno.pl +tarnobrzeg.pl +tgory.pl +turek.pl +tychy.pl +ustka.pl +walbrzych.pl +warmia.pl +warszawa.pl +waw.pl +wegrow.pl +wielun.pl +wlocl.pl +wloclawek.pl +wodzislaw.pl +wolomin.pl +wroclaw.pl +zachpomor.pl +zagan.pl +zarow.pl +zgora.pl +zgorzelec.pl + +// pm : https://www.afnic.fr/wp-media/uploads/2022/12/afnic-naming-policy-2023-01-01.pdf +pm + +// pn : http://www.government.pn/PnRegistry/policies.htm +pn +gov.pn +co.pn +org.pn +edu.pn +net.pn + +// post : https://en.wikipedia.org/wiki/.post +post + +// pr : http://www.nic.pr/index.asp?f=1 +pr +com.pr +net.pr +org.pr +gov.pr +edu.pr +isla.pr +pro.pr +biz.pr +info.pr +name.pr +// these aren't mentioned on nic.pr, but on https://en.wikipedia.org/wiki/.pr +est.pr +prof.pr +ac.pr + +// pro : http://registry.pro/get-pro +pro +aaa.pro +aca.pro +acct.pro +avocat.pro +bar.pro +cpa.pro +eng.pro +jur.pro +law.pro +med.pro +recht.pro + +// ps : https://en.wikipedia.org/wiki/.ps +// http://www.nic.ps/registration/policy.html#reg +ps +edu.ps +gov.ps +sec.ps +plo.ps +com.ps +org.ps +net.ps + +// pt : https://www.dns.pt/en/domain/pt-terms-and-conditions-registration-rules/ +pt +net.pt +gov.pt +org.pt +edu.pt +int.pt +publ.pt +com.pt +nome.pt + +// pw : https://en.wikipedia.org/wiki/.pw +pw +co.pw +ne.pw +or.pw +ed.pw +go.pw +belau.pw + +// py : http://www.nic.py/pautas.html#seccion_9 +// Submitted by registry +py +com.py +coop.py +edu.py +gov.py +mil.py +net.py +org.py + +// qa : http://domains.qa/en/ +qa +com.qa +edu.qa +gov.qa +mil.qa +name.qa +net.qa +org.qa +sch.qa + +// re : https://www.afnic.fr/wp-media/uploads/2022/12/afnic-naming-policy-2023-01-01.pdf +re +asso.re +com.re +nom.re + +// ro : http://www.rotld.ro/ +ro +arts.ro +com.ro +firm.ro +info.ro +nom.ro +nt.ro +org.ro +rec.ro +store.ro +tm.ro +www.ro + +// rs : https://www.rnids.rs/en/domains/national-domains +rs +ac.rs +co.rs +edu.rs +gov.rs +in.rs +org.rs + +// ru : https://cctld.ru/files/pdf/docs/en/rules_ru-rf.pdf +// Submitted by George Georgievsky +ru + +// rw : https://www.ricta.org.rw/sites/default/files/resources/registry_registrar_contract_0.pdf +rw +ac.rw +co.rw +coop.rw +gov.rw +mil.rw +net.rw +org.rw + +// sa : http://www.nic.net.sa/ +sa +com.sa +net.sa +org.sa +gov.sa +med.sa +pub.sa +edu.sa +sch.sa + +// sb : http://www.sbnic.net.sb/ +// Submitted by registry +sb +com.sb +edu.sb +gov.sb +net.sb +org.sb + +// sc : http://www.nic.sc/ +sc +com.sc +gov.sc +net.sc +org.sc +edu.sc + +// sd : http://www.isoc.sd/sudanic.isoc.sd/billing_pricing.htm +// Submitted by registry +sd +com.sd +net.sd +org.sd +edu.sd +med.sd +tv.sd +gov.sd +info.sd + +// se : https://en.wikipedia.org/wiki/.se +// Submitted by registry +se +a.se +ac.se +b.se +bd.se +brand.se +c.se +d.se +e.se +f.se +fh.se +fhsk.se +fhv.se +g.se +h.se +i.se +k.se +komforb.se +kommunalforbund.se +komvux.se +l.se +lanbib.se +m.se +n.se +naturbruksgymn.se +o.se +org.se +p.se +parti.se +pp.se +press.se +r.se +s.se +t.se +tm.se +u.se +w.se +x.se +y.se +z.se + +// sg : http://www.nic.net.sg/page/registration-policies-procedures-and-guidelines +sg +com.sg +net.sg +org.sg +gov.sg +edu.sg +per.sg + +// sh : http://nic.sh/rules.htm +sh +com.sh +net.sh +gov.sh +org.sh +mil.sh + +// si : https://en.wikipedia.org/wiki/.si +si + +// sj : No registrations at this time. +// Submitted by registry +sj + +// sk : https://en.wikipedia.org/wiki/.sk +// list of 2nd level domains ? +sk + +// sl : http://www.nic.sl +// Submitted by registry +sl +com.sl +net.sl +edu.sl +gov.sl +org.sl + +// sm : https://en.wikipedia.org/wiki/.sm +sm + +// sn : https://en.wikipedia.org/wiki/.sn +sn +art.sn +com.sn +edu.sn +gouv.sn +org.sn +perso.sn +univ.sn + +// so : http://sonic.so/policies/ +so +com.so +edu.so +gov.so +me.so +net.so +org.so + +// sr : https://en.wikipedia.org/wiki/.sr +sr + +// ss : https://registry.nic.ss/ +// Submitted by registry +ss +biz.ss +com.ss +edu.ss +gov.ss +me.ss +net.ss +org.ss +sch.ss + +// st : http://www.nic.st/html/policyrules/ +st +co.st +com.st +consulado.st +edu.st +embaixada.st +mil.st +net.st +org.st +principe.st +saotome.st +store.st + +// su : https://en.wikipedia.org/wiki/.su +su + +// sv : http://www.svnet.org.sv/niveldos.pdf +sv +com.sv +edu.sv +gob.sv +org.sv +red.sv + +// sx : https://en.wikipedia.org/wiki/.sx +// Submitted by registry +sx +gov.sx + +// sy : https://en.wikipedia.org/wiki/.sy +// see also: http://www.gobin.info/domainname/sy.doc +sy +edu.sy +gov.sy +net.sy +mil.sy +com.sy +org.sy + +// sz : https://en.wikipedia.org/wiki/.sz +// http://www.sispa.org.sz/ +sz +co.sz +ac.sz +org.sz + +// tc : https://en.wikipedia.org/wiki/.tc +tc + +// td : https://en.wikipedia.org/wiki/.td +td + +// tel: https://en.wikipedia.org/wiki/.tel +// http://www.telnic.org/ +tel + +// tf : https://www.afnic.fr/wp-media/uploads/2022/12/afnic-naming-policy-2023-01-01.pdf +tf + +// tg : https://en.wikipedia.org/wiki/.tg +// http://www.nic.tg/ +tg + +// th : https://en.wikipedia.org/wiki/.th +// Submitted by registry +th +ac.th +co.th +go.th +in.th +mi.th +net.th +or.th + +// tj : http://www.nic.tj/policy.html +tj +ac.tj +biz.tj +co.tj +com.tj +edu.tj +go.tj +gov.tj +int.tj +mil.tj +name.tj +net.tj +nic.tj +org.tj +test.tj +web.tj + +// tk : https://en.wikipedia.org/wiki/.tk +tk + +// tl : https://en.wikipedia.org/wiki/.tl +tl +gov.tl + +// tm : http://www.nic.tm/local.html +tm +com.tm +co.tm +org.tm +net.tm +nom.tm +gov.tm +mil.tm +edu.tm + +// tn : http://www.registre.tn/fr/ +// https://whois.ati.tn/ +tn +com.tn +ens.tn +fin.tn +gov.tn +ind.tn +info.tn +intl.tn +mincom.tn +nat.tn +net.tn +org.tn +perso.tn +tourism.tn + +// to : https://en.wikipedia.org/wiki/.to +// Submitted by registry +to +com.to +gov.to +net.to +org.to +edu.to +mil.to + +// tr : https://nic.tr/ +// https://nic.tr/forms/eng/policies.pdf +// https://nic.tr/index.php?USRACTN=PRICELST +tr +av.tr +bbs.tr +bel.tr +biz.tr +com.tr +dr.tr +edu.tr +gen.tr +gov.tr +info.tr +mil.tr +k12.tr +kep.tr +name.tr +net.tr +org.tr +pol.tr +tel.tr +tsk.tr +tv.tr +web.tr +// Used by Northern Cyprus +nc.tr +// Used by government agencies of Northern Cyprus +gov.nc.tr + +// tt : http://www.nic.tt/ +tt +co.tt +com.tt +org.tt +net.tt +biz.tt +info.tt +pro.tt +int.tt +coop.tt +jobs.tt +mobi.tt +travel.tt +museum.tt +aero.tt +name.tt +gov.tt +edu.tt + +// tv : https://en.wikipedia.org/wiki/.tv +// Not listing any 2LDs as reserved since none seem to exist in practice, +// Wikipedia notwithstanding. +tv + +// tw : https://en.wikipedia.org/wiki/.tw +tw +edu.tw +gov.tw +mil.tw +com.tw +net.tw +org.tw +idv.tw +game.tw +ebiz.tw +club.tw +網路.tw +組織.tw +商業.tw + +// tz : http://www.tznic.or.tz/index.php/domains +// Submitted by registry +tz +ac.tz +co.tz +go.tz +hotel.tz +info.tz +me.tz +mil.tz +mobi.tz +ne.tz +or.tz +sc.tz +tv.tz + +// ua : https://hostmaster.ua/policy/?ua +// Submitted by registry +ua +// ua 2LD +com.ua +edu.ua +gov.ua +in.ua +net.ua +org.ua +// ua geographic names +// https://hostmaster.ua/2ld/ +cherkassy.ua +cherkasy.ua +chernigov.ua +chernihiv.ua +chernivtsi.ua +chernovtsy.ua +ck.ua +cn.ua +cr.ua +crimea.ua +cv.ua +dn.ua +dnepropetrovsk.ua +dnipropetrovsk.ua +donetsk.ua +dp.ua +if.ua +ivano-frankivsk.ua +kh.ua +kharkiv.ua +kharkov.ua +kherson.ua +khmelnitskiy.ua +khmelnytskyi.ua +kiev.ua +kirovograd.ua +km.ua +kr.ua +kropyvnytskyi.ua +krym.ua +ks.ua +kv.ua +kyiv.ua +lg.ua +lt.ua +lugansk.ua +luhansk.ua +lutsk.ua +lv.ua +lviv.ua +mk.ua +mykolaiv.ua +nikolaev.ua +od.ua +odesa.ua +odessa.ua +pl.ua +poltava.ua +rivne.ua +rovno.ua +rv.ua +sb.ua +sebastopol.ua +sevastopol.ua +sm.ua +sumy.ua +te.ua +ternopil.ua +uz.ua +uzhgorod.ua +uzhhorod.ua +vinnica.ua +vinnytsia.ua +vn.ua +volyn.ua +yalta.ua +zakarpattia.ua +zaporizhzhe.ua +zaporizhzhia.ua +zhitomir.ua +zhytomyr.ua +zp.ua +zt.ua + +// ug : https://www.registry.co.ug/ +ug +co.ug +or.ug +ac.ug +sc.ug +go.ug +ne.ug +com.ug +org.ug + +// uk : https://en.wikipedia.org/wiki/.uk +// Submitted by registry +uk +ac.uk +co.uk +gov.uk +ltd.uk +me.uk +net.uk +nhs.uk +org.uk +plc.uk +police.uk +*.sch.uk + +// us : https://en.wikipedia.org/wiki/.us +us +dni.us +fed.us +isa.us +kids.us +nsn.us +// us geographic names +ak.us +al.us +ar.us +as.us +az.us +ca.us +co.us +ct.us +dc.us +de.us +fl.us +ga.us +gu.us +hi.us +ia.us +id.us +il.us +in.us +ks.us +ky.us +la.us +ma.us +md.us +me.us +mi.us +mn.us +mo.us +ms.us +mt.us +nc.us +nd.us +ne.us +nh.us +nj.us +nm.us +nv.us +ny.us +oh.us +ok.us +or.us +pa.us +pr.us +ri.us +sc.us +sd.us +tn.us +tx.us +ut.us +vi.us +vt.us +va.us +wa.us +wi.us +wv.us +wy.us +// The registrar notes several more specific domains available in each state, +// such as state.*.us, dst.*.us, etc., but resolution of these is somewhat +// haphazard; in some states these domains resolve as addresses, while in others +// only subdomains are available, or even nothing at all. We include the +// most common ones where it's clear that different sites are different +// entities. +k12.ak.us +k12.al.us +k12.ar.us +k12.as.us +k12.az.us +k12.ca.us +k12.co.us +k12.ct.us +k12.dc.us +k12.fl.us +k12.ga.us +k12.gu.us +// k12.hi.us Bug 614565 - Hawaii has a state-wide DOE login +k12.ia.us +k12.id.us +k12.il.us +k12.in.us +k12.ks.us +k12.ky.us +k12.la.us +k12.ma.us +k12.md.us +k12.me.us +k12.mi.us +k12.mn.us +k12.mo.us +k12.ms.us +k12.mt.us +k12.nc.us +// k12.nd.us Bug 1028347 - Removed at request of Travis Rosso +k12.ne.us +k12.nh.us +k12.nj.us +k12.nm.us +k12.nv.us +k12.ny.us +k12.oh.us +k12.ok.us +k12.or.us +k12.pa.us +k12.pr.us +// k12.ri.us Removed at request of Kim Cournoyer +k12.sc.us +// k12.sd.us Bug 934131 - Removed at request of James Booze +k12.tn.us +k12.tx.us +k12.ut.us +k12.vi.us +k12.vt.us +k12.va.us +k12.wa.us +k12.wi.us +// k12.wv.us Bug 947705 - Removed at request of Verne Britton +k12.wy.us +cc.ak.us +cc.al.us +cc.ar.us +cc.as.us +cc.az.us +cc.ca.us +cc.co.us +cc.ct.us +cc.dc.us +cc.de.us +cc.fl.us +cc.ga.us +cc.gu.us +cc.hi.us +cc.ia.us +cc.id.us +cc.il.us +cc.in.us +cc.ks.us +cc.ky.us +cc.la.us +cc.ma.us +cc.md.us +cc.me.us +cc.mi.us +cc.mn.us +cc.mo.us +cc.ms.us +cc.mt.us +cc.nc.us +cc.nd.us +cc.ne.us +cc.nh.us +cc.nj.us +cc.nm.us +cc.nv.us +cc.ny.us +cc.oh.us +cc.ok.us +cc.or.us +cc.pa.us +cc.pr.us +cc.ri.us +cc.sc.us +cc.sd.us +cc.tn.us +cc.tx.us +cc.ut.us +cc.vi.us +cc.vt.us +cc.va.us +cc.wa.us +cc.wi.us +cc.wv.us +cc.wy.us +lib.ak.us +lib.al.us +lib.ar.us +lib.as.us +lib.az.us +lib.ca.us +lib.co.us +lib.ct.us +lib.dc.us +// lib.de.us Issue #243 - Moved to Private section at request of Ed Moore +lib.fl.us +lib.ga.us +lib.gu.us +lib.hi.us +lib.ia.us +lib.id.us +lib.il.us +lib.in.us +lib.ks.us +lib.ky.us +lib.la.us +lib.ma.us +lib.md.us +lib.me.us +lib.mi.us +lib.mn.us +lib.mo.us +lib.ms.us +lib.mt.us +lib.nc.us +lib.nd.us +lib.ne.us +lib.nh.us +lib.nj.us +lib.nm.us +lib.nv.us +lib.ny.us +lib.oh.us +lib.ok.us +lib.or.us +lib.pa.us +lib.pr.us +lib.ri.us +lib.sc.us +lib.sd.us +lib.tn.us +lib.tx.us +lib.ut.us +lib.vi.us +lib.vt.us +lib.va.us +lib.wa.us +lib.wi.us +// lib.wv.us Bug 941670 - Removed at request of Larry W Arnold +lib.wy.us +// k12.ma.us contains school districts in Massachusetts. The 4LDs are +// managed independently except for private (PVT), charter (CHTR) and +// parochial (PAROCH) schools. Those are delegated directly to the +// 5LD operators. +pvt.k12.ma.us +chtr.k12.ma.us +paroch.k12.ma.us +// Merit Network, Inc. maintains the registry for =~ /(k12|cc|lib).mi.us/ and the following +// see also: http://domreg.merit.edu +// see also: whois -h whois.domreg.merit.edu help +ann-arbor.mi.us +cog.mi.us +dst.mi.us +eaton.mi.us +gen.mi.us +mus.mi.us +tec.mi.us +washtenaw.mi.us + +// uy : http://www.nic.org.uy/ +uy +com.uy +edu.uy +gub.uy +mil.uy +net.uy +org.uy + +// uz : http://www.reg.uz/ +uz +co.uz +com.uz +net.uz +org.uz + +// va : https://en.wikipedia.org/wiki/.va +va + +// vc : https://en.wikipedia.org/wiki/.vc +// Submitted by registry +vc +com.vc +net.vc +org.vc +gov.vc +mil.vc +edu.vc + +// ve : https://registro.nic.ve/ +// Submitted by registry nic@nic.ve and nicve@conatel.gob.ve +ve +arts.ve +bib.ve +co.ve +com.ve +e12.ve +edu.ve +firm.ve +gob.ve +gov.ve +info.ve +int.ve +mil.ve +net.ve +nom.ve +org.ve +rar.ve +rec.ve +store.ve +tec.ve +web.ve + +// vg : https://en.wikipedia.org/wiki/.vg +vg + +// vi : http://www.nic.vi/newdomainform.htm +// http://www.nic.vi/Domain_Rules/body_domain_rules.html indicates some other +// TLDs are "reserved", such as edu.vi and gov.vi, but doesn't actually say they +// are available for registration (which they do not seem to be). +vi +co.vi +com.vi +k12.vi +net.vi +org.vi + +// vn : https://www.vnnic.vn/en/domain/cctld-vn +// https://vnnic.vn/sites/default/files/tailieu/vn.cctld.domains.txt +vn +ac.vn +ai.vn +biz.vn +com.vn +edu.vn +gov.vn +health.vn +id.vn +info.vn +int.vn +io.vn +name.vn +net.vn +org.vn +pro.vn + +// vn geographical names +angiang.vn +bacgiang.vn +backan.vn +baclieu.vn +bacninh.vn +baria-vungtau.vn +bentre.vn +binhdinh.vn +binhduong.vn +binhphuoc.vn +binhthuan.vn +camau.vn +cantho.vn +caobang.vn +daklak.vn +daknong.vn +danang.vn +dienbien.vn +dongnai.vn +dongthap.vn +gialai.vn +hagiang.vn +haiduong.vn +haiphong.vn +hanam.vn +hanoi.vn +hatinh.vn +haugiang.vn +hoabinh.vn +hungyen.vn +khanhhoa.vn +kiengiang.vn +kontum.vn +laichau.vn +lamdong.vn +langson.vn +laocai.vn +longan.vn +namdinh.vn +nghean.vn +ninhbinh.vn +ninhthuan.vn +phutho.vn +phuyen.vn +quangbinh.vn +quangnam.vn +quangngai.vn +quangninh.vn +quangtri.vn +soctrang.vn +sonla.vn +tayninh.vn +thaibinh.vn +thainguyen.vn +thanhhoa.vn +thanhphohochiminh.vn +thuathienhue.vn +tiengiang.vn +travinh.vn +tuyenquang.vn +vinhlong.vn +vinhphuc.vn +yenbai.vn + +// vu : https://en.wikipedia.org/wiki/.vu +// http://www.vunic.vu/ +vu +com.vu +edu.vu +net.vu +org.vu + +// wf : https://www.afnic.fr/wp-media/uploads/2022/12/afnic-naming-policy-2023-01-01.pdf +wf + +// ws : https://en.wikipedia.org/wiki/.ws +// http://samoanic.ws/index.dhtml +ws +com.ws +net.ws +org.ws +gov.ws +edu.ws + +// yt : https://www.afnic.fr/wp-media/uploads/2022/12/afnic-naming-policy-2023-01-01.pdf +yt + +// IDN ccTLDs +// When submitting patches, please maintain a sort by ISO 3166 ccTLD, then +// U-label, and follow this format: +// // A-Label ("", [, variant info]) : +// // [sponsoring org] +// U-Label + +// xn--mgbaam7a8h ("Emerat", Arabic) : AE +// http://nic.ae/english/arabicdomain/rules.jsp +امارات + +// xn--y9a3aq ("hye", Armenian) : AM +// ISOC AM (operated by .am Registry) +հայ + +// xn--54b7fta0cc ("Bangla", Bangla) : BD +বাংলা + +// xn--90ae ("bg", Bulgarian) : BG +бг + +// xn--mgbcpq6gpa1a ("albahrain", Arabic) : BH +البحرين + +// xn--90ais ("bel", Belarusian/Russian Cyrillic) : BY +// Operated by .by registry +бел + +// xn--fiqs8s ("Zhongguo/China", Chinese, Simplified) : CN +// CNNIC +// http://cnnic.cn/html/Dir/2005/10/11/3218.htm +中国 + +// xn--fiqz9s ("Zhongguo/China", Chinese, Traditional) : CN +// CNNIC +// http://cnnic.cn/html/Dir/2005/10/11/3218.htm +中國 + +// xn--lgbbat1ad8j ("Algeria/Al Jazair", Arabic) : DZ +الجزائر + +// xn--wgbh1c ("Egypt/Masr", Arabic) : EG +// http://www.dotmasr.eg/ +مصر + +// xn--e1a4c ("eu", Cyrillic) : EU +// https://eurid.eu +ею + +// xn--qxa6a ("eu", Greek) : EU +// https://eurid.eu +ευ + +// xn--mgbah1a3hjkrd ("Mauritania", Arabic) : MR +موريتانيا + +// xn--node ("ge", Georgian Mkhedruli) : GE +გე + +// xn--qxam ("el", Greek) : GR +// Hellenic Ministry of Infrastructure, Transport, and Networks +ελ + +// xn--j6w193g ("Hong Kong", Chinese) : HK +// https://www.hkirc.hk +// Submitted by registry +// https://www.hkirc.hk/content.jsp?id=30#!/34 +香港 +公司.香港 +教育.香港 +政府.香港 +個人.香港 +網絡.香港 +組織.香港 + +// xn--2scrj9c ("Bharat", Kannada) : IN +// India +ಭಾರತ + +// xn--3hcrj9c ("Bharat", Oriya) : IN +// India +ଭାରତ + +// xn--45br5cyl ("Bharatam", Assamese) : IN +// India +ভাৰত + +// xn--h2breg3eve ("Bharatam", Sanskrit) : IN +// India +भारतम् + +// xn--h2brj9c8c ("Bharot", Santali) : IN +// India +भारोत + +// xn--mgbgu82a ("Bharat", Sindhi) : IN +// India +ڀارت + +// xn--rvc1e0am3e ("Bharatam", Malayalam) : IN +// India +ഭാരതം + +// xn--h2brj9c ("Bharat", Devanagari) : IN +// India +भारत + +// xn--mgbbh1a ("Bharat", Kashmiri) : IN +// India +بارت + +// xn--mgbbh1a71e ("Bharat", Arabic) : IN +// India +بھارت + +// xn--fpcrj9c3d ("Bharat", Telugu) : IN +// India +భారత్ + +// xn--gecrj9c ("Bharat", Gujarati) : IN +// India +ભારત + +// xn--s9brj9c ("Bharat", Gurmukhi) : IN +// India +ਭਾਰਤ + +// xn--45brj9c ("Bharat", Bengali) : IN +// India +ভারত + +// xn--xkc2dl3a5ee0h ("India", Tamil) : IN +// India +இந்தியா + +// xn--mgba3a4f16a ("Iran", Persian) : IR +ایران + +// xn--mgba3a4fra ("Iran", Arabic) : IR +ايران + +// xn--mgbtx2b ("Iraq", Arabic) : IQ +// Communications and Media Commission +عراق + +// xn--mgbayh7gpa ("al-Ordon", Arabic) : JO +// National Information Technology Center (NITC) +// Royal Scientific Society, Al-Jubeiha +الاردن + +// xn--3e0b707e ("Republic of Korea", Hangul) : KR +한국 + +// xn--80ao21a ("Kaz", Kazakh) : KZ +қаз + +// xn--q7ce6a ("Lao", Lao) : LA +ລາວ + +// xn--fzc2c9e2c ("Lanka", Sinhalese-Sinhala) : LK +// https://nic.lk +ලංකා + +// xn--xkc2al3hye2a ("Ilangai", Tamil) : LK +// https://nic.lk +இலங்கை + +// xn--mgbc0a9azcg ("Morocco/al-Maghrib", Arabic) : MA +المغرب + +// xn--d1alf ("mkd", Macedonian) : MK +// MARnet +мкд + +// xn--l1acc ("mon", Mongolian) : MN +мон + +// xn--mix891f ("Macao", Chinese, Traditional) : MO +// MONIC / HNET Asia (Registry Operator for .mo) +澳門 + +// xn--mix082f ("Macao", Chinese, Simplified) : MO +澳门 + +// xn--mgbx4cd0ab ("Malaysia", Malay) : MY +مليسيا + +// xn--mgb9awbf ("Oman", Arabic) : OM +عمان + +// xn--mgbai9azgqp6j ("Pakistan", Urdu/Arabic) : PK +پاکستان + +// xn--mgbai9a5eva00b ("Pakistan", Urdu/Arabic, variant) : PK +پاكستان + +// xn--ygbi2ammx ("Falasteen", Arabic) : PS +// The Palestinian National Internet Naming Authority (PNINA) +// http://www.pnina.ps +فلسطين + +// xn--90a3ac ("srb", Cyrillic) : RS +// https://www.rnids.rs/en/domains/national-domains +срб +пр.срб +орг.срб +обр.срб +од.срб +упр.срб +ак.срб + +// xn--p1ai ("rf", Russian-Cyrillic) : RU +// https://cctld.ru/files/pdf/docs/en/rules_ru-rf.pdf +// Submitted by George Georgievsky +рф + +// xn--wgbl6a ("Qatar", Arabic) : QA +// http://www.ict.gov.qa/ +قطر + +// xn--mgberp4a5d4ar ("AlSaudiah", Arabic) : SA +// http://www.nic.net.sa/ +السعودية + +// xn--mgberp4a5d4a87g ("AlSaudiah", Arabic, variant) : SA +السعودیة + +// xn--mgbqly7c0a67fbc ("AlSaudiah", Arabic, variant) : SA +السعودیۃ + +// xn--mgbqly7cvafr ("AlSaudiah", Arabic, variant) : SA +السعوديه + +// xn--mgbpl2fh ("sudan", Arabic) : SD +// Operated by .sd registry +سودان + +// xn--yfro4i67o Singapore ("Singapore", Chinese) : SG +新加坡 + +// xn--clchc0ea0b2g2a9gcd ("Singapore", Tamil) : SG +சிங்கப்பூர் + +// xn--ogbpf8fl ("Syria", Arabic) : SY +سورية + +// xn--mgbtf8fl ("Syria", Arabic, variant) : SY +سوريا + +// xn--o3cw4h ("Thai", Thai) : TH +// http://www.thnic.co.th +ไทย +ศึกษา.ไทย +ธุรกิจ.ไทย +รัฐบาล.ไทย +ทหาร.ไทย +เน็ต.ไทย +องค์กร.ไทย + +// xn--pgbs0dh ("Tunisia", Arabic) : TN +// http://nic.tn +تونس + +// xn--kpry57d ("Taiwan", Chinese, Traditional) : TW +// http://www.twnic.net/english/dn/dn_07a.htm +台灣 + +// xn--kprw13d ("Taiwan", Chinese, Simplified) : TW +// http://www.twnic.net/english/dn/dn_07a.htm +台湾 + +// xn--nnx388a ("Taiwan", Chinese, variant) : TW +臺灣 + +// xn--j1amh ("ukr", Cyrillic) : UA +укр + +// xn--mgb2ddes ("AlYemen", Arabic) : YE +اليمن + +// xxx : http://icmregistry.com +xxx + +// ye : http://www.y.net.ye/services/domain_name.htm +ye +com.ye +edu.ye +gov.ye +net.ye +mil.ye +org.ye + +// za : https://www.zadna.org.za/content/page/domain-information/ +ac.za +agric.za +alt.za +co.za +edu.za +gov.za +grondar.za +law.za +mil.za +net.za +ngo.za +nic.za +nis.za +nom.za +org.za +school.za +tm.za +web.za + +// zm : https://zicta.zm/ +// Submitted by registry +zm +ac.zm +biz.zm +co.zm +com.zm +edu.zm +gov.zm +info.zm +mil.zm +net.zm +org.zm +sch.zm + +// zw : https://www.potraz.gov.zw/ +// Confirmed by registry 2017-01-25 +zw +ac.zw +co.zw +gov.zw +mil.zw +org.zw + + +// newGTLDs + +// List of new gTLDs imported from https://www.icann.org/resources/registries/gtlds/v2/gtlds.json on 2023-11-03T15:13:18Z +// This list is auto-generated, don't edit it manually. +// aaa : American Automobile Association, Inc. +// https://www.iana.org/domains/root/db/aaa.html +aaa + +// aarp : AARP +// https://www.iana.org/domains/root/db/aarp.html +aarp + +// abb : ABB Ltd +// https://www.iana.org/domains/root/db/abb.html +abb + +// abbott : Abbott Laboratories, Inc. +// https://www.iana.org/domains/root/db/abbott.html +abbott + +// abbvie : AbbVie Inc. +// https://www.iana.org/domains/root/db/abbvie.html +abbvie + +// abc : Disney Enterprises, Inc. +// https://www.iana.org/domains/root/db/abc.html +abc + +// able : Able Inc. +// https://www.iana.org/domains/root/db/able.html +able + +// abogado : Registry Services, LLC +// https://www.iana.org/domains/root/db/abogado.html +abogado + +// abudhabi : Abu Dhabi Systems and Information Centre +// https://www.iana.org/domains/root/db/abudhabi.html +abudhabi + +// academy : Binky Moon, LLC +// https://www.iana.org/domains/root/db/academy.html +academy + +// accenture : Accenture plc +// https://www.iana.org/domains/root/db/accenture.html +accenture + +// accountant : dot Accountant Limited +// https://www.iana.org/domains/root/db/accountant.html +accountant + +// accountants : Binky Moon, LLC +// https://www.iana.org/domains/root/db/accountants.html +accountants + +// aco : ACO Severin Ahlmann GmbH & Co. KG +// https://www.iana.org/domains/root/db/aco.html +aco + +// actor : Dog Beach, LLC +// https://www.iana.org/domains/root/db/actor.html +actor + +// ads : Charleston Road Registry Inc. +// https://www.iana.org/domains/root/db/ads.html +ads + +// adult : ICM Registry AD LLC +// https://www.iana.org/domains/root/db/adult.html +adult + +// aeg : Aktiebolaget Electrolux +// https://www.iana.org/domains/root/db/aeg.html +aeg + +// aetna : Aetna Life Insurance Company +// https://www.iana.org/domains/root/db/aetna.html +aetna + +// afl : Australian Football League +// https://www.iana.org/domains/root/db/afl.html +afl + +// africa : ZA Central Registry NPC trading as Registry.Africa +// https://www.iana.org/domains/root/db/africa.html +africa + +// agakhan : Fondation Aga Khan (Aga Khan Foundation) +// https://www.iana.org/domains/root/db/agakhan.html +agakhan + +// agency : Binky Moon, LLC +// https://www.iana.org/domains/root/db/agency.html +agency + +// aig : American International Group, Inc. +// https://www.iana.org/domains/root/db/aig.html +aig + +// airbus : Airbus S.A.S. +// https://www.iana.org/domains/root/db/airbus.html +airbus + +// airforce : Dog Beach, LLC +// https://www.iana.org/domains/root/db/airforce.html +airforce + +// airtel : Bharti Airtel Limited +// https://www.iana.org/domains/root/db/airtel.html +airtel + +// akdn : Fondation Aga Khan (Aga Khan Foundation) +// https://www.iana.org/domains/root/db/akdn.html +akdn + +// alibaba : Alibaba Group Holding Limited +// https://www.iana.org/domains/root/db/alibaba.html +alibaba + +// alipay : Alibaba Group Holding Limited +// https://www.iana.org/domains/root/db/alipay.html +alipay + +// allfinanz : Allfinanz Deutsche Vermögensberatung Aktiengesellschaft +// https://www.iana.org/domains/root/db/allfinanz.html +allfinanz + +// allstate : Allstate Fire and Casualty Insurance Company +// https://www.iana.org/domains/root/db/allstate.html +allstate + +// ally : Ally Financial Inc. +// https://www.iana.org/domains/root/db/ally.html +ally + +// alsace : Region Grand Est +// https://www.iana.org/domains/root/db/alsace.html +alsace + +// alstom : ALSTOM +// https://www.iana.org/domains/root/db/alstom.html +alstom + +// amazon : Amazon Registry Services, Inc. +// https://www.iana.org/domains/root/db/amazon.html +amazon + +// americanexpress : American Express Travel Related Services Company, Inc. +// https://www.iana.org/domains/root/db/americanexpress.html +americanexpress + +// americanfamily : AmFam, Inc. +// https://www.iana.org/domains/root/db/americanfamily.html +americanfamily + +// amex : American Express Travel Related Services Company, Inc. +// https://www.iana.org/domains/root/db/amex.html +amex + +// amfam : AmFam, Inc. +// https://www.iana.org/domains/root/db/amfam.html +amfam + +// amica : Amica Mutual Insurance Company +// https://www.iana.org/domains/root/db/amica.html +amica + +// amsterdam : Gemeente Amsterdam +// https://www.iana.org/domains/root/db/amsterdam.html +amsterdam + +// analytics : Campus IP LLC +// https://www.iana.org/domains/root/db/analytics.html +analytics + +// android : Charleston Road Registry Inc. +// https://www.iana.org/domains/root/db/android.html +android + +// anquan : Beijing Qihu Keji Co., Ltd. +// https://www.iana.org/domains/root/db/anquan.html +anquan + +// anz : Australia and New Zealand Banking Group Limited +// https://www.iana.org/domains/root/db/anz.html +anz + +// aol : Oath Inc. +// https://www.iana.org/domains/root/db/aol.html +aol + +// apartments : Binky Moon, LLC +// https://www.iana.org/domains/root/db/apartments.html +apartments + +// app : Charleston Road Registry Inc. +// https://www.iana.org/domains/root/db/app.html +app + +// apple : Apple Inc. +// https://www.iana.org/domains/root/db/apple.html +apple + +// aquarelle : Aquarelle.com +// https://www.iana.org/domains/root/db/aquarelle.html +aquarelle + +// arab : League of Arab States +// https://www.iana.org/domains/root/db/arab.html +arab + +// aramco : Aramco Services Company +// https://www.iana.org/domains/root/db/aramco.html +aramco + +// archi : Identity Digital Limited +// https://www.iana.org/domains/root/db/archi.html +archi + +// army : Dog Beach, LLC +// https://www.iana.org/domains/root/db/army.html +army + +// art : UK Creative Ideas Limited +// https://www.iana.org/domains/root/db/art.html +art + +// arte : Association Relative à la Télévision Européenne G.E.I.E. +// https://www.iana.org/domains/root/db/arte.html +arte + +// asda : Wal-Mart Stores, Inc. +// https://www.iana.org/domains/root/db/asda.html +asda + +// associates : Binky Moon, LLC +// https://www.iana.org/domains/root/db/associates.html +associates + +// athleta : The Gap, Inc. +// https://www.iana.org/domains/root/db/athleta.html +athleta + +// attorney : Dog Beach, LLC +// https://www.iana.org/domains/root/db/attorney.html +attorney + +// auction : Dog Beach, LLC +// https://www.iana.org/domains/root/db/auction.html +auction + +// audi : AUDI Aktiengesellschaft +// https://www.iana.org/domains/root/db/audi.html +audi + +// audible : Amazon Registry Services, Inc. +// https://www.iana.org/domains/root/db/audible.html +audible + +// audio : XYZ.COM LLC +// https://www.iana.org/domains/root/db/audio.html +audio + +// auspost : Australian Postal Corporation +// https://www.iana.org/domains/root/db/auspost.html +auspost + +// author : Amazon Registry Services, Inc. +// https://www.iana.org/domains/root/db/author.html +author + +// auto : XYZ.COM LLC +// https://www.iana.org/domains/root/db/auto.html +auto + +// autos : XYZ.COM LLC +// https://www.iana.org/domains/root/db/autos.html +autos + +// avianca : Avianca Inc. +// https://www.iana.org/domains/root/db/avianca.html +avianca + +// aws : AWS Registry LLC +// https://www.iana.org/domains/root/db/aws.html +aws + +// axa : AXA Group Operations SAS +// https://www.iana.org/domains/root/db/axa.html +axa + +// azure : Microsoft Corporation +// https://www.iana.org/domains/root/db/azure.html +azure + +// baby : XYZ.COM LLC +// https://www.iana.org/domains/root/db/baby.html +baby + +// baidu : Baidu, Inc. +// https://www.iana.org/domains/root/db/baidu.html +baidu + +// banamex : Citigroup Inc. +// https://www.iana.org/domains/root/db/banamex.html +banamex + +// bananarepublic : The Gap, Inc. +// https://www.iana.org/domains/root/db/bananarepublic.html +bananarepublic + +// band : Dog Beach, LLC +// https://www.iana.org/domains/root/db/band.html +band + +// bank : fTLD Registry Services LLC +// https://www.iana.org/domains/root/db/bank.html +bank + +// bar : Punto 2012 Sociedad Anonima Promotora de Inversion de Capital Variable +// https://www.iana.org/domains/root/db/bar.html +bar + +// barcelona : Municipi de Barcelona +// https://www.iana.org/domains/root/db/barcelona.html +barcelona + +// barclaycard : Barclays Bank PLC +// https://www.iana.org/domains/root/db/barclaycard.html +barclaycard + +// barclays : Barclays Bank PLC +// https://www.iana.org/domains/root/db/barclays.html +barclays + +// barefoot : Gallo Vineyards, Inc. +// https://www.iana.org/domains/root/db/barefoot.html +barefoot + +// bargains : Binky Moon, LLC +// https://www.iana.org/domains/root/db/bargains.html +bargains + +// baseball : MLB Advanced Media DH, LLC +// https://www.iana.org/domains/root/db/baseball.html +baseball + +// basketball : Fédération Internationale de Basketball (FIBA) +// https://www.iana.org/domains/root/db/basketball.html +basketball + +// bauhaus : Werkhaus GmbH +// https://www.iana.org/domains/root/db/bauhaus.html +bauhaus + +// bayern : Bayern Connect GmbH +// https://www.iana.org/domains/root/db/bayern.html +bayern + +// bbc : British Broadcasting Corporation +// https://www.iana.org/domains/root/db/bbc.html +bbc + +// bbt : BB&T Corporation +// https://www.iana.org/domains/root/db/bbt.html +bbt + +// bbva : BANCO BILBAO VIZCAYA ARGENTARIA, S.A. +// https://www.iana.org/domains/root/db/bbva.html +bbva + +// bcg : The Boston Consulting Group, Inc. +// https://www.iana.org/domains/root/db/bcg.html +bcg + +// bcn : Municipi de Barcelona +// https://www.iana.org/domains/root/db/bcn.html +bcn + +// beats : Beats Electronics, LLC +// https://www.iana.org/domains/root/db/beats.html +beats + +// beauty : XYZ.COM LLC +// https://www.iana.org/domains/root/db/beauty.html +beauty + +// beer : Registry Services, LLC +// https://www.iana.org/domains/root/db/beer.html +beer + +// bentley : Bentley Motors Limited +// https://www.iana.org/domains/root/db/bentley.html +bentley + +// berlin : dotBERLIN GmbH & Co. KG +// https://www.iana.org/domains/root/db/berlin.html +berlin + +// best : BestTLD Pty Ltd +// https://www.iana.org/domains/root/db/best.html +best + +// bestbuy : BBY Solutions, Inc. +// https://www.iana.org/domains/root/db/bestbuy.html +bestbuy + +// bet : Identity Digital Limited +// https://www.iana.org/domains/root/db/bet.html +bet + +// bharti : Bharti Enterprises (Holding) Private Limited +// https://www.iana.org/domains/root/db/bharti.html +bharti + +// bible : American Bible Society +// https://www.iana.org/domains/root/db/bible.html +bible + +// bid : dot Bid Limited +// https://www.iana.org/domains/root/db/bid.html +bid + +// bike : Binky Moon, LLC +// https://www.iana.org/domains/root/db/bike.html +bike + +// bing : Microsoft Corporation +// https://www.iana.org/domains/root/db/bing.html +bing + +// bingo : Binky Moon, LLC +// https://www.iana.org/domains/root/db/bingo.html +bingo + +// bio : Identity Digital Limited +// https://www.iana.org/domains/root/db/bio.html +bio + +// black : Identity Digital Limited +// https://www.iana.org/domains/root/db/black.html +black + +// blackfriday : Registry Services, LLC +// https://www.iana.org/domains/root/db/blackfriday.html +blackfriday + +// blockbuster : Dish DBS Corporation +// https://www.iana.org/domains/root/db/blockbuster.html +blockbuster + +// blog : Knock Knock WHOIS There, LLC +// https://www.iana.org/domains/root/db/blog.html +blog + +// bloomberg : Bloomberg IP Holdings LLC +// https://www.iana.org/domains/root/db/bloomberg.html +bloomberg + +// blue : Identity Digital Limited +// https://www.iana.org/domains/root/db/blue.html +blue + +// bms : Bristol-Myers Squibb Company +// https://www.iana.org/domains/root/db/bms.html +bms + +// bmw : Bayerische Motoren Werke Aktiengesellschaft +// https://www.iana.org/domains/root/db/bmw.html +bmw + +// bnpparibas : BNP Paribas +// https://www.iana.org/domains/root/db/bnpparibas.html +bnpparibas + +// boats : XYZ.COM LLC +// https://www.iana.org/domains/root/db/boats.html +boats + +// boehringer : Boehringer Ingelheim International GmbH +// https://www.iana.org/domains/root/db/boehringer.html +boehringer + +// bofa : Bank of America Corporation +// https://www.iana.org/domains/root/db/bofa.html +bofa + +// bom : Núcleo de Informação e Coordenação do Ponto BR - NIC.br +// https://www.iana.org/domains/root/db/bom.html +bom + +// bond : ShortDot SA +// https://www.iana.org/domains/root/db/bond.html +bond + +// boo : Charleston Road Registry Inc. +// https://www.iana.org/domains/root/db/boo.html +boo + +// book : Amazon Registry Services, Inc. +// https://www.iana.org/domains/root/db/book.html +book + +// booking : Booking.com B.V. +// https://www.iana.org/domains/root/db/booking.html +booking + +// bosch : Robert Bosch GMBH +// https://www.iana.org/domains/root/db/bosch.html +bosch + +// bostik : Bostik SA +// https://www.iana.org/domains/root/db/bostik.html +bostik + +// boston : Registry Services, LLC +// https://www.iana.org/domains/root/db/boston.html +boston + +// bot : Amazon Registry Services, Inc. +// https://www.iana.org/domains/root/db/bot.html +bot + +// boutique : Binky Moon, LLC +// https://www.iana.org/domains/root/db/boutique.html +boutique + +// box : Intercap Registry Inc. +// https://www.iana.org/domains/root/db/box.html +box + +// bradesco : Banco Bradesco S.A. +// https://www.iana.org/domains/root/db/bradesco.html +bradesco + +// bridgestone : Bridgestone Corporation +// https://www.iana.org/domains/root/db/bridgestone.html +bridgestone + +// broadway : Celebrate Broadway, Inc. +// https://www.iana.org/domains/root/db/broadway.html +broadway + +// broker : Dog Beach, LLC +// https://www.iana.org/domains/root/db/broker.html +broker + +// brother : Brother Industries, Ltd. +// https://www.iana.org/domains/root/db/brother.html +brother + +// brussels : DNS.be vzw +// https://www.iana.org/domains/root/db/brussels.html +brussels + +// build : Plan Bee LLC +// https://www.iana.org/domains/root/db/build.html +build + +// builders : Binky Moon, LLC +// https://www.iana.org/domains/root/db/builders.html +builders + +// business : Binky Moon, LLC +// https://www.iana.org/domains/root/db/business.html +business + +// buy : Amazon Registry Services, Inc. +// https://www.iana.org/domains/root/db/buy.html +buy + +// buzz : DOTSTRATEGY CO. +// https://www.iana.org/domains/root/db/buzz.html +buzz + +// bzh : Association www.bzh +// https://www.iana.org/domains/root/db/bzh.html +bzh + +// cab : Binky Moon, LLC +// https://www.iana.org/domains/root/db/cab.html +cab + +// cafe : Binky Moon, LLC +// https://www.iana.org/domains/root/db/cafe.html +cafe + +// cal : Charleston Road Registry Inc. +// https://www.iana.org/domains/root/db/cal.html +cal + +// call : Amazon Registry Services, Inc. +// https://www.iana.org/domains/root/db/call.html +call + +// calvinklein : PVH gTLD Holdings LLC +// https://www.iana.org/domains/root/db/calvinklein.html +calvinklein + +// cam : Cam Connecting SARL +// https://www.iana.org/domains/root/db/cam.html +cam + +// camera : Binky Moon, LLC +// https://www.iana.org/domains/root/db/camera.html +camera + +// camp : Binky Moon, LLC +// https://www.iana.org/domains/root/db/camp.html +camp + +// canon : Canon Inc. +// https://www.iana.org/domains/root/db/canon.html +canon + +// capetown : ZA Central Registry NPC trading as ZA Central Registry +// https://www.iana.org/domains/root/db/capetown.html +capetown + +// capital : Binky Moon, LLC +// https://www.iana.org/domains/root/db/capital.html +capital + +// capitalone : Capital One Financial Corporation +// https://www.iana.org/domains/root/db/capitalone.html +capitalone + +// car : XYZ.COM LLC +// https://www.iana.org/domains/root/db/car.html +car + +// caravan : Caravan International, Inc. +// https://www.iana.org/domains/root/db/caravan.html +caravan + +// cards : Binky Moon, LLC +// https://www.iana.org/domains/root/db/cards.html +cards + +// care : Binky Moon, LLC +// https://www.iana.org/domains/root/db/care.html +care + +// career : dotCareer LLC +// https://www.iana.org/domains/root/db/career.html +career + +// careers : Binky Moon, LLC +// https://www.iana.org/domains/root/db/careers.html +careers + +// cars : XYZ.COM LLC +// https://www.iana.org/domains/root/db/cars.html +cars + +// casa : Registry Services, LLC +// https://www.iana.org/domains/root/db/casa.html +casa + +// case : Digity, LLC +// https://www.iana.org/domains/root/db/case.html +case + +// cash : Binky Moon, LLC +// https://www.iana.org/domains/root/db/cash.html +cash + +// casino : Binky Moon, LLC +// https://www.iana.org/domains/root/db/casino.html +casino + +// catering : Binky Moon, LLC +// https://www.iana.org/domains/root/db/catering.html +catering + +// catholic : Pontificium Consilium de Comunicationibus Socialibus (PCCS) (Pontifical Council for Social Communication) +// https://www.iana.org/domains/root/db/catholic.html +catholic + +// cba : COMMONWEALTH BANK OF AUSTRALIA +// https://www.iana.org/domains/root/db/cba.html +cba + +// cbn : The Christian Broadcasting Network, Inc. +// https://www.iana.org/domains/root/db/cbn.html +cbn + +// cbre : CBRE, Inc. +// https://www.iana.org/domains/root/db/cbre.html +cbre + +// center : Binky Moon, LLC +// https://www.iana.org/domains/root/db/center.html +center + +// ceo : XYZ.COM LLC +// https://www.iana.org/domains/root/db/ceo.html +ceo + +// cern : European Organization for Nuclear Research ("CERN") +// https://www.iana.org/domains/root/db/cern.html +cern + +// cfa : CFA Institute +// https://www.iana.org/domains/root/db/cfa.html +cfa + +// cfd : ShortDot SA +// https://www.iana.org/domains/root/db/cfd.html +cfd + +// chanel : Chanel International B.V. +// https://www.iana.org/domains/root/db/chanel.html +chanel + +// channel : Charleston Road Registry Inc. +// https://www.iana.org/domains/root/db/channel.html +channel + +// charity : Public Interest Registry +// https://www.iana.org/domains/root/db/charity.html +charity + +// chase : JPMorgan Chase Bank, National Association +// https://www.iana.org/domains/root/db/chase.html +chase + +// chat : Binky Moon, LLC +// https://www.iana.org/domains/root/db/chat.html +chat + +// cheap : Binky Moon, LLC +// https://www.iana.org/domains/root/db/cheap.html +cheap + +// chintai : CHINTAI Corporation +// https://www.iana.org/domains/root/db/chintai.html +chintai + +// christmas : XYZ.COM LLC +// https://www.iana.org/domains/root/db/christmas.html +christmas + +// chrome : Charleston Road Registry Inc. +// https://www.iana.org/domains/root/db/chrome.html +chrome + +// church : Binky Moon, LLC +// https://www.iana.org/domains/root/db/church.html +church + +// cipriani : Hotel Cipriani Srl +// https://www.iana.org/domains/root/db/cipriani.html +cipriani + +// circle : Amazon Registry Services, Inc. +// https://www.iana.org/domains/root/db/circle.html +circle + +// cisco : Cisco Technology, Inc. +// https://www.iana.org/domains/root/db/cisco.html +cisco + +// citadel : Citadel Domain LLC +// https://www.iana.org/domains/root/db/citadel.html +citadel + +// citi : Citigroup Inc. +// https://www.iana.org/domains/root/db/citi.html +citi + +// citic : CITIC Group Corporation +// https://www.iana.org/domains/root/db/citic.html +citic + +// city : Binky Moon, LLC +// https://www.iana.org/domains/root/db/city.html +city + +// claims : Binky Moon, LLC +// https://www.iana.org/domains/root/db/claims.html +claims + +// cleaning : Binky Moon, LLC +// https://www.iana.org/domains/root/db/cleaning.html +cleaning + +// click : Internet Naming Company LLC +// https://www.iana.org/domains/root/db/click.html +click + +// clinic : Binky Moon, LLC +// https://www.iana.org/domains/root/db/clinic.html +clinic + +// clinique : The Estée Lauder Companies Inc. +// https://www.iana.org/domains/root/db/clinique.html +clinique + +// clothing : Binky Moon, LLC +// https://www.iana.org/domains/root/db/clothing.html +clothing + +// cloud : Aruba PEC S.p.A. +// https://www.iana.org/domains/root/db/cloud.html +cloud + +// club : Registry Services, LLC +// https://www.iana.org/domains/root/db/club.html +club + +// clubmed : Club Méditerranée S.A. +// https://www.iana.org/domains/root/db/clubmed.html +clubmed + +// coach : Binky Moon, LLC +// https://www.iana.org/domains/root/db/coach.html +coach + +// codes : Binky Moon, LLC +// https://www.iana.org/domains/root/db/codes.html +codes + +// coffee : Binky Moon, LLC +// https://www.iana.org/domains/root/db/coffee.html +coffee + +// college : XYZ.COM LLC +// https://www.iana.org/domains/root/db/college.html +college + +// cologne : dotKoeln GmbH +// https://www.iana.org/domains/root/db/cologne.html +cologne + +// comcast : Comcast IP Holdings I, LLC +// https://www.iana.org/domains/root/db/comcast.html +comcast + +// commbank : COMMONWEALTH BANK OF AUSTRALIA +// https://www.iana.org/domains/root/db/commbank.html +commbank + +// community : Binky Moon, LLC +// https://www.iana.org/domains/root/db/community.html +community + +// company : Binky Moon, LLC +// https://www.iana.org/domains/root/db/company.html +company + +// compare : Registry Services, LLC +// https://www.iana.org/domains/root/db/compare.html +compare + +// computer : Binky Moon, LLC +// https://www.iana.org/domains/root/db/computer.html +computer + +// comsec : VeriSign, Inc. +// https://www.iana.org/domains/root/db/comsec.html +comsec + +// condos : Binky Moon, LLC +// https://www.iana.org/domains/root/db/condos.html +condos + +// construction : Binky Moon, LLC +// https://www.iana.org/domains/root/db/construction.html +construction + +// consulting : Dog Beach, LLC +// https://www.iana.org/domains/root/db/consulting.html +consulting + +// contact : Dog Beach, LLC +// https://www.iana.org/domains/root/db/contact.html +contact + +// contractors : Binky Moon, LLC +// https://www.iana.org/domains/root/db/contractors.html +contractors + +// cooking : Registry Services, LLC +// https://www.iana.org/domains/root/db/cooking.html +cooking + +// cool : Binky Moon, LLC +// https://www.iana.org/domains/root/db/cool.html +cool + +// corsica : Collectivité de Corse +// https://www.iana.org/domains/root/db/corsica.html +corsica + +// country : Internet Naming Company LLC +// https://www.iana.org/domains/root/db/country.html +country + +// coupon : Amazon Registry Services, Inc. +// https://www.iana.org/domains/root/db/coupon.html +coupon + +// coupons : Binky Moon, LLC +// https://www.iana.org/domains/root/db/coupons.html +coupons + +// courses : Registry Services, LLC +// https://www.iana.org/domains/root/db/courses.html +courses + +// cpa : American Institute of Certified Public Accountants +// https://www.iana.org/domains/root/db/cpa.html +cpa + +// credit : Binky Moon, LLC +// https://www.iana.org/domains/root/db/credit.html +credit + +// creditcard : Binky Moon, LLC +// https://www.iana.org/domains/root/db/creditcard.html +creditcard + +// creditunion : DotCooperation LLC +// https://www.iana.org/domains/root/db/creditunion.html +creditunion + +// cricket : dot Cricket Limited +// https://www.iana.org/domains/root/db/cricket.html +cricket + +// crown : Crown Equipment Corporation +// https://www.iana.org/domains/root/db/crown.html +crown + +// crs : Federated Co-operatives Limited +// https://www.iana.org/domains/root/db/crs.html +crs + +// cruise : Viking River Cruises (Bermuda) Ltd. +// https://www.iana.org/domains/root/db/cruise.html +cruise + +// cruises : Binky Moon, LLC +// https://www.iana.org/domains/root/db/cruises.html +cruises + +// cuisinella : SCHMIDT GROUPE S.A.S. +// https://www.iana.org/domains/root/db/cuisinella.html +cuisinella + +// cymru : Nominet UK +// https://www.iana.org/domains/root/db/cymru.html +cymru + +// cyou : ShortDot SA +// https://www.iana.org/domains/root/db/cyou.html +cyou + +// dabur : Dabur India Limited +// https://www.iana.org/domains/root/db/dabur.html +dabur + +// dad : Charleston Road Registry Inc. +// https://www.iana.org/domains/root/db/dad.html +dad + +// dance : Dog Beach, LLC +// https://www.iana.org/domains/root/db/dance.html +dance + +// data : Dish DBS Corporation +// https://www.iana.org/domains/root/db/data.html +data + +// date : dot Date Limited +// https://www.iana.org/domains/root/db/date.html +date + +// dating : Binky Moon, LLC +// https://www.iana.org/domains/root/db/dating.html +dating + +// datsun : NISSAN MOTOR CO., LTD. +// https://www.iana.org/domains/root/db/datsun.html +datsun + +// day : Charleston Road Registry Inc. +// https://www.iana.org/domains/root/db/day.html +day + +// dclk : Charleston Road Registry Inc. +// https://www.iana.org/domains/root/db/dclk.html +dclk + +// dds : Registry Services, LLC +// https://www.iana.org/domains/root/db/dds.html +dds + +// deal : Amazon Registry Services, Inc. +// https://www.iana.org/domains/root/db/deal.html +deal + +// dealer : Intercap Registry Inc. +// https://www.iana.org/domains/root/db/dealer.html +dealer + +// deals : Binky Moon, LLC +// https://www.iana.org/domains/root/db/deals.html +deals + +// degree : Dog Beach, LLC +// https://www.iana.org/domains/root/db/degree.html +degree + +// delivery : Binky Moon, LLC +// https://www.iana.org/domains/root/db/delivery.html +delivery + +// dell : Dell Inc. +// https://www.iana.org/domains/root/db/dell.html +dell + +// deloitte : Deloitte Touche Tohmatsu +// https://www.iana.org/domains/root/db/deloitte.html +deloitte + +// delta : Delta Air Lines, Inc. +// https://www.iana.org/domains/root/db/delta.html +delta + +// democrat : Dog Beach, LLC +// https://www.iana.org/domains/root/db/democrat.html +democrat + +// dental : Binky Moon, LLC +// https://www.iana.org/domains/root/db/dental.html +dental + +// dentist : Dog Beach, LLC +// https://www.iana.org/domains/root/db/dentist.html +dentist + +// design : Registry Services, LLC +// https://www.iana.org/domains/root/db/design.html +design + +// dev : Charleston Road Registry Inc. +// https://www.iana.org/domains/root/db/dev.html +dev + +// dhl : Deutsche Post AG +// https://www.iana.org/domains/root/db/dhl.html +dhl + +// diamonds : Binky Moon, LLC +// https://www.iana.org/domains/root/db/diamonds.html +diamonds + +// diet : XYZ.COM LLC +// https://www.iana.org/domains/root/db/diet.html +diet + +// digital : Binky Moon, LLC +// https://www.iana.org/domains/root/db/digital.html +digital + +// direct : Binky Moon, LLC +// https://www.iana.org/domains/root/db/direct.html +direct + +// directory : Binky Moon, LLC +// https://www.iana.org/domains/root/db/directory.html +directory + +// discount : Binky Moon, LLC +// https://www.iana.org/domains/root/db/discount.html +discount + +// discover : Discover Financial Services +// https://www.iana.org/domains/root/db/discover.html +discover + +// dish : Dish DBS Corporation +// https://www.iana.org/domains/root/db/dish.html +dish + +// diy : Lifestyle Domain Holdings, Inc. +// https://www.iana.org/domains/root/db/diy.html +diy + +// dnp : Dai Nippon Printing Co., Ltd. +// https://www.iana.org/domains/root/db/dnp.html +dnp + +// docs : Charleston Road Registry Inc. +// https://www.iana.org/domains/root/db/docs.html +docs + +// doctor : Binky Moon, LLC +// https://www.iana.org/domains/root/db/doctor.html +doctor + +// dog : Binky Moon, LLC +// https://www.iana.org/domains/root/db/dog.html +dog + +// domains : Binky Moon, LLC +// https://www.iana.org/domains/root/db/domains.html +domains + +// dot : Dish DBS Corporation +// https://www.iana.org/domains/root/db/dot.html +dot + +// download : dot Support Limited +// https://www.iana.org/domains/root/db/download.html +download + +// drive : Charleston Road Registry Inc. +// https://www.iana.org/domains/root/db/drive.html +drive + +// dtv : Dish DBS Corporation +// https://www.iana.org/domains/root/db/dtv.html +dtv + +// dubai : Dubai Smart Government Department +// https://www.iana.org/domains/root/db/dubai.html +dubai + +// dunlop : The Goodyear Tire & Rubber Company +// https://www.iana.org/domains/root/db/dunlop.html +dunlop + +// dupont : DuPont Specialty Products USA, LLC +// https://www.iana.org/domains/root/db/dupont.html +dupont + +// durban : ZA Central Registry NPC trading as ZA Central Registry +// https://www.iana.org/domains/root/db/durban.html +durban + +// dvag : Deutsche Vermögensberatung Aktiengesellschaft DVAG +// https://www.iana.org/domains/root/db/dvag.html +dvag + +// dvr : DISH Technologies L.L.C. +// https://www.iana.org/domains/root/db/dvr.html +dvr + +// earth : Interlink Systems Innovation Institute K.K. +// https://www.iana.org/domains/root/db/earth.html +earth + +// eat : Charleston Road Registry Inc. +// https://www.iana.org/domains/root/db/eat.html +eat + +// eco : Big Room Inc. +// https://www.iana.org/domains/root/db/eco.html +eco + +// edeka : EDEKA Verband kaufmännischer Genossenschaften e.V. +// https://www.iana.org/domains/root/db/edeka.html +edeka + +// education : Binky Moon, LLC +// https://www.iana.org/domains/root/db/education.html +education + +// email : Binky Moon, LLC +// https://www.iana.org/domains/root/db/email.html +email + +// emerck : Merck KGaA +// https://www.iana.org/domains/root/db/emerck.html +emerck + +// energy : Binky Moon, LLC +// https://www.iana.org/domains/root/db/energy.html +energy + +// engineer : Dog Beach, LLC +// https://www.iana.org/domains/root/db/engineer.html +engineer + +// engineering : Binky Moon, LLC +// https://www.iana.org/domains/root/db/engineering.html +engineering + +// enterprises : Binky Moon, LLC +// https://www.iana.org/domains/root/db/enterprises.html +enterprises + +// epson : Seiko Epson Corporation +// https://www.iana.org/domains/root/db/epson.html +epson + +// equipment : Binky Moon, LLC +// https://www.iana.org/domains/root/db/equipment.html +equipment + +// ericsson : Telefonaktiebolaget L M Ericsson +// https://www.iana.org/domains/root/db/ericsson.html +ericsson + +// erni : ERNI Group Holding AG +// https://www.iana.org/domains/root/db/erni.html +erni + +// esq : Charleston Road Registry Inc. +// https://www.iana.org/domains/root/db/esq.html +esq + +// estate : Binky Moon, LLC +// https://www.iana.org/domains/root/db/estate.html +estate + +// etisalat : Emirates Telecommunications Corporation (trading as Etisalat) +// https://www.iana.org/domains/root/db/etisalat.html +etisalat + +// eurovision : European Broadcasting Union (EBU) +// https://www.iana.org/domains/root/db/eurovision.html +eurovision + +// eus : Puntueus Fundazioa +// https://www.iana.org/domains/root/db/eus.html +eus + +// events : Binky Moon, LLC +// https://www.iana.org/domains/root/db/events.html +events + +// exchange : Binky Moon, LLC +// https://www.iana.org/domains/root/db/exchange.html +exchange + +// expert : Binky Moon, LLC +// https://www.iana.org/domains/root/db/expert.html +expert + +// exposed : Binky Moon, LLC +// https://www.iana.org/domains/root/db/exposed.html +exposed + +// express : Binky Moon, LLC +// https://www.iana.org/domains/root/db/express.html +express + +// extraspace : Extra Space Storage LLC +// https://www.iana.org/domains/root/db/extraspace.html +extraspace + +// fage : Fage International S.A. +// https://www.iana.org/domains/root/db/fage.html +fage + +// fail : Binky Moon, LLC +// https://www.iana.org/domains/root/db/fail.html +fail + +// fairwinds : FairWinds Partners, LLC +// https://www.iana.org/domains/root/db/fairwinds.html +fairwinds + +// faith : dot Faith Limited +// https://www.iana.org/domains/root/db/faith.html +faith + +// family : Dog Beach, LLC +// https://www.iana.org/domains/root/db/family.html +family + +// fan : Dog Beach, LLC +// https://www.iana.org/domains/root/db/fan.html +fan + +// fans : ZDNS International Limited +// https://www.iana.org/domains/root/db/fans.html +fans + +// farm : Binky Moon, LLC +// https://www.iana.org/domains/root/db/farm.html +farm + +// farmers : Farmers Insurance Exchange +// https://www.iana.org/domains/root/db/farmers.html +farmers + +// fashion : Registry Services, LLC +// https://www.iana.org/domains/root/db/fashion.html +fashion + +// fast : Amazon Registry Services, Inc. +// https://www.iana.org/domains/root/db/fast.html +fast + +// fedex : Federal Express Corporation +// https://www.iana.org/domains/root/db/fedex.html +fedex + +// feedback : Top Level Spectrum, Inc. +// https://www.iana.org/domains/root/db/feedback.html +feedback + +// ferrari : Fiat Chrysler Automobiles N.V. +// https://www.iana.org/domains/root/db/ferrari.html +ferrari + +// ferrero : Ferrero Trading Lux S.A. +// https://www.iana.org/domains/root/db/ferrero.html +ferrero + +// fidelity : Fidelity Brokerage Services LLC +// https://www.iana.org/domains/root/db/fidelity.html +fidelity + +// fido : Rogers Communications Canada Inc. +// https://www.iana.org/domains/root/db/fido.html +fido + +// film : Motion Picture Domain Registry Pty Ltd +// https://www.iana.org/domains/root/db/film.html +film + +// final : Núcleo de Informação e Coordenação do Ponto BR - NIC.br +// https://www.iana.org/domains/root/db/final.html +final + +// finance : Binky Moon, LLC +// https://www.iana.org/domains/root/db/finance.html +finance + +// financial : Binky Moon, LLC +// https://www.iana.org/domains/root/db/financial.html +financial + +// fire : Amazon Registry Services, Inc. +// https://www.iana.org/domains/root/db/fire.html +fire + +// firestone : Bridgestone Licensing Services, Inc +// https://www.iana.org/domains/root/db/firestone.html +firestone + +// firmdale : Firmdale Holdings Limited +// https://www.iana.org/domains/root/db/firmdale.html +firmdale + +// fish : Binky Moon, LLC +// https://www.iana.org/domains/root/db/fish.html +fish + +// fishing : Registry Services, LLC +// https://www.iana.org/domains/root/db/fishing.html +fishing + +// fit : Registry Services, LLC +// https://www.iana.org/domains/root/db/fit.html +fit + +// fitness : Binky Moon, LLC +// https://www.iana.org/domains/root/db/fitness.html +fitness + +// flickr : Flickr, Inc. +// https://www.iana.org/domains/root/db/flickr.html +flickr + +// flights : Binky Moon, LLC +// https://www.iana.org/domains/root/db/flights.html +flights + +// flir : FLIR Systems, Inc. +// https://www.iana.org/domains/root/db/flir.html +flir + +// florist : Binky Moon, LLC +// https://www.iana.org/domains/root/db/florist.html +florist + +// flowers : XYZ.COM LLC +// https://www.iana.org/domains/root/db/flowers.html +flowers + +// fly : Charleston Road Registry Inc. +// https://www.iana.org/domains/root/db/fly.html +fly + +// foo : Charleston Road Registry Inc. +// https://www.iana.org/domains/root/db/foo.html +foo + +// food : Lifestyle Domain Holdings, Inc. +// https://www.iana.org/domains/root/db/food.html +food + +// football : Binky Moon, LLC +// https://www.iana.org/domains/root/db/football.html +football + +// ford : Ford Motor Company +// https://www.iana.org/domains/root/db/ford.html +ford + +// forex : Dog Beach, LLC +// https://www.iana.org/domains/root/db/forex.html +forex + +// forsale : Dog Beach, LLC +// https://www.iana.org/domains/root/db/forsale.html +forsale + +// forum : Fegistry, LLC +// https://www.iana.org/domains/root/db/forum.html +forum + +// foundation : Public Interest Registry +// https://www.iana.org/domains/root/db/foundation.html +foundation + +// fox : FOX Registry, LLC +// https://www.iana.org/domains/root/db/fox.html +fox + +// free : Amazon Registry Services, Inc. +// https://www.iana.org/domains/root/db/free.html +free + +// fresenius : Fresenius Immobilien-Verwaltungs-GmbH +// https://www.iana.org/domains/root/db/fresenius.html +fresenius + +// frl : FRLregistry B.V. +// https://www.iana.org/domains/root/db/frl.html +frl + +// frogans : OP3FT +// https://www.iana.org/domains/root/db/frogans.html +frogans + +// frontier : Frontier Communications Corporation +// https://www.iana.org/domains/root/db/frontier.html +frontier + +// ftr : Frontier Communications Corporation +// https://www.iana.org/domains/root/db/ftr.html +ftr + +// fujitsu : Fujitsu Limited +// https://www.iana.org/domains/root/db/fujitsu.html +fujitsu + +// fun : Radix FZC DMCC +// https://www.iana.org/domains/root/db/fun.html +fun + +// fund : Binky Moon, LLC +// https://www.iana.org/domains/root/db/fund.html +fund + +// furniture : Binky Moon, LLC +// https://www.iana.org/domains/root/db/furniture.html +furniture + +// futbol : Dog Beach, LLC +// https://www.iana.org/domains/root/db/futbol.html +futbol + +// fyi : Binky Moon, LLC +// https://www.iana.org/domains/root/db/fyi.html +fyi + +// gal : Asociación puntoGAL +// https://www.iana.org/domains/root/db/gal.html +gal + +// gallery : Binky Moon, LLC +// https://www.iana.org/domains/root/db/gallery.html +gallery + +// gallo : Gallo Vineyards, Inc. +// https://www.iana.org/domains/root/db/gallo.html +gallo + +// gallup : Gallup, Inc. +// https://www.iana.org/domains/root/db/gallup.html +gallup + +// game : XYZ.COM LLC +// https://www.iana.org/domains/root/db/game.html +game + +// games : Dog Beach, LLC +// https://www.iana.org/domains/root/db/games.html +games + +// gap : The Gap, Inc. +// https://www.iana.org/domains/root/db/gap.html +gap + +// garden : Registry Services, LLC +// https://www.iana.org/domains/root/db/garden.html +garden + +// gay : Registry Services, LLC +// https://www.iana.org/domains/root/db/gay.html +gay + +// gbiz : Charleston Road Registry Inc. +// https://www.iana.org/domains/root/db/gbiz.html +gbiz + +// gdn : Joint Stock Company "Navigation-information systems" +// https://www.iana.org/domains/root/db/gdn.html +gdn + +// gea : GEA Group Aktiengesellschaft +// https://www.iana.org/domains/root/db/gea.html +gea + +// gent : Easyhost BV +// https://www.iana.org/domains/root/db/gent.html +gent + +// genting : Resorts World Inc Pte. Ltd. +// https://www.iana.org/domains/root/db/genting.html +genting + +// george : Wal-Mart Stores, Inc. +// https://www.iana.org/domains/root/db/george.html +george + +// ggee : GMO Internet, Inc. +// https://www.iana.org/domains/root/db/ggee.html +ggee + +// gift : DotGift, LLC +// https://www.iana.org/domains/root/db/gift.html +gift + +// gifts : Binky Moon, LLC +// https://www.iana.org/domains/root/db/gifts.html +gifts + +// gives : Public Interest Registry +// https://www.iana.org/domains/root/db/gives.html +gives + +// giving : Public Interest Registry +// https://www.iana.org/domains/root/db/giving.html +giving + +// glass : Binky Moon, LLC +// https://www.iana.org/domains/root/db/glass.html +glass + +// gle : Charleston Road Registry Inc. +// https://www.iana.org/domains/root/db/gle.html +gle + +// global : Identity Digital Limited +// https://www.iana.org/domains/root/db/global.html +global + +// globo : Globo Comunicação e Participações S.A +// https://www.iana.org/domains/root/db/globo.html +globo + +// gmail : Charleston Road Registry Inc. +// https://www.iana.org/domains/root/db/gmail.html +gmail + +// gmbh : Binky Moon, LLC +// https://www.iana.org/domains/root/db/gmbh.html +gmbh + +// gmo : GMO Internet, Inc. +// https://www.iana.org/domains/root/db/gmo.html +gmo + +// gmx : 1&1 Mail & Media GmbH +// https://www.iana.org/domains/root/db/gmx.html +gmx + +// godaddy : Go Daddy East, LLC +// https://www.iana.org/domains/root/db/godaddy.html +godaddy + +// gold : Binky Moon, LLC +// https://www.iana.org/domains/root/db/gold.html +gold + +// goldpoint : YODOBASHI CAMERA CO.,LTD. +// https://www.iana.org/domains/root/db/goldpoint.html +goldpoint + +// golf : Binky Moon, LLC +// https://www.iana.org/domains/root/db/golf.html +golf + +// goo : NTT Resonant Inc. +// https://www.iana.org/domains/root/db/goo.html +goo + +// goodyear : The Goodyear Tire & Rubber Company +// https://www.iana.org/domains/root/db/goodyear.html +goodyear + +// goog : Charleston Road Registry Inc. +// https://www.iana.org/domains/root/db/goog.html +goog + +// google : Charleston Road Registry Inc. +// https://www.iana.org/domains/root/db/google.html +google + +// gop : Republican State Leadership Committee, Inc. +// https://www.iana.org/domains/root/db/gop.html +gop + +// got : Amazon Registry Services, Inc. +// https://www.iana.org/domains/root/db/got.html +got + +// grainger : Grainger Registry Services, LLC +// https://www.iana.org/domains/root/db/grainger.html +grainger + +// graphics : Binky Moon, LLC +// https://www.iana.org/domains/root/db/graphics.html +graphics + +// gratis : Binky Moon, LLC +// https://www.iana.org/domains/root/db/gratis.html +gratis + +// green : Identity Digital Limited +// https://www.iana.org/domains/root/db/green.html +green + +// gripe : Binky Moon, LLC +// https://www.iana.org/domains/root/db/gripe.html +gripe + +// grocery : Wal-Mart Stores, Inc. +// https://www.iana.org/domains/root/db/grocery.html +grocery + +// group : Binky Moon, LLC +// https://www.iana.org/domains/root/db/group.html +group + +// guardian : The Guardian Life Insurance Company of America +// https://www.iana.org/domains/root/db/guardian.html +guardian + +// gucci : Guccio Gucci S.p.a. +// https://www.iana.org/domains/root/db/gucci.html +gucci + +// guge : Charleston Road Registry Inc. +// https://www.iana.org/domains/root/db/guge.html +guge + +// guide : Binky Moon, LLC +// https://www.iana.org/domains/root/db/guide.html +guide + +// guitars : XYZ.COM LLC +// https://www.iana.org/domains/root/db/guitars.html +guitars + +// guru : Binky Moon, LLC +// https://www.iana.org/domains/root/db/guru.html +guru + +// hair : XYZ.COM LLC +// https://www.iana.org/domains/root/db/hair.html +hair + +// hamburg : Hamburg Top-Level-Domain GmbH +// https://www.iana.org/domains/root/db/hamburg.html +hamburg + +// hangout : Charleston Road Registry Inc. +// https://www.iana.org/domains/root/db/hangout.html +hangout + +// haus : Dog Beach, LLC +// https://www.iana.org/domains/root/db/haus.html +haus + +// hbo : HBO Registry Services, Inc. +// https://www.iana.org/domains/root/db/hbo.html +hbo + +// hdfc : HOUSING DEVELOPMENT FINANCE CORPORATION LIMITED +// https://www.iana.org/domains/root/db/hdfc.html +hdfc + +// hdfcbank : HDFC Bank Limited +// https://www.iana.org/domains/root/db/hdfcbank.html +hdfcbank + +// health : Registry Services, LLC +// https://www.iana.org/domains/root/db/health.html +health + +// healthcare : Binky Moon, LLC +// https://www.iana.org/domains/root/db/healthcare.html +healthcare + +// help : Innovation service Limited +// https://www.iana.org/domains/root/db/help.html +help + +// helsinki : City of Helsinki +// https://www.iana.org/domains/root/db/helsinki.html +helsinki + +// here : Charleston Road Registry Inc. +// https://www.iana.org/domains/root/db/here.html +here + +// hermes : HERMES INTERNATIONAL +// https://www.iana.org/domains/root/db/hermes.html +hermes + +// hiphop : Dot Hip Hop, LLC +// https://www.iana.org/domains/root/db/hiphop.html +hiphop + +// hisamitsu : Hisamitsu Pharmaceutical Co.,Inc. +// https://www.iana.org/domains/root/db/hisamitsu.html +hisamitsu + +// hitachi : Hitachi, Ltd. +// https://www.iana.org/domains/root/db/hitachi.html +hitachi + +// hiv : Internet Naming Company LLC +// https://www.iana.org/domains/root/db/hiv.html +hiv + +// hkt : PCCW-HKT DataCom Services Limited +// https://www.iana.org/domains/root/db/hkt.html +hkt + +// hockey : Binky Moon, LLC +// https://www.iana.org/domains/root/db/hockey.html +hockey + +// holdings : Binky Moon, LLC +// https://www.iana.org/domains/root/db/holdings.html +holdings + +// holiday : Binky Moon, LLC +// https://www.iana.org/domains/root/db/holiday.html +holiday + +// homedepot : Home Depot Product Authority, LLC +// https://www.iana.org/domains/root/db/homedepot.html +homedepot + +// homegoods : The TJX Companies, Inc. +// https://www.iana.org/domains/root/db/homegoods.html +homegoods + +// homes : XYZ.COM LLC +// https://www.iana.org/domains/root/db/homes.html +homes + +// homesense : The TJX Companies, Inc. +// https://www.iana.org/domains/root/db/homesense.html +homesense + +// honda : Honda Motor Co., Ltd. +// https://www.iana.org/domains/root/db/honda.html +honda + +// horse : Registry Services, LLC +// https://www.iana.org/domains/root/db/horse.html +horse + +// hospital : Binky Moon, LLC +// https://www.iana.org/domains/root/db/hospital.html +hospital + +// host : Radix FZC DMCC +// https://www.iana.org/domains/root/db/host.html +host + +// hosting : XYZ.COM LLC +// https://www.iana.org/domains/root/db/hosting.html +hosting + +// hot : Amazon Registry Services, Inc. +// https://www.iana.org/domains/root/db/hot.html +hot + +// hotels : Booking.com B.V. +// https://www.iana.org/domains/root/db/hotels.html +hotels + +// hotmail : Microsoft Corporation +// https://www.iana.org/domains/root/db/hotmail.html +hotmail + +// house : Binky Moon, LLC +// https://www.iana.org/domains/root/db/house.html +house + +// how : Charleston Road Registry Inc. +// https://www.iana.org/domains/root/db/how.html +how + +// hsbc : HSBC Global Services (UK) Limited +// https://www.iana.org/domains/root/db/hsbc.html +hsbc + +// hughes : Hughes Satellite Systems Corporation +// https://www.iana.org/domains/root/db/hughes.html +hughes + +// hyatt : Hyatt GTLD, L.L.C. +// https://www.iana.org/domains/root/db/hyatt.html +hyatt + +// hyundai : Hyundai Motor Company +// https://www.iana.org/domains/root/db/hyundai.html +hyundai + +// ibm : International Business Machines Corporation +// https://www.iana.org/domains/root/db/ibm.html +ibm + +// icbc : Industrial and Commercial Bank of China Limited +// https://www.iana.org/domains/root/db/icbc.html +icbc + +// ice : IntercontinentalExchange, Inc. +// https://www.iana.org/domains/root/db/ice.html +ice + +// icu : ShortDot SA +// https://www.iana.org/domains/root/db/icu.html +icu + +// ieee : IEEE Global LLC +// https://www.iana.org/domains/root/db/ieee.html +ieee + +// ifm : ifm electronic gmbh +// https://www.iana.org/domains/root/db/ifm.html +ifm + +// ikano : Ikano S.A. +// https://www.iana.org/domains/root/db/ikano.html +ikano + +// imamat : Fondation Aga Khan (Aga Khan Foundation) +// https://www.iana.org/domains/root/db/imamat.html +imamat + +// imdb : Amazon Registry Services, Inc. +// https://www.iana.org/domains/root/db/imdb.html +imdb + +// immo : Binky Moon, LLC +// https://www.iana.org/domains/root/db/immo.html +immo + +// immobilien : Dog Beach, LLC +// https://www.iana.org/domains/root/db/immobilien.html +immobilien + +// inc : Intercap Registry Inc. +// https://www.iana.org/domains/root/db/inc.html +inc + +// industries : Binky Moon, LLC +// https://www.iana.org/domains/root/db/industries.html +industries + +// infiniti : NISSAN MOTOR CO., LTD. +// https://www.iana.org/domains/root/db/infiniti.html +infiniti + +// ing : Charleston Road Registry Inc. +// https://www.iana.org/domains/root/db/ing.html +ing + +// ink : Registry Services, LLC +// https://www.iana.org/domains/root/db/ink.html +ink + +// institute : Binky Moon, LLC +// https://www.iana.org/domains/root/db/institute.html +institute + +// insurance : fTLD Registry Services LLC +// https://www.iana.org/domains/root/db/insurance.html +insurance + +// insure : Binky Moon, LLC +// https://www.iana.org/domains/root/db/insure.html +insure + +// international : Binky Moon, LLC +// https://www.iana.org/domains/root/db/international.html +international + +// intuit : Intuit Administrative Services, Inc. +// https://www.iana.org/domains/root/db/intuit.html +intuit + +// investments : Binky Moon, LLC +// https://www.iana.org/domains/root/db/investments.html +investments + +// ipiranga : Ipiranga Produtos de Petroleo S.A. +// https://www.iana.org/domains/root/db/ipiranga.html +ipiranga + +// irish : Binky Moon, LLC +// https://www.iana.org/domains/root/db/irish.html +irish + +// ismaili : Fondation Aga Khan (Aga Khan Foundation) +// https://www.iana.org/domains/root/db/ismaili.html +ismaili + +// ist : Istanbul Metropolitan Municipality +// https://www.iana.org/domains/root/db/ist.html +ist + +// istanbul : Istanbul Metropolitan Municipality +// https://www.iana.org/domains/root/db/istanbul.html +istanbul + +// itau : Itau Unibanco Holding S.A. +// https://www.iana.org/domains/root/db/itau.html +itau + +// itv : ITV Services Limited +// https://www.iana.org/domains/root/db/itv.html +itv + +// jaguar : Jaguar Land Rover Ltd +// https://www.iana.org/domains/root/db/jaguar.html +jaguar + +// java : Oracle Corporation +// https://www.iana.org/domains/root/db/java.html +java + +// jcb : JCB Co., Ltd. +// https://www.iana.org/domains/root/db/jcb.html +jcb + +// jeep : FCA US LLC. +// https://www.iana.org/domains/root/db/jeep.html +jeep + +// jetzt : Binky Moon, LLC +// https://www.iana.org/domains/root/db/jetzt.html +jetzt + +// jewelry : Binky Moon, LLC +// https://www.iana.org/domains/root/db/jewelry.html +jewelry + +// jio : Reliance Industries Limited +// https://www.iana.org/domains/root/db/jio.html +jio + +// jll : Jones Lang LaSalle Incorporated +// https://www.iana.org/domains/root/db/jll.html +jll + +// jmp : Matrix IP LLC +// https://www.iana.org/domains/root/db/jmp.html +jmp + +// jnj : Johnson & Johnson Services, Inc. +// https://www.iana.org/domains/root/db/jnj.html +jnj + +// joburg : ZA Central Registry NPC trading as ZA Central Registry +// https://www.iana.org/domains/root/db/joburg.html +joburg + +// jot : Amazon Registry Services, Inc. +// https://www.iana.org/domains/root/db/jot.html +jot + +// joy : Amazon Registry Services, Inc. +// https://www.iana.org/domains/root/db/joy.html +joy + +// jpmorgan : JPMorgan Chase Bank, National Association +// https://www.iana.org/domains/root/db/jpmorgan.html +jpmorgan + +// jprs : Japan Registry Services Co., Ltd. +// https://www.iana.org/domains/root/db/jprs.html +jprs + +// juegos : Internet Naming Company LLC +// https://www.iana.org/domains/root/db/juegos.html +juegos + +// juniper : JUNIPER NETWORKS, INC. +// https://www.iana.org/domains/root/db/juniper.html +juniper + +// kaufen : Dog Beach, LLC +// https://www.iana.org/domains/root/db/kaufen.html +kaufen + +// kddi : KDDI CORPORATION +// https://www.iana.org/domains/root/db/kddi.html +kddi + +// kerryhotels : Kerry Trading Co. Limited +// https://www.iana.org/domains/root/db/kerryhotels.html +kerryhotels + +// kerrylogistics : Kerry Trading Co. Limited +// https://www.iana.org/domains/root/db/kerrylogistics.html +kerrylogistics + +// kerryproperties : Kerry Trading Co. Limited +// https://www.iana.org/domains/root/db/kerryproperties.html +kerryproperties + +// kfh : Kuwait Finance House +// https://www.iana.org/domains/root/db/kfh.html +kfh + +// kia : KIA MOTORS CORPORATION +// https://www.iana.org/domains/root/db/kia.html +kia + +// kids : DotKids Foundation Limited +// https://www.iana.org/domains/root/db/kids.html +kids + +// kim : Identity Digital Limited +// https://www.iana.org/domains/root/db/kim.html +kim + +// kindle : Amazon Registry Services, Inc. +// https://www.iana.org/domains/root/db/kindle.html +kindle + +// kitchen : Binky Moon, LLC +// https://www.iana.org/domains/root/db/kitchen.html +kitchen + +// kiwi : DOT KIWI LIMITED +// https://www.iana.org/domains/root/db/kiwi.html +kiwi + +// koeln : dotKoeln GmbH +// https://www.iana.org/domains/root/db/koeln.html +koeln + +// komatsu : Komatsu Ltd. +// https://www.iana.org/domains/root/db/komatsu.html +komatsu + +// kosher : Kosher Marketing Assets LLC +// https://www.iana.org/domains/root/db/kosher.html +kosher + +// kpmg : KPMG International Cooperative (KPMG International Genossenschaft) +// https://www.iana.org/domains/root/db/kpmg.html +kpmg + +// kpn : Koninklijke KPN N.V. +// https://www.iana.org/domains/root/db/kpn.html +kpn + +// krd : KRG Department of Information Technology +// https://www.iana.org/domains/root/db/krd.html +krd + +// kred : KredTLD Pty Ltd +// https://www.iana.org/domains/root/db/kred.html +kred + +// kuokgroup : Kerry Trading Co. Limited +// https://www.iana.org/domains/root/db/kuokgroup.html +kuokgroup + +// kyoto : Academic Institution: Kyoto Jyoho Gakuen +// https://www.iana.org/domains/root/db/kyoto.html +kyoto + +// lacaixa : Fundación Bancaria Caixa d’Estalvis i Pensions de Barcelona, “la Caixa” +// https://www.iana.org/domains/root/db/lacaixa.html +lacaixa + +// lamborghini : Automobili Lamborghini S.p.A. +// https://www.iana.org/domains/root/db/lamborghini.html +lamborghini + +// lamer : The Estée Lauder Companies Inc. +// https://www.iana.org/domains/root/db/lamer.html +lamer + +// lancaster : LANCASTER +// https://www.iana.org/domains/root/db/lancaster.html +lancaster + +// land : Binky Moon, LLC +// https://www.iana.org/domains/root/db/land.html +land + +// landrover : Jaguar Land Rover Ltd +// https://www.iana.org/domains/root/db/landrover.html +landrover + +// lanxess : LANXESS Corporation +// https://www.iana.org/domains/root/db/lanxess.html +lanxess + +// lasalle : Jones Lang LaSalle Incorporated +// https://www.iana.org/domains/root/db/lasalle.html +lasalle + +// lat : XYZ.COM LLC +// https://www.iana.org/domains/root/db/lat.html +lat + +// latino : Dish DBS Corporation +// https://www.iana.org/domains/root/db/latino.html +latino + +// latrobe : La Trobe University +// https://www.iana.org/domains/root/db/latrobe.html +latrobe + +// law : Registry Services, LLC +// https://www.iana.org/domains/root/db/law.html +law + +// lawyer : Dog Beach, LLC +// https://www.iana.org/domains/root/db/lawyer.html +lawyer + +// lds : IRI Domain Management, LLC +// https://www.iana.org/domains/root/db/lds.html +lds + +// lease : Binky Moon, LLC +// https://www.iana.org/domains/root/db/lease.html +lease + +// leclerc : A.C.D. LEC Association des Centres Distributeurs Edouard Leclerc +// https://www.iana.org/domains/root/db/leclerc.html +leclerc + +// lefrak : LeFrak Organization, Inc. +// https://www.iana.org/domains/root/db/lefrak.html +lefrak + +// legal : Binky Moon, LLC +// https://www.iana.org/domains/root/db/legal.html +legal + +// lego : LEGO Juris A/S +// https://www.iana.org/domains/root/db/lego.html +lego + +// lexus : TOYOTA MOTOR CORPORATION +// https://www.iana.org/domains/root/db/lexus.html +lexus + +// lgbt : Identity Digital Limited +// https://www.iana.org/domains/root/db/lgbt.html +lgbt + +// lidl : Schwarz Domains und Services GmbH & Co. KG +// https://www.iana.org/domains/root/db/lidl.html +lidl + +// life : Binky Moon, LLC +// https://www.iana.org/domains/root/db/life.html +life + +// lifeinsurance : American Council of Life Insurers +// https://www.iana.org/domains/root/db/lifeinsurance.html +lifeinsurance + +// lifestyle : Lifestyle Domain Holdings, Inc. +// https://www.iana.org/domains/root/db/lifestyle.html +lifestyle + +// lighting : Binky Moon, LLC +// https://www.iana.org/domains/root/db/lighting.html +lighting + +// like : Amazon Registry Services, Inc. +// https://www.iana.org/domains/root/db/like.html +like + +// lilly : Eli Lilly and Company +// https://www.iana.org/domains/root/db/lilly.html +lilly + +// limited : Binky Moon, LLC +// https://www.iana.org/domains/root/db/limited.html +limited + +// limo : Binky Moon, LLC +// https://www.iana.org/domains/root/db/limo.html +limo + +// lincoln : Ford Motor Company +// https://www.iana.org/domains/root/db/lincoln.html +lincoln + +// link : Nova Registry Ltd +// https://www.iana.org/domains/root/db/link.html +link + +// lipsy : Lipsy Ltd +// https://www.iana.org/domains/root/db/lipsy.html +lipsy + +// live : Dog Beach, LLC +// https://www.iana.org/domains/root/db/live.html +live + +// living : Lifestyle Domain Holdings, Inc. +// https://www.iana.org/domains/root/db/living.html +living + +// llc : Identity Digital Limited +// https://www.iana.org/domains/root/db/llc.html +llc + +// llp : Intercap Registry Inc. +// https://www.iana.org/domains/root/db/llp.html +llp + +// loan : dot Loan Limited +// https://www.iana.org/domains/root/db/loan.html +loan + +// loans : Binky Moon, LLC +// https://www.iana.org/domains/root/db/loans.html +loans + +// locker : Orange Domains LLC +// https://www.iana.org/domains/root/db/locker.html +locker + +// locus : Locus Analytics LLC +// https://www.iana.org/domains/root/db/locus.html +locus + +// lol : XYZ.COM LLC +// https://www.iana.org/domains/root/db/lol.html +lol + +// london : Dot London Domains Limited +// https://www.iana.org/domains/root/db/london.html +london + +// lotte : Lotte Holdings Co., Ltd. +// https://www.iana.org/domains/root/db/lotte.html +lotte + +// lotto : Identity Digital Limited +// https://www.iana.org/domains/root/db/lotto.html +lotto + +// love : Merchant Law Group LLP +// https://www.iana.org/domains/root/db/love.html +love + +// lpl : LPL Holdings, Inc. +// https://www.iana.org/domains/root/db/lpl.html +lpl + +// lplfinancial : LPL Holdings, Inc. +// https://www.iana.org/domains/root/db/lplfinancial.html +lplfinancial + +// ltd : Binky Moon, LLC +// https://www.iana.org/domains/root/db/ltd.html +ltd + +// ltda : InterNetX, Corp +// https://www.iana.org/domains/root/db/ltda.html +ltda + +// lundbeck : H. Lundbeck A/S +// https://www.iana.org/domains/root/db/lundbeck.html +lundbeck + +// luxe : Registry Services, LLC +// https://www.iana.org/domains/root/db/luxe.html +luxe + +// luxury : Luxury Partners, LLC +// https://www.iana.org/domains/root/db/luxury.html +luxury + +// madrid : Comunidad de Madrid +// https://www.iana.org/domains/root/db/madrid.html +madrid + +// maif : Mutuelle Assurance Instituteur France (MAIF) +// https://www.iana.org/domains/root/db/maif.html +maif + +// maison : Binky Moon, LLC +// https://www.iana.org/domains/root/db/maison.html +maison + +// makeup : XYZ.COM LLC +// https://www.iana.org/domains/root/db/makeup.html +makeup + +// man : MAN SE +// https://www.iana.org/domains/root/db/man.html +man + +// management : Binky Moon, LLC +// https://www.iana.org/domains/root/db/management.html +management + +// mango : PUNTO FA S.L. +// https://www.iana.org/domains/root/db/mango.html +mango + +// map : Charleston Road Registry Inc. +// https://www.iana.org/domains/root/db/map.html +map + +// market : Dog Beach, LLC +// https://www.iana.org/domains/root/db/market.html +market + +// marketing : Binky Moon, LLC +// https://www.iana.org/domains/root/db/marketing.html +marketing + +// markets : Dog Beach, LLC +// https://www.iana.org/domains/root/db/markets.html +markets + +// marriott : Marriott Worldwide Corporation +// https://www.iana.org/domains/root/db/marriott.html +marriott + +// marshalls : The TJX Companies, Inc. +// https://www.iana.org/domains/root/db/marshalls.html +marshalls + +// mattel : Mattel Sites, Inc. +// https://www.iana.org/domains/root/db/mattel.html +mattel + +// mba : Binky Moon, LLC +// https://www.iana.org/domains/root/db/mba.html +mba + +// mckinsey : McKinsey Holdings, Inc. +// https://www.iana.org/domains/root/db/mckinsey.html +mckinsey + +// med : Medistry LLC +// https://www.iana.org/domains/root/db/med.html +med + +// media : Binky Moon, LLC +// https://www.iana.org/domains/root/db/media.html +media + +// meet : Charleston Road Registry Inc. +// https://www.iana.org/domains/root/db/meet.html +meet + +// melbourne : The Crown in right of the State of Victoria, represented by its Department of State Development, Business and Innovation +// https://www.iana.org/domains/root/db/melbourne.html +melbourne + +// meme : Charleston Road Registry Inc. +// https://www.iana.org/domains/root/db/meme.html +meme + +// memorial : Dog Beach, LLC +// https://www.iana.org/domains/root/db/memorial.html +memorial + +// men : Exclusive Registry Limited +// https://www.iana.org/domains/root/db/men.html +men + +// menu : Dot Menu Registry, LLC +// https://www.iana.org/domains/root/db/menu.html +menu + +// merckmsd : MSD Registry Holdings, Inc. +// https://www.iana.org/domains/root/db/merckmsd.html +merckmsd + +// miami : Registry Services, LLC +// https://www.iana.org/domains/root/db/miami.html +miami + +// microsoft : Microsoft Corporation +// https://www.iana.org/domains/root/db/microsoft.html +microsoft + +// mini : Bayerische Motoren Werke Aktiengesellschaft +// https://www.iana.org/domains/root/db/mini.html +mini + +// mint : Intuit Administrative Services, Inc. +// https://www.iana.org/domains/root/db/mint.html +mint + +// mit : Massachusetts Institute of Technology +// https://www.iana.org/domains/root/db/mit.html +mit + +// mitsubishi : Mitsubishi Corporation +// https://www.iana.org/domains/root/db/mitsubishi.html +mitsubishi + +// mlb : MLB Advanced Media DH, LLC +// https://www.iana.org/domains/root/db/mlb.html +mlb + +// mls : The Canadian Real Estate Association +// https://www.iana.org/domains/root/db/mls.html +mls + +// mma : MMA IARD +// https://www.iana.org/domains/root/db/mma.html +mma + +// mobile : Dish DBS Corporation +// https://www.iana.org/domains/root/db/mobile.html +mobile + +// moda : Dog Beach, LLC +// https://www.iana.org/domains/root/db/moda.html +moda + +// moe : Interlink Systems Innovation Institute K.K. +// https://www.iana.org/domains/root/db/moe.html +moe + +// moi : Amazon Registry Services, Inc. +// https://www.iana.org/domains/root/db/moi.html +moi + +// mom : XYZ.COM LLC +// https://www.iana.org/domains/root/db/mom.html +mom + +// monash : Monash University +// https://www.iana.org/domains/root/db/monash.html +monash + +// money : Binky Moon, LLC +// https://www.iana.org/domains/root/db/money.html +money + +// monster : XYZ.COM LLC +// https://www.iana.org/domains/root/db/monster.html +monster + +// mormon : IRI Domain Management, LLC +// https://www.iana.org/domains/root/db/mormon.html +mormon + +// mortgage : Dog Beach, LLC +// https://www.iana.org/domains/root/db/mortgage.html +mortgage + +// moscow : Foundation for Assistance for Internet Technologies and Infrastructure Development (FAITID) +// https://www.iana.org/domains/root/db/moscow.html +moscow + +// moto : Motorola Trademark Holdings, LLC +// https://www.iana.org/domains/root/db/moto.html +moto + +// motorcycles : XYZ.COM LLC +// https://www.iana.org/domains/root/db/motorcycles.html +motorcycles + +// mov : Charleston Road Registry Inc. +// https://www.iana.org/domains/root/db/mov.html +mov + +// movie : Binky Moon, LLC +// https://www.iana.org/domains/root/db/movie.html +movie + +// msd : MSD Registry Holdings, Inc. +// https://www.iana.org/domains/root/db/msd.html +msd + +// mtn : MTN Dubai Limited +// https://www.iana.org/domains/root/db/mtn.html +mtn + +// mtr : MTR Corporation Limited +// https://www.iana.org/domains/root/db/mtr.html +mtr + +// music : DotMusic Limited +// https://www.iana.org/domains/root/db/music.html +music + +// nab : National Australia Bank Limited +// https://www.iana.org/domains/root/db/nab.html +nab + +// nagoya : GMO Registry, Inc. +// https://www.iana.org/domains/root/db/nagoya.html +nagoya + +// natura : NATURA COSMÉTICOS S.A. +// https://www.iana.org/domains/root/db/natura.html +natura + +// navy : Dog Beach, LLC +// https://www.iana.org/domains/root/db/navy.html +navy + +// nba : NBA REGISTRY, LLC +// https://www.iana.org/domains/root/db/nba.html +nba + +// nec : NEC Corporation +// https://www.iana.org/domains/root/db/nec.html +nec + +// netbank : COMMONWEALTH BANK OF AUSTRALIA +// https://www.iana.org/domains/root/db/netbank.html +netbank + +// netflix : Netflix, Inc. +// https://www.iana.org/domains/root/db/netflix.html +netflix + +// network : Binky Moon, LLC +// https://www.iana.org/domains/root/db/network.html +network + +// neustar : NeuStar, Inc. +// https://www.iana.org/domains/root/db/neustar.html +neustar + +// new : Charleston Road Registry Inc. +// https://www.iana.org/domains/root/db/new.html +new + +// news : Dog Beach, LLC +// https://www.iana.org/domains/root/db/news.html +news + +// next : Next plc +// https://www.iana.org/domains/root/db/next.html +next + +// nextdirect : Next plc +// https://www.iana.org/domains/root/db/nextdirect.html +nextdirect + +// nexus : Charleston Road Registry Inc. +// https://www.iana.org/domains/root/db/nexus.html +nexus + +// nfl : NFL Reg Ops LLC +// https://www.iana.org/domains/root/db/nfl.html +nfl + +// ngo : Public Interest Registry +// https://www.iana.org/domains/root/db/ngo.html +ngo + +// nhk : Japan Broadcasting Corporation (NHK) +// https://www.iana.org/domains/root/db/nhk.html +nhk + +// nico : DWANGO Co., Ltd. +// https://www.iana.org/domains/root/db/nico.html +nico + +// nike : NIKE, Inc. +// https://www.iana.org/domains/root/db/nike.html +nike + +// nikon : NIKON CORPORATION +// https://www.iana.org/domains/root/db/nikon.html +nikon + +// ninja : Dog Beach, LLC +// https://www.iana.org/domains/root/db/ninja.html +ninja + +// nissan : NISSAN MOTOR CO., LTD. +// https://www.iana.org/domains/root/db/nissan.html +nissan + +// nissay : Nippon Life Insurance Company +// https://www.iana.org/domains/root/db/nissay.html +nissay + +// nokia : Nokia Corporation +// https://www.iana.org/domains/root/db/nokia.html +nokia + +// norton : NortonLifeLock Inc. +// https://www.iana.org/domains/root/db/norton.html +norton + +// now : Amazon Registry Services, Inc. +// https://www.iana.org/domains/root/db/now.html +now + +// nowruz : Asia Green IT System Bilgisayar San. ve Tic. Ltd. Sti. +// https://www.iana.org/domains/root/db/nowruz.html +nowruz + +// nowtv : Starbucks (HK) Limited +// https://www.iana.org/domains/root/db/nowtv.html +nowtv + +// nra : NRA Holdings Company, INC. +// https://www.iana.org/domains/root/db/nra.html +nra + +// nrw : Minds + Machines GmbH +// https://www.iana.org/domains/root/db/nrw.html +nrw + +// ntt : NIPPON TELEGRAPH AND TELEPHONE CORPORATION +// https://www.iana.org/domains/root/db/ntt.html +ntt + +// nyc : The City of New York by and through the New York City Department of Information Technology & Telecommunications +// https://www.iana.org/domains/root/db/nyc.html +nyc + +// obi : OBI Group Holding SE & Co. KGaA +// https://www.iana.org/domains/root/db/obi.html +obi + +// observer : Fegistry, LLC +// https://www.iana.org/domains/root/db/observer.html +observer + +// office : Microsoft Corporation +// https://www.iana.org/domains/root/db/office.html +office + +// okinawa : BRregistry, Inc. +// https://www.iana.org/domains/root/db/okinawa.html +okinawa + +// olayan : Competrol (Luxembourg) Sarl +// https://www.iana.org/domains/root/db/olayan.html +olayan + +// olayangroup : Competrol (Luxembourg) Sarl +// https://www.iana.org/domains/root/db/olayangroup.html +olayangroup + +// oldnavy : The Gap, Inc. +// https://www.iana.org/domains/root/db/oldnavy.html +oldnavy + +// ollo : Dish DBS Corporation +// https://www.iana.org/domains/root/db/ollo.html +ollo + +// omega : The Swatch Group Ltd +// https://www.iana.org/domains/root/db/omega.html +omega + +// one : One.com A/S +// https://www.iana.org/domains/root/db/one.html +one + +// ong : Public Interest Registry +// https://www.iana.org/domains/root/db/ong.html +ong + +// onl : iRegistry GmbH +// https://www.iana.org/domains/root/db/onl.html +onl + +// online : Radix FZC DMCC +// https://www.iana.org/domains/root/db/online.html +online + +// ooo : INFIBEAM AVENUES LIMITED +// https://www.iana.org/domains/root/db/ooo.html +ooo + +// open : American Express Travel Related Services Company, Inc. +// https://www.iana.org/domains/root/db/open.html +open + +// oracle : Oracle Corporation +// https://www.iana.org/domains/root/db/oracle.html +oracle + +// orange : Orange Brand Services Limited +// https://www.iana.org/domains/root/db/orange.html +orange + +// organic : Identity Digital Limited +// https://www.iana.org/domains/root/db/organic.html +organic + +// origins : The Estée Lauder Companies Inc. +// https://www.iana.org/domains/root/db/origins.html +origins + +// osaka : Osaka Registry Co., Ltd. +// https://www.iana.org/domains/root/db/osaka.html +osaka + +// otsuka : Otsuka Holdings Co., Ltd. +// https://www.iana.org/domains/root/db/otsuka.html +otsuka + +// ott : Dish DBS Corporation +// https://www.iana.org/domains/root/db/ott.html +ott + +// ovh : MédiaBC +// https://www.iana.org/domains/root/db/ovh.html +ovh + +// page : Charleston Road Registry Inc. +// https://www.iana.org/domains/root/db/page.html +page + +// panasonic : Panasonic Holdings Corporation +// https://www.iana.org/domains/root/db/panasonic.html +panasonic + +// paris : City of Paris +// https://www.iana.org/domains/root/db/paris.html +paris + +// pars : Asia Green IT System Bilgisayar San. ve Tic. Ltd. Sti. +// https://www.iana.org/domains/root/db/pars.html +pars + +// partners : Binky Moon, LLC +// https://www.iana.org/domains/root/db/partners.html +partners + +// parts : Binky Moon, LLC +// https://www.iana.org/domains/root/db/parts.html +parts + +// party : Blue Sky Registry Limited +// https://www.iana.org/domains/root/db/party.html +party + +// pay : Amazon Registry Services, Inc. +// https://www.iana.org/domains/root/db/pay.html +pay + +// pccw : PCCW Enterprises Limited +// https://www.iana.org/domains/root/db/pccw.html +pccw + +// pet : Identity Digital Limited +// https://www.iana.org/domains/root/db/pet.html +pet + +// pfizer : Pfizer Inc. +// https://www.iana.org/domains/root/db/pfizer.html +pfizer + +// pharmacy : National Association of Boards of Pharmacy +// https://www.iana.org/domains/root/db/pharmacy.html +pharmacy + +// phd : Charleston Road Registry Inc. +// https://www.iana.org/domains/root/db/phd.html +phd + +// philips : Koninklijke Philips N.V. +// https://www.iana.org/domains/root/db/philips.html +philips + +// phone : Dish DBS Corporation +// https://www.iana.org/domains/root/db/phone.html +phone + +// photo : Registry Services, LLC +// https://www.iana.org/domains/root/db/photo.html +photo + +// photography : Binky Moon, LLC +// https://www.iana.org/domains/root/db/photography.html +photography + +// photos : Binky Moon, LLC +// https://www.iana.org/domains/root/db/photos.html +photos + +// physio : PhysBiz Pty Ltd +// https://www.iana.org/domains/root/db/physio.html +physio + +// pics : XYZ.COM LLC +// https://www.iana.org/domains/root/db/pics.html +pics + +// pictet : Pictet Europe S.A. +// https://www.iana.org/domains/root/db/pictet.html +pictet + +// pictures : Binky Moon, LLC +// https://www.iana.org/domains/root/db/pictures.html +pictures + +// pid : Top Level Spectrum, Inc. +// https://www.iana.org/domains/root/db/pid.html +pid + +// pin : Amazon Registry Services, Inc. +// https://www.iana.org/domains/root/db/pin.html +pin + +// ping : Ping Registry Provider, Inc. +// https://www.iana.org/domains/root/db/ping.html +ping + +// pink : Identity Digital Limited +// https://www.iana.org/domains/root/db/pink.html +pink + +// pioneer : Pioneer Corporation +// https://www.iana.org/domains/root/db/pioneer.html +pioneer + +// pizza : Binky Moon, LLC +// https://www.iana.org/domains/root/db/pizza.html +pizza + +// place : Binky Moon, LLC +// https://www.iana.org/domains/root/db/place.html +place + +// play : Charleston Road Registry Inc. +// https://www.iana.org/domains/root/db/play.html +play + +// playstation : Sony Interactive Entertainment Inc. +// https://www.iana.org/domains/root/db/playstation.html +playstation + +// plumbing : Binky Moon, LLC +// https://www.iana.org/domains/root/db/plumbing.html +plumbing + +// plus : Binky Moon, LLC +// https://www.iana.org/domains/root/db/plus.html +plus + +// pnc : PNC Domain Co., LLC +// https://www.iana.org/domains/root/db/pnc.html +pnc + +// pohl : Deutsche Vermögensberatung Aktiengesellschaft DVAG +// https://www.iana.org/domains/root/db/pohl.html +pohl + +// poker : Identity Digital Limited +// https://www.iana.org/domains/root/db/poker.html +poker + +// politie : Politie Nederland +// https://www.iana.org/domains/root/db/politie.html +politie + +// porn : ICM Registry PN LLC +// https://www.iana.org/domains/root/db/porn.html +porn + +// pramerica : Prudential Financial, Inc. +// https://www.iana.org/domains/root/db/pramerica.html +pramerica + +// praxi : Praxi S.p.A. +// https://www.iana.org/domains/root/db/praxi.html +praxi + +// press : Radix FZC DMCC +// https://www.iana.org/domains/root/db/press.html +press + +// prime : Amazon Registry Services, Inc. +// https://www.iana.org/domains/root/db/prime.html +prime + +// prod : Charleston Road Registry Inc. +// https://www.iana.org/domains/root/db/prod.html +prod + +// productions : Binky Moon, LLC +// https://www.iana.org/domains/root/db/productions.html +productions + +// prof : Charleston Road Registry Inc. +// https://www.iana.org/domains/root/db/prof.html +prof + +// progressive : Progressive Casualty Insurance Company +// https://www.iana.org/domains/root/db/progressive.html +progressive + +// promo : Identity Digital Limited +// https://www.iana.org/domains/root/db/promo.html +promo + +// properties : Binky Moon, LLC +// https://www.iana.org/domains/root/db/properties.html +properties + +// property : Digital Property Infrastructure Limited +// https://www.iana.org/domains/root/db/property.html +property + +// protection : XYZ.COM LLC +// https://www.iana.org/domains/root/db/protection.html +protection + +// pru : Prudential Financial, Inc. +// https://www.iana.org/domains/root/db/pru.html +pru + +// prudential : Prudential Financial, Inc. +// https://www.iana.org/domains/root/db/prudential.html +prudential + +// pub : Dog Beach, LLC +// https://www.iana.org/domains/root/db/pub.html +pub + +// pwc : PricewaterhouseCoopers LLP +// https://www.iana.org/domains/root/db/pwc.html +pwc + +// qpon : dotQPON LLC +// https://www.iana.org/domains/root/db/qpon.html +qpon + +// quebec : PointQuébec Inc +// https://www.iana.org/domains/root/db/quebec.html +quebec + +// quest : XYZ.COM LLC +// https://www.iana.org/domains/root/db/quest.html +quest + +// racing : Premier Registry Limited +// https://www.iana.org/domains/root/db/racing.html +racing + +// radio : European Broadcasting Union (EBU) +// https://www.iana.org/domains/root/db/radio.html +radio + +// read : Amazon Registry Services, Inc. +// https://www.iana.org/domains/root/db/read.html +read + +// realestate : dotRealEstate LLC +// https://www.iana.org/domains/root/db/realestate.html +realestate + +// realtor : Real Estate Domains LLC +// https://www.iana.org/domains/root/db/realtor.html +realtor + +// realty : Internet Naming Company LLC +// https://www.iana.org/domains/root/db/realty.html +realty + +// recipes : Binky Moon, LLC +// https://www.iana.org/domains/root/db/recipes.html +recipes + +// red : Identity Digital Limited +// https://www.iana.org/domains/root/db/red.html +red + +// redstone : Redstone Haute Couture Co., Ltd. +// https://www.iana.org/domains/root/db/redstone.html +redstone + +// redumbrella : Travelers TLD, LLC +// https://www.iana.org/domains/root/db/redumbrella.html +redumbrella + +// rehab : Dog Beach, LLC +// https://www.iana.org/domains/root/db/rehab.html +rehab + +// reise : Binky Moon, LLC +// https://www.iana.org/domains/root/db/reise.html +reise + +// reisen : Binky Moon, LLC +// https://www.iana.org/domains/root/db/reisen.html +reisen + +// reit : National Association of Real Estate Investment Trusts, Inc. +// https://www.iana.org/domains/root/db/reit.html +reit + +// reliance : Reliance Industries Limited +// https://www.iana.org/domains/root/db/reliance.html +reliance + +// ren : ZDNS International Limited +// https://www.iana.org/domains/root/db/ren.html +ren + +// rent : XYZ.COM LLC +// https://www.iana.org/domains/root/db/rent.html +rent + +// rentals : Binky Moon, LLC +// https://www.iana.org/domains/root/db/rentals.html +rentals + +// repair : Binky Moon, LLC +// https://www.iana.org/domains/root/db/repair.html +repair + +// report : Binky Moon, LLC +// https://www.iana.org/domains/root/db/report.html +report + +// republican : Dog Beach, LLC +// https://www.iana.org/domains/root/db/republican.html +republican + +// rest : Punto 2012 Sociedad Anonima Promotora de Inversion de Capital Variable +// https://www.iana.org/domains/root/db/rest.html +rest + +// restaurant : Binky Moon, LLC +// https://www.iana.org/domains/root/db/restaurant.html +restaurant + +// review : dot Review Limited +// https://www.iana.org/domains/root/db/review.html +review + +// reviews : Dog Beach, LLC +// https://www.iana.org/domains/root/db/reviews.html +reviews + +// rexroth : Robert Bosch GMBH +// https://www.iana.org/domains/root/db/rexroth.html +rexroth + +// rich : iRegistry GmbH +// https://www.iana.org/domains/root/db/rich.html +rich + +// richardli : Pacific Century Asset Management (HK) Limited +// https://www.iana.org/domains/root/db/richardli.html +richardli + +// ricoh : Ricoh Company, Ltd. +// https://www.iana.org/domains/root/db/ricoh.html +ricoh + +// ril : Reliance Industries Limited +// https://www.iana.org/domains/root/db/ril.html +ril + +// rio : Empresa Municipal de Informática SA - IPLANRIO +// https://www.iana.org/domains/root/db/rio.html +rio + +// rip : Dog Beach, LLC +// https://www.iana.org/domains/root/db/rip.html +rip + +// rocks : Dog Beach, LLC +// https://www.iana.org/domains/root/db/rocks.html +rocks + +// rodeo : Registry Services, LLC +// https://www.iana.org/domains/root/db/rodeo.html +rodeo + +// rogers : Rogers Communications Canada Inc. +// https://www.iana.org/domains/root/db/rogers.html +rogers + +// room : Amazon Registry Services, Inc. +// https://www.iana.org/domains/root/db/room.html +room + +// rsvp : Charleston Road Registry Inc. +// https://www.iana.org/domains/root/db/rsvp.html +rsvp + +// rugby : World Rugby Strategic Developments Limited +// https://www.iana.org/domains/root/db/rugby.html +rugby + +// ruhr : dotSaarland GmbH +// https://www.iana.org/domains/root/db/ruhr.html +ruhr + +// run : Binky Moon, LLC +// https://www.iana.org/domains/root/db/run.html +run + +// rwe : RWE AG +// https://www.iana.org/domains/root/db/rwe.html +rwe + +// ryukyu : BRregistry, Inc. +// https://www.iana.org/domains/root/db/ryukyu.html +ryukyu + +// saarland : dotSaarland GmbH +// https://www.iana.org/domains/root/db/saarland.html +saarland + +// safe : Amazon Registry Services, Inc. +// https://www.iana.org/domains/root/db/safe.html +safe + +// safety : Safety Registry Services, LLC. +// https://www.iana.org/domains/root/db/safety.html +safety + +// sakura : SAKURA Internet Inc. +// https://www.iana.org/domains/root/db/sakura.html +sakura + +// sale : Dog Beach, LLC +// https://www.iana.org/domains/root/db/sale.html +sale + +// salon : Binky Moon, LLC +// https://www.iana.org/domains/root/db/salon.html +salon + +// samsclub : Wal-Mart Stores, Inc. +// https://www.iana.org/domains/root/db/samsclub.html +samsclub + +// samsung : SAMSUNG SDS CO., LTD +// https://www.iana.org/domains/root/db/samsung.html +samsung + +// sandvik : Sandvik AB +// https://www.iana.org/domains/root/db/sandvik.html +sandvik + +// sandvikcoromant : Sandvik AB +// https://www.iana.org/domains/root/db/sandvikcoromant.html +sandvikcoromant + +// sanofi : Sanofi +// https://www.iana.org/domains/root/db/sanofi.html +sanofi + +// sap : SAP AG +// https://www.iana.org/domains/root/db/sap.html +sap + +// sarl : Binky Moon, LLC +// https://www.iana.org/domains/root/db/sarl.html +sarl + +// sas : Research IP LLC +// https://www.iana.org/domains/root/db/sas.html +sas + +// save : Amazon Registry Services, Inc. +// https://www.iana.org/domains/root/db/save.html +save + +// saxo : Saxo Bank A/S +// https://www.iana.org/domains/root/db/saxo.html +saxo + +// sbi : STATE BANK OF INDIA +// https://www.iana.org/domains/root/db/sbi.html +sbi + +// sbs : ShortDot SA +// https://www.iana.org/domains/root/db/sbs.html +sbs + +// sca : SVENSKA CELLULOSA AKTIEBOLAGET SCA (publ) +// https://www.iana.org/domains/root/db/sca.html +sca + +// scb : The Siam Commercial Bank Public Company Limited ("SCB") +// https://www.iana.org/domains/root/db/scb.html +scb + +// schaeffler : Schaeffler Technologies AG & Co. KG +// https://www.iana.org/domains/root/db/schaeffler.html +schaeffler + +// schmidt : SCHMIDT GROUPE S.A.S. +// https://www.iana.org/domains/root/db/schmidt.html +schmidt + +// scholarships : Scholarships.com, LLC +// https://www.iana.org/domains/root/db/scholarships.html +scholarships + +// school : Binky Moon, LLC +// https://www.iana.org/domains/root/db/school.html +school + +// schule : Binky Moon, LLC +// https://www.iana.org/domains/root/db/schule.html +schule + +// schwarz : Schwarz Domains und Services GmbH & Co. KG +// https://www.iana.org/domains/root/db/schwarz.html +schwarz + +// science : dot Science Limited +// https://www.iana.org/domains/root/db/science.html +science + +// scot : Dot Scot Registry Limited +// https://www.iana.org/domains/root/db/scot.html +scot + +// search : Charleston Road Registry Inc. +// https://www.iana.org/domains/root/db/search.html +search + +// seat : SEAT, S.A. (Sociedad Unipersonal) +// https://www.iana.org/domains/root/db/seat.html +seat + +// secure : Amazon Registry Services, Inc. +// https://www.iana.org/domains/root/db/secure.html +secure + +// security : XYZ.COM LLC +// https://www.iana.org/domains/root/db/security.html +security + +// seek : Seek Limited +// https://www.iana.org/domains/root/db/seek.html +seek + +// select : Registry Services, LLC +// https://www.iana.org/domains/root/db/select.html +select + +// sener : Sener Ingeniería y Sistemas, S.A. +// https://www.iana.org/domains/root/db/sener.html +sener + +// services : Binky Moon, LLC +// https://www.iana.org/domains/root/db/services.html +services + +// seven : Seven West Media Ltd +// https://www.iana.org/domains/root/db/seven.html +seven + +// sew : SEW-EURODRIVE GmbH & Co KG +// https://www.iana.org/domains/root/db/sew.html +sew + +// sex : ICM Registry SX LLC +// https://www.iana.org/domains/root/db/sex.html +sex + +// sexy : Internet Naming Company LLC +// https://www.iana.org/domains/root/db/sexy.html +sexy + +// sfr : Societe Francaise du Radiotelephone - SFR +// https://www.iana.org/domains/root/db/sfr.html +sfr + +// shangrila : Shangri‐La International Hotel Management Limited +// https://www.iana.org/domains/root/db/shangrila.html +shangrila + +// sharp : Sharp Corporation +// https://www.iana.org/domains/root/db/sharp.html +sharp + +// shaw : Shaw Cablesystems G.P. +// https://www.iana.org/domains/root/db/shaw.html +shaw + +// shell : Shell Information Technology International Inc +// https://www.iana.org/domains/root/db/shell.html +shell + +// shia : Asia Green IT System Bilgisayar San. ve Tic. Ltd. Sti. +// https://www.iana.org/domains/root/db/shia.html +shia + +// shiksha : Identity Digital Limited +// https://www.iana.org/domains/root/db/shiksha.html +shiksha + +// shoes : Binky Moon, LLC +// https://www.iana.org/domains/root/db/shoes.html +shoes + +// shop : GMO Registry, Inc. +// https://www.iana.org/domains/root/db/shop.html +shop + +// shopping : Binky Moon, LLC +// https://www.iana.org/domains/root/db/shopping.html +shopping + +// shouji : Beijing Qihu Keji Co., Ltd. +// https://www.iana.org/domains/root/db/shouji.html +shouji + +// show : Binky Moon, LLC +// https://www.iana.org/domains/root/db/show.html +show + +// silk : Amazon Registry Services, Inc. +// https://www.iana.org/domains/root/db/silk.html +silk + +// sina : Sina Corporation +// https://www.iana.org/domains/root/db/sina.html +sina + +// singles : Binky Moon, LLC +// https://www.iana.org/domains/root/db/singles.html +singles + +// site : Radix FZC DMCC +// https://www.iana.org/domains/root/db/site.html +site + +// ski : Identity Digital Limited +// https://www.iana.org/domains/root/db/ski.html +ski + +// skin : XYZ.COM LLC +// https://www.iana.org/domains/root/db/skin.html +skin + +// sky : Sky International AG +// https://www.iana.org/domains/root/db/sky.html +sky + +// skype : Microsoft Corporation +// https://www.iana.org/domains/root/db/skype.html +skype + +// sling : DISH Technologies L.L.C. +// https://www.iana.org/domains/root/db/sling.html +sling + +// smart : Smart Communications, Inc. (SMART) +// https://www.iana.org/domains/root/db/smart.html +smart + +// smile : Amazon Registry Services, Inc. +// https://www.iana.org/domains/root/db/smile.html +smile + +// sncf : Société Nationale SNCF +// https://www.iana.org/domains/root/db/sncf.html +sncf + +// soccer : Binky Moon, LLC +// https://www.iana.org/domains/root/db/soccer.html +soccer + +// social : Dog Beach, LLC +// https://www.iana.org/domains/root/db/social.html +social + +// softbank : SoftBank Group Corp. +// https://www.iana.org/domains/root/db/softbank.html +softbank + +// software : Dog Beach, LLC +// https://www.iana.org/domains/root/db/software.html +software + +// sohu : Sohu.com Limited +// https://www.iana.org/domains/root/db/sohu.html +sohu + +// solar : Binky Moon, LLC +// https://www.iana.org/domains/root/db/solar.html +solar + +// solutions : Binky Moon, LLC +// https://www.iana.org/domains/root/db/solutions.html +solutions + +// song : Amazon Registry Services, Inc. +// https://www.iana.org/domains/root/db/song.html +song + +// sony : Sony Corporation +// https://www.iana.org/domains/root/db/sony.html +sony + +// soy : Charleston Road Registry Inc. +// https://www.iana.org/domains/root/db/soy.html +soy + +// spa : Asia Spa and Wellness Promotion Council Limited +// https://www.iana.org/domains/root/db/spa.html +spa + +// space : Radix FZC DMCC +// https://www.iana.org/domains/root/db/space.html +space + +// sport : SportAccord +// https://www.iana.org/domains/root/db/sport.html +sport + +// spot : Amazon Registry Services, Inc. +// https://www.iana.org/domains/root/db/spot.html +spot + +// srl : InterNetX, Corp +// https://www.iana.org/domains/root/db/srl.html +srl + +// stada : STADA Arzneimittel AG +// https://www.iana.org/domains/root/db/stada.html +stada + +// staples : Staples, Inc. +// https://www.iana.org/domains/root/db/staples.html +staples + +// star : Star India Private Limited +// https://www.iana.org/domains/root/db/star.html +star + +// statebank : STATE BANK OF INDIA +// https://www.iana.org/domains/root/db/statebank.html +statebank + +// statefarm : State Farm Mutual Automobile Insurance Company +// https://www.iana.org/domains/root/db/statefarm.html +statefarm + +// stc : Saudi Telecom Company +// https://www.iana.org/domains/root/db/stc.html +stc + +// stcgroup : Saudi Telecom Company +// https://www.iana.org/domains/root/db/stcgroup.html +stcgroup + +// stockholm : Stockholms kommun +// https://www.iana.org/domains/root/db/stockholm.html +stockholm + +// storage : XYZ.COM LLC +// https://www.iana.org/domains/root/db/storage.html +storage + +// store : Radix FZC DMCC +// https://www.iana.org/domains/root/db/store.html +store + +// stream : dot Stream Limited +// https://www.iana.org/domains/root/db/stream.html +stream + +// studio : Dog Beach, LLC +// https://www.iana.org/domains/root/db/studio.html +studio + +// study : Registry Services, LLC +// https://www.iana.org/domains/root/db/study.html +study + +// style : Binky Moon, LLC +// https://www.iana.org/domains/root/db/style.html +style + +// sucks : Vox Populi Registry Ltd. +// https://www.iana.org/domains/root/db/sucks.html +sucks + +// supplies : Binky Moon, LLC +// https://www.iana.org/domains/root/db/supplies.html +supplies + +// supply : Binky Moon, LLC +// https://www.iana.org/domains/root/db/supply.html +supply + +// support : Binky Moon, LLC +// https://www.iana.org/domains/root/db/support.html +support + +// surf : Registry Services, LLC +// https://www.iana.org/domains/root/db/surf.html +surf + +// surgery : Binky Moon, LLC +// https://www.iana.org/domains/root/db/surgery.html +surgery + +// suzuki : SUZUKI MOTOR CORPORATION +// https://www.iana.org/domains/root/db/suzuki.html +suzuki + +// swatch : The Swatch Group Ltd +// https://www.iana.org/domains/root/db/swatch.html +swatch + +// swiss : Swiss Confederation +// https://www.iana.org/domains/root/db/swiss.html +swiss + +// sydney : State of New South Wales, Department of Premier and Cabinet +// https://www.iana.org/domains/root/db/sydney.html +sydney + +// systems : Binky Moon, LLC +// https://www.iana.org/domains/root/db/systems.html +systems + +// tab : Tabcorp Holdings Limited +// https://www.iana.org/domains/root/db/tab.html +tab + +// taipei : Taipei City Government +// https://www.iana.org/domains/root/db/taipei.html +taipei + +// talk : Amazon Registry Services, Inc. +// https://www.iana.org/domains/root/db/talk.html +talk + +// taobao : Alibaba Group Holding Limited +// https://www.iana.org/domains/root/db/taobao.html +taobao + +// target : Target Domain Holdings, LLC +// https://www.iana.org/domains/root/db/target.html +target + +// tatamotors : Tata Motors Ltd +// https://www.iana.org/domains/root/db/tatamotors.html +tatamotors + +// tatar : Limited Liability Company "Coordination Center of Regional Domain of Tatarstan Republic" +// https://www.iana.org/domains/root/db/tatar.html +tatar + +// tattoo : Registry Services, LLC +// https://www.iana.org/domains/root/db/tattoo.html +tattoo + +// tax : Binky Moon, LLC +// https://www.iana.org/domains/root/db/tax.html +tax + +// taxi : Binky Moon, LLC +// https://www.iana.org/domains/root/db/taxi.html +taxi + +// tci : Asia Green IT System Bilgisayar San. ve Tic. Ltd. Sti. +// https://www.iana.org/domains/root/db/tci.html +tci + +// tdk : TDK Corporation +// https://www.iana.org/domains/root/db/tdk.html +tdk + +// team : Binky Moon, LLC +// https://www.iana.org/domains/root/db/team.html +team + +// tech : Radix FZC DMCC +// https://www.iana.org/domains/root/db/tech.html +tech + +// technology : Binky Moon, LLC +// https://www.iana.org/domains/root/db/technology.html +technology + +// temasek : Temasek Holdings (Private) Limited +// https://www.iana.org/domains/root/db/temasek.html +temasek + +// tennis : Binky Moon, LLC +// https://www.iana.org/domains/root/db/tennis.html +tennis + +// teva : Teva Pharmaceutical Industries Limited +// https://www.iana.org/domains/root/db/teva.html +teva + +// thd : Home Depot Product Authority, LLC +// https://www.iana.org/domains/root/db/thd.html +thd + +// theater : Binky Moon, LLC +// https://www.iana.org/domains/root/db/theater.html +theater + +// theatre : XYZ.COM LLC +// https://www.iana.org/domains/root/db/theatre.html +theatre + +// tiaa : Teachers Insurance and Annuity Association of America +// https://www.iana.org/domains/root/db/tiaa.html +tiaa + +// tickets : XYZ.COM LLC +// https://www.iana.org/domains/root/db/tickets.html +tickets + +// tienda : Binky Moon, LLC +// https://www.iana.org/domains/root/db/tienda.html +tienda + +// tips : Binky Moon, LLC +// https://www.iana.org/domains/root/db/tips.html +tips + +// tires : Binky Moon, LLC +// https://www.iana.org/domains/root/db/tires.html +tires + +// tirol : punkt Tirol GmbH +// https://www.iana.org/domains/root/db/tirol.html +tirol + +// tjmaxx : The TJX Companies, Inc. +// https://www.iana.org/domains/root/db/tjmaxx.html +tjmaxx + +// tjx : The TJX Companies, Inc. +// https://www.iana.org/domains/root/db/tjx.html +tjx + +// tkmaxx : The TJX Companies, Inc. +// https://www.iana.org/domains/root/db/tkmaxx.html +tkmaxx + +// tmall : Alibaba Group Holding Limited +// https://www.iana.org/domains/root/db/tmall.html +tmall + +// today : Binky Moon, LLC +// https://www.iana.org/domains/root/db/today.html +today + +// tokyo : GMO Registry, Inc. +// https://www.iana.org/domains/root/db/tokyo.html +tokyo + +// tools : Binky Moon, LLC +// https://www.iana.org/domains/root/db/tools.html +tools + +// top : .TOP Registry +// https://www.iana.org/domains/root/db/top.html +top + +// toray : Toray Industries, Inc. +// https://www.iana.org/domains/root/db/toray.html +toray + +// toshiba : TOSHIBA Corporation +// https://www.iana.org/domains/root/db/toshiba.html +toshiba + +// total : TotalEnergies SE +// https://www.iana.org/domains/root/db/total.html +total + +// tours : Binky Moon, LLC +// https://www.iana.org/domains/root/db/tours.html +tours + +// town : Binky Moon, LLC +// https://www.iana.org/domains/root/db/town.html +town + +// toyota : TOYOTA MOTOR CORPORATION +// https://www.iana.org/domains/root/db/toyota.html +toyota + +// toys : Binky Moon, LLC +// https://www.iana.org/domains/root/db/toys.html +toys + +// trade : Elite Registry Limited +// https://www.iana.org/domains/root/db/trade.html +trade + +// trading : Dog Beach, LLC +// https://www.iana.org/domains/root/db/trading.html +trading + +// training : Binky Moon, LLC +// https://www.iana.org/domains/root/db/training.html +training + +// travel : Dog Beach, LLC +// https://www.iana.org/domains/root/db/travel.html +travel + +// travelers : Travelers TLD, LLC +// https://www.iana.org/domains/root/db/travelers.html +travelers + +// travelersinsurance : Travelers TLD, LLC +// https://www.iana.org/domains/root/db/travelersinsurance.html +travelersinsurance + +// trust : Internet Naming Company LLC +// https://www.iana.org/domains/root/db/trust.html +trust + +// trv : Travelers TLD, LLC +// https://www.iana.org/domains/root/db/trv.html +trv + +// tube : Latin American Telecom LLC +// https://www.iana.org/domains/root/db/tube.html +tube + +// tui : TUI AG +// https://www.iana.org/domains/root/db/tui.html +tui + +// tunes : Amazon Registry Services, Inc. +// https://www.iana.org/domains/root/db/tunes.html +tunes + +// tushu : Amazon Registry Services, Inc. +// https://www.iana.org/domains/root/db/tushu.html +tushu + +// tvs : T V SUNDRAM IYENGAR & SONS LIMITED +// https://www.iana.org/domains/root/db/tvs.html +tvs + +// ubank : National Australia Bank Limited +// https://www.iana.org/domains/root/db/ubank.html +ubank + +// ubs : UBS AG +// https://www.iana.org/domains/root/db/ubs.html +ubs + +// unicom : China United Network Communications Corporation Limited +// https://www.iana.org/domains/root/db/unicom.html +unicom + +// university : Binky Moon, LLC +// https://www.iana.org/domains/root/db/university.html +university + +// uno : Radix FZC DMCC +// https://www.iana.org/domains/root/db/uno.html +uno + +// uol : UBN INTERNET LTDA. +// https://www.iana.org/domains/root/db/uol.html +uol + +// ups : UPS Market Driver, Inc. +// https://www.iana.org/domains/root/db/ups.html +ups + +// vacations : Binky Moon, LLC +// https://www.iana.org/domains/root/db/vacations.html +vacations + +// vana : Lifestyle Domain Holdings, Inc. +// https://www.iana.org/domains/root/db/vana.html +vana + +// vanguard : The Vanguard Group, Inc. +// https://www.iana.org/domains/root/db/vanguard.html +vanguard + +// vegas : Dot Vegas, Inc. +// https://www.iana.org/domains/root/db/vegas.html +vegas + +// ventures : Binky Moon, LLC +// https://www.iana.org/domains/root/db/ventures.html +ventures + +// verisign : VeriSign, Inc. +// https://www.iana.org/domains/root/db/verisign.html +verisign + +// versicherung : tldbox GmbH +// https://www.iana.org/domains/root/db/versicherung.html +versicherung + +// vet : Dog Beach, LLC +// https://www.iana.org/domains/root/db/vet.html +vet + +// viajes : Binky Moon, LLC +// https://www.iana.org/domains/root/db/viajes.html +viajes + +// video : Dog Beach, LLC +// https://www.iana.org/domains/root/db/video.html +video + +// vig : VIENNA INSURANCE GROUP AG Wiener Versicherung Gruppe +// https://www.iana.org/domains/root/db/vig.html +vig + +// viking : Viking River Cruises (Bermuda) Ltd. +// https://www.iana.org/domains/root/db/viking.html +viking + +// villas : Binky Moon, LLC +// https://www.iana.org/domains/root/db/villas.html +villas + +// vin : Binky Moon, LLC +// https://www.iana.org/domains/root/db/vin.html +vin + +// vip : Registry Services, LLC +// https://www.iana.org/domains/root/db/vip.html +vip + +// virgin : Virgin Enterprises Limited +// https://www.iana.org/domains/root/db/virgin.html +virgin + +// visa : Visa Worldwide Pte. Limited +// https://www.iana.org/domains/root/db/visa.html +visa + +// vision : Binky Moon, LLC +// https://www.iana.org/domains/root/db/vision.html +vision + +// viva : Saudi Telecom Company +// https://www.iana.org/domains/root/db/viva.html +viva + +// vivo : Telefonica Brasil S.A. +// https://www.iana.org/domains/root/db/vivo.html +vivo + +// vlaanderen : DNS.be vzw +// https://www.iana.org/domains/root/db/vlaanderen.html +vlaanderen + +// vodka : Registry Services, LLC +// https://www.iana.org/domains/root/db/vodka.html +vodka + +// volkswagen : Volkswagen Group of America Inc. +// https://www.iana.org/domains/root/db/volkswagen.html +volkswagen + +// volvo : Volvo Holding Sverige Aktiebolag +// https://www.iana.org/domains/root/db/volvo.html +volvo + +// vote : Monolith Registry LLC +// https://www.iana.org/domains/root/db/vote.html +vote + +// voting : Valuetainment Corp. +// https://www.iana.org/domains/root/db/voting.html +voting + +// voto : Monolith Registry LLC +// https://www.iana.org/domains/root/db/voto.html +voto + +// voyage : Binky Moon, LLC +// https://www.iana.org/domains/root/db/voyage.html +voyage + +// wales : Nominet UK +// https://www.iana.org/domains/root/db/wales.html +wales + +// walmart : Wal-Mart Stores, Inc. +// https://www.iana.org/domains/root/db/walmart.html +walmart + +// walter : Sandvik AB +// https://www.iana.org/domains/root/db/walter.html +walter + +// wang : Zodiac Wang Limited +// https://www.iana.org/domains/root/db/wang.html +wang + +// wanggou : Amazon Registry Services, Inc. +// https://www.iana.org/domains/root/db/wanggou.html +wanggou + +// watch : Binky Moon, LLC +// https://www.iana.org/domains/root/db/watch.html +watch + +// watches : Identity Digital Limited +// https://www.iana.org/domains/root/db/watches.html +watches + +// weather : International Business Machines Corporation +// https://www.iana.org/domains/root/db/weather.html +weather + +// weatherchannel : International Business Machines Corporation +// https://www.iana.org/domains/root/db/weatherchannel.html +weatherchannel + +// webcam : dot Webcam Limited +// https://www.iana.org/domains/root/db/webcam.html +webcam + +// weber : Saint-Gobain Weber SA +// https://www.iana.org/domains/root/db/weber.html +weber + +// website : Radix FZC DMCC +// https://www.iana.org/domains/root/db/website.html +website + +// wedding : Registry Services, LLC +// https://www.iana.org/domains/root/db/wedding.html +wedding + +// weibo : Sina Corporation +// https://www.iana.org/domains/root/db/weibo.html +weibo + +// weir : Weir Group IP Limited +// https://www.iana.org/domains/root/db/weir.html +weir + +// whoswho : Who's Who Registry +// https://www.iana.org/domains/root/db/whoswho.html +whoswho + +// wien : punkt.wien GmbH +// https://www.iana.org/domains/root/db/wien.html +wien + +// wiki : Registry Services, LLC +// https://www.iana.org/domains/root/db/wiki.html +wiki + +// williamhill : William Hill Organization Limited +// https://www.iana.org/domains/root/db/williamhill.html +williamhill + +// win : First Registry Limited +// https://www.iana.org/domains/root/db/win.html +win + +// windows : Microsoft Corporation +// https://www.iana.org/domains/root/db/windows.html +windows + +// wine : Binky Moon, LLC +// https://www.iana.org/domains/root/db/wine.html +wine + +// winners : The TJX Companies, Inc. +// https://www.iana.org/domains/root/db/winners.html +winners + +// wme : William Morris Endeavor Entertainment, LLC +// https://www.iana.org/domains/root/db/wme.html +wme + +// wolterskluwer : Wolters Kluwer N.V. +// https://www.iana.org/domains/root/db/wolterskluwer.html +wolterskluwer + +// woodside : Woodside Petroleum Limited +// https://www.iana.org/domains/root/db/woodside.html +woodside + +// work : Registry Services, LLC +// https://www.iana.org/domains/root/db/work.html +work + +// works : Binky Moon, LLC +// https://www.iana.org/domains/root/db/works.html +works + +// world : Binky Moon, LLC +// https://www.iana.org/domains/root/db/world.html +world + +// wow : Amazon Registry Services, Inc. +// https://www.iana.org/domains/root/db/wow.html +wow + +// wtc : World Trade Centers Association, Inc. +// https://www.iana.org/domains/root/db/wtc.html +wtc + +// wtf : Binky Moon, LLC +// https://www.iana.org/domains/root/db/wtf.html +wtf + +// xbox : Microsoft Corporation +// https://www.iana.org/domains/root/db/xbox.html +xbox + +// xerox : Xerox DNHC LLC +// https://www.iana.org/domains/root/db/xerox.html +xerox + +// xfinity : Comcast IP Holdings I, LLC +// https://www.iana.org/domains/root/db/xfinity.html +xfinity + +// xihuan : Beijing Qihu Keji Co., Ltd. +// https://www.iana.org/domains/root/db/xihuan.html +xihuan + +// xin : Elegant Leader Limited +// https://www.iana.org/domains/root/db/xin.html +xin + +// xn--11b4c3d : VeriSign Sarl +// https://www.iana.org/domains/root/db/xn--11b4c3d.html +कॉम + +// xn--1ck2e1b : Amazon Registry Services, Inc. +// https://www.iana.org/domains/root/db/xn--1ck2e1b.html +セール + +// xn--1qqw23a : Guangzhou YU Wei Information Technology Co., Ltd. +// https://www.iana.org/domains/root/db/xn--1qqw23a.html +佛山 + +// xn--30rr7y : Excellent First Limited +// https://www.iana.org/domains/root/db/xn--30rr7y.html +慈善 + +// xn--3bst00m : Eagle Horizon Limited +// https://www.iana.org/domains/root/db/xn--3bst00m.html +集团 + +// xn--3ds443g : TLD REGISTRY LIMITED OY +// https://www.iana.org/domains/root/db/xn--3ds443g.html +在线 + +// xn--3pxu8k : VeriSign Sarl +// https://www.iana.org/domains/root/db/xn--3pxu8k.html +点看 + +// xn--42c2d9a : VeriSign Sarl +// https://www.iana.org/domains/root/db/xn--42c2d9a.html +คอม + +// xn--45q11c : Zodiac Gemini Ltd +// https://www.iana.org/domains/root/db/xn--45q11c.html +八卦 + +// xn--4gbrim : Helium TLDs Ltd +// https://www.iana.org/domains/root/db/xn--4gbrim.html +موقع + +// xn--55qw42g : China Organizational Name Administration Center +// https://www.iana.org/domains/root/db/xn--55qw42g.html +公益 + +// xn--55qx5d : China Internet Network Information Center (CNNIC) +// https://www.iana.org/domains/root/db/xn--55qx5d.html +公司 + +// xn--5su34j936bgsg : Shangri‐La International Hotel Management Limited +// https://www.iana.org/domains/root/db/xn--5su34j936bgsg.html +香格里拉 + +// xn--5tzm5g : Global Website TLD Asia Limited +// https://www.iana.org/domains/root/db/xn--5tzm5g.html +网站 + +// xn--6frz82g : Identity Digital Limited +// https://www.iana.org/domains/root/db/xn--6frz82g.html +移动 + +// xn--6qq986b3xl : Tycoon Treasure Limited +// https://www.iana.org/domains/root/db/xn--6qq986b3xl.html +我爱你 + +// xn--80adxhks : Foundation for Assistance for Internet Technologies and Infrastructure Development (FAITID) +// https://www.iana.org/domains/root/db/xn--80adxhks.html +москва + +// xn--80aqecdr1a : Pontificium Consilium de Comunicationibus Socialibus (PCCS) (Pontifical Council for Social Communication) +// https://www.iana.org/domains/root/db/xn--80aqecdr1a.html +католик + +// xn--80asehdb : CORE Association +// https://www.iana.org/domains/root/db/xn--80asehdb.html +онлайн + +// xn--80aswg : CORE Association +// https://www.iana.org/domains/root/db/xn--80aswg.html +сайт + +// xn--8y0a063a : China United Network Communications Corporation Limited +// https://www.iana.org/domains/root/db/xn--8y0a063a.html +联通 + +// xn--9dbq2a : VeriSign Sarl +// https://www.iana.org/domains/root/db/xn--9dbq2a.html +קום + +// xn--9et52u : RISE VICTORY LIMITED +// https://www.iana.org/domains/root/db/xn--9et52u.html +时尚 + +// xn--9krt00a : Sina Corporation +// https://www.iana.org/domains/root/db/xn--9krt00a.html +微博 + +// xn--b4w605ferd : Temasek Holdings (Private) Limited +// https://www.iana.org/domains/root/db/xn--b4w605ferd.html +淡马锡 + +// xn--bck1b9a5dre4c : Amazon Registry Services, Inc. +// https://www.iana.org/domains/root/db/xn--bck1b9a5dre4c.html +ファッション + +// xn--c1avg : Public Interest Registry +// https://www.iana.org/domains/root/db/xn--c1avg.html +орг + +// xn--c2br7g : VeriSign Sarl +// https://www.iana.org/domains/root/db/xn--c2br7g.html +नेट + +// xn--cck2b3b : Amazon Registry Services, Inc. +// https://www.iana.org/domains/root/db/xn--cck2b3b.html +ストア + +// xn--cckwcxetd : Amazon Registry Services, Inc. +// https://www.iana.org/domains/root/db/xn--cckwcxetd.html +アマゾン + +// xn--cg4bki : SAMSUNG SDS CO., LTD +// https://www.iana.org/domains/root/db/xn--cg4bki.html +삼성 + +// xn--czr694b : Internet DotTrademark Organisation Limited +// https://www.iana.org/domains/root/db/xn--czr694b.html +商标 + +// xn--czrs0t : Binky Moon, LLC +// https://www.iana.org/domains/root/db/xn--czrs0t.html +商店 + +// xn--czru2d : Zodiac Aquarius Limited +// https://www.iana.org/domains/root/db/xn--czru2d.html +商城 + +// xn--d1acj3b : The Foundation for Network Initiatives “The Smart Internet” +// https://www.iana.org/domains/root/db/xn--d1acj3b.html +дети + +// xn--eckvdtc9d : Amazon Registry Services, Inc. +// https://www.iana.org/domains/root/db/xn--eckvdtc9d.html +ポイント + +// xn--efvy88h : Guangzhou YU Wei Information Technology Co., Ltd. +// https://www.iana.org/domains/root/db/xn--efvy88h.html +新闻 + +// xn--fct429k : Amazon Registry Services, Inc. +// https://www.iana.org/domains/root/db/xn--fct429k.html +家電 + +// xn--fhbei : VeriSign Sarl +// https://www.iana.org/domains/root/db/xn--fhbei.html +كوم + +// xn--fiq228c5hs : TLD REGISTRY LIMITED OY +// https://www.iana.org/domains/root/db/xn--fiq228c5hs.html +中文网 + +// xn--fiq64b : CITIC Group Corporation +// https://www.iana.org/domains/root/db/xn--fiq64b.html +中信 + +// xn--fjq720a : Binky Moon, LLC +// https://www.iana.org/domains/root/db/xn--fjq720a.html +娱乐 + +// xn--flw351e : Charleston Road Registry Inc. +// https://www.iana.org/domains/root/db/xn--flw351e.html +谷歌 + +// xn--fzys8d69uvgm : PCCW Enterprises Limited +// https://www.iana.org/domains/root/db/xn--fzys8d69uvgm.html +電訊盈科 + +// xn--g2xx48c : Nawang Heli(Xiamen) Network Service Co., LTD. +// https://www.iana.org/domains/root/db/xn--g2xx48c.html +购物 + +// xn--gckr3f0f : Amazon Registry Services, Inc. +// https://www.iana.org/domains/root/db/xn--gckr3f0f.html +クラウド + +// xn--gk3at1e : Amazon Registry Services, Inc. +// https://www.iana.org/domains/root/db/xn--gk3at1e.html +通販 + +// xn--hxt814e : Zodiac Taurus Limited +// https://www.iana.org/domains/root/db/xn--hxt814e.html +网店 + +// xn--i1b6b1a6a2e : Public Interest Registry +// https://www.iana.org/domains/root/db/xn--i1b6b1a6a2e.html +संगठन + +// xn--imr513n : Internet DotTrademark Organisation Limited +// https://www.iana.org/domains/root/db/xn--imr513n.html +餐厅 + +// xn--io0a7i : China Internet Network Information Center (CNNIC) +// https://www.iana.org/domains/root/db/xn--io0a7i.html +网络 + +// xn--j1aef : VeriSign Sarl +// https://www.iana.org/domains/root/db/xn--j1aef.html +ком + +// xn--jlq480n2rg : Amazon Registry Services, Inc. +// https://www.iana.org/domains/root/db/xn--jlq480n2rg.html +亚马逊 + +// xn--jvr189m : Amazon Registry Services, Inc. +// https://www.iana.org/domains/root/db/xn--jvr189m.html +食品 + +// xn--kcrx77d1x4a : Koninklijke Philips N.V. +// https://www.iana.org/domains/root/db/xn--kcrx77d1x4a.html +飞利浦 + +// xn--kput3i : Beijing RITT-Net Technology Development Co., Ltd +// https://www.iana.org/domains/root/db/xn--kput3i.html +手机 + +// xn--mgba3a3ejt : Aramco Services Company +// https://www.iana.org/domains/root/db/xn--mgba3a3ejt.html +ارامكو + +// xn--mgba7c0bbn0a : Competrol (Luxembourg) Sarl +// https://www.iana.org/domains/root/db/xn--mgba7c0bbn0a.html +العليان + +// xn--mgbaakc7dvf : Emirates Telecommunications Corporation (trading as Etisalat) +// https://www.iana.org/domains/root/db/xn--mgbaakc7dvf.html +اتصالات + +// xn--mgbab2bd : CORE Association +// https://www.iana.org/domains/root/db/xn--mgbab2bd.html +بازار + +// xn--mgbca7dzdo : Abu Dhabi Systems and Information Centre +// https://www.iana.org/domains/root/db/xn--mgbca7dzdo.html +ابوظبي + +// xn--mgbi4ecexp : Pontificium Consilium de Comunicationibus Socialibus (PCCS) (Pontifical Council for Social Communication) +// https://www.iana.org/domains/root/db/xn--mgbi4ecexp.html +كاثوليك + +// xn--mgbt3dhd : Asia Green IT System Bilgisayar San. ve Tic. Ltd. Sti. +// https://www.iana.org/domains/root/db/xn--mgbt3dhd.html +همراه + +// xn--mk1bu44c : VeriSign Sarl +// https://www.iana.org/domains/root/db/xn--mk1bu44c.html +닷컴 + +// xn--mxtq1m : Net-Chinese Co., Ltd. +// https://www.iana.org/domains/root/db/xn--mxtq1m.html +政府 + +// xn--ngbc5azd : International Domain Registry Pty. Ltd. +// https://www.iana.org/domains/root/db/xn--ngbc5azd.html +شبكة + +// xn--ngbe9e0a : Kuwait Finance House +// https://www.iana.org/domains/root/db/xn--ngbe9e0a.html +بيتك + +// xn--ngbrx : League of Arab States +// https://www.iana.org/domains/root/db/xn--ngbrx.html +عرب + +// xn--nqv7f : Public Interest Registry +// https://www.iana.org/domains/root/db/xn--nqv7f.html +机构 + +// xn--nqv7fs00ema : Public Interest Registry +// https://www.iana.org/domains/root/db/xn--nqv7fs00ema.html +组织机构 + +// xn--nyqy26a : Stable Tone Limited +// https://www.iana.org/domains/root/db/xn--nyqy26a.html +健康 + +// xn--otu796d : Jiang Yu Liang Cai Technology Company Limited +// https://www.iana.org/domains/root/db/xn--otu796d.html +招聘 + +// xn--p1acf : Rusnames Limited +// https://www.iana.org/domains/root/db/xn--p1acf.html +рус + +// xn--pssy2u : VeriSign Sarl +// https://www.iana.org/domains/root/db/xn--pssy2u.html +大拿 + +// xn--q9jyb4c : Charleston Road Registry Inc. +// https://www.iana.org/domains/root/db/xn--q9jyb4c.html +みんな + +// xn--qcka1pmc : Charleston Road Registry Inc. +// https://www.iana.org/domains/root/db/xn--qcka1pmc.html +グーグル + +// xn--rhqv96g : Stable Tone Limited +// https://www.iana.org/domains/root/db/xn--rhqv96g.html +世界 + +// xn--rovu88b : Amazon Registry Services, Inc. +// https://www.iana.org/domains/root/db/xn--rovu88b.html +書籍 + +// xn--ses554g : KNET Co., Ltd. +// https://www.iana.org/domains/root/db/xn--ses554g.html +网址 + +// xn--t60b56a : VeriSign Sarl +// https://www.iana.org/domains/root/db/xn--t60b56a.html +닷넷 + +// xn--tckwe : VeriSign Sarl +// https://www.iana.org/domains/root/db/xn--tckwe.html +コム + +// xn--tiq49xqyj : Pontificium Consilium de Comunicationibus Socialibus (PCCS) (Pontifical Council for Social Communication) +// https://www.iana.org/domains/root/db/xn--tiq49xqyj.html +天主教 + +// xn--unup4y : Binky Moon, LLC +// https://www.iana.org/domains/root/db/xn--unup4y.html +游戏 + +// xn--vermgensberater-ctb : Deutsche Vermögensberatung Aktiengesellschaft DVAG +// https://www.iana.org/domains/root/db/xn--vermgensberater-ctb.html +vermögensberater + +// xn--vermgensberatung-pwb : Deutsche Vermögensberatung Aktiengesellschaft DVAG +// https://www.iana.org/domains/root/db/xn--vermgensberatung-pwb.html +vermögensberatung + +// xn--vhquv : Binky Moon, LLC +// https://www.iana.org/domains/root/db/xn--vhquv.html +企业 + +// xn--vuq861b : Beijing Tele-info Technology Co., Ltd. +// https://www.iana.org/domains/root/db/xn--vuq861b.html +信息 + +// xn--w4r85el8fhu5dnra : Kerry Trading Co. Limited +// https://www.iana.org/domains/root/db/xn--w4r85el8fhu5dnra.html +嘉里大酒店 + +// xn--w4rs40l : Kerry Trading Co. Limited +// https://www.iana.org/domains/root/db/xn--w4rs40l.html +嘉里 + +// xn--xhq521b : Guangzhou YU Wei Information Technology Co., Ltd. +// https://www.iana.org/domains/root/db/xn--xhq521b.html +广东 + +// xn--zfr164b : China Organizational Name Administration Center +// https://www.iana.org/domains/root/db/xn--zfr164b.html +政务 + +// xyz : XYZ.COM LLC +// https://www.iana.org/domains/root/db/xyz.html +xyz + +// yachts : XYZ.COM LLC +// https://www.iana.org/domains/root/db/yachts.html +yachts + +// yahoo : Oath Inc. +// https://www.iana.org/domains/root/db/yahoo.html +yahoo + +// yamaxun : Amazon Registry Services, Inc. +// https://www.iana.org/domains/root/db/yamaxun.html +yamaxun + +// yandex : Yandex Europe B.V. +// https://www.iana.org/domains/root/db/yandex.html +yandex + +// yodobashi : YODOBASHI CAMERA CO.,LTD. +// https://www.iana.org/domains/root/db/yodobashi.html +yodobashi + +// yoga : Registry Services, LLC +// https://www.iana.org/domains/root/db/yoga.html +yoga + +// yokohama : GMO Registry, Inc. +// https://www.iana.org/domains/root/db/yokohama.html +yokohama + +// you : Amazon Registry Services, Inc. +// https://www.iana.org/domains/root/db/you.html +you + +// youtube : Charleston Road Registry Inc. +// https://www.iana.org/domains/root/db/youtube.html +youtube + +// yun : Beijing Qihu Keji Co., Ltd. +// https://www.iana.org/domains/root/db/yun.html +yun + +// zappos : Amazon Registry Services, Inc. +// https://www.iana.org/domains/root/db/zappos.html +zappos + +// zara : Industria de Diseño Textil, S.A. (INDITEX, S.A.) +// https://www.iana.org/domains/root/db/zara.html +zara + +// zero : Amazon Registry Services, Inc. +// https://www.iana.org/domains/root/db/zero.html +zero + +// zip : Charleston Road Registry Inc. +// https://www.iana.org/domains/root/db/zip.html +zip + +// zone : Binky Moon, LLC +// https://www.iana.org/domains/root/db/zone.html +zone + +// zuerich : Kanton Zürich (Canton of Zurich) +// https://www.iana.org/domains/root/db/zuerich.html +zuerich + + +// ===END ICANN DOMAINS=== +// ===BEGIN PRIVATE DOMAINS=== +// (Note: these are in alphabetical order by company name) + +// 1GB LLC : https://www.1gb.ua/ +// Submitted by 1GB LLC +cc.ua +inf.ua +ltd.ua + +// 611coin : https://611project.org/ +611.to + +// Aaron Marais' Gitlab pages: https://lab.aaronleem.co.za +// Submitted by Aaron Marais +graphox.us + +// accesso Technology Group, plc. : https://accesso.com/ +// Submitted by accesso Team +*.devcdnaccesso.com + +// Acorn Labs : https://acorn.io +// Submitted by Craig Jellick +*.on-acorn.io + +// ActiveTrail: https://www.activetrail.biz/ +// Submitted by Ofer Kalaora +activetrail.biz + +// Adobe : https://www.adobe.com/ +// Submitted by Ian Boston and Lars Trieloff +adobeaemcloud.com +*.dev.adobeaemcloud.com +hlx.live +adobeaemcloud.net +hlx.page +hlx3.page + +// Adobe Developer Platform : https://developer.adobe.com +// Submitted by Jesse MacFadyen +adobeio-static.net +adobeioruntime.net + +// Agnat sp. z o.o. : https://domena.pl +// Submitted by Przemyslaw Plewa +beep.pl + +// Airkit : https://www.airkit.com/ +// Submitted by Grant Cooksey +airkitapps.com +airkitapps-au.com +airkitapps.eu + +// Aiven: https://aiven.io/ +// Submitted by Etienne Stalmans +aivencloud.com + +// Akamai : https://www.akamai.com/ +// Submitted by Akamai Team +akadns.net +akamai.net +akamai-staging.net +akamaiedge.net +akamaiedge-staging.net +akamaihd.net +akamaihd-staging.net +akamaiorigin.net +akamaiorigin-staging.net +akamaized.net +akamaized-staging.net +edgekey.net +edgekey-staging.net +edgesuite.net +edgesuite-staging.net + +// alboto.ca : http://alboto.ca +// Submitted by Anton Avramov +barsy.ca + +// Alces Software Ltd : http://alces-software.com +// Submitted by Mark J. Titorenko +*.compute.estate +*.alces.network + +// all-inkl.com : https://all-inkl.com +// Submitted by Werner Kaltofen +kasserver.com + +// Altervista: https://www.altervista.org +// Submitted by Carlo Cannas +altervista.org + +// alwaysdata : https://www.alwaysdata.com +// Submitted by Cyril +alwaysdata.net + +// Amaze Software : https://amaze.co +// Submitted by Domain Admin +myamaze.net + +// Amazon : https://www.amazon.com/ +// Submitted by AWS Security +// Subsections of Amazon/subsidiaries will appear until "concludes" tag + +// Amazon API Gateway +// Submitted by AWS Security +// Reference: 4d863337-ff98-4501-a6f2-361eba8445d6 +execute-api.cn-north-1.amazonaws.com.cn +execute-api.cn-northwest-1.amazonaws.com.cn +execute-api.af-south-1.amazonaws.com +execute-api.ap-east-1.amazonaws.com +execute-api.ap-northeast-1.amazonaws.com +execute-api.ap-northeast-2.amazonaws.com +execute-api.ap-northeast-3.amazonaws.com +execute-api.ap-south-1.amazonaws.com +execute-api.ap-south-2.amazonaws.com +execute-api.ap-southeast-1.amazonaws.com +execute-api.ap-southeast-2.amazonaws.com +execute-api.ap-southeast-3.amazonaws.com +execute-api.ap-southeast-4.amazonaws.com +execute-api.ca-central-1.amazonaws.com +execute-api.eu-central-1.amazonaws.com +execute-api.eu-central-2.amazonaws.com +execute-api.eu-north-1.amazonaws.com +execute-api.eu-south-1.amazonaws.com +execute-api.eu-south-2.amazonaws.com +execute-api.eu-west-1.amazonaws.com +execute-api.eu-west-2.amazonaws.com +execute-api.eu-west-3.amazonaws.com +execute-api.il-central-1.amazonaws.com +execute-api.me-central-1.amazonaws.com +execute-api.me-south-1.amazonaws.com +execute-api.sa-east-1.amazonaws.com +execute-api.us-east-1.amazonaws.com +execute-api.us-east-2.amazonaws.com +execute-api.us-gov-east-1.amazonaws.com +execute-api.us-gov-west-1.amazonaws.com +execute-api.us-west-1.amazonaws.com +execute-api.us-west-2.amazonaws.com + +// Amazon CloudFront +// Submitted by Donavan Miller +// Reference: 54144616-fd49-4435-8535-19c6a601bdb3 +cloudfront.net + +// Amazon Cognito +// Submitted by AWS Security +// Reference: 7bee1013-f456-47df-bfe8-03c78d946d61 +auth.af-south-1.amazoncognito.com +auth.ap-northeast-1.amazoncognito.com +auth.ap-northeast-2.amazoncognito.com +auth.ap-northeast-3.amazoncognito.com +auth.ap-south-1.amazoncognito.com +auth.ap-southeast-1.amazoncognito.com +auth.ap-southeast-2.amazoncognito.com +auth.ap-southeast-3.amazoncognito.com +auth.ca-central-1.amazoncognito.com +auth.eu-central-1.amazoncognito.com +auth.eu-north-1.amazoncognito.com +auth.eu-south-1.amazoncognito.com +auth.eu-west-1.amazoncognito.com +auth.eu-west-2.amazoncognito.com +auth.eu-west-3.amazoncognito.com +auth.il-central-1.amazoncognito.com +auth.me-south-1.amazoncognito.com +auth.sa-east-1.amazoncognito.com +auth.us-east-1.amazoncognito.com +auth-fips.us-east-1.amazoncognito.com +auth.us-east-2.amazoncognito.com +auth-fips.us-east-2.amazoncognito.com +auth-fips.us-gov-west-1.amazoncognito.com +auth.us-west-1.amazoncognito.com +auth-fips.us-west-1.amazoncognito.com +auth.us-west-2.amazoncognito.com +auth-fips.us-west-2.amazoncognito.com + +// Amazon EC2 +// Submitted by Luke Wells +// Reference: 4c38fa71-58ac-4768-99e5-689c1767e537 +*.compute.amazonaws.com +*.compute-1.amazonaws.com +*.compute.amazonaws.com.cn +us-east-1.amazonaws.com + +// Amazon EMR +// Submitted by AWS Security +// Reference: 597f3f8e-9283-4e48-8e32-7ee25a1ff6ab +emrappui-prod.cn-north-1.amazonaws.com.cn +emrnotebooks-prod.cn-north-1.amazonaws.com.cn +emrstudio-prod.cn-north-1.amazonaws.com.cn +emrappui-prod.cn-northwest-1.amazonaws.com.cn +emrnotebooks-prod.cn-northwest-1.amazonaws.com.cn +emrstudio-prod.cn-northwest-1.amazonaws.com.cn +emrappui-prod.af-south-1.amazonaws.com +emrnotebooks-prod.af-south-1.amazonaws.com +emrstudio-prod.af-south-1.amazonaws.com +emrappui-prod.ap-east-1.amazonaws.com +emrnotebooks-prod.ap-east-1.amazonaws.com +emrstudio-prod.ap-east-1.amazonaws.com +emrappui-prod.ap-northeast-1.amazonaws.com +emrnotebooks-prod.ap-northeast-1.amazonaws.com +emrstudio-prod.ap-northeast-1.amazonaws.com +emrappui-prod.ap-northeast-2.amazonaws.com +emrnotebooks-prod.ap-northeast-2.amazonaws.com +emrstudio-prod.ap-northeast-2.amazonaws.com +emrappui-prod.ap-northeast-3.amazonaws.com +emrnotebooks-prod.ap-northeast-3.amazonaws.com +emrstudio-prod.ap-northeast-3.amazonaws.com +emrappui-prod.ap-south-1.amazonaws.com +emrnotebooks-prod.ap-south-1.amazonaws.com +emrstudio-prod.ap-south-1.amazonaws.com +emrappui-prod.ap-southeast-1.amazonaws.com +emrnotebooks-prod.ap-southeast-1.amazonaws.com +emrstudio-prod.ap-southeast-1.amazonaws.com +emrappui-prod.ap-southeast-2.amazonaws.com +emrnotebooks-prod.ap-southeast-2.amazonaws.com +emrstudio-prod.ap-southeast-2.amazonaws.com +emrappui-prod.ap-southeast-3.amazonaws.com +emrnotebooks-prod.ap-southeast-3.amazonaws.com +emrstudio-prod.ap-southeast-3.amazonaws.com +emrappui-prod.ca-central-1.amazonaws.com +emrnotebooks-prod.ca-central-1.amazonaws.com +emrstudio-prod.ca-central-1.amazonaws.com +emrappui-prod.eu-central-1.amazonaws.com +emrnotebooks-prod.eu-central-1.amazonaws.com +emrstudio-prod.eu-central-1.amazonaws.com +emrappui-prod.eu-north-1.amazonaws.com +emrnotebooks-prod.eu-north-1.amazonaws.com +emrstudio-prod.eu-north-1.amazonaws.com +emrappui-prod.eu-south-1.amazonaws.com +emrnotebooks-prod.eu-south-1.amazonaws.com +emrstudio-prod.eu-south-1.amazonaws.com +emrappui-prod.eu-west-1.amazonaws.com +emrnotebooks-prod.eu-west-1.amazonaws.com +emrstudio-prod.eu-west-1.amazonaws.com +emrappui-prod.eu-west-2.amazonaws.com +emrnotebooks-prod.eu-west-2.amazonaws.com +emrstudio-prod.eu-west-2.amazonaws.com +emrappui-prod.eu-west-3.amazonaws.com +emrnotebooks-prod.eu-west-3.amazonaws.com +emrstudio-prod.eu-west-3.amazonaws.com +emrappui-prod.me-central-1.amazonaws.com +emrnotebooks-prod.me-central-1.amazonaws.com +emrstudio-prod.me-central-1.amazonaws.com +emrappui-prod.me-south-1.amazonaws.com +emrnotebooks-prod.me-south-1.amazonaws.com +emrstudio-prod.me-south-1.amazonaws.com +emrappui-prod.sa-east-1.amazonaws.com +emrnotebooks-prod.sa-east-1.amazonaws.com +emrstudio-prod.sa-east-1.amazonaws.com +emrappui-prod.us-east-1.amazonaws.com +emrnotebooks-prod.us-east-1.amazonaws.com +emrstudio-prod.us-east-1.amazonaws.com +emrappui-prod.us-east-2.amazonaws.com +emrnotebooks-prod.us-east-2.amazonaws.com +emrstudio-prod.us-east-2.amazonaws.com +emrappui-prod.us-gov-east-1.amazonaws.com +emrnotebooks-prod.us-gov-east-1.amazonaws.com +emrstudio-prod.us-gov-east-1.amazonaws.com +emrappui-prod.us-gov-west-1.amazonaws.com +emrnotebooks-prod.us-gov-west-1.amazonaws.com +emrstudio-prod.us-gov-west-1.amazonaws.com +emrappui-prod.us-west-1.amazonaws.com +emrnotebooks-prod.us-west-1.amazonaws.com +emrstudio-prod.us-west-1.amazonaws.com +emrappui-prod.us-west-2.amazonaws.com +emrnotebooks-prod.us-west-2.amazonaws.com +emrstudio-prod.us-west-2.amazonaws.com + +// Amazon Managed Workflows for Apache Airflow +// Submitted by AWS Security +// Reference: 4ab55e6f-90c0-4a8d-b6a0-52ca5dbb1c2e +*.cn-north-1.airflow.amazonaws.com.cn +*.cn-northwest-1.airflow.amazonaws.com.cn +*.ap-northeast-1.airflow.amazonaws.com +*.ap-northeast-2.airflow.amazonaws.com +*.ap-south-1.airflow.amazonaws.com +*.ap-southeast-1.airflow.amazonaws.com +*.ap-southeast-2.airflow.amazonaws.com +*.ca-central-1.airflow.amazonaws.com +*.eu-central-1.airflow.amazonaws.com +*.eu-north-1.airflow.amazonaws.com +*.eu-west-1.airflow.amazonaws.com +*.eu-west-2.airflow.amazonaws.com +*.eu-west-3.airflow.amazonaws.com +*.sa-east-1.airflow.amazonaws.com +*.us-east-1.airflow.amazonaws.com +*.us-east-2.airflow.amazonaws.com +*.us-west-2.airflow.amazonaws.com + +// Amazon S3 +// Submitted by AWS Security +// Reference: 0e801048-08f2-4064-9cb8-e7373e0b57f4 +s3.dualstack.cn-north-1.amazonaws.com.cn +s3-accesspoint.dualstack.cn-north-1.amazonaws.com.cn +s3-website.dualstack.cn-north-1.amazonaws.com.cn +s3.cn-north-1.amazonaws.com.cn +s3-accesspoint.cn-north-1.amazonaws.com.cn +s3-deprecated.cn-north-1.amazonaws.com.cn +s3-object-lambda.cn-north-1.amazonaws.com.cn +s3-website.cn-north-1.amazonaws.com.cn +s3.dualstack.cn-northwest-1.amazonaws.com.cn +s3-accesspoint.dualstack.cn-northwest-1.amazonaws.com.cn +s3.cn-northwest-1.amazonaws.com.cn +s3-accesspoint.cn-northwest-1.amazonaws.com.cn +s3-object-lambda.cn-northwest-1.amazonaws.com.cn +s3-website.cn-northwest-1.amazonaws.com.cn +s3.dualstack.af-south-1.amazonaws.com +s3-accesspoint.dualstack.af-south-1.amazonaws.com +s3-website.dualstack.af-south-1.amazonaws.com +s3.af-south-1.amazonaws.com +s3-accesspoint.af-south-1.amazonaws.com +s3-object-lambda.af-south-1.amazonaws.com +s3-website.af-south-1.amazonaws.com +s3.dualstack.ap-east-1.amazonaws.com +s3-accesspoint.dualstack.ap-east-1.amazonaws.com +s3.ap-east-1.amazonaws.com +s3-accesspoint.ap-east-1.amazonaws.com +s3-object-lambda.ap-east-1.amazonaws.com +s3-website.ap-east-1.amazonaws.com +s3.dualstack.ap-northeast-1.amazonaws.com +s3-accesspoint.dualstack.ap-northeast-1.amazonaws.com +s3-website.dualstack.ap-northeast-1.amazonaws.com +s3.ap-northeast-1.amazonaws.com +s3-accesspoint.ap-northeast-1.amazonaws.com +s3-object-lambda.ap-northeast-1.amazonaws.com +s3-website.ap-northeast-1.amazonaws.com +s3.dualstack.ap-northeast-2.amazonaws.com +s3-accesspoint.dualstack.ap-northeast-2.amazonaws.com +s3-website.dualstack.ap-northeast-2.amazonaws.com +s3.ap-northeast-2.amazonaws.com +s3-accesspoint.ap-northeast-2.amazonaws.com +s3-object-lambda.ap-northeast-2.amazonaws.com +s3-website.ap-northeast-2.amazonaws.com +s3.dualstack.ap-northeast-3.amazonaws.com +s3-accesspoint.dualstack.ap-northeast-3.amazonaws.com +s3-website.dualstack.ap-northeast-3.amazonaws.com +s3.ap-northeast-3.amazonaws.com +s3-accesspoint.ap-northeast-3.amazonaws.com +s3-object-lambda.ap-northeast-3.amazonaws.com +s3-website.ap-northeast-3.amazonaws.com +s3.dualstack.ap-south-1.amazonaws.com +s3-accesspoint.dualstack.ap-south-1.amazonaws.com +s3-website.dualstack.ap-south-1.amazonaws.com +s3.ap-south-1.amazonaws.com +s3-accesspoint.ap-south-1.amazonaws.com +s3-object-lambda.ap-south-1.amazonaws.com +s3-website.ap-south-1.amazonaws.com +s3.dualstack.ap-south-2.amazonaws.com +s3-accesspoint.dualstack.ap-south-2.amazonaws.com +s3.ap-south-2.amazonaws.com +s3-accesspoint.ap-south-2.amazonaws.com +s3-object-lambda.ap-south-2.amazonaws.com +s3-website.ap-south-2.amazonaws.com +s3.dualstack.ap-southeast-1.amazonaws.com +s3-accesspoint.dualstack.ap-southeast-1.amazonaws.com +s3-website.dualstack.ap-southeast-1.amazonaws.com +s3.ap-southeast-1.amazonaws.com +s3-accesspoint.ap-southeast-1.amazonaws.com +s3-object-lambda.ap-southeast-1.amazonaws.com +s3-website.ap-southeast-1.amazonaws.com +s3.dualstack.ap-southeast-2.amazonaws.com +s3-accesspoint.dualstack.ap-southeast-2.amazonaws.com +s3-website.dualstack.ap-southeast-2.amazonaws.com +s3.ap-southeast-2.amazonaws.com +s3-accesspoint.ap-southeast-2.amazonaws.com +s3-object-lambda.ap-southeast-2.amazonaws.com +s3-website.ap-southeast-2.amazonaws.com +s3.dualstack.ap-southeast-3.amazonaws.com +s3-accesspoint.dualstack.ap-southeast-3.amazonaws.com +s3.ap-southeast-3.amazonaws.com +s3-accesspoint.ap-southeast-3.amazonaws.com +s3-object-lambda.ap-southeast-3.amazonaws.com +s3-website.ap-southeast-3.amazonaws.com +s3.dualstack.ap-southeast-4.amazonaws.com +s3-accesspoint.dualstack.ap-southeast-4.amazonaws.com +s3.ap-southeast-4.amazonaws.com +s3-accesspoint.ap-southeast-4.amazonaws.com +s3-object-lambda.ap-southeast-4.amazonaws.com +s3-website.ap-southeast-4.amazonaws.com +s3.dualstack.ca-central-1.amazonaws.com +s3-accesspoint.dualstack.ca-central-1.amazonaws.com +s3-accesspoint-fips.dualstack.ca-central-1.amazonaws.com +s3-fips.dualstack.ca-central-1.amazonaws.com +s3-website.dualstack.ca-central-1.amazonaws.com +s3.ca-central-1.amazonaws.com +s3-accesspoint.ca-central-1.amazonaws.com +s3-accesspoint-fips.ca-central-1.amazonaws.com +s3-fips.ca-central-1.amazonaws.com +s3-object-lambda.ca-central-1.amazonaws.com +s3-website.ca-central-1.amazonaws.com +s3.dualstack.eu-central-1.amazonaws.com +s3-accesspoint.dualstack.eu-central-1.amazonaws.com +s3-website.dualstack.eu-central-1.amazonaws.com +s3.eu-central-1.amazonaws.com +s3-accesspoint.eu-central-1.amazonaws.com +s3-object-lambda.eu-central-1.amazonaws.com +s3-website.eu-central-1.amazonaws.com +s3.dualstack.eu-central-2.amazonaws.com +s3-accesspoint.dualstack.eu-central-2.amazonaws.com +s3.eu-central-2.amazonaws.com +s3-accesspoint.eu-central-2.amazonaws.com +s3-object-lambda.eu-central-2.amazonaws.com +s3-website.eu-central-2.amazonaws.com +s3.dualstack.eu-north-1.amazonaws.com +s3-accesspoint.dualstack.eu-north-1.amazonaws.com +s3.eu-north-1.amazonaws.com +s3-accesspoint.eu-north-1.amazonaws.com +s3-object-lambda.eu-north-1.amazonaws.com +s3-website.eu-north-1.amazonaws.com +s3.dualstack.eu-south-1.amazonaws.com +s3-accesspoint.dualstack.eu-south-1.amazonaws.com +s3-website.dualstack.eu-south-1.amazonaws.com +s3.eu-south-1.amazonaws.com +s3-accesspoint.eu-south-1.amazonaws.com +s3-object-lambda.eu-south-1.amazonaws.com +s3-website.eu-south-1.amazonaws.com +s3.dualstack.eu-south-2.amazonaws.com +s3-accesspoint.dualstack.eu-south-2.amazonaws.com +s3.eu-south-2.amazonaws.com +s3-accesspoint.eu-south-2.amazonaws.com +s3-object-lambda.eu-south-2.amazonaws.com +s3-website.eu-south-2.amazonaws.com +s3.dualstack.eu-west-1.amazonaws.com +s3-accesspoint.dualstack.eu-west-1.amazonaws.com +s3-website.dualstack.eu-west-1.amazonaws.com +s3.eu-west-1.amazonaws.com +s3-accesspoint.eu-west-1.amazonaws.com +s3-deprecated.eu-west-1.amazonaws.com +s3-object-lambda.eu-west-1.amazonaws.com +s3-website.eu-west-1.amazonaws.com +s3.dualstack.eu-west-2.amazonaws.com +s3-accesspoint.dualstack.eu-west-2.amazonaws.com +s3.eu-west-2.amazonaws.com +s3-accesspoint.eu-west-2.amazonaws.com +s3-object-lambda.eu-west-2.amazonaws.com +s3-website.eu-west-2.amazonaws.com +s3.dualstack.eu-west-3.amazonaws.com +s3-accesspoint.dualstack.eu-west-3.amazonaws.com +s3-website.dualstack.eu-west-3.amazonaws.com +s3.eu-west-3.amazonaws.com +s3-accesspoint.eu-west-3.amazonaws.com +s3-object-lambda.eu-west-3.amazonaws.com +s3-website.eu-west-3.amazonaws.com +s3.dualstack.il-central-1.amazonaws.com +s3-accesspoint.dualstack.il-central-1.amazonaws.com +s3.il-central-1.amazonaws.com +s3-accesspoint.il-central-1.amazonaws.com +s3-object-lambda.il-central-1.amazonaws.com +s3-website.il-central-1.amazonaws.com +s3.dualstack.me-central-1.amazonaws.com +s3-accesspoint.dualstack.me-central-1.amazonaws.com +s3.me-central-1.amazonaws.com +s3-accesspoint.me-central-1.amazonaws.com +s3-object-lambda.me-central-1.amazonaws.com +s3-website.me-central-1.amazonaws.com +s3.dualstack.me-south-1.amazonaws.com +s3-accesspoint.dualstack.me-south-1.amazonaws.com +s3.me-south-1.amazonaws.com +s3-accesspoint.me-south-1.amazonaws.com +s3-object-lambda.me-south-1.amazonaws.com +s3-website.me-south-1.amazonaws.com +s3.amazonaws.com +s3-1.amazonaws.com +s3-ap-east-1.amazonaws.com +s3-ap-northeast-1.amazonaws.com +s3-ap-northeast-2.amazonaws.com +s3-ap-northeast-3.amazonaws.com +s3-ap-south-1.amazonaws.com +s3-ap-southeast-1.amazonaws.com +s3-ap-southeast-2.amazonaws.com +s3-ca-central-1.amazonaws.com +s3-eu-central-1.amazonaws.com +s3-eu-north-1.amazonaws.com +s3-eu-west-1.amazonaws.com +s3-eu-west-2.amazonaws.com +s3-eu-west-3.amazonaws.com +s3-external-1.amazonaws.com +s3-fips-us-gov-east-1.amazonaws.com +s3-fips-us-gov-west-1.amazonaws.com +mrap.accesspoint.s3-global.amazonaws.com +s3-me-south-1.amazonaws.com +s3-sa-east-1.amazonaws.com +s3-us-east-2.amazonaws.com +s3-us-gov-east-1.amazonaws.com +s3-us-gov-west-1.amazonaws.com +s3-us-west-1.amazonaws.com +s3-us-west-2.amazonaws.com +s3-website-ap-northeast-1.amazonaws.com +s3-website-ap-southeast-1.amazonaws.com +s3-website-ap-southeast-2.amazonaws.com +s3-website-eu-west-1.amazonaws.com +s3-website-sa-east-1.amazonaws.com +s3-website-us-east-1.amazonaws.com +s3-website-us-gov-west-1.amazonaws.com +s3-website-us-west-1.amazonaws.com +s3-website-us-west-2.amazonaws.com +s3.dualstack.sa-east-1.amazonaws.com +s3-accesspoint.dualstack.sa-east-1.amazonaws.com +s3-website.dualstack.sa-east-1.amazonaws.com +s3.sa-east-1.amazonaws.com +s3-accesspoint.sa-east-1.amazonaws.com +s3-object-lambda.sa-east-1.amazonaws.com +s3-website.sa-east-1.amazonaws.com +s3.dualstack.us-east-1.amazonaws.com +s3-accesspoint.dualstack.us-east-1.amazonaws.com +s3-accesspoint-fips.dualstack.us-east-1.amazonaws.com +s3-fips.dualstack.us-east-1.amazonaws.com +s3-website.dualstack.us-east-1.amazonaws.com +s3.us-east-1.amazonaws.com +s3-accesspoint.us-east-1.amazonaws.com +s3-accesspoint-fips.us-east-1.amazonaws.com +s3-deprecated.us-east-1.amazonaws.com +s3-fips.us-east-1.amazonaws.com +s3-object-lambda.us-east-1.amazonaws.com +s3-website.us-east-1.amazonaws.com +s3.dualstack.us-east-2.amazonaws.com +s3-accesspoint.dualstack.us-east-2.amazonaws.com +s3-accesspoint-fips.dualstack.us-east-2.amazonaws.com +s3-fips.dualstack.us-east-2.amazonaws.com +s3.us-east-2.amazonaws.com +s3-accesspoint.us-east-2.amazonaws.com +s3-accesspoint-fips.us-east-2.amazonaws.com +s3-deprecated.us-east-2.amazonaws.com +s3-fips.us-east-2.amazonaws.com +s3-object-lambda.us-east-2.amazonaws.com +s3-website.us-east-2.amazonaws.com +s3.dualstack.us-gov-east-1.amazonaws.com +s3-accesspoint.dualstack.us-gov-east-1.amazonaws.com +s3-accesspoint-fips.dualstack.us-gov-east-1.amazonaws.com +s3-fips.dualstack.us-gov-east-1.amazonaws.com +s3.us-gov-east-1.amazonaws.com +s3-accesspoint.us-gov-east-1.amazonaws.com +s3-accesspoint-fips.us-gov-east-1.amazonaws.com +s3-fips.us-gov-east-1.amazonaws.com +s3-object-lambda.us-gov-east-1.amazonaws.com +s3-website.us-gov-east-1.amazonaws.com +s3.dualstack.us-gov-west-1.amazonaws.com +s3-accesspoint.dualstack.us-gov-west-1.amazonaws.com +s3-accesspoint-fips.dualstack.us-gov-west-1.amazonaws.com +s3-fips.dualstack.us-gov-west-1.amazonaws.com +s3.us-gov-west-1.amazonaws.com +s3-accesspoint.us-gov-west-1.amazonaws.com +s3-accesspoint-fips.us-gov-west-1.amazonaws.com +s3-fips.us-gov-west-1.amazonaws.com +s3-object-lambda.us-gov-west-1.amazonaws.com +s3-website.us-gov-west-1.amazonaws.com +s3.dualstack.us-west-1.amazonaws.com +s3-accesspoint.dualstack.us-west-1.amazonaws.com +s3-accesspoint-fips.dualstack.us-west-1.amazonaws.com +s3-fips.dualstack.us-west-1.amazonaws.com +s3-website.dualstack.us-west-1.amazonaws.com +s3.us-west-1.amazonaws.com +s3-accesspoint.us-west-1.amazonaws.com +s3-accesspoint-fips.us-west-1.amazonaws.com +s3-fips.us-west-1.amazonaws.com +s3-object-lambda.us-west-1.amazonaws.com +s3-website.us-west-1.amazonaws.com +s3.dualstack.us-west-2.amazonaws.com +s3-accesspoint.dualstack.us-west-2.amazonaws.com +s3-accesspoint-fips.dualstack.us-west-2.amazonaws.com +s3-fips.dualstack.us-west-2.amazonaws.com +s3-website.dualstack.us-west-2.amazonaws.com +s3.us-west-2.amazonaws.com +s3-accesspoint.us-west-2.amazonaws.com +s3-accesspoint-fips.us-west-2.amazonaws.com +s3-deprecated.us-west-2.amazonaws.com +s3-fips.us-west-2.amazonaws.com +s3-object-lambda.us-west-2.amazonaws.com +s3-website.us-west-2.amazonaws.com + +// Amazon SageMaker Notebook Instances +// Submitted by AWS Security +// Reference: fe8c9e94-5a22-486d-8750-991a3a9b13c6 +notebook.af-south-1.sagemaker.aws +notebook.ap-east-1.sagemaker.aws +notebook.ap-northeast-1.sagemaker.aws +notebook.ap-northeast-2.sagemaker.aws +notebook.ap-northeast-3.sagemaker.aws +notebook.ap-south-1.sagemaker.aws +notebook.ap-south-2.sagemaker.aws +notebook.ap-southeast-1.sagemaker.aws +notebook.ap-southeast-2.sagemaker.aws +notebook.ap-southeast-3.sagemaker.aws +notebook.ap-southeast-4.sagemaker.aws +notebook.ca-central-1.sagemaker.aws +notebook.eu-central-1.sagemaker.aws +notebook.eu-central-2.sagemaker.aws +notebook.eu-north-1.sagemaker.aws +notebook.eu-south-1.sagemaker.aws +notebook.eu-south-2.sagemaker.aws +notebook.eu-west-1.sagemaker.aws +notebook.eu-west-2.sagemaker.aws +notebook.eu-west-3.sagemaker.aws +notebook.il-central-1.sagemaker.aws +notebook.me-central-1.sagemaker.aws +notebook.me-south-1.sagemaker.aws +notebook.sa-east-1.sagemaker.aws +notebook.us-east-1.sagemaker.aws +notebook-fips.us-east-1.sagemaker.aws +notebook.us-east-2.sagemaker.aws +notebook-fips.us-east-2.sagemaker.aws +notebook.us-gov-east-1.sagemaker.aws +notebook-fips.us-gov-east-1.sagemaker.aws +notebook.us-gov-west-1.sagemaker.aws +notebook-fips.us-gov-west-1.sagemaker.aws +notebook.us-west-1.sagemaker.aws +notebook.us-west-2.sagemaker.aws +notebook-fips.us-west-2.sagemaker.aws +notebook.cn-north-1.sagemaker.com.cn +notebook.cn-northwest-1.sagemaker.com.cn + +// Amazon SageMaker Studio +// Submitted by AWS Security +// Reference: 057ee397-6bf8-4f20-b807-d7bc145ac980 +studio.af-south-1.sagemaker.aws +studio.ap-east-1.sagemaker.aws +studio.ap-northeast-1.sagemaker.aws +studio.ap-northeast-2.sagemaker.aws +studio.ap-northeast-3.sagemaker.aws +studio.ap-south-1.sagemaker.aws +studio.ap-southeast-1.sagemaker.aws +studio.ap-southeast-2.sagemaker.aws +studio.ap-southeast-3.sagemaker.aws +studio.ca-central-1.sagemaker.aws +studio.eu-central-1.sagemaker.aws +studio.eu-north-1.sagemaker.aws +studio.eu-south-1.sagemaker.aws +studio.eu-west-1.sagemaker.aws +studio.eu-west-2.sagemaker.aws +studio.eu-west-3.sagemaker.aws +studio.il-central-1.sagemaker.aws +studio.me-central-1.sagemaker.aws +studio.me-south-1.sagemaker.aws +studio.sa-east-1.sagemaker.aws +studio.us-east-1.sagemaker.aws +studio.us-east-2.sagemaker.aws +studio.us-gov-east-1.sagemaker.aws +studio-fips.us-gov-east-1.sagemaker.aws +studio.us-gov-west-1.sagemaker.aws +studio-fips.us-gov-west-1.sagemaker.aws +studio.us-west-1.sagemaker.aws +studio.us-west-2.sagemaker.aws +studio.cn-north-1.sagemaker.com.cn +studio.cn-northwest-1.sagemaker.com.cn + +// Analytics on AWS +// Submitted by AWS Security +// Reference: 955f9f40-a495-4e73-ae85-67b77ac9cadd +analytics-gateway.ap-northeast-1.amazonaws.com +analytics-gateway.ap-northeast-2.amazonaws.com +analytics-gateway.ap-south-1.amazonaws.com +analytics-gateway.ap-southeast-1.amazonaws.com +analytics-gateway.ap-southeast-2.amazonaws.com +analytics-gateway.eu-central-1.amazonaws.com +analytics-gateway.eu-west-1.amazonaws.com +analytics-gateway.us-east-1.amazonaws.com +analytics-gateway.us-east-2.amazonaws.com +analytics-gateway.us-west-2.amazonaws.com + +// AWS Amplify +// Submitted by AWS Security +// Reference: 5ecce854-c033-4fc4-a755-1a9916d9a9bb +*.amplifyapp.com + +// AWS App Runner +// Submitted by AWS Security +// Reference: 6828c008-ba5d-442f-ade5-48da4e7c2316 +*.awsapprunner.com + +// AWS Cloud9 +// Submitted by: AWS Security +// Reference: 05c44955-977c-4b57-938a-f2af92733f9f +webview-assets.aws-cloud9.af-south-1.amazonaws.com +vfs.cloud9.af-south-1.amazonaws.com +webview-assets.cloud9.af-south-1.amazonaws.com +webview-assets.aws-cloud9.ap-east-1.amazonaws.com +vfs.cloud9.ap-east-1.amazonaws.com +webview-assets.cloud9.ap-east-1.amazonaws.com +webview-assets.aws-cloud9.ap-northeast-1.amazonaws.com +vfs.cloud9.ap-northeast-1.amazonaws.com +webview-assets.cloud9.ap-northeast-1.amazonaws.com +webview-assets.aws-cloud9.ap-northeast-2.amazonaws.com +vfs.cloud9.ap-northeast-2.amazonaws.com +webview-assets.cloud9.ap-northeast-2.amazonaws.com +webview-assets.aws-cloud9.ap-northeast-3.amazonaws.com +vfs.cloud9.ap-northeast-3.amazonaws.com +webview-assets.cloud9.ap-northeast-3.amazonaws.com +webview-assets.aws-cloud9.ap-south-1.amazonaws.com +vfs.cloud9.ap-south-1.amazonaws.com +webview-assets.cloud9.ap-south-1.amazonaws.com +webview-assets.aws-cloud9.ap-southeast-1.amazonaws.com +vfs.cloud9.ap-southeast-1.amazonaws.com +webview-assets.cloud9.ap-southeast-1.amazonaws.com +webview-assets.aws-cloud9.ap-southeast-2.amazonaws.com +vfs.cloud9.ap-southeast-2.amazonaws.com +webview-assets.cloud9.ap-southeast-2.amazonaws.com +webview-assets.aws-cloud9.ca-central-1.amazonaws.com +vfs.cloud9.ca-central-1.amazonaws.com +webview-assets.cloud9.ca-central-1.amazonaws.com +webview-assets.aws-cloud9.eu-central-1.amazonaws.com +vfs.cloud9.eu-central-1.amazonaws.com +webview-assets.cloud9.eu-central-1.amazonaws.com +webview-assets.aws-cloud9.eu-north-1.amazonaws.com +vfs.cloud9.eu-north-1.amazonaws.com +webview-assets.cloud9.eu-north-1.amazonaws.com +webview-assets.aws-cloud9.eu-south-1.amazonaws.com +vfs.cloud9.eu-south-1.amazonaws.com +webview-assets.cloud9.eu-south-1.amazonaws.com +webview-assets.aws-cloud9.eu-west-1.amazonaws.com +vfs.cloud9.eu-west-1.amazonaws.com +webview-assets.cloud9.eu-west-1.amazonaws.com +webview-assets.aws-cloud9.eu-west-2.amazonaws.com +vfs.cloud9.eu-west-2.amazonaws.com +webview-assets.cloud9.eu-west-2.amazonaws.com +webview-assets.aws-cloud9.eu-west-3.amazonaws.com +vfs.cloud9.eu-west-3.amazonaws.com +webview-assets.cloud9.eu-west-3.amazonaws.com +webview-assets.aws-cloud9.me-south-1.amazonaws.com +vfs.cloud9.me-south-1.amazonaws.com +webview-assets.cloud9.me-south-1.amazonaws.com +webview-assets.aws-cloud9.sa-east-1.amazonaws.com +vfs.cloud9.sa-east-1.amazonaws.com +webview-assets.cloud9.sa-east-1.amazonaws.com +webview-assets.aws-cloud9.us-east-1.amazonaws.com +vfs.cloud9.us-east-1.amazonaws.com +webview-assets.cloud9.us-east-1.amazonaws.com +webview-assets.aws-cloud9.us-east-2.amazonaws.com +vfs.cloud9.us-east-2.amazonaws.com +webview-assets.cloud9.us-east-2.amazonaws.com +webview-assets.aws-cloud9.us-west-1.amazonaws.com +vfs.cloud9.us-west-1.amazonaws.com +webview-assets.cloud9.us-west-1.amazonaws.com +webview-assets.aws-cloud9.us-west-2.amazonaws.com +vfs.cloud9.us-west-2.amazonaws.com +webview-assets.cloud9.us-west-2.amazonaws.com + +// AWS Elastic Beanstalk +// Submitted by AWS Security +// Reference: bb5a965c-dec3-4967-aa22-e306ad064797 +cn-north-1.eb.amazonaws.com.cn +cn-northwest-1.eb.amazonaws.com.cn +elasticbeanstalk.com +af-south-1.elasticbeanstalk.com +ap-east-1.elasticbeanstalk.com +ap-northeast-1.elasticbeanstalk.com +ap-northeast-2.elasticbeanstalk.com +ap-northeast-3.elasticbeanstalk.com +ap-south-1.elasticbeanstalk.com +ap-southeast-1.elasticbeanstalk.com +ap-southeast-2.elasticbeanstalk.com +ap-southeast-3.elasticbeanstalk.com +ca-central-1.elasticbeanstalk.com +eu-central-1.elasticbeanstalk.com +eu-north-1.elasticbeanstalk.com +eu-south-1.elasticbeanstalk.com +eu-west-1.elasticbeanstalk.com +eu-west-2.elasticbeanstalk.com +eu-west-3.elasticbeanstalk.com +il-central-1.elasticbeanstalk.com +me-south-1.elasticbeanstalk.com +sa-east-1.elasticbeanstalk.com +us-east-1.elasticbeanstalk.com +us-east-2.elasticbeanstalk.com +us-gov-east-1.elasticbeanstalk.com +us-gov-west-1.elasticbeanstalk.com +us-west-1.elasticbeanstalk.com +us-west-2.elasticbeanstalk.com + +// (AWS) Elastic Load Balancing +// Submitted by Luke Wells +// Reference: 12a3d528-1bac-4433-a359-a395867ffed2 +*.elb.amazonaws.com.cn +*.elb.amazonaws.com + +// AWS Global Accelerator +// Submitted by Daniel Massaguer +// Reference: d916759d-a08b-4241-b536-4db887383a6a +awsglobalaccelerator.com + +// eero +// Submitted by Yue Kang +// Reference: 264afe70-f62c-4c02-8ab9-b5281ed24461 +eero.online +eero-stage.online + +// concludes Amazon + +// Amune : https://amune.org/ +// Submitted by Team Amune +t3l3p0rt.net +tele.amune.org + +// Apigee : https://apigee.com/ +// Submitted by Apigee Security Team +apigee.io + +// Apphud : https://apphud.com +// Submitted by Alexander Selivanov +siiites.com + +// Appspace : https://www.appspace.com +// Submitted by Appspace Security Team +appspacehosted.com +appspaceusercontent.com + +// Appudo UG (haftungsbeschränkt) : https://www.appudo.com +// Submitted by Alexander Hochbaum +appudo.net + +// Aptible : https://www.aptible.com/ +// Submitted by Thomas Orozco +on-aptible.com + +// ASEINet : https://www.aseinet.com/ +// Submitted by Asei SEKIGUCHI +user.aseinet.ne.jp +gv.vc +d.gv.vc + +// Asociación Amigos de la Informática "Euskalamiga" : http://encounter.eus/ +// Submitted by Hector Martin +user.party.eus + +// Association potager.org : https://potager.org/ +// Submitted by Lunar +pimienta.org +poivron.org +potager.org +sweetpepper.org + +// ASUSTOR Inc. : http://www.asustor.com +// Submitted by Vincent Tseng +myasustor.com + +// Atlassian : https://atlassian.com +// Submitted by Sam Smyth +cdn.prod.atlassian-dev.net + +// Authentick UG (haftungsbeschränkt) : https://authentick.net +// Submitted by Lukas Reschke +translated.page + +// Autocode : https://autocode.com +// Submitted by Jacob Lee +autocode.dev + +// AVM : https://avm.de +// Submitted by Andreas Weise +myfritz.net + +// AVStack Pte. Ltd. : https://avstack.io +// Submitted by Jasper Hugo +onavstack.net + +// AW AdvisorWebsites.com Software Inc : https://advisorwebsites.com +// Submitted by James Kennedy +*.awdev.ca +*.advisor.ws + +// AZ.pl sp. z.o.o: https://az.pl +// Submitted by Krzysztof Wolski +ecommerce-shop.pl + +// b-data GmbH : https://www.b-data.io +// Submitted by Olivier Benz +b-data.io + +// backplane : https://www.backplane.io +// Submitted by Anthony Voutas +backplaneapp.io + +// Balena : https://www.balena.io +// Submitted by Petros Angelatos +balena-devices.com + +// University of Banja Luka : https://unibl.org +// Domains for Republic of Srpska administrative entity. +// Submitted by Marko Ivanovic +rs.ba + +// Banzai Cloud +// Submitted by Janos Matyas +*.banzai.cloud +app.banzaicloud.io +*.backyards.banzaicloud.io + +// BASE, Inc. : https://binc.jp +// Submitted by Yuya NAGASAWA +base.ec +official.ec +buyshop.jp +fashionstore.jp +handcrafted.jp +kawaiishop.jp +supersale.jp +theshop.jp +shopselect.net +base.shop + +// BeagleBoard.org Foundation : https://beagleboard.org +// Submitted by Jason Kridner +beagleboard.io + +// Beget Ltd +// Submitted by Lev Nekrasov +*.beget.app + +// BetaInABox +// Submitted by Adrian +betainabox.com + +// BinaryLane : http://www.binarylane.com +// Submitted by Nathan O'Sullivan +bnr.la + +// Bitbucket : http://bitbucket.org +// Submitted by Andy Ortlieb +bitbucket.io + +// Blackbaud, Inc. : https://www.blackbaud.com +// Submitted by Paul Crowder +blackbaudcdn.net + +// Blatech : http://www.blatech.net +// Submitted by Luke Bratch +of.je + +// Blue Bite, LLC : https://bluebite.com +// Submitted by Joshua Weiss +bluebite.io + +// Boomla : https://boomla.com +// Submitted by Tibor Halter +boomla.net + +// Boutir : https://www.boutir.com +// Submitted by Eric Ng Ka Ka +boutir.com + +// Boxfuse : https://boxfuse.com +// Submitted by Axel Fontaine +boxfuse.io + +// bplaced : https://www.bplaced.net/ +// Submitted by Miroslav Bozic +square7.ch +bplaced.com +bplaced.de +square7.de +bplaced.net +square7.net + +// Brendly : https://brendly.rs +// Submitted by Dusan Radovanovic +shop.brendly.rs + +// BrowserSafetyMark +// Submitted by Dave Tharp +browsersafetymark.io + +// Bytemark Hosting : https://www.bytemark.co.uk +// Submitted by Paul Cammish +uk0.bigv.io +dh.bytemark.co.uk +vm.bytemark.co.uk + +// Caf.js Labs LLC : https://www.cafjs.com +// Submitted by Antonio Lain +cafjs.com + +// callidomus : https://www.callidomus.com/ +// Submitted by Marcus Popp +mycd.eu + +// Canva Pty Ltd : https://canva.com/ +// Submitted by Joel Aquilina +canva-apps.cn +canva-apps.com + +// Carrd : https://carrd.co +// Submitted by AJ +drr.ac +uwu.ai +carrd.co +crd.co +ju.mp + +// CentralNic : http://www.centralnic.com/names/domains +// Submitted by registry +ae.org +br.com +cn.com +com.de +com.se +de.com +eu.com +gb.net +hu.net +jp.net +jpn.com +mex.com +ru.com +sa.com +se.net +uk.com +uk.net +us.com +za.bz +za.com + +// No longer operated by CentralNic, these entries should be adopted and/or removed by current operators +// Submitted by Gavin Brown +ar.com +hu.com +kr.com +no.com +qc.com +uy.com + +// Africa.com Web Solutions Ltd : https://registry.africa.com +// Submitted by Gavin Brown +africa.com + +// iDOT Services Limited : http://www.domain.gr.com +// Submitted by Gavin Brown +gr.com + +// Radix FZC : http://domains.in.net +// Submitted by Gavin Brown +in.net +web.in + +// US REGISTRY LLC : http://us.org +// Submitted by Gavin Brown +us.org + +// co.com Registry, LLC : https://registry.co.com +// Submitted by Gavin Brown +co.com + +// Roar Domains LLC : https://roar.basketball/ +// Submitted by Gavin Brown +aus.basketball +nz.basketball + +// BRS Media : https://brsmedia.com/ +// Submitted by Gavin Brown +radio.am +radio.fm + +// c.la : http://www.c.la/ +c.la + +// certmgr.org : https://certmgr.org +// Submitted by B. Blechschmidt +certmgr.org + +// Cityhost LLC : https://cityhost.ua +// Submitted by Maksym Rivtin +cx.ua + +// Civilized Discourse Construction Kit, Inc. : https://www.discourse.org/ +// Submitted by Rishabh Nambiar & Michael Brown +discourse.group +discourse.team + +// Clever Cloud : https://www.clever-cloud.com/ +// Submitted by Quentin Adam +cleverapps.io + +// Clerk : https://www.clerk.dev +// Submitted by Colin Sidoti +clerk.app +clerkstage.app +*.lcl.dev +*.lclstage.dev +*.stg.dev +*.stgstage.dev + +// ClickRising : https://clickrising.com/ +// Submitted by Umut Gumeli +clickrising.net + +// Cloud66 : https://www.cloud66.com/ +// Submitted by Khash Sajadi +c66.me +cloud66.ws +cloud66.zone + +// CloudAccess.net : https://www.cloudaccess.net/ +// Submitted by Pawel Panek +jdevcloud.com +wpdevcloud.com +cloudaccess.host +freesite.host +cloudaccess.net + +// cloudControl : https://www.cloudcontrol.com/ +// Submitted by Tobias Wilken +cloudcontrolled.com +cloudcontrolapp.com + +// Cloudera, Inc. : https://www.cloudera.com/ +// Submitted by Kedarnath Waikar +*.cloudera.site + +// Cloudflare, Inc. : https://www.cloudflare.com/ +// Submitted by Cloudflare Team +cf-ipfs.com +cloudflare-ipfs.com +trycloudflare.com +pages.dev +r2.dev +workers.dev + +// Clovyr : https://clovyr.io +// Submitted by Patrick Nielsen +wnext.app + +// co.ca : http://registry.co.ca/ +co.ca + +// Co & Co : https://co-co.nl/ +// Submitted by Govert Versluis +*.otap.co + +// i-registry s.r.o. : http://www.i-registry.cz/ +// Submitted by Martin Semrad +co.cz + +// CDN77.com : http://www.cdn77.com +// Submitted by Jan Krpes +c.cdn77.org +cdn77-ssl.net +r.cdn77.net +rsc.cdn77.org +ssl.origin.cdn77-secure.org + +// Cloud DNS Ltd : http://www.cloudns.net +// Submitted by Aleksander Hristov +cloudns.asia +cloudns.biz +cloudns.club +cloudns.cc +cloudns.eu +cloudns.in +cloudns.info +cloudns.org +cloudns.pro +cloudns.pw +cloudns.us + +// CNPY : https://cnpy.gdn +// Submitted by Angelo Gladding +cnpy.gdn + +// Codeberg e. V. : https://codeberg.org +// Submitted by Moritz Marquardt +codeberg.page + +// CoDNS B.V. +co.nl +co.no + +// Combell.com : https://www.combell.com +// Submitted by Thomas Wouters +webhosting.be +hosting-cluster.nl + +// Coordination Center for TLD RU and XN--P1AI : https://cctld.ru/en/domains/domens_ru/reserved/ +// Submitted by George Georgievsky +ac.ru +edu.ru +gov.ru +int.ru +mil.ru +test.ru + +// COSIMO GmbH : http://www.cosimo.de +// Submitted by Rene Marticke +dyn.cosidns.de +dynamisches-dns.de +dnsupdater.de +internet-dns.de +l-o-g-i-n.de +dynamic-dns.info +feste-ip.net +knx-server.net +static-access.net + +// Craynic, s.r.o. : http://www.craynic.com/ +// Submitted by Ales Krajnik +realm.cz + +// Cryptonomic : https://cryptonomic.net/ +// Submitted by Andrew Cady +*.cryptonomic.net + +// Cupcake : https://cupcake.io/ +// Submitted by Jonathan Rudenberg +cupcake.is + +// Curv UG : https://curv-labs.de/ +// Submitted by Marvin Wiesner +curv.dev + +// Customer OCI - Oracle Dyn https://cloud.oracle.com/home https://dyn.com/dns/ +// Submitted by Gregory Drake +// Note: This is intended to also include customer-oci.com due to wildcards implicitly including the current label +*.customer-oci.com +*.oci.customer-oci.com +*.ocp.customer-oci.com +*.ocs.customer-oci.com + +// cyon GmbH : https://www.cyon.ch/ +// Submitted by Dominic Luechinger +cyon.link +cyon.site + +// Danger Science Group: https://dangerscience.com/ +// Submitted by Skylar MacDonald +fnwk.site +folionetwork.site +platform0.app + +// Daplie, Inc : https://daplie.com +// Submitted by AJ ONeal +daplie.me +localhost.daplie.me + +// Datto, Inc. : https://www.datto.com/ +// Submitted by Philipp Heckel +dattolocal.com +dattorelay.com +dattoweb.com +mydatto.com +dattolocal.net +mydatto.net + +// Dansk.net : http://www.dansk.net/ +// Submitted by Anani Voule +biz.dk +co.dk +firm.dk +reg.dk +store.dk + +// dappnode.io : https://dappnode.io/ +// Submitted by Abel Boldu / DAppNode Team +dyndns.dappnode.io + +// dapps.earth : https://dapps.earth/ +// Submitted by Daniil Burdakov +*.dapps.earth +*.bzz.dapps.earth + +// Dark, Inc. : https://darklang.com +// Submitted by Paul Biggar +builtwithdark.com + +// DataDetect, LLC. : https://datadetect.com +// Submitted by Andrew Banchich +demo.datadetect.com +instance.datadetect.com + +// Datawire, Inc : https://www.datawire.io +// Submitted by Richard Li +edgestack.me + +// DDNS5 : https://ddns5.com +// Submitted by Cameron Elliott +ddns5.com + +// Debian : https://www.debian.org/ +// Submitted by Peter Palfrader / Debian Sysadmin Team +debian.net + +// Deno Land Inc : https://deno.com/ +// Submitted by Luca Casonato +deno.dev +deno-staging.dev + +// deSEC : https://desec.io/ +// Submitted by Peter Thomassen +dedyn.io + +// Deta: https://www.deta.sh/ +// Submitted by Aavash Shrestha +deta.app +deta.dev + +// Diher Solutions : https://diher.solutions +// Submitted by Didi Hermawan +*.rss.my.id +*.diher.solutions + +// Discord Inc : https://discord.com +// Submitted by Sahn Lam +discordsays.com +discordsez.com + +// DNS Africa Ltd https://dns.business +// Submitted by Calvin Browne +jozi.biz + +// DNShome : https://www.dnshome.de/ +// Submitted by Norbert Auler +dnshome.de + +// DotArai : https://www.dotarai.com/ +// Submitted by Atsadawat Netcharadsang +online.th +shop.th + +// DrayTek Corp. : https://www.draytek.com/ +// Submitted by Paul Fang +drayddns.com + +// DreamCommerce : https://shoper.pl/ +// Submitted by Konrad Kotarba +shoparena.pl + +// DreamHost : http://www.dreamhost.com/ +// Submitted by Andrew Farmer +dreamhosters.com + +// Drobo : http://www.drobo.com/ +// Submitted by Ricardo Padilha +mydrobo.com + +// Drud Holdings, LLC. : https://www.drud.com/ +// Submitted by Kevin Bridges +drud.io +drud.us + +// DuckDNS : http://www.duckdns.org/ +// Submitted by Richard Harper +duckdns.org + +// Bip : https://bip.sh +// Submitted by Joel Kennedy +bip.sh + +// bitbridge.net : Submitted by Craig Welch, abeliidev@gmail.com +bitbridge.net + +// dy.fi : http://dy.fi/ +// Submitted by Heikki Hannikainen +dy.fi +tunk.org + +// DynDNS.com : http://www.dyndns.com/services/dns/dyndns/ +dyndns-at-home.com +dyndns-at-work.com +dyndns-blog.com +dyndns-free.com +dyndns-home.com +dyndns-ip.com +dyndns-mail.com +dyndns-office.com +dyndns-pics.com +dyndns-remote.com +dyndns-server.com +dyndns-web.com +dyndns-wiki.com +dyndns-work.com +dyndns.biz +dyndns.info +dyndns.org +dyndns.tv +at-band-camp.net +ath.cx +barrel-of-knowledge.info +barrell-of-knowledge.info +better-than.tv +blogdns.com +blogdns.net +blogdns.org +blogsite.org +boldlygoingnowhere.org +broke-it.net +buyshouses.net +cechire.com +dnsalias.com +dnsalias.net +dnsalias.org +dnsdojo.com +dnsdojo.net +dnsdojo.org +does-it.net +doesntexist.com +doesntexist.org +dontexist.com +dontexist.net +dontexist.org +doomdns.com +doomdns.org +dvrdns.org +dyn-o-saur.com +dynalias.com +dynalias.net +dynalias.org +dynathome.net +dyndns.ws +endofinternet.net +endofinternet.org +endoftheinternet.org +est-a-la-maison.com +est-a-la-masion.com +est-le-patron.com +est-mon-blogueur.com +for-better.biz +for-more.biz +for-our.info +for-some.biz +for-the.biz +forgot.her.name +forgot.his.name +from-ak.com +from-al.com +from-ar.com +from-az.net +from-ca.com +from-co.net +from-ct.com +from-dc.com +from-de.com +from-fl.com +from-ga.com +from-hi.com +from-ia.com +from-id.com +from-il.com +from-in.com +from-ks.com +from-ky.com +from-la.net +from-ma.com +from-md.com +from-me.org +from-mi.com +from-mn.com +from-mo.com +from-ms.com +from-mt.com +from-nc.com +from-nd.com +from-ne.com +from-nh.com +from-nj.com +from-nm.com +from-nv.com +from-ny.net +from-oh.com +from-ok.com +from-or.com +from-pa.com +from-pr.com +from-ri.com +from-sc.com +from-sd.com +from-tn.com +from-tx.com +from-ut.com +from-va.com +from-vt.com +from-wa.com +from-wi.com +from-wv.com +from-wy.com +ftpaccess.cc +fuettertdasnetz.de +game-host.org +game-server.cc +getmyip.com +gets-it.net +go.dyndns.org +gotdns.com +gotdns.org +groks-the.info +groks-this.info +ham-radio-op.net +here-for-more.info +hobby-site.com +hobby-site.org +home.dyndns.org +homedns.org +homeftp.net +homeftp.org +homeip.net +homelinux.com +homelinux.net +homelinux.org +homeunix.com +homeunix.net +homeunix.org +iamallama.com +in-the-band.net +is-a-anarchist.com +is-a-blogger.com +is-a-bookkeeper.com +is-a-bruinsfan.org +is-a-bulls-fan.com +is-a-candidate.org +is-a-caterer.com +is-a-celticsfan.org +is-a-chef.com +is-a-chef.net +is-a-chef.org +is-a-conservative.com +is-a-cpa.com +is-a-cubicle-slave.com +is-a-democrat.com +is-a-designer.com +is-a-doctor.com +is-a-financialadvisor.com +is-a-geek.com +is-a-geek.net +is-a-geek.org +is-a-green.com +is-a-guru.com +is-a-hard-worker.com +is-a-hunter.com +is-a-knight.org +is-a-landscaper.com +is-a-lawyer.com +is-a-liberal.com +is-a-libertarian.com +is-a-linux-user.org +is-a-llama.com +is-a-musician.com +is-a-nascarfan.com +is-a-nurse.com +is-a-painter.com +is-a-patsfan.org +is-a-personaltrainer.com +is-a-photographer.com +is-a-player.com +is-a-republican.com +is-a-rockstar.com +is-a-socialist.com +is-a-soxfan.org +is-a-student.com +is-a-teacher.com +is-a-techie.com +is-a-therapist.com +is-an-accountant.com +is-an-actor.com +is-an-actress.com +is-an-anarchist.com +is-an-artist.com +is-an-engineer.com +is-an-entertainer.com +is-by.us +is-certified.com +is-found.org +is-gone.com +is-into-anime.com +is-into-cars.com +is-into-cartoons.com +is-into-games.com +is-leet.com +is-lost.org +is-not-certified.com +is-saved.org +is-slick.com +is-uberleet.com +is-very-bad.org +is-very-evil.org +is-very-good.org +is-very-nice.org +is-very-sweet.org +is-with-theband.com +isa-geek.com +isa-geek.net +isa-geek.org +isa-hockeynut.com +issmarterthanyou.com +isteingeek.de +istmein.de +kicks-ass.net +kicks-ass.org +knowsitall.info +land-4-sale.us +lebtimnetz.de +leitungsen.de +likes-pie.com +likescandy.com +merseine.nu +mine.nu +misconfused.org +mypets.ws +myphotos.cc +neat-url.com +office-on-the.net +on-the-web.tv +podzone.net +podzone.org +readmyblog.org +saves-the-whales.com +scrapper-site.net +scrapping.cc +selfip.biz +selfip.com +selfip.info +selfip.net +selfip.org +sells-for-less.com +sells-for-u.com +sells-it.net +sellsyourhome.org +servebbs.com +servebbs.net +servebbs.org +serveftp.net +serveftp.org +servegame.org +shacknet.nu +simple-url.com +space-to-rent.com +stuff-4-sale.org +stuff-4-sale.us +teaches-yoga.com +thruhere.net +traeumtgerade.de +webhop.biz +webhop.info +webhop.net +webhop.org +worse-than.tv +writesthisblog.com + +// ddnss.de : https://www.ddnss.de/ +// Submitted by Robert Niedziela +ddnss.de +dyn.ddnss.de +dyndns.ddnss.de +dyndns1.de +dyn-ip24.de +home-webserver.de +dyn.home-webserver.de +myhome-server.de +ddnss.org + +// Definima : http://www.definima.com/ +// Submitted by Maxence Bitterli +definima.net +definima.io + +// DigitalOcean App Platform : https://www.digitalocean.com/products/app-platform/ +// Submitted by Braxton Huggins +ondigitalocean.app + +// DigitalOcean Spaces : https://www.digitalocean.com/products/spaces/ +// Submitted by Robin H. Johnson +*.digitaloceanspaces.com + +// dnstrace.pro : https://dnstrace.pro/ +// Submitted by Chris Partridge +bci.dnstrace.pro + +// Dynu.com : https://www.dynu.com/ +// Submitted by Sue Ye +ddnsfree.com +ddnsgeek.com +giize.com +gleeze.com +kozow.com +loseyourip.com +ooguy.com +theworkpc.com +casacam.net +dynu.net +accesscam.org +camdvr.org +freeddns.org +mywire.org +webredirect.org +myddns.rocks +blogsite.xyz + +// dynv6 : https://dynv6.com +// Submitted by Dominik Menke +dynv6.net + +// E4YOU spol. s.r.o. : https://e4you.cz/ +// Submitted by Vladimir Dudr +e4.cz + +// Easypanel : https://easypanel.io +// Submitted by Andrei Canta +easypanel.app +easypanel.host + +// Elementor : Elementor Ltd. +// Submitted by Anton Barkan +elementor.cloud +elementor.cool + +// En root‽ : https://en-root.org +// Submitted by Emmanuel Raviart +en-root.fr + +// Enalean SAS: https://www.enalean.com +// Submitted by Thomas Cottier +mytuleap.com +tuleap-partners.com + +// Encoretivity AB: https://encore.dev +// Submitted by André Eriksson +encr.app +encoreapi.com + +// ECG Robotics, Inc: https://ecgrobotics.org +// Submitted by +onred.one +staging.onred.one + +// encoway GmbH : https://www.encoway.de +// Submitted by Marcel Daus +eu.encoway.cloud + +// EU.org https://eu.org/ +// Submitted by Pierre Beyssac +eu.org +al.eu.org +asso.eu.org +at.eu.org +au.eu.org +be.eu.org +bg.eu.org +ca.eu.org +cd.eu.org +ch.eu.org +cn.eu.org +cy.eu.org +cz.eu.org +de.eu.org +dk.eu.org +edu.eu.org +ee.eu.org +es.eu.org +fi.eu.org +fr.eu.org +gr.eu.org +hr.eu.org +hu.eu.org +ie.eu.org +il.eu.org +in.eu.org +int.eu.org +is.eu.org +it.eu.org +jp.eu.org +kr.eu.org +lt.eu.org +lu.eu.org +lv.eu.org +mc.eu.org +me.eu.org +mk.eu.org +mt.eu.org +my.eu.org +net.eu.org +ng.eu.org +nl.eu.org +no.eu.org +nz.eu.org +paris.eu.org +pl.eu.org +pt.eu.org +q-a.eu.org +ro.eu.org +ru.eu.org +se.eu.org +si.eu.org +sk.eu.org +tr.eu.org +uk.eu.org +us.eu.org + +// Eurobyte : https://eurobyte.ru +// Submitted by Evgeniy Subbotin +eurodir.ru + +// Evennode : http://www.evennode.com/ +// Submitted by Michal Kralik +eu-1.evennode.com +eu-2.evennode.com +eu-3.evennode.com +eu-4.evennode.com +us-1.evennode.com +us-2.evennode.com +us-3.evennode.com +us-4.evennode.com + +// eDirect Corp. : https://hosting.url.com.tw/ +// Submitted by C.S. chang +twmail.cc +twmail.net +twmail.org +mymailer.com.tw +url.tw + +// Fabrica Technologies, Inc. : https://www.fabrica.dev/ +// Submitted by Eric Jiang +onfabrica.com + +// Facebook, Inc. +// Submitted by Peter Ruibal +apps.fbsbx.com + +// FAITID : https://faitid.org/ +// Submitted by Maxim Alzoba +// https://www.flexireg.net/stat_info +ru.net +adygeya.ru +bashkiria.ru +bir.ru +cbg.ru +com.ru +dagestan.ru +grozny.ru +kalmykia.ru +kustanai.ru +marine.ru +mordovia.ru +msk.ru +mytis.ru +nalchik.ru +nov.ru +pyatigorsk.ru +spb.ru +vladikavkaz.ru +vladimir.ru +abkhazia.su +adygeya.su +aktyubinsk.su +arkhangelsk.su +armenia.su +ashgabad.su +azerbaijan.su +balashov.su +bashkiria.su +bryansk.su +bukhara.su +chimkent.su +dagestan.su +east-kazakhstan.su +exnet.su +georgia.su +grozny.su +ivanovo.su +jambyl.su +kalmykia.su +kaluga.su +karacol.su +karaganda.su +karelia.su +khakassia.su +krasnodar.su +kurgan.su +kustanai.su +lenug.su +mangyshlak.su +mordovia.su +msk.su +murmansk.su +nalchik.su +navoi.su +north-kazakhstan.su +nov.su +obninsk.su +penza.su +pokrovsk.su +sochi.su +spb.su +tashkent.su +termez.su +togliatti.su +troitsk.su +tselinograd.su +tula.su +tuva.su +vladikavkaz.su +vladimir.su +vologda.su + +// Fancy Bits, LLC : http://getchannels.com +// Submitted by Aman Gupta +channelsdvr.net +u.channelsdvr.net + +// Fastly Inc. : http://www.fastly.com/ +// Submitted by Fastly Security +edgecompute.app +fastly-edge.com +fastly-terrarium.com +fastlylb.net +map.fastlylb.net +freetls.fastly.net +map.fastly.net +a.prod.fastly.net +global.prod.fastly.net +a.ssl.fastly.net +b.ssl.fastly.net +global.ssl.fastly.net + +// Fastmail : https://www.fastmail.com/ +// Submitted by Marc Bradshaw +*.user.fm + +// FASTVPS EESTI OU : https://fastvps.ru/ +// Submitted by Likhachev Vasiliy +fastvps-server.com +fastvps.host +myfast.host +fastvps.site +myfast.space + +// Fedora : https://fedoraproject.org/ +// submitted by Patrick Uiterwijk +fedorainfracloud.org +fedorapeople.org +cloud.fedoraproject.org +app.os.fedoraproject.org +app.os.stg.fedoraproject.org + +// FearWorks Media Ltd. : https://fearworksmedia.co.uk +// submitted by Keith Fairley +conn.uk +copro.uk +hosp.uk + +// Fermax : https://fermax.com/ +// submitted by Koen Van Isterdael +mydobiss.com + +// FH Muenster : https://www.fh-muenster.de +// Submitted by Robin Naundorf +fh-muenster.io + +// Filegear Inc. : https://www.filegear.com +// Submitted by Jason Zhu +filegear.me +filegear-au.me +filegear-de.me +filegear-gb.me +filegear-ie.me +filegear-jp.me +filegear-sg.me + +// Firebase, Inc. +// Submitted by Chris Raynor +firebaseapp.com + +// Firewebkit : https://www.firewebkit.com +// Submitted by Majid Qureshi +fireweb.app + +// FLAP : https://www.flap.cloud +// Submitted by Louis Chemineau +flap.id + +// FlashDrive : https://flashdrive.io +// Submitted by Eric Chan +onflashdrive.app +fldrv.com + +// fly.io: https://fly.io +// Submitted by Kurt Mackey +fly.dev +edgeapp.net +shw.io + +// Flynn : https://flynn.io +// Submitted by Jonathan Rudenberg +flynnhosting.net + +// Forgerock : https://www.forgerock.com +// Submitted by Roderick Parr +forgeblocks.com +id.forgerock.io + +// Framer : https://www.framer.com +// Submitted by Koen Rouwhorst +framer.app +framercanvas.com +framer.media +framer.photos +framer.website +framer.wiki + +// Frusky MEDIA&PR : https://www.frusky.de +// Submitted by Victor Pupynin +*.frusky.de + +// RavPage : https://www.ravpage.co.il +// Submitted by Roni Horowitz +ravpage.co.il + +// Frederik Braun https://frederik-braun.com +// Submitted by Frederik Braun +0e.vc + +// Freebox : http://www.freebox.fr +// Submitted by Romain Fliedel +freebox-os.com +freeboxos.com +fbx-os.fr +fbxos.fr +freebox-os.fr +freeboxos.fr + +// freedesktop.org : https://www.freedesktop.org +// Submitted by Daniel Stone +freedesktop.org + +// freemyip.com : https://freemyip.com +// Submitted by Cadence +freemyip.com + +// FunkFeuer - Verein zur Förderung freier Netze : https://www.funkfeuer.at +// Submitted by Daniel A. Maierhofer +wien.funkfeuer.at + +// Futureweb GmbH : https://www.futureweb.at +// Submitted by Andreas Schnederle-Wagner +*.futurecms.at +*.ex.futurecms.at +*.in.futurecms.at +futurehosting.at +futuremailing.at +*.ex.ortsinfo.at +*.kunden.ortsinfo.at +*.statics.cloud + +// GDS : https://www.gov.uk/service-manual/technology/managing-domain-names +// Submitted by Stephen Ford +independent-commission.uk +independent-inquest.uk +independent-inquiry.uk +independent-panel.uk +independent-review.uk +public-inquiry.uk +royal-commission.uk +campaign.gov.uk +service.gov.uk + +// CDDO : https://www.gov.uk/guidance/get-an-api-domain-on-govuk +// Submitted by Jamie Tanna +api.gov.uk + +// Gehirn Inc. : https://www.gehirn.co.jp/ +// Submitted by Kohei YOSHIDA +gehirn.ne.jp +usercontent.jp + +// Gentlent, Inc. : https://www.gentlent.com +// Submitted by Tom Klein +gentapps.com +gentlentapis.com +lab.ms +cdn-edges.net + +// Ghost Foundation : https://ghost.org +// Submitted by Matt Hanley +ghost.io + +// GignoSystemJapan: http://gsj.bz +// Submitted by GignoSystemJapan +gsj.bz + +// GitHub, Inc. +// Submitted by Patrick Toomey +githubusercontent.com +githubpreview.dev +github.io + +// GitLab, Inc. +// Submitted by Alex Hanselka +gitlab.io + +// Gitplac.si - https://gitplac.si +// Submitted by Aljaž Starc +gitapp.si +gitpage.si + +// Glitch, Inc : https://glitch.com +// Submitted by Mads Hartmann +glitch.me + +// Global NOG Alliance : https://nogalliance.org/ +// Submitted by Sander Steffann +nog.community + +// Globe Hosting SRL : https://www.globehosting.com/ +// Submitted by Gavin Brown +co.ro +shop.ro + +// GMO Pepabo, Inc. : https://pepabo.com/ +// Submitted by Hosting Div +lolipop.io +angry.jp +babyblue.jp +babymilk.jp +backdrop.jp +bambina.jp +bitter.jp +blush.jp +boo.jp +boy.jp +boyfriend.jp +but.jp +candypop.jp +capoo.jp +catfood.jp +cheap.jp +chicappa.jp +chillout.jp +chips.jp +chowder.jp +chu.jp +ciao.jp +cocotte.jp +coolblog.jp +cranky.jp +cutegirl.jp +daa.jp +deca.jp +deci.jp +digick.jp +egoism.jp +fakefur.jp +fem.jp +flier.jp +floppy.jp +fool.jp +frenchkiss.jp +girlfriend.jp +girly.jp +gloomy.jp +gonna.jp +greater.jp +hacca.jp +heavy.jp +her.jp +hiho.jp +hippy.jp +holy.jp +hungry.jp +icurus.jp +itigo.jp +jellybean.jp +kikirara.jp +kill.jp +kilo.jp +kuron.jp +littlestar.jp +lolipopmc.jp +lolitapunk.jp +lomo.jp +lovepop.jp +lovesick.jp +main.jp +mods.jp +mond.jp +mongolian.jp +moo.jp +namaste.jp +nikita.jp +nobushi.jp +noor.jp +oops.jp +parallel.jp +parasite.jp +pecori.jp +peewee.jp +penne.jp +pepper.jp +perma.jp +pigboat.jp +pinoko.jp +punyu.jp +pupu.jp +pussycat.jp +pya.jp +raindrop.jp +readymade.jp +sadist.jp +schoolbus.jp +secret.jp +staba.jp +stripper.jp +sub.jp +sunnyday.jp +thick.jp +tonkotsu.jp +under.jp +upper.jp +velvet.jp +verse.jp +versus.jp +vivian.jp +watson.jp +weblike.jp +whitesnow.jp +zombie.jp +heteml.net + +// GOV.UK Platform as a Service : https://www.cloud.service.gov.uk/ +// Submitted by Tom Whitwell +cloudapps.digital +london.cloudapps.digital + +// GOV.UK Pay : https://www.payments.service.gov.uk/ +// Submitted by Richard Baker +pymnt.uk + +// UKHomeOffice : https://www.gov.uk/government/organisations/home-office +// Submitted by Jon Shanks +homeoffice.gov.uk + +// GlobeHosting, Inc. +// Submitted by Zoltan Egresi +ro.im + +// GoIP DNS Services : http://www.goip.de +// Submitted by Christian Poulter +goip.de + +// Google, Inc. +// Submitted by Eduardo Vela +run.app +a.run.app +web.app +*.0emm.com +appspot.com +*.r.appspot.com +codespot.com +googleapis.com +googlecode.com +pagespeedmobilizer.com +publishproxy.com +withgoogle.com +withyoutube.com +*.gateway.dev +cloud.goog +translate.goog +*.usercontent.goog +cloudfunctions.net +blogspot.ae +blogspot.al +blogspot.am +blogspot.ba +blogspot.be +blogspot.bg +blogspot.bj +blogspot.ca +blogspot.cf +blogspot.ch +blogspot.cl +blogspot.co.at +blogspot.co.id +blogspot.co.il +blogspot.co.ke +blogspot.co.nz +blogspot.co.uk +blogspot.co.za +blogspot.com +blogspot.com.ar +blogspot.com.au +blogspot.com.br +blogspot.com.by +blogspot.com.co +blogspot.com.cy +blogspot.com.ee +blogspot.com.eg +blogspot.com.es +blogspot.com.mt +blogspot.com.ng +blogspot.com.tr +blogspot.com.uy +blogspot.cv +blogspot.cz +blogspot.de +blogspot.dk +blogspot.fi +blogspot.fr +blogspot.gr +blogspot.hk +blogspot.hr +blogspot.hu +blogspot.ie +blogspot.in +blogspot.is +blogspot.it +blogspot.jp +blogspot.kr +blogspot.li +blogspot.lt +blogspot.lu +blogspot.md +blogspot.mk +blogspot.mr +blogspot.mx +blogspot.my +blogspot.nl +blogspot.no +blogspot.pe +blogspot.pt +blogspot.qa +blogspot.re +blogspot.ro +blogspot.rs +blogspot.ru +blogspot.se +blogspot.sg +blogspot.si +blogspot.sk +blogspot.sn +blogspot.td +blogspot.tw +blogspot.ug +blogspot.vn + +// Goupile : https://goupile.fr +// Submitted by Niels Martignene +goupile.fr + +// Government of the Netherlands: https://www.government.nl +// Submitted by +gov.nl + +// Group 53, LLC : https://www.group53.com +// Submitted by Tyler Todd +awsmppl.com + +// GünstigBestellen : https://günstigbestellen.de +// Submitted by Furkan Akkoc +günstigbestellen.de +günstigliefern.de + +// Hakaran group: http://hakaran.cz +// Submitted by Arseniy Sokolov +fin.ci +free.hr +caa.li +ua.rs +conf.se + +// Handshake : https://handshake.org +// Submitted by Mike Damm +hs.zone +hs.run + +// Hashbang : https://hashbang.sh +hashbang.sh + +// Hasura : https://hasura.io +// Submitted by Shahidh K Muhammed +hasura.app +hasura-app.io + +// Heilbronn University of Applied Sciences - Faculty Informatics (GitLab Pages): https://www.hs-heilbronn.de +// Submitted by Richard Zowalla +pages.it.hs-heilbronn.de + +// Hepforge : https://www.hepforge.org +// Submitted by David Grellscheid +hepforge.org + +// Heroku : https://www.heroku.com/ +// Submitted by Tom Maher +herokuapp.com +herokussl.com + +// Hibernating Rhinos +// Submitted by Oren Eini +ravendb.cloud +ravendb.community +ravendb.me +development.run +ravendb.run + +// home.pl S.A.: https://home.pl +// Submitted by Krzysztof Wolski +homesklep.pl + +// Hong Kong Productivity Council: https://www.hkpc.org/ +// Submitted by SECaaS Team +secaas.hk + +// Hoplix : https://www.hoplix.com +// Submitted by Danilo De Franco +hoplix.shop + + +// HOSTBIP REGISTRY : https://www.hostbip.com/ +// Submitted by Atanunu Igbunuroghene +orx.biz +biz.gl +col.ng +firm.ng +gen.ng +ltd.ng +ngo.ng +edu.scot +sch.so + +// HostFly : https://www.ie.ua +// Submitted by Bohdan Dub +ie.ua + +// HostyHosting (hostyhosting.com) +hostyhosting.io + +// Häkkinen.fi +// Submitted by Eero Häkkinen +häkkinen.fi + +// Ici la Lune : http://www.icilalune.com/ +// Submitted by Simon Morvan +*.moonscale.io +moonscale.net + +// iki.fi +// Submitted by Hannu Aronsson +iki.fi + +// iliad italia: https://www.iliad.it +// Submitted by Marios Makassikis +ibxos.it +iliadboxos.it + +// Impertrix Solutions : +// Submitted by Zhixiang Zhao +impertrixcdn.com +impertrix.com + +// Incsub, LLC: https://incsub.com/ +// Submitted by Aaron Edwards +smushcdn.com +wphostedmail.com +wpmucdn.com +tempurl.host +wpmudev.host + +// Individual Network Berlin e.V. : https://www.in-berlin.de/ +// Submitted by Christian Seitz +dyn-berlin.de +in-berlin.de +in-brb.de +in-butter.de +in-dsl.de +in-dsl.net +in-dsl.org +in-vpn.de +in-vpn.net +in-vpn.org + +// info.at : http://www.info.at/ +biz.at +info.at + +// info.cx : http://info.cx +// Submitted by Jacob Slater +info.cx + +// Interlegis : http://www.interlegis.leg.br +// Submitted by Gabriel Ferreira +ac.leg.br +al.leg.br +am.leg.br +ap.leg.br +ba.leg.br +ce.leg.br +df.leg.br +es.leg.br +go.leg.br +ma.leg.br +mg.leg.br +ms.leg.br +mt.leg.br +pa.leg.br +pb.leg.br +pe.leg.br +pi.leg.br +pr.leg.br +rj.leg.br +rn.leg.br +ro.leg.br +rr.leg.br +rs.leg.br +sc.leg.br +se.leg.br +sp.leg.br +to.leg.br + +// intermetrics GmbH : https://pixolino.com/ +// Submitted by Wolfgang Schwarz +pixolino.com + +// Internet-Pro, LLP: https://netangels.ru/ +// Submitted by Vasiliy Sheredeko +na4u.ru + +// iopsys software solutions AB : https://iopsys.eu/ +// Submitted by Roman Azarenko +iopsys.se + +// IPiFony Systems, Inc. : https://www.ipifony.com/ +// Submitted by Matthew Hardeman +ipifony.net + +// IServ GmbH : https://iserv.de +// Submitted by Mario Hoberg +iservschule.de +mein-iserv.de +schulplattform.de +schulserver.de +test-iserv.de +iserv.dev + +// I-O DATA DEVICE, INC. : http://www.iodata.com/ +// Submitted by Yuji Minagawa +iobb.net + +// Jelastic, Inc. : https://jelastic.com/ +// Submitted by Ihor Kolodyuk +mel.cloudlets.com.au +cloud.interhostsolutions.be +mycloud.by +alp1.ae.flow.ch +appengine.flow.ch +es-1.axarnet.cloud +diadem.cloud +vip.jelastic.cloud +jele.cloud +it1.eur.aruba.jenv-aruba.cloud +it1.jenv-aruba.cloud +keliweb.cloud +cs.keliweb.cloud +oxa.cloud +tn.oxa.cloud +uk.oxa.cloud +primetel.cloud +uk.primetel.cloud +ca.reclaim.cloud +uk.reclaim.cloud +us.reclaim.cloud +ch.trendhosting.cloud +de.trendhosting.cloud +jele.club +amscompute.com +dopaas.com +paas.hosted-by-previder.com +rag-cloud.hosteur.com +rag-cloud-ch.hosteur.com +jcloud.ik-server.com +jcloud-ver-jpc.ik-server.com +demo.jelastic.com +kilatiron.com +paas.massivegrid.com +jed.wafaicloud.com +lon.wafaicloud.com +ryd.wafaicloud.com +j.scaleforce.com.cy +jelastic.dogado.eu +fi.cloudplatform.fi +demo.datacenter.fi +paas.datacenter.fi +jele.host +mircloud.host +paas.beebyte.io +sekd1.beebyteapp.io +jele.io +cloud-fr1.unispace.io +jc.neen.it +cloud.jelastic.open.tim.it +jcloud.kz +upaas.kazteleport.kz +cloudjiffy.net +fra1-de.cloudjiffy.net +west1-us.cloudjiffy.net +jls-sto1.elastx.net +jls-sto2.elastx.net +jls-sto3.elastx.net +faststacks.net +fr-1.paas.massivegrid.net +lon-1.paas.massivegrid.net +lon-2.paas.massivegrid.net +ny-1.paas.massivegrid.net +ny-2.paas.massivegrid.net +sg-1.paas.massivegrid.net +jelastic.saveincloud.net +nordeste-idc.saveincloud.net +j.scaleforce.net +jelastic.tsukaeru.net +sdscloud.pl +unicloud.pl +mircloud.ru +jelastic.regruhosting.ru +enscaled.sg +jele.site +jelastic.team +orangecloud.tn +j.layershift.co.uk +phx.enscaled.us +mircloud.us + +// Jino : https://www.jino.ru +// Submitted by Sergey Ulyashin +myjino.ru +*.hosting.myjino.ru +*.landing.myjino.ru +*.spectrum.myjino.ru +*.vps.myjino.ru + +// Jotelulu S.L. : https://jotelulu.com +// Submitted by Daniel Fariña +jotelulu.cloud + +// Joyent : https://www.joyent.com/ +// Submitted by Brian Bennett +*.triton.zone +*.cns.joyent.com + +// JS.ORG : http://dns.js.org +// Submitted by Stefan Keim +js.org + +// KaasHosting : http://www.kaashosting.nl/ +// Submitted by Wouter Bakker +kaas.gg +khplay.nl + +// Kakao : https://www.kakaocorp.com/ +// Submitted by JaeYoong Lee +ktistory.com + +// Kapsi : https://kapsi.fi +// Submitted by Tomi Juntunen +kapsi.fi + +// Keyweb AG : https://www.keyweb.de +// Submitted by Martin Dannehl +keymachine.de + +// KingHost : https://king.host +// Submitted by Felipe Keller Braz +kinghost.net +uni5.net + +// KnightPoint Systems, LLC : http://www.knightpoint.com/ +// Submitted by Roy Keene +knightpoint.systems + +// KoobinEvent, SL: https://www.koobin.com +// Submitted by Iván Oliva +koobin.events + +// KUROKU LTD : https://kuroku.ltd/ +// Submitted by DisposaBoy +oya.to + +// Katholieke Universiteit Leuven: https://www.kuleuven.be +// Submitted by Abuse KU Leuven +kuleuven.cloud +ezproxy.kuleuven.be + +// .KRD : http://nic.krd/data/krd/Registration%20Policy.pdf +co.krd +edu.krd + +// Krellian Ltd. : https://krellian.com +// Submitted by Ben Francis +krellian.net +webthings.io + +// LCube - Professional hosting e.K. : https://www.lcube-webhosting.de +// Submitted by Lars Laehn +git-repos.de +lcube-server.de +svn-repos.de + +// Leadpages : https://www.leadpages.net +// Submitted by Greg Dallavalle +leadpages.co +lpages.co +lpusercontent.com + +// Lelux.fi : https://lelux.fi/ +// Submitted by Lelux Admin +lelux.site + +// Lifetime Hosting : https://Lifetime.Hosting/ +// Submitted by Mike Fillator +co.business +co.education +co.events +co.financial +co.network +co.place +co.technology + +// Lightmaker Property Manager, Inc. : https://app.lmpm.com/ +// Submitted by Greg Holland +app.lmpm.com + +// linkyard ldt: https://www.linkyard.ch/ +// Submitted by Mario Siegenthaler +linkyard.cloud +linkyard-cloud.ch + +// Linode : https://linode.com +// Submitted by +members.linode.com +*.nodebalancer.linode.com +*.linodeobjects.com +ip.linodeusercontent.com + +// LiquidNet Ltd : http://www.liquidnetlimited.com/ +// Submitted by Victor Velchev +we.bs + +// Localcert : https://localcert.dev +// Submitted by Lann Martin +*.user.localcert.dev + +// localzone.xyz +// Submitted by Kenny Niehage +localzone.xyz + +// Log'in Line : https://www.loginline.com/ +// Submitted by Rémi Mach +loginline.app +loginline.dev +loginline.io +loginline.services +loginline.site + +// Lokalized : https://lokalized.nl +// Submitted by Noah Taheij +servers.run + +// Lõhmus Family, The +// Submitted by Heiki Lõhmus +lohmus.me + +// LubMAN UMCS Sp. z o.o : https://lubman.pl/ +// Submitted by Ireneusz Maliszewski +krasnik.pl +leczna.pl +lubartow.pl +lublin.pl +poniatowa.pl +swidnik.pl + +// Lug.org.uk : https://lug.org.uk +// Submitted by Jon Spriggs +glug.org.uk +lug.org.uk +lugs.org.uk + +// Lukanet Ltd : https://lukanet.com +// Submitted by Anton Avramov +barsy.bg +barsy.co.uk +barsyonline.co.uk +barsycenter.com +barsyonline.com +barsy.club +barsy.de +barsy.eu +barsy.in +barsy.info +barsy.io +barsy.me +barsy.menu +barsy.mobi +barsy.net +barsy.online +barsy.org +barsy.pro +barsy.pub +barsy.ro +barsy.shop +barsy.site +barsy.support +barsy.uk + +// Magento Commerce +// Submitted by Damien Tournoud +*.magentosite.cloud + +// May First - People Link : https://mayfirst.org/ +// Submitted by Jamie McClelland +mayfirst.info +mayfirst.org + +// Mail.Ru Group : https://hb.cldmail.ru +// Submitted by Ilya Zaretskiy +hb.cldmail.ru + +// Mail Transfer Platform : https://www.neupeer.com +// Submitted by Li Hui +cn.vu + +// Maze Play: https://www.mazeplay.com +// Submitted by Adam Humpherys +mazeplay.com + +// mcpe.me : https://mcpe.me +// Submitted by Noa Heyl +mcpe.me + +// McHost : https://mchost.ru +// Submitted by Evgeniy Subbotin +mcdir.me +mcdir.ru +mcpre.ru +vps.mcdir.ru + +// Mediatech : https://mediatech.by +// Submitted by Evgeniy Kozhuhovskiy +mediatech.by +mediatech.dev + +// Medicom Health : https://medicomhealth.com +// Submitted by Michael Olson +hra.health + +// Memset hosting : https://www.memset.com +// Submitted by Tom Whitwell +miniserver.com +memset.net + +// Messerli Informatik AG : https://www.messerli.ch/ +// Submitted by Ruben Schmidmeister +messerli.app + +// MetaCentrum, CESNET z.s.p.o. : https://www.metacentrum.cz/en/ +// Submitted by Zdeněk Šustr +*.cloud.metacentrum.cz +custom.metacentrum.cz + +// MetaCentrum, CESNET z.s.p.o. : https://www.metacentrum.cz/en/ +// Submitted by Radim Janča +flt.cloud.muni.cz +usr.cloud.muni.cz + +// Meteor Development Group : https://www.meteor.com/hosting +// Submitted by Pierre Carrier +meteorapp.com +eu.meteorapp.com + +// Michau Enterprises Limited : http://www.co.pl/ +co.pl + +// Microsoft Corporation : http://microsoft.com +// Submitted by Public Suffix List Admin +*.azurecontainer.io +azurewebsites.net +azure-mobile.net +cloudapp.net +azurestaticapps.net +1.azurestaticapps.net +2.azurestaticapps.net +3.azurestaticapps.net +4.azurestaticapps.net +5.azurestaticapps.net +6.azurestaticapps.net +7.azurestaticapps.net +centralus.azurestaticapps.net +eastasia.azurestaticapps.net +eastus2.azurestaticapps.net +westeurope.azurestaticapps.net +westus2.azurestaticapps.net + +// minion.systems : http://minion.systems +// Submitted by Robert Böttinger +csx.cc + +// Mintere : https://mintere.com/ +// Submitted by Ben Aubin +mintere.site + +// MobileEducation, LLC : https://joinforte.com +// Submitted by Grayson Martin +forte.id + +// Mozilla Corporation : https://mozilla.com +// Submitted by Ben Francis +mozilla-iot.org + +// Mozilla Foundation : https://mozilla.org/ +// Submitted by glob +bmoattachments.org + +// MSK-IX : https://www.msk-ix.ru/ +// Submitted by Khannanov Roman +net.ru +org.ru +pp.ru + +// Mythic Beasts : https://www.mythic-beasts.com +// Submitted by Paul Cammish +hostedpi.com +customer.mythic-beasts.com +caracal.mythic-beasts.com +fentiger.mythic-beasts.com +lynx.mythic-beasts.com +ocelot.mythic-beasts.com +oncilla.mythic-beasts.com +onza.mythic-beasts.com +sphinx.mythic-beasts.com +vs.mythic-beasts.com +x.mythic-beasts.com +yali.mythic-beasts.com +cust.retrosnub.co.uk + +// Nabu Casa : https://www.nabucasa.com +// Submitted by Paulus Schoutsen +ui.nabu.casa + +// Net at Work Gmbh : https://www.netatwork.de +// Submitted by Jan Jaeschke +cloud.nospamproxy.com + +// Netlify : https://www.netlify.com +// Submitted by Jessica Parsons +netlify.app + +// Neustar Inc. +// Submitted by Trung Tran +4u.com + +// ngrok : https://ngrok.com/ +// Submitted by Alan Shreve +ngrok.app +ngrok-free.app +ngrok.dev +ngrok-free.dev +ngrok.io +ap.ngrok.io +au.ngrok.io +eu.ngrok.io +in.ngrok.io +jp.ngrok.io +sa.ngrok.io +us.ngrok.io +ngrok.pizza + +// Nicolaus Copernicus University in Torun - MSK TORMAN (https://www.man.torun.pl) +torun.pl + +// Nimbus Hosting Ltd. : https://www.nimbushosting.co.uk/ +// Submitted by Nicholas Ford +nh-serv.co.uk + +// NFSN, Inc. : https://www.NearlyFreeSpeech.NET/ +// Submitted by Jeff Wheelhouse +nfshost.com + +// Noop : https://noop.app +// Submitted by Nathaniel Schweinberg +*.developer.app +noop.app + +// Northflank Ltd. : https://northflank.com/ +// Submitted by Marco Suter +*.northflank.app +*.build.run +*.code.run +*.database.run +*.migration.run + +// Noticeable : https://noticeable.io +// Submitted by Laurent Pellegrino +noticeable.news + +// Now-DNS : https://now-dns.com +// Submitted by Steve Russell +dnsking.ch +mypi.co +n4t.co +001www.com +ddnslive.com +myiphost.com +forumz.info +16-b.it +32-b.it +64-b.it +soundcast.me +tcp4.me +dnsup.net +hicam.net +now-dns.net +ownip.net +vpndns.net +dynserv.org +now-dns.org +x443.pw +now-dns.top +ntdll.top +freeddns.us +crafting.xyz +zapto.xyz + +// nsupdate.info : https://www.nsupdate.info/ +// Submitted by Thomas Waldmann +nsupdate.info +nerdpol.ovh + +// No-IP.com : https://noip.com/ +// Submitted by Deven Reza +blogsyte.com +brasilia.me +cable-modem.org +ciscofreak.com +collegefan.org +couchpotatofries.org +damnserver.com +ddns.me +ditchyourip.com +dnsfor.me +dnsiskinky.com +dvrcam.info +dynns.com +eating-organic.net +fantasyleague.cc +geekgalaxy.com +golffan.us +health-carereform.com +homesecuritymac.com +homesecuritypc.com +hopto.me +ilovecollege.info +loginto.me +mlbfan.org +mmafan.biz +myactivedirectory.com +mydissent.net +myeffect.net +mymediapc.net +mypsx.net +mysecuritycamera.com +mysecuritycamera.net +mysecuritycamera.org +net-freaks.com +nflfan.org +nhlfan.net +no-ip.ca +no-ip.co.uk +no-ip.net +noip.us +onthewifi.com +pgafan.net +point2this.com +pointto.us +privatizehealthinsurance.net +quicksytes.com +read-books.org +securitytactics.com +serveexchange.com +servehumour.com +servep2p.com +servesarcasm.com +stufftoread.com +ufcfan.org +unusualperson.com +workisboring.com +3utilities.com +bounceme.net +ddns.net +ddnsking.com +gotdns.ch +hopto.org +myftp.biz +myftp.org +myvnc.com +no-ip.biz +no-ip.info +no-ip.org +noip.me +redirectme.net +servebeer.com +serveblog.net +servecounterstrike.com +serveftp.com +servegame.com +servehalflife.com +servehttp.com +serveirc.com +serveminecraft.net +servemp3.com +servepics.com +servequake.com +sytes.net +webhop.me +zapto.org + +// NodeArt : https://nodeart.io +// Submitted by Konstantin Nosov +stage.nodeart.io + +// Nucleos Inc. : https://nucleos.com +// Submitted by Piotr Zduniak +pcloud.host + +// NYC.mn : http://www.information.nyc.mn +// Submitted by Matthew Brown +nyc.mn + +// Observable, Inc. : https://observablehq.com +// Submitted by Mike Bostock +static.observableusercontent.com + +// Octopodal Solutions, LLC. : https://ulterius.io/ +// Submitted by Andrew Sampson +cya.gg + +// OMG.LOL : +// Submitted by Adam Newbold +omg.lol + +// Omnibond Systems, LLC. : https://www.omnibond.com +// Submitted by Cole Estep +cloudycluster.net + +// OmniWe Limited: https://omniwe.com +// Submitted by Vicary Archangel +omniwe.site + +// One.com: https://www.one.com/ +// Submitted by Jacob Bunk Nielsen +123hjemmeside.dk +123hjemmeside.no +123homepage.it +123kotisivu.fi +123minsida.se +123miweb.es +123paginaweb.pt +123sait.ru +123siteweb.fr +123webseite.at +123webseite.de +123website.be +123website.ch +123website.lu +123website.nl +service.one +simplesite.com +simplesite.com.br +simplesite.gr +simplesite.pl + +// One Fold Media : http://www.onefoldmedia.com/ +// Submitted by Eddie Jones +nid.io + +// Open Social : https://www.getopensocial.com/ +// Submitted by Alexander Varwijk +opensocial.site + +// OpenCraft GmbH : http://opencraft.com/ +// Submitted by Sven Marnach +opencraft.hosting + +// OpenResearch GmbH: https://openresearch.com/ +// Submitted by Philipp Schmid +orsites.com + +// Opera Software, A.S.A. +// Submitted by Yngve Pettersen +operaunite.com + +// Orange : https://www.orange.com +// Submitted by Alexandre Linte +tech.orange + +// Oursky Limited : https://authgear.com/, https://skygear.io/ +// Submitted by Authgear Team , Skygear Developer +authgear-staging.com +authgearapps.com +skygearapp.com + +// OutSystems +// Submitted by Duarte Santos +outsystemscloud.com + +// OVHcloud: https://ovhcloud.com +// Submitted by Vincent Cassé +*.webpaas.ovh.net +*.hosting.ovh.net + +// OwnProvider GmbH: http://www.ownprovider.com +// Submitted by Jan Moennich +ownprovider.com +own.pm + +// OwO : https://whats-th.is/ +// Submitted by Dean Sheather +*.owo.codes + +// OX : http://www.ox.rs +// Submitted by Adam Grand +ox.rs + +// oy.lc +// Submitted by Charly Coste +oy.lc + +// Pagefog : https://pagefog.com/ +// Submitted by Derek Myers +pgfog.com + +// Pagefront : https://www.pagefronthq.com/ +// Submitted by Jason Kriss +pagefrontapp.com + +// PageXL : https://pagexl.com +// Submitted by Yann Guichard +pagexl.com + +// Paywhirl, Inc : https://paywhirl.com/ +// Submitted by Daniel Netzer +*.paywhirl.com + +// pcarrier.ca Software Inc: https://pcarrier.ca/ +// Submitted by Pierre Carrier +bar0.net +bar1.net +bar2.net +rdv.to + +// .pl domains (grandfathered) +art.pl +gliwice.pl +krakow.pl +poznan.pl +wroc.pl +zakopane.pl + +// Pantheon Systems, Inc. : https://pantheon.io/ +// Submitted by Gary Dylina +pantheonsite.io +gotpantheon.com + +// Peplink | Pepwave : http://peplink.com/ +// Submitted by Steve Leung +mypep.link + +// Perspecta : https://perspecta.com/ +// Submitted by Kenneth Van Alstyne +perspecta.cloud + +// PE Ulyanov Kirill Sergeevich : https://airy.host +// Submitted by Kirill Ulyanov +lk3.ru + +// Planet-Work : https://www.planet-work.com/ +// Submitted by Frédéric VANNIÈRE +on-web.fr + +// Platform.sh : https://platform.sh +// Submitted by Nikola Kotur +bc.platform.sh +ent.platform.sh +eu.platform.sh +us.platform.sh +*.platformsh.site +*.tst.site + +// Platter: https://platter.dev +// Submitted by Patrick Flor +platter-app.com +platter-app.dev +platterp.us + +// Plesk : https://www.plesk.com/ +// Submitted by Anton Akhtyamov +pdns.page +plesk.page +pleskns.com + +// Port53 : https://port53.io/ +// Submitted by Maximilian Schieder +dyn53.io + +// Porter : https://porter.run/ +// Submitted by Rudraksh MK +onporter.run + +// Positive Codes Technology Company : http://co.bn/faq.html +// Submitted by Zulfais +co.bn + +// Postman, Inc : https://postman.com +// Submitted by Rahul Dhawan +postman-echo.com +pstmn.io +mock.pstmn.io +httpbin.org + +//prequalifyme.today : https://prequalifyme.today +//Submitted by DeepakTiwari deepak@ivylead.io +prequalifyme.today + +// prgmr.com : https://prgmr.com/ +// Submitted by Sarah Newman +xen.prgmr.com + +// priv.at : http://www.nic.priv.at/ +// Submitted by registry +priv.at + +// privacytools.io : https://www.privacytools.io/ +// Submitted by Jonah Aragon +prvcy.page + +// Protocol Labs : https://protocol.ai/ +// Submitted by Michael Burns +*.dweb.link + +// Protonet GmbH : http://protonet.io +// Submitted by Martin Meier +protonet.io + +// Publication Presse Communication SARL : https://ppcom.fr +// Submitted by Yaacov Akiba Slama +chirurgiens-dentistes-en-france.fr +byen.site + +// pubtls.org: https://www.pubtls.org +// Submitted by Kor Nielsen +pubtls.org + +// PythonAnywhere LLP: https://www.pythonanywhere.com +// Submitted by Giles Thomas +pythonanywhere.com +eu.pythonanywhere.com + +// QOTO, Org. +// Submitted by Jeffrey Phillips Freeman +qoto.io + +// Qualifio : https://qualifio.com/ +// Submitted by Xavier De Cock +qualifioapp.com + +// Quality Unit: https://qualityunit.com +// Submitted by Vasyl Tsalko +ladesk.com + +// QuickBackend: https://www.quickbackend.com +// Submitted by Dani Biro +qbuser.com + +// Rad Web Hosting: https://radwebhosting.com +// Submitted by Scott Claeys +cloudsite.builders + +// Redgate Software: https://red-gate.com +// Submitted by Andrew Farries +instances.spawn.cc + +// Redstar Consultants : https://www.redstarconsultants.com/ +// Submitted by Jons Slemmer +instantcloud.cn + +// Russian Academy of Sciences +// Submitted by Tech Support +ras.ru + +// QA2 +// Submitted by Daniel Dent (https://www.danieldent.com/) +qa2.com + +// QCX +// Submitted by Cassandra Beelen +qcx.io +*.sys.qcx.io + +// QNAP System Inc : https://www.qnap.com +// Submitted by Nick Chang +dev-myqnapcloud.com +alpha-myqnapcloud.com +myqnapcloud.com + +// Quip : https://quip.com +// Submitted by Patrick Linehan +*.quipelements.com + +// Qutheory LLC : http://qutheory.io +// Submitted by Jonas Schwartz +vapor.cloud +vaporcloud.io + +// Rackmaze LLC : https://www.rackmaze.com +// Submitted by Kirill Pertsev +rackmaze.com +rackmaze.net + +// Rakuten Games, Inc : https://dev.viberplay.io +// Submitted by Joshua Zhang +g.vbrplsbx.io + +// Rancher Labs, Inc : https://rancher.com +// Submitted by Vincent Fiduccia +*.on-k3s.io +*.on-rancher.cloud +*.on-rio.io + +// Read The Docs, Inc : https://www.readthedocs.org +// Submitted by David Fischer +readthedocs.io + +// Red Hat, Inc. OpenShift : https://openshift.redhat.com/ +// Submitted by Tim Kramer +rhcloud.com + +// Render : https://render.com +// Submitted by Anurag Goel +app.render.com +onrender.com + +// Repl.it : https://repl.it +// Submitted by Lincoln Bergeson +firewalledreplit.co +id.firewalledreplit.co +repl.co +id.repl.co +repl.run + +// Resin.io : https://resin.io +// Submitted by Tim Perry +resindevice.io +devices.resinstaging.io + +// RethinkDB : https://www.rethinkdb.com/ +// Submitted by Chris Kastorff +hzc.io + +// Revitalised Limited : http://www.revitalised.co.uk +// Submitted by Jack Price +wellbeingzone.eu +wellbeingzone.co.uk + +// Rico Developments Limited : https://adimo.co +// Submitted by Colin Brown +adimo.co.uk + +// Riseup Networks : https://riseup.net +// Submitted by Micah Anderson +itcouldbewor.se + +// Rochester Institute of Technology : http://www.rit.edu/ +// Submitted by Jennifer Herting +git-pages.rit.edu + +// Rocky Enterprise Software Foundation : https://resf.org +// Submitted by Neil Hanlon +rocky.page + +// Rusnames Limited: http://rusnames.ru/ +// Submitted by Sergey Zotov +биз.рус +ком.рус +крым.рус +мир.рус +мск.рус +орг.рус +самара.рус +сочи.рус +спб.рус +я.рус + +// SAKURA Internet Inc. : https://www.sakura.ad.jp/ +// Submitted by Internet Service Department +180r.com +dojin.com +sakuratan.com +sakuraweb.com +x0.com +2-d.jp +bona.jp +crap.jp +daynight.jp +eek.jp +flop.jp +halfmoon.jp +jeez.jp +matrix.jp +mimoza.jp +ivory.ne.jp +mail-box.ne.jp +mints.ne.jp +mokuren.ne.jp +opal.ne.jp +sakura.ne.jp +sumomo.ne.jp +topaz.ne.jp +netgamers.jp +nyanta.jp +o0o0.jp +rdy.jp +rgr.jp +rulez.jp +s3.isk01.sakurastorage.jp +s3.isk02.sakurastorage.jp +saloon.jp +sblo.jp +skr.jp +tank.jp +uh-oh.jp +undo.jp +rs.webaccel.jp +user.webaccel.jp +websozai.jp +xii.jp +squares.net +jpn.org +kirara.st +x0.to +from.tv +sakura.tv + +// Salesforce.com, Inc. https://salesforce.com/ +// Submitted by Michael Biven +*.builder.code.com +*.dev-builder.code.com +*.stg-builder.code.com + +// Sandstorm Development Group, Inc. : https://sandcats.io/ +// Submitted by Asheesh Laroia +sandcats.io + +// SBE network solutions GmbH : https://www.sbe.de/ +// Submitted by Norman Meilick +logoip.de +logoip.com + +// Scaleway : https://www.scaleway.com/ +// Submitted by Rémy Léone +fr-par-1.baremetal.scw.cloud +fr-par-2.baremetal.scw.cloud +nl-ams-1.baremetal.scw.cloud +fnc.fr-par.scw.cloud +functions.fnc.fr-par.scw.cloud +k8s.fr-par.scw.cloud +nodes.k8s.fr-par.scw.cloud +s3.fr-par.scw.cloud +s3-website.fr-par.scw.cloud +whm.fr-par.scw.cloud +priv.instances.scw.cloud +pub.instances.scw.cloud +k8s.scw.cloud +k8s.nl-ams.scw.cloud +nodes.k8s.nl-ams.scw.cloud +s3.nl-ams.scw.cloud +s3-website.nl-ams.scw.cloud +whm.nl-ams.scw.cloud +k8s.pl-waw.scw.cloud +nodes.k8s.pl-waw.scw.cloud +s3.pl-waw.scw.cloud +s3-website.pl-waw.scw.cloud +scalebook.scw.cloud +smartlabeling.scw.cloud +dedibox.fr + +// schokokeks.org GbR : https://schokokeks.org/ +// Submitted by Hanno Böck +schokokeks.net + +// Scottish Government: https://www.gov.scot +// Submitted by Martin Ellis +gov.scot +service.gov.scot + +// Scry Security : http://www.scrysec.com +// Submitted by Shante Adam +scrysec.com + +// Securepoint GmbH : https://www.securepoint.de +// Submitted by Erik Anders +firewall-gateway.com +firewall-gateway.de +my-gateway.de +my-router.de +spdns.de +spdns.eu +firewall-gateway.net +my-firewall.org +myfirewall.org +spdns.org + +// Seidat : https://www.seidat.com +// Submitted by Artem Kondratev +seidat.net + +// Sellfy : https://sellfy.com +// Submitted by Yuriy Romadin +sellfy.store + +// Senseering GmbH : https://www.senseering.de +// Submitted by Felix Mönckemeyer +senseering.net + +// Sendmsg: https://www.sendmsg.co.il +// Submitted by Assaf Stern +minisite.ms + +// Service Magnet : https://myservicemagnet.com +// Submitted by Dave Sanders +magnet.page + +// Service Online LLC : http://drs.ua/ +// Submitted by Serhii Bulakh +biz.ua +co.ua +pp.ua + +// Shift Crypto AG : https://shiftcrypto.ch +// Submitted by alex +shiftcrypto.dev +shiftcrypto.io + +// ShiftEdit : https://shiftedit.net/ +// Submitted by Adam Jimenez +shiftedit.io + +// Shopblocks : http://www.shopblocks.com/ +// Submitted by Alex Bowers +myshopblocks.com + +// Shopify : https://www.shopify.com +// Submitted by Alex Richter +myshopify.com + +// Shopit : https://www.shopitcommerce.com/ +// Submitted by Craig McMahon +shopitsite.com + +// shopware AG : https://shopware.com +// Submitted by Jens Küper +shopware.store + +// Siemens Mobility GmbH +// Submitted by Oliver Graebner +mo-siemens.io + +// SinaAppEngine : http://sae.sina.com.cn/ +// Submitted by SinaAppEngine +1kapp.com +appchizi.com +applinzi.com +sinaapp.com +vipsinaapp.com + +// Siteleaf : https://www.siteleaf.com/ +// Submitted by Skylar Challand +siteleaf.net + +// Skyhat : http://www.skyhat.io +// Submitted by Shante Adam +bounty-full.com +alpha.bounty-full.com +beta.bounty-full.com + +// Smallregistry by Promopixel SARL: https://www.smallregistry.net +// Former AFNIC's SLDs +// Submitted by Jérôme Lipowicz +aeroport.fr +avocat.fr +chambagri.fr +chirurgiens-dentistes.fr +experts-comptables.fr +medecin.fr +notaires.fr +pharmacien.fr +port.fr +veterinaire.fr + +// Small Technology Foundation : https://small-tech.org +// Submitted by Aral Balkan +small-web.org + +// Smoove.io : https://www.smoove.io/ +// Submitted by Dan Kozak +vp4.me + +// Snowflake Inc : https://www.snowflake.com/ +// Submitted by Faith Olapade +snowflake.app +privatelink.snowflake.app +streamlit.app +streamlitapp.com + +// Snowplow Analytics : https://snowplowanalytics.com/ +// Submitted by Ian Streeter +try-snowplow.com + +// SourceHut : https://sourcehut.org +// Submitted by Drew DeVault +srht.site + +// Stackhero : https://www.stackhero.io +// Submitted by Adrien Gillon +stackhero-network.com + +// Staclar : https://staclar.com +// Submitted by Q Misell +musician.io +// Submitted by Matthias Merkel +novecore.site + +// staticland : https://static.land +// Submitted by Seth Vincent +static.land +dev.static.land +sites.static.land + +// Storebase : https://www.storebase.io +// Submitted by Tony Schirmer +storebase.store + +// Strategic System Consulting (eApps Hosting): https://www.eapps.com/ +// Submitted by Alex Oancea +vps-host.net +atl.jelastic.vps-host.net +njs.jelastic.vps-host.net +ric.jelastic.vps-host.net + +// Sony Interactive Entertainment LLC : https://sie.com/ +// Submitted by David Coles +playstation-cloud.com + +// SourceLair PC : https://www.sourcelair.com +// Submitted by Antonis Kalipetis +apps.lair.io +*.stolos.io + +// SpaceKit : https://www.spacekit.io/ +// Submitted by Reza Akhavan +spacekit.io + +// SpeedPartner GmbH: https://www.speedpartner.de/ +// Submitted by Stefan Neufeind +customer.speedpartner.de + +// Spreadshop (sprd.net AG) : https://www.spreadshop.com/ +// Submitted by Martin Breest +myspreadshop.at +myspreadshop.com.au +myspreadshop.be +myspreadshop.ca +myspreadshop.ch +myspreadshop.com +myspreadshop.de +myspreadshop.dk +myspreadshop.es +myspreadshop.fi +myspreadshop.fr +myspreadshop.ie +myspreadshop.it +myspreadshop.net +myspreadshop.nl +myspreadshop.no +myspreadshop.pl +myspreadshop.se +myspreadshop.co.uk + +// Standard Library : https://stdlib.com +// Submitted by Jacob Lee +api.stdlib.com + +// Storipress : https://storipress.com +// Submitted by Benno Liu +storipress.app + +// Storj Labs Inc. : https://storj.io/ +// Submitted by Philip Hutchins +storj.farm + +// Studenten Net Twente : http://www.snt.utwente.nl/ +// Submitted by Silke Hofstra +utwente.io + +// Student-Run Computing Facility : https://www.srcf.net/ +// Submitted by Edwin Balani +soc.srcf.net +user.srcf.net + +// Sub 6 Limited: http://www.sub6.com +// Submitted by Dan Miller +temp-dns.com + +// Supabase : https://supabase.io +// Submitted by Inian Parameshwaran +supabase.co +supabase.in +supabase.net +su.paba.se + +// Symfony, SAS : https://symfony.com/ +// Submitted by Fabien Potencier +*.s5y.io +*.sensiosite.cloud + +// Syncloud : https://syncloud.org +// Submitted by Boris Rybalkin +syncloud.it + +// Synology, Inc. : https://www.synology.com/ +// Submitted by Rony Weng +dscloud.biz +direct.quickconnect.cn +dsmynas.com +familyds.com +diskstation.me +dscloud.me +i234.me +myds.me +synology.me +dscloud.mobi +dsmynas.net +familyds.net +dsmynas.org +familyds.org +vpnplus.to +direct.quickconnect.to + +// Tabit Technologies Ltd. : https://tabit.cloud/ +// Submitted by Oren Agiv +tabitorder.co.il +mytabit.co.il +mytabit.com + +// TAIFUN Software AG : http://taifun-software.de +// Submitted by Bjoern Henke +taifun-dns.de + +// Tailscale Inc. : https://www.tailscale.com +// Submitted by David Anderson +beta.tailscale.net +ts.net + +// TASK geographical domains (www.task.gda.pl/uslugi/dns) +gda.pl +gdansk.pl +gdynia.pl +med.pl +sopot.pl + +// team.blue https://team.blue +// Submitted by Cedric Dubois +site.tb-hosting.com + +// Teckids e.V. : https://www.teckids.org +// Submitted by Dominik George +edugit.io +s3.teckids.org + +// Telebit : https://telebit.cloud +// Submitted by AJ ONeal +telebit.app +telebit.io +*.telebit.xyz + +// Thingdust AG : https://thingdust.com/ +// Submitted by Adrian Imboden +*.firenet.ch +*.svc.firenet.ch +reservd.com +thingdustdata.com +cust.dev.thingdust.io +cust.disrec.thingdust.io +cust.prod.thingdust.io +cust.testing.thingdust.io +reservd.dev.thingdust.io +reservd.disrec.thingdust.io +reservd.testing.thingdust.io + +// ticket i/O GmbH : https://ticket.io +// Submitted by Christian Franke +tickets.io + +// Tlon.io : https://tlon.io +// Submitted by Mark Staarink +arvo.network +azimuth.network +tlon.network + +// Tor Project, Inc. : https://torproject.org +// Submitted by Antoine Beaupré +bloxcms.com +townnews-staging.com + +// TrafficPlex GmbH : https://www.trafficplex.de/ +// Submitted by Phillipp Röll +12hp.at +2ix.at +4lima.at +lima-city.at +12hp.ch +2ix.ch +4lima.ch +lima-city.ch +trafficplex.cloud +de.cool +12hp.de +2ix.de +4lima.de +lima-city.de +1337.pictures +clan.rip +lima-city.rocks +webspace.rocks +lima.zone + +// TransIP : https://www.transip.nl +// Submitted by Rory Breuk +*.transurl.be +*.transurl.eu +*.transurl.nl + +// TransIP: https://www.transip.nl +// Submitted by Cedric Dubois +site.transip.me + +// TuxFamily : http://tuxfamily.org +// Submitted by TuxFamily administrators +tuxfamily.org + +// TwoDNS : https://www.twodns.de/ +// Submitted by TwoDNS-Support +dd-dns.de +diskstation.eu +diskstation.org +dray-dns.de +draydns.de +dyn-vpn.de +dynvpn.de +mein-vigor.de +my-vigor.de +my-wan.de +syno-ds.de +synology-diskstation.de +synology-ds.de + +// Typedream : https://typedream.com +// Submitted by Putri Karunia +typedream.app + +// Typeform : https://www.typeform.com +// Submitted by Sergi Ferriz +pro.typeform.com + +// Uberspace : https://uberspace.de +// Submitted by Moritz Werner +uber.space +*.uberspace.de + +// UDR Limited : http://www.udr.hk.com +// Submitted by registry +hk.com +hk.org +ltd.hk +inc.hk + +// UK Intis Telecom LTD : https://it.com +// Submitted by ITComdomains +it.com + +// UNIVERSAL DOMAIN REGISTRY : https://www.udr.org.yt/ +// see also: whois -h whois.udr.org.yt help +// Submitted by Atanunu Igbunuroghene +name.pm +sch.tf +biz.wf +sch.wf +org.yt + +// United Gameserver GmbH : https://united-gameserver.de +// Submitted by Stefan Schwarz +virtualuser.de +virtual-user.de + +// Upli : https://upli.io +// Submitted by Lenny Bakkalian +upli.io + +// urown.net : https://urown.net +// Submitted by Hostmaster +urown.cloud +dnsupdate.info + +// .US +// Submitted by Ed Moore +lib.de.us + +// VeryPositive SIA : http://very.lv +// Submitted by Danko Aleksejevs +2038.io + +// Vercel, Inc : https://vercel.com/ +// Submitted by Connor Davis +vercel.app +vercel.dev +now.sh + +// Viprinet Europe GmbH : http://www.viprinet.com +// Submitted by Simon Kissel +router.management + +// Virtual-Info : https://www.virtual-info.info/ +// Submitted by Adnan RIHAN +v-info.info + +// Voorloper.com: https://voorloper.com +// Submitted by Nathan van Bakel +voorloper.cloud + +// Voxel.sh DNS : https://voxel.sh/dns/ +// Submitted by Mia Rehlinger +neko.am +nyaa.am +be.ax +cat.ax +es.ax +eu.ax +gg.ax +mc.ax +us.ax +xy.ax +nl.ci +xx.gl +app.gp +blog.gt +de.gt +to.gt +be.gy +cc.hn +blog.kg +io.kg +jp.kg +tv.kg +uk.kg +us.kg +de.ls +at.md +de.md +jp.md +to.md +indie.porn +vxl.sh +ch.tc +me.tc +we.tc +nyan.to +at.vg +blog.vu +dev.vu +me.vu + +// V.UA Domain Administrator : https://domain.v.ua/ +// Submitted by Serhii Rostilo +v.ua + +// Vultr Objects : https://www.vultr.com/products/object-storage/ +// Submitted by Niels Maumenee +*.vultrobjects.com + +// Waffle Computer Inc., Ltd. : https://docs.waffleinfo.com +// Submitted by Masayuki Note +wafflecell.com + +// WebHare bv: https://www.webhare.com/ +// Submitted by Arnold Hendriks +*.webhare.dev + +// WebHotelier Technologies Ltd: https://www.webhotelier.net/ +// Submitted by Apostolos Tsakpinis +reserve-online.net +reserve-online.com +bookonline.app +hotelwithflight.com + +// WeDeploy by Liferay, Inc. : https://www.wedeploy.com +// Submitted by Henrique Vicente +wedeploy.io +wedeploy.me +wedeploy.sh + +// Western Digital Technologies, Inc : https://www.wdc.com +// Submitted by Jung Jin +remotewd.com + +// WIARD Enterprises : https://wiardweb.com +// Submitted by Kidd Hustle +pages.wiardweb.com + +// Wikimedia Labs : https://wikitech.wikimedia.org +// Submitted by Arturo Borrero Gonzalez +wmflabs.org +toolforge.org +wmcloud.org + +// WISP : https://wisp.gg +// Submitted by Stepan Fedotov +panel.gg +daemon.panel.gg + +// Wizard Zines : https://wizardzines.com +// Submitted by Julia Evans +messwithdns.com + +// WoltLab GmbH : https://www.woltlab.com +// Submitted by Tim Düsterhus +woltlab-demo.com +myforum.community +community-pro.de +diskussionsbereich.de +community-pro.net +meinforum.net + +// Woods Valldata : https://www.woodsvalldata.co.uk/ +// Submitted by Chris Whittle +affinitylottery.org.uk +raffleentry.org.uk +weeklylottery.org.uk + +// WP Engine : https://wpengine.com/ +// Submitted by Michael Smith +// Submitted by Brandon DuRette +wpenginepowered.com +js.wpenginepowered.com + +// Wix.com, Inc. : https://www.wix.com +// Submitted by Shahar Talmi +wixsite.com +editorx.io +wixstudio.io +wix.run + +// XenonCloud GbR: https://xenoncloud.net +// Submitted by Julian Uphoff +half.host + +// XnBay Technology : http://www.xnbay.com/ +// Submitted by XnBay Developer +xnbay.com +u2.xnbay.com +u2-local.xnbay.com + +// XS4ALL Internet bv : https://www.xs4all.nl/ +// Submitted by Daniel Mostertman +cistron.nl +demon.nl +xs4all.space + +// Yandex.Cloud LLC: https://cloud.yandex.com +// Submitted by Alexander Lodin +yandexcloud.net +storage.yandexcloud.net +website.yandexcloud.net + +// YesCourse Pty Ltd : https://yescourse.com +// Submitted by Atul Bhouraskar +official.academy + +// Yola : https://www.yola.com/ +// Submitted by Stefano Rivera +yolasite.com + +// Yombo : https://yombo.net +// Submitted by Mitch Schwenk +ybo.faith +yombo.me +homelink.one +ybo.party +ybo.review +ybo.science +ybo.trade + +// Yunohost : https://yunohost.org +// Submitted by Valentin Grimaud +ynh.fr +nohost.me +noho.st + +// ZaNiC : http://www.za.net/ +// Submitted by registry +za.net +za.org + +// Zine EOOD : https://zine.bg/ +// Submitted by Martin Angelov +bss.design + +// Zitcom A/S : https://www.zitcom.dk +// Submitted by Emil Stahl +basicserver.io +virtualserver.io +enterprisecloud.nu + +// ===END PRIVATE DOMAINS=== diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/public_suffix-5.0.4/lib/public_suffix.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/public_suffix-5.0.4/lib/public_suffix.rb new file mode 100644 index 0000000000..b36dfbe7f6 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/public_suffix-5.0.4/lib/public_suffix.rb @@ -0,0 +1,177 @@ +# frozen_string_literal: true + +# = Public Suffix +# +# Domain name parser based on the Public Suffix List. +# +# Copyright (c) 2009-2023 Simone Carletti + +require_relative "public_suffix/domain" +require_relative "public_suffix/version" +require_relative "public_suffix/errors" +require_relative "public_suffix/rule" +require_relative "public_suffix/list" + +# PublicSuffix is a Ruby domain name parser based on the Public Suffix List. +# +# The [Public Suffix List](https://publicsuffix.org) is a cross-vendor initiative +# to provide an accurate list of domain name suffixes. +# +# The Public Suffix List is an initiative of the Mozilla Project, +# but is maintained as a community resource. It is available for use in any software, +# but was originally created to meet the needs of browser manufacturers. +module PublicSuffix + + DOT = "." + BANG = "!" + STAR = "*" + + # Parses +name+ and returns the {PublicSuffix::Domain} instance. + # + # @example Parse a valid domain + # PublicSuffix.parse("google.com") + # # => # + # + # @example Parse a valid subdomain + # PublicSuffix.parse("www.google.com") + # # => # + # + # @example Parse a fully qualified domain + # PublicSuffix.parse("google.com.") + # # => # + # + # @example Parse a fully qualified domain (subdomain) + # PublicSuffix.parse("www.google.com.") + # # => # + # + # @example Parse an invalid (unlisted) domain + # PublicSuffix.parse("x.yz") + # # => # + # + # @example Parse an invalid (unlisted) domain with strict checking (without applying the default * rule) + # PublicSuffix.parse("x.yz", default_rule: nil) + # # => PublicSuffix::DomainInvalid: `x.yz` is not a valid domain + # + # @example Parse an URL (not supported, only domains) + # PublicSuffix.parse("http://www.google.com") + # # => PublicSuffix::DomainInvalid: http://www.google.com is not expected to contain a scheme + # + # + # @param name [#to_s] The domain name or fully qualified domain name to parse. + # @param list [PublicSuffix::List] The rule list to search, defaults to the default {PublicSuffix::List} + # @param ignore_private [Boolean] + # @return [PublicSuffix::Domain] + # + # @raise [PublicSuffix::DomainInvalid] If domain is not a valid domain. + # @raise [PublicSuffix::DomainNotAllowed] If a rule for +domain+ is found, but the rule doesn't allow +domain+. + def self.parse(name, list: List.default, default_rule: list.default_rule, ignore_private: false) + what = normalize(name) + raise what if what.is_a?(DomainInvalid) + + rule = list.find(what, default: default_rule, ignore_private: ignore_private) + + # rubocop:disable Style/IfUnlessModifier + if rule.nil? + raise DomainInvalid, "`#{what}` is not a valid domain" + end + if rule.decompose(what).last.nil? + raise DomainNotAllowed, "`#{what}` is not allowed according to Registry policy" + end + + # rubocop:enable Style/IfUnlessModifier + + decompose(what, rule) + end + + # Checks whether +domain+ is assigned and allowed, without actually parsing it. + # + # This method doesn't care whether domain is a domain or subdomain. + # The validation is performed using the default {PublicSuffix::List}. + # + # @example Validate a valid domain + # PublicSuffix.valid?("example.com") + # # => true + # + # @example Validate a valid subdomain + # PublicSuffix.valid?("www.example.com") + # # => true + # + # @example Validate a not-listed domain + # PublicSuffix.valid?("example.tldnotlisted") + # # => true + # + # @example Validate a not-listed domain with strict checking (without applying the default * rule) + # PublicSuffix.valid?("example.tldnotlisted") + # # => true + # PublicSuffix.valid?("example.tldnotlisted", default_rule: nil) + # # => false + # + # @example Validate a fully qualified domain + # PublicSuffix.valid?("google.com.") + # # => true + # PublicSuffix.valid?("www.google.com.") + # # => true + # + # @example Check an URL (which is not a valid domain) + # PublicSuffix.valid?("http://www.example.com") + # # => false + # + # + # @param name [#to_s] The domain name or fully qualified domain name to validate. + # @param ignore_private [Boolean] + # @return [Boolean] + def self.valid?(name, list: List.default, default_rule: list.default_rule, ignore_private: false) + what = normalize(name) + return false if what.is_a?(DomainInvalid) + + rule = list.find(what, default: default_rule, ignore_private: ignore_private) + + !rule.nil? && !rule.decompose(what).last.nil? + end + + # Attempt to parse the name and returns the domain, if valid. + # + # This method doesn't raise. Instead, it returns nil if the domain is not valid for whatever reason. + # + # @param name [#to_s] The domain name or fully qualified domain name to parse. + # @param list [PublicSuffix::List] The rule list to search, defaults to the default {PublicSuffix::List} + # @param ignore_private [Boolean] + # @return [String] + def self.domain(name, **options) + parse(name, **options).domain + rescue PublicSuffix::Error + nil + end + + + # private + + def self.decompose(name, rule) + left, right = rule.decompose(name) + + parts = left.split(DOT) + # If we have 0 parts left, there is just a tld and no domain or subdomain + # If we have 1 part left, there is just a tld, domain and not subdomain + # If we have 2 parts left, the last part is the domain, the other parts (combined) are the subdomain + tld = right + sld = parts.empty? ? nil : parts.pop + trd = parts.empty? ? nil : parts.join(DOT) + + Domain.new(tld, sld, trd) + end + + # Pretend we know how to deal with user input. + def self.normalize(name) + name = name.to_s.dup + name.strip! + name.chomp!(DOT) + name.downcase! + + return DomainInvalid.new("Name is blank") if name.empty? + return DomainInvalid.new("Name starts with a dot") if name.start_with?(DOT) + return DomainInvalid.new(format("%s is not expected to contain a scheme", name)) if name.include?("://") + + name + end + +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/public_suffix-5.0.4/lib/public_suffix/domain.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/public_suffix-5.0.4/lib/public_suffix/domain.rb new file mode 100644 index 0000000000..5cfb06a342 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/public_suffix-5.0.4/lib/public_suffix/domain.rb @@ -0,0 +1,235 @@ +# frozen_string_literal: true + +# = Public Suffix +# +# Domain name parser based on the Public Suffix List. +# +# Copyright (c) 2009-2023 Simone Carletti + +module PublicSuffix + + # Domain represents a domain name, composed by a TLD, SLD and TRD. + class Domain + + # Splits a string into the labels, that is the dot-separated parts. + # + # The input is not validated, but it is assumed to be a valid domain name. + # + # @example + # + # name_to_labels('example.com') + # # => ['example', 'com'] + # + # name_to_labels('example.co.uk') + # # => ['example', 'co', 'uk'] + # + # @param name [String, #to_s] The domain name to split. + # @return [Array] + def self.name_to_labels(name) + name.to_s.split(DOT) + end + + + attr_reader :tld, :sld, :trd + + # Creates and returns a new {PublicSuffix::Domain} instance. + # + # @overload initialize(tld) + # Initializes with a +tld+. + # @param [String] tld The TLD (extension) + # @overload initialize(tld, sld) + # Initializes with a +tld+ and +sld+. + # @param [String] tld The TLD (extension) + # @param [String] sld The TRD (domain) + # @overload initialize(tld, sld, trd) + # Initializes with a +tld+, +sld+ and +trd+. + # @param [String] tld The TLD (extension) + # @param [String] sld The SLD (domain) + # @param [String] trd The TRD (subdomain) + # + # @yield [self] Yields on self. + # @yieldparam [PublicSuffix::Domain] self The newly creates instance + # + # @example Initialize with a TLD + # PublicSuffix::Domain.new("com") + # # => # + # + # @example Initialize with a TLD and SLD + # PublicSuffix::Domain.new("com", "example") + # # => # + # + # @example Initialize with a TLD, SLD and TRD + # PublicSuffix::Domain.new("com", "example", "wwww") + # # => # + # + def initialize(*args) + @tld, @sld, @trd = args + yield(self) if block_given? + end + + # Returns a string representation of this object. + # + # @return [String] + def to_s + name + end + + # Returns an array containing the domain parts. + # + # @return [Array] + # + # @example + # + # PublicSuffix::Domain.new("google.com").to_a + # # => [nil, "google", "com"] + # + # PublicSuffix::Domain.new("www.google.com").to_a + # # => [nil, "google", "com"] + # + def to_a + [@trd, @sld, @tld] + end + + # Returns the full domain name. + # + # @return [String] + # + # @example Gets the domain name of a domain + # PublicSuffix::Domain.new("com", "google").name + # # => "google.com" + # + # @example Gets the domain name of a subdomain + # PublicSuffix::Domain.new("com", "google", "www").name + # # => "www.google.com" + # + def name + [@trd, @sld, @tld].compact.join(DOT) + end + + # Returns a domain-like representation of this object + # if the object is a {#domain?}, nil otherwise. + # + # PublicSuffix::Domain.new("com").domain + # # => nil + # + # PublicSuffix::Domain.new("com", "google").domain + # # => "google.com" + # + # PublicSuffix::Domain.new("com", "google", "www").domain + # # => "www.google.com" + # + # This method doesn't validate the input. It handles the domain + # as a valid domain name and simply applies the necessary transformations. + # + # This method returns a FQD, not just the domain part. + # To get the domain part, use #sld (aka second level domain). + # + # PublicSuffix::Domain.new("com", "google", "www").domain + # # => "google.com" + # + # PublicSuffix::Domain.new("com", "google", "www").sld + # # => "google" + # + # @see #domain? + # @see #subdomain + # + # @return [String] + def domain + [@sld, @tld].join(DOT) if domain? + end + + # Returns a subdomain-like representation of this object + # if the object is a {#subdomain?}, nil otherwise. + # + # PublicSuffix::Domain.new("com").subdomain + # # => nil + # + # PublicSuffix::Domain.new("com", "google").subdomain + # # => nil + # + # PublicSuffix::Domain.new("com", "google", "www").subdomain + # # => "www.google.com" + # + # This method doesn't validate the input. It handles the domain + # as a valid domain name and simply applies the necessary transformations. + # + # This method returns a FQD, not just the subdomain part. + # To get the subdomain part, use #trd (aka third level domain). + # + # PublicSuffix::Domain.new("com", "google", "www").subdomain + # # => "www.google.com" + # + # PublicSuffix::Domain.new("com", "google", "www").trd + # # => "www" + # + # @see #subdomain? + # @see #domain + # + # @return [String] + def subdomain + [@trd, @sld, @tld].join(DOT) if subdomain? + end + + # Checks whether self looks like a domain. + # + # This method doesn't actually validate the domain. + # It only checks whether the instance contains + # a value for the {#tld} and {#sld} attributes. + # + # @example + # + # PublicSuffix::Domain.new("com").domain? + # # => false + # + # PublicSuffix::Domain.new("com", "google").domain? + # # => true + # + # PublicSuffix::Domain.new("com", "google", "www").domain? + # # => true + # + # # This is an invalid domain, but returns true + # # because this method doesn't validate the content. + # PublicSuffix::Domain.new("com", nil).domain? + # # => true + # + # @see #subdomain? + # + # @return [Boolean] + def domain? + !(@tld.nil? || @sld.nil?) + end + + # Checks whether self looks like a subdomain. + # + # This method doesn't actually validate the subdomain. + # It only checks whether the instance contains + # a value for the {#tld}, {#sld} and {#trd} attributes. + # If you also want to validate the domain, + # use {#valid_subdomain?} instead. + # + # @example + # + # PublicSuffix::Domain.new("com").subdomain? + # # => false + # + # PublicSuffix::Domain.new("com", "google").subdomain? + # # => false + # + # PublicSuffix::Domain.new("com", "google", "www").subdomain? + # # => true + # + # # This is an invalid domain, but returns true + # # because this method doesn't validate the content. + # PublicSuffix::Domain.new("com", "example", nil).subdomain? + # # => true + # + # @see #domain? + # + # @return [Boolean] + def subdomain? + !(@tld.nil? || @sld.nil? || @trd.nil?) + end + + end + +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/public_suffix-5.0.4/lib/public_suffix/errors.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/public_suffix-5.0.4/lib/public_suffix/errors.rb new file mode 100644 index 0000000000..7414ffd415 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/public_suffix-5.0.4/lib/public_suffix/errors.rb @@ -0,0 +1,41 @@ +# frozen_string_literal: true + +# = Public Suffix +# +# Domain name parser based on the Public Suffix List. +# +# Copyright (c) 2009-2023 Simone Carletti + +module PublicSuffix + + class Error < StandardError + end + + # Raised when trying to parse an invalid name. + # A name is considered invalid when no rule is found in the definition list. + # + # @example + # + # PublicSuffix.parse("nic.test") + # # => PublicSuffix::DomainInvalid + # + # PublicSuffix.parse("http://www.nic.it") + # # => PublicSuffix::DomainInvalid + # + class DomainInvalid < Error + end + + # Raised when trying to parse a name that matches a suffix. + # + # @example + # + # PublicSuffix.parse("nic.do") + # # => PublicSuffix::DomainNotAllowed + # + # PublicSuffix.parse("www.nic.do") + # # => PublicSuffix::Domain + # + class DomainNotAllowed < DomainInvalid + end + +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/public_suffix-5.0.4/lib/public_suffix/list.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/public_suffix-5.0.4/lib/public_suffix/list.rb new file mode 100644 index 0000000000..4bb4f1bd75 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/public_suffix-5.0.4/lib/public_suffix/list.rb @@ -0,0 +1,247 @@ +# frozen_string_literal: true + +# = Public Suffix +# +# Domain name parser based on the Public Suffix List. +# +# Copyright (c) 2009-2023 Simone Carletti + +module PublicSuffix + + # A {PublicSuffix::List} is a collection of one + # or more {PublicSuffix::Rule}. + # + # Given a {PublicSuffix::List}, + # you can add or remove {PublicSuffix::Rule}, + # iterate all items in the list or search for the first rule + # which matches a specific domain name. + # + # # Create a new list + # list = PublicSuffix::List.new + # + # # Push two rules to the list + # list << PublicSuffix::Rule.factory("it") + # list << PublicSuffix::Rule.factory("com") + # + # # Get the size of the list + # list.size + # # => 2 + # + # # Search for the rule matching given domain + # list.find("example.com") + # # => # + # list.find("example.org") + # # => nil + # + # You can create as many {PublicSuffix::List} you want. + # The {PublicSuffix::List.default} rule list is used + # to tokenize and validate a domain. + # + class List + + DEFAULT_LIST_PATH = File.expand_path("../../data/list.txt", __dir__) + + # Gets the default rule list. + # + # Initializes a new {PublicSuffix::List} parsing the content + # of {PublicSuffix::List.default_list_content}, if required. + # + # @return [PublicSuffix::List] + def self.default(**options) + @default ||= parse(File.read(DEFAULT_LIST_PATH), **options) + end + + # Sets the default rule list to +value+. + # + # @param value [PublicSuffix::List] the new list + # @return [PublicSuffix::List] + def self.default=(value) + @default = value + end + + # Parse given +input+ treating the content as Public Suffix List. + # + # See http://publicsuffix.org/format/ for more details about input format. + # + # @param input [#each_line] the list to parse + # @param private_domains [Boolean] whether to ignore the private domains section + # @return [PublicSuffix::List] + def self.parse(input, private_domains: true) + comment_token = "//" + private_token = "===BEGIN PRIVATE DOMAINS===" + section = nil # 1 == ICANN, 2 == PRIVATE + + new do |list| + input.each_line do |line| + line.strip! + case # rubocop:disable Style/EmptyCaseCondition + + # skip blank lines + when line.empty? + next + + # include private domains or stop scanner + when line.include?(private_token) + break if !private_domains + + section = 2 + + # skip comments + when line.start_with?(comment_token) # rubocop:disable Lint/DuplicateBranch + next + + else + list.add(Rule.factory(line, private: section == 2)) + + end + end + end + end + + + # Initializes an empty {PublicSuffix::List}. + # + # @yield [self] Yields on self. + # @yieldparam [PublicSuffix::List] self The newly created instance. + def initialize + @rules = {} + yield(self) if block_given? + end + + + # Checks whether two lists are equal. + # + # List one is equal to two, if two is an instance of + # {PublicSuffix::List} and each +PublicSuffix::Rule::*+ + # in list one is available in list two, in the same order. + # + # @param other [PublicSuffix::List] the List to compare + # @return [Boolean] + def ==(other) + return false unless other.is_a?(List) + + equal?(other) || @rules == other.rules + end + alias eql? == + + # Iterates each rule in the list. + def each(&block) + Enumerator.new do |y| + @rules.each do |key, node| + y << entry_to_rule(node, key) + end + end.each(&block) + end + + + # Adds the given object to the list and optionally refreshes the rule index. + # + # @param rule [PublicSuffix::Rule::*] the rule to add to the list + # @return [self] + def add(rule) + @rules[rule.value] = rule_to_entry(rule) + self + end + alias << add + + # Gets the number of rules in the list. + # + # @return [Integer] + def size + @rules.size + end + + # Checks whether the list is empty. + # + # @return [Boolean] + def empty? + @rules.empty? + end + + # Removes all rules. + # + # @return [self] + def clear + @rules.clear + self + end + + # Finds and returns the rule corresponding to the longest public suffix for the hostname. + # + # @param name [#to_s] the hostname + # @param default [PublicSuffix::Rule::*] the default rule to return in case no rule matches + # @return [PublicSuffix::Rule::*] + def find(name, default: default_rule, **options) + rule = select(name, **options).inject do |l, r| + return r if r.instance_of?(Rule::Exception) + + l.length > r.length ? l : r + end + rule || default + end + + # Selects all the rules matching given hostame. + # + # If `ignore_private` is set to true, the algorithm will skip the rules that are flagged as + # private domain. Note that the rules will still be part of the loop. + # If you frequently need to access lists ignoring the private domains, + # you should create a list that doesn't include these domains setting the + # `private_domains: false` option when calling {.parse}. + # + # Note that this method is currently private, as you should not rely on it. Instead, + # the public interface is {#find}. The current internal algorithm allows to return all + # matching rules, but different data structures may not be able to do it, and instead would + # return only the match. For this reason, you should rely on {#find}. + # + # @param name [#to_s] the hostname + # @param ignore_private [Boolean] + # @return [Array] + def select(name, ignore_private: false) + name = name.to_s + + parts = name.split(DOT).reverse! + index = 0 + query = parts[index] + rules = [] + + loop do + match = @rules[query] + rules << entry_to_rule(match, query) if !match.nil? && (ignore_private == false || match.private == false) + + index += 1 + break if index >= parts.size + + query = parts[index] + DOT + query + end + + rules + end + private :select + + # Gets the default rule. + # + # @see PublicSuffix::Rule.default_rule + # + # @return [PublicSuffix::Rule::*] + def default_rule + PublicSuffix::Rule.default + end + + + protected + + attr_reader :rules + + + private + + def entry_to_rule(entry, value) + entry.type.new(value: value, length: entry.length, private: entry.private) + end + + def rule_to_entry(rule) + Rule::Entry.new(rule.class, rule.length, rule.private) + end + + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/public_suffix-5.0.4/lib/public_suffix/rule.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/public_suffix-5.0.4/lib/public_suffix/rule.rb new file mode 100644 index 0000000000..520e08c27e --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/public_suffix-5.0.4/lib/public_suffix/rule.rb @@ -0,0 +1,350 @@ +# frozen_string_literal: true + +# = Public Suffix +# +# Domain name parser based on the Public Suffix List. +# +# Copyright (c) 2009-2023 Simone Carletti + +module PublicSuffix + + # A Rule is a special object which holds a single definition + # of the Public Suffix List. + # + # There are 3 types of rules, each one represented by a specific + # subclass within the +PublicSuffix::Rule+ namespace. + # + # To create a new Rule, use the {PublicSuffix::Rule#factory} method. + # + # PublicSuffix::Rule.factory("ar") + # # => # + # + module Rule + + # @api internal + Entry = Struct.new(:type, :length, :private) # rubocop:disable Lint/StructNewOverride + + # = Abstract rule class + # + # This represent the base class for a Rule definition + # in the {Public Suffix List}[https://publicsuffix.org]. + # + # This is intended to be an Abstract class + # and you shouldn't create a direct instance. The only purpose + # of this class is to expose a common interface + # for all the available subclasses. + # + # * {PublicSuffix::Rule::Normal} + # * {PublicSuffix::Rule::Exception} + # * {PublicSuffix::Rule::Wildcard} + # + # ## Properties + # + # A rule is composed by 4 properties: + # + # value - A normalized version of the rule name. + # The normalization process depends on rule tpe. + # + # Here's an example + # + # PublicSuffix::Rule.factory("*.google.com") + # # + # + # ## Rule Creation + # + # The best way to create a new rule is passing the rule name + # to the PublicSuffix::Rule.factory method. + # + # PublicSuffix::Rule.factory("com") + # # => PublicSuffix::Rule::Normal + # + # PublicSuffix::Rule.factory("*.com") + # # => PublicSuffix::Rule::Wildcard + # + # This method will detect the rule type and create an instance + # from the proper rule class. + # + # ## Rule Usage + # + # A rule describes the composition of a domain name and explains how to tokenize + # the name into tld, sld and trd. + # + # To use a rule, you first need to be sure the name you want to tokenize + # can be handled by the current rule. + # You can use the #match? method. + # + # rule = PublicSuffix::Rule.factory("com") + # + # rule.match?("google.com") + # # => true + # + # rule.match?("google.com") + # # => false + # + # Rule order is significant. A name can match more than one rule. + # See the {Public Suffix Documentation}[http://publicsuffix.org/format/] + # to learn more about rule priority. + # + # When you have the right rule, you can use it to tokenize the domain name. + # + # rule = PublicSuffix::Rule.factory("com") + # + # rule.decompose("google.com") + # # => ["google", "com"] + # + # rule.decompose("www.google.com") + # # => ["www.google", "com"] + # + # @abstract + # + class Base + + # @return [String] the rule definition + attr_reader :value + + # @return [String] the length of the rule + attr_reader :length + + # @return [Boolean] true if the rule is a private domain + attr_reader :private + + + # Initializes a new rule from the content. + # + # @param content [String] the content of the rule + # @param private [Boolean] + def self.build(content, private: false) + new(value: content, private: private) + end + + # Initializes a new rule. + # + # @param value [String] + # @param private [Boolean] + def initialize(value:, length: nil, private: false) + @value = value.to_s + @length = length || (@value.count(DOT) + 1) + @private = private + end + + # Checks whether this rule is equal to other. + # + # @param other [PublicSuffix::Rule::*] The rule to compare + # @return [Boolean] true if this rule and other are instances of the same class + # and has the same value, false otherwise. + def ==(other) + equal?(other) || (self.class == other.class && value == other.value) + end + alias eql? == + + # Checks if this rule matches +name+. + # + # A domain name is said to match a rule if and only if + # all of the following conditions are met: + # + # - When the domain and rule are split into corresponding labels, + # that the domain contains as many or more labels than the rule. + # - Beginning with the right-most labels of both the domain and the rule, + # and continuing for all labels in the rule, one finds that for every pair, + # either they are identical, or that the label from the rule is "*". + # + # @see https://publicsuffix.org/list/ + # + # @example + # PublicSuffix::Rule.factory("com").match?("example.com") + # # => true + # PublicSuffix::Rule.factory("com").match?("example.net") + # # => false + # + # @param name [String] the domain name to check + # @return [Boolean] + def match?(name) + # NOTE: it works because of the assumption there are no + # rules like foo.*.com. If the assumption is incorrect, + # we need to properly walk the input and skip parts according + # to wildcard component. + diff = name.chomp(value) + diff.empty? || diff.end_with?(DOT) + end + + # @abstract + def parts + raise NotImplementedError + end + + # @abstract + # @param domain [#to_s] The domain name to decompose + # @return [Array] + def decompose(*) + raise NotImplementedError + end + + end + + # Normal represents a standard rule (e.g. com). + class Normal < Base + + # Gets the original rule definition. + # + # @return [String] The rule definition. + def rule + value + end + + # Decomposes the domain name according to rule properties. + # + # @param domain [#to_s] The domain name to decompose + # @return [Array] The array with [trd + sld, tld]. + def decompose(domain) + suffix = parts.join('\.') + matches = domain.to_s.match(/^(.*)\.(#{suffix})$/) + matches ? matches[1..2] : [nil, nil] + end + + # dot-split rule value and returns all rule parts + # in the order they appear in the value. + # + # @return [Array] + def parts + @value.split(DOT) + end + + end + + # Wildcard represents a wildcard rule (e.g. *.co.uk). + class Wildcard < Base + + # Initializes a new rule from the content. + # + # @param content [String] the content of the rule + # @param private [Boolean] + def self.build(content, private: false) + new(value: content.to_s[2..], private: private) + end + + # Initializes a new rule. + # + # @param value [String] + # @param length [Integer] + # @param private [Boolean] + def initialize(value:, length: nil, private: false) + super(value: value, length: length, private: private) + length or @length += 1 # * counts as 1 + end + + # Gets the original rule definition. + # + # @return [String] The rule definition. + def rule + value == "" ? STAR : STAR + DOT + value + end + + # Decomposes the domain name according to rule properties. + # + # @param domain [#to_s] The domain name to decompose + # @return [Array] The array with [trd + sld, tld]. + def decompose(domain) + suffix = ([".*?"] + parts).join('\.') + matches = domain.to_s.match(/^(.*)\.(#{suffix})$/) + matches ? matches[1..2] : [nil, nil] + end + + # dot-split rule value and returns all rule parts + # in the order they appear in the value. + # + # @return [Array] + def parts + @value.split(DOT) + end + + end + + # Exception represents an exception rule (e.g. !parliament.uk). + class Exception < Base + + # Initializes a new rule from the content. + # + # @param content [#to_s] the content of the rule + # @param private [Boolean] + def self.build(content, private: false) + new(value: content.to_s[1..], private: private) + end + + # Gets the original rule definition. + # + # @return [String] The rule definition. + def rule + BANG + value + end + + # Decomposes the domain name according to rule properties. + # + # @param domain [#to_s] The domain name to decompose + # @return [Array] The array with [trd + sld, tld]. + def decompose(domain) + suffix = parts.join('\.') + matches = domain.to_s.match(/^(.*)\.(#{suffix})$/) + matches ? matches[1..2] : [nil, nil] + end + + # dot-split rule value and returns all rule parts + # in the order they appear in the value. + # The leftmost label is not considered a label. + # + # See http://publicsuffix.org/format/: + # If the prevailing rule is a exception rule, + # modify it by removing the leftmost label. + # + # @return [Array] + def parts + @value.split(DOT)[1..] + end + + end + + + # Takes the +name+ of the rule, detects the specific rule class + # and creates a new instance of that class. + # The +name+ becomes the rule +value+. + # + # @example Creates a Normal rule + # PublicSuffix::Rule.factory("ar") + # # => # + # + # @example Creates a Wildcard rule + # PublicSuffix::Rule.factory("*.ar") + # # => # + # + # @example Creates an Exception rule + # PublicSuffix::Rule.factory("!congresodelalengua3.ar") + # # => # + # + # @param content [#to_s] the content of the rule + # @return [PublicSuffix::Rule::*] A rule instance. + def self.factory(content, private: false) + case content.to_s[0, 1] + when STAR + Wildcard + when BANG + Exception + else + Normal + end.build(content, private: private) + end + + # The default rule to use if no rule match. + # + # The default rule is "*". From https://publicsuffix.org/list/: + # + # > If no rules match, the prevailing rule is "*". + # + # @return [PublicSuffix::Rule::Wildcard] The default rule. + def self.default + factory(STAR) + end + + end + +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/public_suffix-5.0.4/lib/public_suffix/version.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/public_suffix-5.0.4/lib/public_suffix/version.rb new file mode 100644 index 0000000000..a819359fc3 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/public_suffix-5.0.4/lib/public_suffix/version.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +# = Public Suffix +# +# Domain name parser based on the Public Suffix List. +# +# Copyright (c) 2009-2023 Simone Carletti + +module PublicSuffix + + # @return [String] the current library version + VERSION = "5.0.4" + +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/ruby-macho-4.0.0/LICENSE b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/ruby-macho-4.0.0/LICENSE new file mode 100644 index 0000000000..89dd7d651b --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/ruby-macho-4.0.0/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2015, 2016, 2017, 2018 William Woodruff + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/ruby-macho-4.0.0/lib/macho.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/ruby-macho-4.0.0/lib/macho.rb new file mode 100644 index 0000000000..f11343c81d --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/ruby-macho-4.0.0/lib/macho.rb @@ -0,0 +1,61 @@ +# frozen_string_literal: true + +require "open3" + +require_relative "macho/utils" +require_relative "macho/structure" +require_relative "macho/view" +require_relative "macho/headers" +require_relative "macho/load_commands" +require_relative "macho/sections" +require_relative "macho/macho_file" +require_relative "macho/fat_file" +require_relative "macho/exceptions" +require_relative "macho/tools" + +# The primary namespace for ruby-macho. +module MachO + # release version + VERSION = "4.0.0" + + # Opens the given filename as a MachOFile or FatFile, depending on its magic. + # @param filename [String] the file being opened + # @return [MachOFile] if the file is a Mach-O + # @return [FatFile] if the file is a Fat file + # @raise [ArgumentError] if the given file does not exist + # @raise [TruncatedFileError] if the file is too small to have a valid header + # @raise [MagicError] if the file's magic is not valid Mach-O magic + def self.open(filename) + raise ArgumentError, "#{filename}: no such file" unless File.file?(filename) + raise TruncatedFileError unless File.stat(filename).size >= 4 + + magic = File.open(filename, "rb") { |f| f.read(4) }.unpack1("N") + + if Utils.fat_magic?(magic) + file = FatFile.new(filename) + elsif Utils.magic?(magic) + file = MachOFile.new(filename) + else + raise MagicError, magic + end + + file + end + + # Signs the dylib using an ad-hoc identity. + # Necessary after making any changes to a dylib, since otherwise + # changing a signed file invalidates its signature. + # @param filename [String] the file being opened + # @return [void] + # @raise [ModificationError] if the operation fails + def self.codesign!(filename) + raise ArgumentError, "codesign binary is not available on Linux" if RUBY_PLATFORM !~ /darwin/ + raise ArgumentError, "#{filename}: no such file" unless File.file?(filename) + + _, _, status = Open3.capture3("codesign", "--sign", "-", "--force", + "--preserve-metadata=entitlements,requirements,flags,runtime", + filename) + + raise CodeSigningError, "#{filename}: signing failed!" unless status.success? + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/ruby-macho-4.0.0/lib/macho/exceptions.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/ruby-macho-4.0.0/lib/macho/exceptions.rb new file mode 100644 index 0000000000..66af33427f --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/ruby-macho-4.0.0/lib/macho/exceptions.rb @@ -0,0 +1,242 @@ +# frozen_string_literal: true + +module MachO + # A generic Mach-O error in execution. + class MachOError < RuntimeError + end + + # Raised when a Mach-O file modification fails. + class ModificationError < MachOError + end + + # Raised when codesigning fails. Certain environments + # may want to rescue this to treat it as non-fatal. + class CodeSigningError < MachOError + end + + # Raised when a Mach-O file modification fails but can be recovered when + # operating on multiple Mach-O slices of a fat binary in non-strict mode. + class RecoverableModificationError < ModificationError + # @return [Integer, nil] The index of the Mach-O slice of a fat binary for + # which modification failed or `nil` if not a fat binary. This is used to + # make the error message more useful. + attr_accessor :macho_slice + + # @return [String] The exception message. + def to_s + s = super.to_s + s = "While modifying Mach-O slice #{@macho_slice}: #{s}" if @macho_slice + s + end + end + + # Raised when a file is not a Mach-O. + class NotAMachOError < MachOError + end + + # Raised when a file is too short to be a valid Mach-O file. + class TruncatedFileError < NotAMachOError + def initialize + super "File is too short to be a valid Mach-O" + end + end + + # Raised when a file's magic bytes are not valid Mach-O magic. + class MagicError < NotAMachOError + # @param num [Integer] the unknown number + def initialize(magic) + super "Unrecognized Mach-O magic: 0x%02x" % { :magic => magic } + end + end + + # Raised when a file is a Java classfile instead of a fat Mach-O. + class JavaClassFileError < NotAMachOError + def initialize + super "File is a Java class file" + end + end + + # Raised when a a fat Mach-O file has zero architectures + class ZeroArchitectureError < NotAMachOError + def initialize + super "Fat file has zero internal architectures" + end + end + + # Raised when there is a mismatch between the fat arch + # and internal slice cputype or cpusubtype. + class CPUTypeMismatchError < NotAMachOError + def initialize(fat_cputype, fat_cpusubtype, macho_cputype, macho_cpusubtype) + # @param cputype_fat [Integer] the CPU type in the fat header + # @param cpusubtype_fat [Integer] the CPU subtype in the fat header + # @param cputype_macho [Integer] the CPU type in the macho header + # @param cpusubtype_macho [Integer] the CPU subtype in the macho header + super ("Mismatch between cputypes >> 0x%08x and 0x%08x\n" \ + "and/or cpusubtypes >> 0x%08x and 0x%08x" % + { :fat_cputype => fat_cputype, :macho_cputype => macho_cputype, + :fat_cpusubtype => fat_cpusubtype, :macho_cpusubtype => macho_cpusubtype }) + end + end + + # Raised when a fat binary is loaded with MachOFile. + class FatBinaryError < MachOError + def initialize + super "Fat binaries must be loaded with MachO::FatFile" + end + end + + # Raised when a Mach-O is loaded with FatFile. + class MachOBinaryError < MachOError + def initialize + super "Normal binaries must be loaded with MachO::MachOFile" + end + end + + # Raised when the CPU type is unknown. + class CPUTypeError < MachOError + # @param cputype [Integer] the unknown CPU type + def initialize(cputype) + super "Unrecognized CPU type: 0x%08x" % { :cputype => cputype } + end + end + + # Raised when the CPU type/sub-type pair is unknown. + class CPUSubtypeError < MachOError + # @param cputype [Integer] the CPU type of the unknown pair + # @param cpusubtype [Integer] the CPU sub-type of the unknown pair + def initialize(cputype, cpusubtype) + super "Unrecognized CPU sub-type: 0x%08x " \ + "(for CPU type: 0x%08x" % { :cputype => cputype, :cpusubtype => cpusubtype } + end + end + + # Raised when a mach-o file's filetype field is unknown. + class FiletypeError < MachOError + # @param num [Integer] the unknown number + def initialize(num) + super "Unrecognized Mach-O filetype code: 0x%02x" % { :num => num } + end + end + + # Raised when an unknown load command is encountered. + class LoadCommandError < MachOError + # @param num [Integer] the unknown number + def initialize(num) + super "Unrecognized Mach-O load command: 0x%02x" % { :num => num } + end + end + + # Raised when a load command can't be created manually. + class LoadCommandNotCreatableError < MachOError + # @param cmd_sym [Symbol] the uncreatable load command's symbol + def initialize(cmd_sym) + super "Load commands of type #{cmd_sym} cannot be created manually" + end + end + + # Raised when the number of arguments used to create a load command manually + # is wrong. + class LoadCommandCreationArityError < MachOError + # @param cmd_sym [Symbol] the load command's symbol + # @param expected_arity [Integer] the number of arguments expected + # @param actual_arity [Integer] the number of arguments received + def initialize(cmd_sym, expected_arity, actual_arity) + super "Expected #{expected_arity} arguments for #{cmd_sym} creation, " \ + "got #{actual_arity}" + end + end + + # Raised when a load command can't be serialized. + class LoadCommandNotSerializableError < MachOError + # @param cmd_sym [Symbol] the load command's symbol + def initialize(cmd_sym) + super "Load commands of type #{cmd_sym} cannot be serialized" + end + end + + # Raised when a load command string is malformed in some way. + class LCStrMalformedError < MachOError + # @param lc [MachO::LoadCommand] the load command containing the string + def initialize(lc) + super "Load command #{lc.type} at offset #{lc.view.offset} contains a " \ + "malformed string" + end + end + + # Raised when a change at an offset is not valid. + class OffsetInsertionError < ModificationError + # @param offset [Integer] the invalid offset + def initialize(offset) + super "Insertion at offset #{offset} is not valid" + end + end + + # Raised when load commands are too large to fit in the current file. + class HeaderPadError < ModificationError + # @param filename [String] the filename + def initialize(filename) + super "Updated load commands do not fit in the header of " \ + "#{filename}. #{filename} needs to be relinked, possibly with " \ + "-headerpad or -headerpad_max_install_names" + end + end + + # Raised when attempting to change a dylib name that doesn't exist. + class DylibUnknownError < RecoverableModificationError + # @param dylib [String] the unknown shared library name + def initialize(dylib) + super "No such dylib name: #{dylib}" + end + end + + # Raised when a dylib is missing an ID + class DylibIdMissingError < RecoverableModificationError + def initialize + super "Dylib is missing a dylib ID" + end + end + + # Raised when attempting to change an rpath that doesn't exist. + class RpathUnknownError < RecoverableModificationError + # @param path [String] the unknown runtime path + def initialize(path) + super "No such runtime path: #{path}" + end + end + + # Raised when attempting to add an rpath that already exists. + class RpathExistsError < RecoverableModificationError + # @param path [String] the extant path + def initialize(path) + super "#{path} already exists" + end + end + + # Raised whenever unfinished code is called. + class UnimplementedError < MachOError + # @param thing [String] the thing that is unimplemented + def initialize(thing) + super "Unimplemented: #{thing}" + end + end + + # Raised when attempting to create a {FatFile} from one or more {MachOFile}s + # whose offsets will not fit within the resulting 32-bit {Headers::FatArch#offset} fields. + class FatArchOffsetOverflowError < MachOError + # @param offset [Integer] the offending offset + def initialize(offset) + super "Offset #{offset} exceeds the 32-bit width of a fat_arch offset. " \ + "Consider merging with `fat64: true`" + end + end + + # Raised when attempting to parse a compressed Mach-O without explicitly + # requesting decompression. + class CompressedMachOError < MachOError + end + + # Raised when attempting to decompress a compressed Mach-O without adequate + # dependencies, or on other decompression errors. + class DecompressionError < MachOError + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/ruby-macho-4.0.0/lib/macho/fat_file.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/ruby-macho-4.0.0/lib/macho/fat_file.rb new file mode 100644 index 0000000000..637e1c5aa5 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/ruby-macho-4.0.0/lib/macho/fat_file.rb @@ -0,0 +1,440 @@ +# frozen_string_literal: true + +require "forwardable" + +module MachO + # Represents a "Fat" file, which contains a header, a listing of available + # architectures, and one or more Mach-O binaries. + # @see https://en.wikipedia.org/wiki/Mach-O#Multi-architecture_binaries + # @see MachOFile + class FatFile + extend Forwardable + + # @return [String] the filename loaded from, or nil if loaded from a binary string + attr_accessor :filename + + # @return [Hash] any parser options that the instance was created with + # @note Options specified in a {FatFile} trickle down into the internal {MachOFile}s. + attr_reader :options + + # @return [Headers::FatHeader] the file's header + attr_reader :header + + # @return [Array, Array] an array of Mach-O binaries + attr_reader :machos + + # Creates a new FatFile from the given (single-arch) Mach-Os + # @param machos [Array] the machos to combine + # @param fat64 [Boolean] whether to use {Headers::FatArch64}s to represent each slice + # @return [FatFile] a new FatFile containing the give machos + # @raise [ArgumentError] if less than one Mach-O is given + # @raise [FatArchOffsetOverflowError] if the Mach-Os are too big to be represented + # in a 32-bit {Headers::FatArch} and `fat64` is `false`. + def self.new_from_machos(*machos, fat64: false) + raise ArgumentError, "expected at least one Mach-O" if machos.empty? + + fa_klass, magic = if fat64 + [Headers::FatArch64, Headers::FAT_MAGIC_64] + else + [Headers::FatArch, Headers::FAT_MAGIC] + end + + # put the smaller alignments further forwards in fat macho, so that we do less padding + machos = machos.sort_by(&:segment_alignment) + + bin = +"" + + bin << Headers::FatHeader.new(magic, machos.size).serialize + offset = Headers::FatHeader.bytesize + (machos.size * fa_klass.bytesize) + + macho_pads = {} + + machos.each do |macho| + macho_offset = Utils.round(offset, 2**macho.segment_alignment) + + raise FatArchOffsetOverflowError, macho_offset if !fat64 && macho_offset > ((2**32) - 1) + + macho_pads[macho] = Utils.padding_for(offset, 2**macho.segment_alignment) + + bin << fa_klass.new(macho.header.cputype, macho.header.cpusubtype, + macho_offset, macho.serialize.bytesize, + macho.segment_alignment).serialize + + offset += (macho.serialize.bytesize + macho_pads[macho]) + end + + machos.each do |macho| # rubocop:disable Style/CombinableLoops + bin << Utils.nullpad(macho_pads[macho]) + bin << macho.serialize + end + + new_from_bin(bin) + end + + # Creates a new FatFile instance from a binary string. + # @param bin [String] a binary string containing raw Mach-O data + # @param opts [Hash] options to control the parser with + # @note see {MachOFile#initialize} for currently valid options + # @return [FatFile] a new FatFile + def self.new_from_bin(bin, **opts) + instance = allocate + instance.initialize_from_bin(bin, opts) + + instance + end + + # Creates a new FatFile from the given filename. + # @param filename [String] the fat file to load from + # @param opts [Hash] options to control the parser with + # @note see {MachOFile#initialize} for currently valid options + # @raise [ArgumentError] if the given file does not exist + def initialize(filename, **opts) + raise ArgumentError, "#{filename}: no such file" unless File.file?(filename) + + @filename = filename + @options = opts + @raw_data = File.binread(@filename) + populate_fields + end + + # Initializes a new FatFile instance from a binary string with the given options. + # @see new_from_bin + # @api private + def initialize_from_bin(bin, opts) + @filename = nil + @options = opts + @raw_data = bin + populate_fields + end + + # The file's raw fat data. + # @return [String] the raw fat data + def serialize + @raw_data + end + + # @!method object? + # @return (see MachO::MachOFile#object?) + # @!method executable? + # @return (see MachO::MachOFile#executable?) + # @!method fvmlib? + # @return (see MachO::MachOFile#fvmlib?) + # @!method core? + # @return (see MachO::MachOFile#core?) + # @!method preload? + # @return (see MachO::MachOFile#preload?) + # @!method dylib? + # @return (see MachO::MachOFile#dylib?) + # @!method dylinker? + # @return (see MachO::MachOFile#dylinker?) + # @!method bundle? + # @return (see MachO::MachOFile#bundle?) + # @!method dsym? + # @return (see MachO::MachOFile#dsym?) + # @!method kext? + # @return (see MachO::MachOFile#kext?) + # @!method filetype + # @return (see MachO::MachOFile#filetype) + # @!method dylib_id + # @return (see MachO::MachOFile#dylib_id) + def_delegators :canonical_macho, :object?, :executable?, :fvmlib?, + :core?, :preload?, :dylib?, :dylinker?, :bundle?, + :dsym?, :kext?, :filetype, :dylib_id + + # @!method magic + # @return (see MachO::Headers::FatHeader#magic) + def_delegators :header, :magic + + # @return [String] a string representation of the file's magic number + def magic_string + Headers::MH_MAGICS[magic] + end + + # Populate the instance's fields with the raw Fat Mach-O data. + # @return [void] + # @note This method is public, but should (almost) never need to be called. + def populate_fields + @header = populate_fat_header + @fat_archs = populate_fat_archs + @machos = populate_machos + end + + # All load commands responsible for loading dylibs in the file's Mach-O's. + # @return [Array] an array of DylibCommands + def dylib_load_commands + machos.map(&:dylib_load_commands).flatten + end + + # Changes the file's dylib ID to `new_id`. If the file is not a dylib, + # does nothing. + # @example + # file.change_dylib_id('libFoo.dylib') + # @param new_id [String] the new dylib ID + # @param options [Hash] + # @option options [Boolean] :strict (true) if true, fail if one slice fails. + # if false, fail only if all slices fail. + # @return [void] + # @raise [ArgumentError] if `new_id` is not a String + # @see MachOFile#linked_dylibs + def change_dylib_id(new_id, options = {}) + raise ArgumentError, "argument must be a String" unless new_id.is_a?(String) + return unless machos.all?(&:dylib?) + + each_macho(options) do |macho| + macho.change_dylib_id(new_id, options) + end + + repopulate_raw_machos + end + + alias dylib_id= change_dylib_id + + # All shared libraries linked to the file's Mach-Os. + # @return [Array] an array of all shared libraries + # @see MachOFile#linked_dylibs + def linked_dylibs + # Individual architectures in a fat binary can link to different subsets + # of libraries, but at this point we want to have the full picture, i.e. + # the union of all libraries used by all architectures. + machos.map(&:linked_dylibs).flatten.uniq + end + + # Changes all dependent shared library install names from `old_name` to + # `new_name`. In a fat file, this changes install names in all internal + # Mach-Os. + # @example + # file.change_install_name('/usr/lib/libFoo.dylib', '/usr/lib/libBar.dylib') + # @param old_name [String] the shared library name being changed + # @param new_name [String] the new name + # @param options [Hash] + # @option options [Boolean] :strict (true) if true, fail if one slice fails. + # if false, fail only if all slices fail. + # @return [void] + # @see MachOFile#change_install_name + def change_install_name(old_name, new_name, options = {}) + each_macho(options) do |macho| + macho.change_install_name(old_name, new_name, options) + end + + repopulate_raw_machos + end + + alias change_dylib change_install_name + + # All runtime paths associated with the file's Mach-Os. + # @return [Array] an array of all runtime paths + # @see MachOFile#rpaths + def rpaths + # Can individual architectures have different runtime paths? + machos.map(&:rpaths).flatten.uniq + end + + # Change the runtime path `old_path` to `new_path` in the file's Mach-Os. + # @param old_path [String] the old runtime path + # @param new_path [String] the new runtime path + # @param options [Hash] + # @option options [Boolean] :strict (true) if true, fail if one slice fails. + # if false, fail only if all slices fail. + # @option options [Boolean] :uniq (false) for each slice: if true, change + # each rpath simultaneously. + # @return [void] + # @see MachOFile#change_rpath + def change_rpath(old_path, new_path, options = {}) + each_macho(options) do |macho| + macho.change_rpath(old_path, new_path, options) + end + + repopulate_raw_machos + end + + # Add the given runtime path to the file's Mach-Os. + # @param path [String] the new runtime path + # @param options [Hash] + # @option options [Boolean] :strict (true) if true, fail if one slice fails. + # if false, fail only if all slices fail. + # @return [void] + # @see MachOFile#add_rpath + def add_rpath(path, options = {}) + each_macho(options) do |macho| + macho.add_rpath(path, options) + end + + repopulate_raw_machos + end + + # Delete the given runtime path from the file's Mach-Os. + # @param path [String] the runtime path to delete + # @param options [Hash] + # @option options [Boolean] :strict (true) if true, fail if one slice fails. + # if false, fail only if all slices fail. + # @option options [Boolean] :uniq (false) for each slice: if true, delete + # only the first runtime path that matches. if false, delete all duplicate + # paths that match. + # @return void + # @see MachOFile#delete_rpath + def delete_rpath(path, options = {}) + each_macho(options) do |macho| + macho.delete_rpath(path, options) + end + + repopulate_raw_machos + end + + # Extract a Mach-O with the given CPU type from the file. + # @example + # file.extract(:i386) # => MachO::MachOFile + # @param cputype [Symbol] the CPU type of the Mach-O being extracted + # @return [MachOFile, nil] the extracted Mach-O or nil if no Mach-O has the given CPU type + def extract(cputype) + machos.select { |macho| macho.cputype == cputype }.first + end + + # Write all (fat) data to the given filename. + # @param filename [String] the file to write to + # @return [void] + def write(filename) + File.binwrite(filename, @raw_data) + end + + # Write all (fat) data to the file used to initialize the instance. + # @return [void] + # @raise [MachOError] if the instance was initialized without a file + # @note Overwrites all data in the file! + def write! + raise MachOError, "no initial file to write to" if filename.nil? + + File.binwrite(@filename, @raw_data) + end + + # @return [Hash] a hash representation of this {FatFile} + def to_h + { + "header" => header.to_h, + "fat_archs" => fat_archs.map(&:to_h), + "machos" => machos.map(&:to_h), + } + end + + private + + # Obtain the fat header from raw file data. + # @return [Headers::FatHeader] the fat header + # @raise [TruncatedFileError] if the file is too small to have a + # valid header + # @raise [MagicError] if the magic is not valid Mach-O magic + # @raise [MachOBinaryError] if the magic is for a non-fat Mach-O file + # @raise [JavaClassFileError] if the file is a Java classfile + # @raise [ZeroArchitectureError] if the file has no internal slices + # (i.e., nfat_arch == 0) and the permissive option is not set + # @api private + def populate_fat_header + # the smallest fat Mach-O header is 8 bytes + raise TruncatedFileError if @raw_data.size < 8 + + fh = Headers::FatHeader.new_from_bin(:big, @raw_data[0, Headers::FatHeader.bytesize]) + + raise MagicError, fh.magic unless Utils.magic?(fh.magic) + raise MachOBinaryError unless Utils.fat_magic?(fh.magic) + + # Rationale: Java classfiles have the same magic as big-endian fat + # Mach-Os. Classfiles encode their version at the same offset as + # `nfat_arch` and the lowest version number is 43, so we error out + # if a file claims to have over 30 internal architectures. It's + # technically possible for a fat Mach-O to have over 30 architectures, + # but this is extremely unlikely and in practice distinguishes the two + # formats. + raise JavaClassFileError if fh.nfat_arch > 30 + + # Rationale: return an error if the file has no internal slices. + raise ZeroArchitectureError if fh.nfat_arch.zero? + + fh + end + + # Obtain an array of fat architectures from raw file data. + # @return [Array] an array of fat architectures + # @api private + def populate_fat_archs + archs = [] + + fa_klass = Utils.fat_magic32?(header.magic) ? Headers::FatArch : Headers::FatArch64 + fa_off = Headers::FatHeader.bytesize + fa_len = fa_klass.bytesize + + header.nfat_arch.times do |i| + archs << fa_klass.new_from_bin(:big, @raw_data[fa_off + (fa_len * i), fa_len]) + end + + archs + end + + # Obtain an array of Mach-O blobs from raw file data. + # @return [Array] an array of Mach-Os + # @api private + def populate_machos + machos = [] + + fat_archs.each do |arch| + machos << MachOFile.new_from_bin(@raw_data[arch.offset, arch.size], **options) + + # Make sure that each fat_arch and internal slice. + # contain matching cputypes and cpusubtypes + next if machos.last.header.cputype == arch.cputype && + machos.last.header.cpusubtype == arch.cpusubtype + + raise CPUTypeMismatchError.new(arch.cputype, arch.cpusubtype, machos.last.header.cputype, machos.last.header.cpusubtype) + end + + machos + end + + # Repopulate the raw Mach-O data with each internal Mach-O object. + # @return [void] + # @api private + def repopulate_raw_machos + machos.each_with_index do |macho, i| + arch = fat_archs[i] + + @raw_data[arch.offset, arch.size] = macho.serialize + end + end + + # Yield each Mach-O object in the file, rescuing and accumulating errors. + # @param options [Hash] + # @option options [Boolean] :strict (true) whether or not to fail loudly + # with an exception if at least one Mach-O raises an exception. If false, + # only raises an exception if *all* Mach-Os raise exceptions. + # @raise [RecoverableModificationError] under the conditions of + # the `:strict` option above. + # @api private + def each_macho(options = {}) + strict = options.fetch(:strict, true) + errors = [] + + machos.each_with_index do |macho, index| + yield macho + rescue RecoverableModificationError => e + e.macho_slice = index + + # Strict mode: Immediately re-raise. Otherwise: Retain, check later. + raise e if strict + + errors << e + end + + # Non-strict mode: Raise first error if *all* Mach-O slices failed. + raise errors.first if errors.size == machos.size + end + + # Return a single-arch Mach-O that represents this fat Mach-O for purposes + # of delegation. + # @return [MachOFile] the Mach-O file + # @api private + def canonical_macho + machos.first + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/ruby-macho-4.0.0/lib/macho/headers.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/ruby-macho-4.0.0/lib/macho/headers.rb new file mode 100644 index 0000000000..4abdd533d4 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/ruby-macho-4.0.0/lib/macho/headers.rb @@ -0,0 +1,793 @@ +# frozen_string_literal: true + +module MachO + # Classes and constants for parsing the headers of Mach-O binaries. + module Headers + # big-endian fat magic + # @api private + FAT_MAGIC = 0xcafebabe + + # little-endian fat magic + # @note This is defined for completeness, but should never appear in ruby-macho code, + # since fat headers are always big-endian. + # @api private + FAT_CIGAM = 0xbebafeca + + # 64-bit big-endian fat magic + FAT_MAGIC_64 = 0xcafebabf + + # 64-bit little-endian fat magic + # @note This is defined for completeness, but should never appear in ruby-macho code, + # since fat headers are always big-endian. + FAT_CIGAM_64 = 0xbfbafeca + + # 32-bit big-endian magic + # @api private + MH_MAGIC = 0xfeedface + + # 32-bit little-endian magic + # @api private + MH_CIGAM = 0xcefaedfe + + # 64-bit big-endian magic + # @api private + MH_MAGIC_64 = 0xfeedfacf + + # 64-bit little-endian magic + # @api private + MH_CIGAM_64 = 0xcffaedfe + + # compressed mach-o magic + # @api private + COMPRESSED_MAGIC = 0x636f6d70 # "comp" + + # a compressed mach-o slice, using LZSS for compression + # @api private + COMP_TYPE_LZSS = 0x6c7a7373 # "lzss" + + # a compressed mach-o slice, using LZVN ("FastLib") for compression + # @api private + COMP_TYPE_FASTLIB = 0x6c7a766e # "lzvn" + + # association of magic numbers to string representations + # @api private + MH_MAGICS = { + FAT_MAGIC => "FAT_MAGIC", + FAT_MAGIC_64 => "FAT_MAGIC_64", + MH_MAGIC => "MH_MAGIC", + MH_CIGAM => "MH_CIGAM", + MH_MAGIC_64 => "MH_MAGIC_64", + MH_CIGAM_64 => "MH_CIGAM_64", + }.freeze + + # mask for CPUs with 64-bit architectures (when running a 64-bit ABI?) + # @api private + CPU_ARCH_ABI64 = 0x01000000 + + # mask for CPUs with 64-bit architectures (when running a 32-bit ABI?) + # @see https://github.com/Homebrew/ruby-macho/issues/113 + # @api private + CPU_ARCH_ABI32 = 0x02000000 + + # any CPU (unused?) + # @api private + CPU_TYPE_ANY = -1 + + # m68k compatible CPUs + # @api private + CPU_TYPE_MC680X0 = 0x06 + + # i386 and later compatible CPUs + # @api private + CPU_TYPE_I386 = 0x07 + + # x86_64 (AMD64) compatible CPUs + # @api private + CPU_TYPE_X86_64 = (CPU_TYPE_I386 | CPU_ARCH_ABI64) + + # 32-bit ARM compatible CPUs + # @api private + CPU_TYPE_ARM = 0x0c + + # m88k compatible CPUs + # @api private + CPU_TYPE_MC88000 = 0xd + + # 64-bit ARM compatible CPUs + # @api private + CPU_TYPE_ARM64 = (CPU_TYPE_ARM | CPU_ARCH_ABI64) + + # 64-bit ARM compatible CPUs (running in 32-bit mode?) + # @see https://github.com/Homebrew/ruby-macho/issues/113 + CPU_TYPE_ARM64_32 = (CPU_TYPE_ARM | CPU_ARCH_ABI32) + + # PowerPC compatible CPUs + # @api private + CPU_TYPE_POWERPC = 0x12 + + # PowerPC64 compatible CPUs + # @api private + CPU_TYPE_POWERPC64 = (CPU_TYPE_POWERPC | CPU_ARCH_ABI64) + + # association of cpu types to symbol representations + # @api private + CPU_TYPES = { + CPU_TYPE_ANY => :any, + CPU_TYPE_I386 => :i386, + CPU_TYPE_X86_64 => :x86_64, + CPU_TYPE_ARM => :arm, + CPU_TYPE_ARM64 => :arm64, + CPU_TYPE_ARM64_32 => :arm64_32, + CPU_TYPE_POWERPC => :ppc, + CPU_TYPE_POWERPC64 => :ppc64, + }.freeze + + # mask for CPU subtype capabilities + # @api private + CPU_SUBTYPE_MASK = 0xff000000 + + # 64-bit libraries (undocumented!) + # @see http://llvm.org/docs/doxygen/html/Support_2MachO_8h_source.html + # @api private + CPU_SUBTYPE_LIB64 = 0x80000000 + + # the lowest common sub-type for `CPU_TYPE_I386` + # @api private + CPU_SUBTYPE_I386 = 3 + + # the i486 sub-type for `CPU_TYPE_I386` + # @api private + CPU_SUBTYPE_486 = 4 + + # the i486SX sub-type for `CPU_TYPE_I386` + # @api private + CPU_SUBTYPE_486SX = 132 + + # the i586 (P5, Pentium) sub-type for `CPU_TYPE_I386` + # @api private + CPU_SUBTYPE_586 = 5 + + # @see CPU_SUBTYPE_586 + # @api private + CPU_SUBTYPE_PENT = CPU_SUBTYPE_586 + + # the Pentium Pro (P6) sub-type for `CPU_TYPE_I386` + # @api private + CPU_SUBTYPE_PENTPRO = 22 + + # the Pentium II (P6, M3?) sub-type for `CPU_TYPE_I386` + # @api private + CPU_SUBTYPE_PENTII_M3 = 54 + + # the Pentium II (P6, M5?) sub-type for `CPU_TYPE_I386` + # @api private + CPU_SUBTYPE_PENTII_M5 = 86 + + # the Pentium 4 (Netburst) sub-type for `CPU_TYPE_I386` + # @api private + CPU_SUBTYPE_PENTIUM_4 = 10 + + # the lowest common sub-type for `CPU_TYPE_MC680X0` + # @api private + CPU_SUBTYPE_MC680X0_ALL = 1 + + # @see CPU_SUBTYPE_MC680X0_ALL + # @api private + CPU_SUBTYPE_MC68030 = CPU_SUBTYPE_MC680X0_ALL + + # the 040 subtype for `CPU_TYPE_MC680X0` + # @api private + CPU_SUBTYPE_MC68040 = 2 + + # the 030 subtype for `CPU_TYPE_MC680X0` + # @api private + CPU_SUBTYPE_MC68030_ONLY = 3 + + # the lowest common sub-type for `CPU_TYPE_X86_64` + # @api private + CPU_SUBTYPE_X86_64_ALL = CPU_SUBTYPE_I386 + + # the Haskell sub-type for `CPU_TYPE_X86_64` + # @api private + CPU_SUBTYPE_X86_64_H = 8 + + # the lowest common sub-type for `CPU_TYPE_ARM` + # @api private + CPU_SUBTYPE_ARM_ALL = 0 + + # the v4t sub-type for `CPU_TYPE_ARM` + # @api private + CPU_SUBTYPE_ARM_V4T = 5 + + # the v6 sub-type for `CPU_TYPE_ARM` + # @api private + CPU_SUBTYPE_ARM_V6 = 6 + + # the v5 sub-type for `CPU_TYPE_ARM` + # @api private + CPU_SUBTYPE_ARM_V5TEJ = 7 + + # the xscale (v5 family) sub-type for `CPU_TYPE_ARM` + # @api private + CPU_SUBTYPE_ARM_XSCALE = 8 + + # the v7 sub-type for `CPU_TYPE_ARM` + # @api private + CPU_SUBTYPE_ARM_V7 = 9 + + # the v7f (Cortex A9) sub-type for `CPU_TYPE_ARM` + # @api private + CPU_SUBTYPE_ARM_V7F = 10 + + # the v7s ("Swift") sub-type for `CPU_TYPE_ARM` + # @api private + CPU_SUBTYPE_ARM_V7S = 11 + + # the v7k ("Kirkwood40") sub-type for `CPU_TYPE_ARM` + # @api private + CPU_SUBTYPE_ARM_V7K = 12 + + # the v6m sub-type for `CPU_TYPE_ARM` + # @api private + CPU_SUBTYPE_ARM_V6M = 14 + + # the v7m sub-type for `CPU_TYPE_ARM` + # @api private + CPU_SUBTYPE_ARM_V7M = 15 + + # the v7em sub-type for `CPU_TYPE_ARM` + # @api private + CPU_SUBTYPE_ARM_V7EM = 16 + + # the v8 sub-type for `CPU_TYPE_ARM` + # @api private + CPU_SUBTYPE_ARM_V8 = 13 + + # the lowest common sub-type for `CPU_TYPE_ARM64` + # @api private + CPU_SUBTYPE_ARM64_ALL = 0 + + # the v8 sub-type for `CPU_TYPE_ARM64` + # @api private + CPU_SUBTYPE_ARM64_V8 = 1 + + # the v8 sub-type for `CPU_TYPE_ARM64_32` + # @api private + CPU_SUBTYPE_ARM64_32_V8 = 1 + + # the e (A12) sub-type for `CPU_TYPE_ARM64` + # @api private + CPU_SUBTYPE_ARM64E = 2 + + # the lowest common sub-type for `CPU_TYPE_MC88000` + # @api private + CPU_SUBTYPE_MC88000_ALL = 0 + + # @see CPU_SUBTYPE_MC88000_ALL + # @api private + CPU_SUBTYPE_MMAX_JPC = CPU_SUBTYPE_MC88000_ALL + + # the 100 sub-type for `CPU_TYPE_MC88000` + # @api private + CPU_SUBTYPE_MC88100 = 1 + + # the 110 sub-type for `CPU_TYPE_MC88000` + # @api private + CPU_SUBTYPE_MC88110 = 2 + + # the lowest common sub-type for `CPU_TYPE_POWERPC` + # @api private + CPU_SUBTYPE_POWERPC_ALL = 0 + + # the 601 sub-type for `CPU_TYPE_POWERPC` + # @api private + CPU_SUBTYPE_POWERPC_601 = 1 + + # the 602 sub-type for `CPU_TYPE_POWERPC` + # @api private + CPU_SUBTYPE_POWERPC_602 = 2 + + # the 603 sub-type for `CPU_TYPE_POWERPC` + # @api private + CPU_SUBTYPE_POWERPC_603 = 3 + + # the 603e (G2) sub-type for `CPU_TYPE_POWERPC` + # @api private + CPU_SUBTYPE_POWERPC_603E = 4 + + # the 603ev sub-type for `CPU_TYPE_POWERPC` + # @api private + CPU_SUBTYPE_POWERPC_603EV = 5 + + # the 604 sub-type for `CPU_TYPE_POWERPC` + # @api private + CPU_SUBTYPE_POWERPC_604 = 6 + + # the 604e sub-type for `CPU_TYPE_POWERPC` + # @api private + CPU_SUBTYPE_POWERPC_604E = 7 + + # the 620 sub-type for `CPU_TYPE_POWERPC` + # @api private + CPU_SUBTYPE_POWERPC_620 = 8 + + # the 750 (G3) sub-type for `CPU_TYPE_POWERPC` + # @api private + CPU_SUBTYPE_POWERPC_750 = 9 + + # the 7400 (G4) sub-type for `CPU_TYPE_POWERPC` + # @api private + CPU_SUBTYPE_POWERPC_7400 = 10 + + # the 7450 (G4 "Voyager") sub-type for `CPU_TYPE_POWERPC` + # @api private + CPU_SUBTYPE_POWERPC_7450 = 11 + + # the 970 (G5) sub-type for `CPU_TYPE_POWERPC` + # @api private + CPU_SUBTYPE_POWERPC_970 = 100 + + # any CPU sub-type for CPU type `CPU_TYPE_POWERPC64` + # @api private + CPU_SUBTYPE_POWERPC64_ALL = CPU_SUBTYPE_POWERPC_ALL + + # association of CPU types/subtype pairs to symbol representations in + # (very) roughly descending order of commonness + # @see https://opensource.apple.com/source/cctools/cctools-877.8/libstuff/arch.c + # @api private + CPU_SUBTYPES = { + CPU_TYPE_I386 => { + CPU_SUBTYPE_I386 => :i386, + CPU_SUBTYPE_486 => :i486, + CPU_SUBTYPE_486SX => :i486SX, + CPU_SUBTYPE_586 => :i586, # also "pentium" in arch(3) + CPU_SUBTYPE_PENTPRO => :i686, # also "pentpro" in arch(3) + CPU_SUBTYPE_PENTII_M3 => :pentIIm3, + CPU_SUBTYPE_PENTII_M5 => :pentIIm5, + CPU_SUBTYPE_PENTIUM_4 => :pentium4, + }.freeze, + CPU_TYPE_X86_64 => { + CPU_SUBTYPE_X86_64_ALL => :x86_64, + CPU_SUBTYPE_X86_64_H => :x86_64h, + }.freeze, + CPU_TYPE_ARM => { + CPU_SUBTYPE_ARM_ALL => :arm, + CPU_SUBTYPE_ARM_V4T => :armv4t, + CPU_SUBTYPE_ARM_V6 => :armv6, + CPU_SUBTYPE_ARM_V5TEJ => :armv5, + CPU_SUBTYPE_ARM_XSCALE => :xscale, + CPU_SUBTYPE_ARM_V7 => :armv7, + CPU_SUBTYPE_ARM_V7F => :armv7f, + CPU_SUBTYPE_ARM_V7S => :armv7s, + CPU_SUBTYPE_ARM_V7K => :armv7k, + CPU_SUBTYPE_ARM_V6M => :armv6m, + CPU_SUBTYPE_ARM_V7M => :armv7m, + CPU_SUBTYPE_ARM_V7EM => :armv7em, + CPU_SUBTYPE_ARM_V8 => :armv8, + }.freeze, + CPU_TYPE_ARM64 => { + CPU_SUBTYPE_ARM64_ALL => :arm64, + CPU_SUBTYPE_ARM64_V8 => :arm64v8, + CPU_SUBTYPE_ARM64E => :arm64e, + }.freeze, + CPU_TYPE_ARM64_32 => { + CPU_SUBTYPE_ARM64_32_V8 => :arm64_32v8, + }.freeze, + CPU_TYPE_POWERPC => { + CPU_SUBTYPE_POWERPC_ALL => :ppc, + CPU_SUBTYPE_POWERPC_601 => :ppc601, + CPU_SUBTYPE_POWERPC_603 => :ppc603, + CPU_SUBTYPE_POWERPC_603E => :ppc603e, + CPU_SUBTYPE_POWERPC_603EV => :ppc603ev, + CPU_SUBTYPE_POWERPC_604 => :ppc604, + CPU_SUBTYPE_POWERPC_604E => :ppc604e, + CPU_SUBTYPE_POWERPC_750 => :ppc750, + CPU_SUBTYPE_POWERPC_7400 => :ppc7400, + CPU_SUBTYPE_POWERPC_7450 => :ppc7450, + CPU_SUBTYPE_POWERPC_970 => :ppc970, + }.freeze, + CPU_TYPE_POWERPC64 => { + CPU_SUBTYPE_POWERPC64_ALL => :ppc64, + # apparently the only exception to the naming scheme + CPU_SUBTYPE_POWERPC_970 => :ppc970_64, + }.freeze, + CPU_TYPE_MC680X0 => { + CPU_SUBTYPE_MC680X0_ALL => :m68k, + CPU_SUBTYPE_MC68030 => :mc68030, + CPU_SUBTYPE_MC68040 => :mc68040, + }, + CPU_TYPE_MC88000 => { + CPU_SUBTYPE_MC88000_ALL => :m88k, + }, + }.freeze + + # relocatable object file + # @api private + MH_OBJECT = 0x1 + + # demand paged executable file + # @api private + MH_EXECUTE = 0x2 + + # fixed VM shared library file + # @api private + MH_FVMLIB = 0x3 + + # core dump file + # @api private + MH_CORE = 0x4 + + # preloaded executable file + # @api private + MH_PRELOAD = 0x5 + + # dynamically bound shared library + # @api private + MH_DYLIB = 0x6 + + # dynamic link editor + # @api private + MH_DYLINKER = 0x7 + + # dynamically bound bundle file + # @api private + MH_BUNDLE = 0x8 + + # shared library stub for static linking only, no section contents + # @api private + MH_DYLIB_STUB = 0x9 + + # companion file with only debug sections + # @api private + MH_DSYM = 0xa + + # x86_64 kexts + # @api private + MH_KEXT_BUNDLE = 0xb + + # a set of Mach-Os, running in the same userspace, sharing a linkedit. The kext collection files are an example + # of this object type + # @api private + MH_FILESET = 0xc + + # association of filetypes to Symbol representations + # @api private + MH_FILETYPES = { + MH_OBJECT => :object, + MH_EXECUTE => :execute, + MH_FVMLIB => :fvmlib, + MH_CORE => :core, + MH_PRELOAD => :preload, + MH_DYLIB => :dylib, + MH_DYLINKER => :dylinker, + MH_BUNDLE => :bundle, + MH_DYLIB_STUB => :dylib_stub, + MH_DSYM => :dsym, + MH_KEXT_BUNDLE => :kext_bundle, + MH_FILESET => :fileset, + }.freeze + + # association of mach header flag symbols to values + # @api private + MH_FLAGS = { + :MH_NOUNDEFS => 0x1, + :MH_INCRLINK => 0x2, + :MH_DYLDLINK => 0x4, + :MH_BINDATLOAD => 0x8, + :MH_PREBOUND => 0x10, + :MH_SPLIT_SEGS => 0x20, + :MH_LAZY_INIT => 0x40, + :MH_TWOLEVEL => 0x80, + :MH_FORCE_FLAT => 0x100, + :MH_NOMULTIDEFS => 0x200, + :MH_NOPREFIXBINDING => 0x400, + :MH_PREBINDABLE => 0x800, + :MH_ALLMODSBOUND => 0x1000, + :MH_SUBSECTIONS_VIA_SYMBOLS => 0x2000, + :MH_CANONICAL => 0x4000, + :MH_WEAK_DEFINES => 0x8000, + :MH_BINDS_TO_WEAK => 0x10000, + :MH_ALLOW_STACK_EXECUTION => 0x20000, + :MH_ROOT_SAFE => 0x40000, + :MH_SETUID_SAFE => 0x80000, + :MH_NO_REEXPORTED_DYLIBS => 0x100000, + :MH_PIE => 0x200000, + :MH_DEAD_STRIPPABLE_DYLIB => 0x400000, + :MH_HAS_TLV_DESCRIPTORS => 0x800000, + :MH_NO_HEAP_EXECUTION => 0x1000000, + :MH_APP_EXTENSION_SAFE => 0x02000000, + :MH_NLIST_OUTOFSYNC_WITH_DYLDINFO => 0x04000000, + :MH_SIM_SUPPORT => 0x08000000, + :MH_DYLIB_IN_CACHE => 0x80000000, + }.freeze + + # Fat binary header structure + # @see MachO::FatArch + class FatHeader < MachOStructure + # @return [Integer] the magic number of the header (and file) + field :magic, :uint32, :endian => :big + + # @return [Integer] the number of fat architecture structures following the header + field :nfat_arch, :uint32, :endian => :big + + # @return [String] the serialized fields of the fat header + def serialize + [magic, nfat_arch].pack(self.class.format) + end + + # @return [Hash] a hash representation of this {FatHeader} + def to_h + { + "magic" => magic, + "magic_sym" => MH_MAGICS[magic], + "nfat_arch" => nfat_arch, + }.merge super + end + end + + # 32-bit fat binary header architecture structure. A 32-bit fat Mach-O has one or more of + # these, indicating one or more internal Mach-O blobs. + # @note "32-bit" indicates the fact that this structure stores 32-bit offsets, not that the + # Mach-Os that it points to necessarily *are* 32-bit. + # @see MachO::Headers::FatHeader + class FatArch < MachOStructure + # @return [Integer] the CPU type of the Mach-O + field :cputype, :uint32, :endian => :big + + # @return [Integer] the CPU subtype of the Mach-O + field :cpusubtype, :uint32, :endian => :big, :mask => CPU_SUBTYPE_MASK + + # @return [Integer] the file offset to the beginning of the Mach-O data + field :offset, :uint32, :endian => :big + + # @return [Integer] the size, in bytes, of the Mach-O data + field :size, :uint32, :endian => :big + + # @return [Integer] the alignment, as a power of 2 + field :align, :uint32, :endian => :big + + # @return [String] the serialized fields of the fat arch + def serialize + [cputype, cpusubtype, offset, size, align].pack(self.class.format) + end + + # @return [Hash] a hash representation of this {FatArch} + def to_h + { + "cputype" => cputype, + "cputype_sym" => CPU_TYPES[cputype], + "cpusubtype" => cpusubtype, + "cpusubtype_sym" => CPU_SUBTYPES[cputype][cpusubtype], + "offset" => offset, + "size" => size, + "align" => align, + }.merge super + end + end + + # 64-bit fat binary header architecture structure. A 64-bit fat Mach-O has one or more of + # these, indicating one or more internal Mach-O blobs. + # @note "64-bit" indicates the fact that this structure stores 64-bit offsets, not that the + # Mach-Os that it points to necessarily *are* 64-bit. + # @see MachO::Headers::FatHeader + class FatArch64 < FatArch + # @return [Integer] the file offset to the beginning of the Mach-O data + field :offset, :uint64, :endian => :big + + # @return [Integer] the size, in bytes, of the Mach-O data + field :size, :uint64, :endian => :big + + # @return [void] + field :reserved, :uint32, :endian => :big, :default => 0 + + # @return [String] the serialized fields of the fat arch + def serialize + [cputype, cpusubtype, offset, size, align, reserved].pack(self.class.format) + end + + # @return [Hash] a hash representation of this {FatArch64} + def to_h + { + "reserved" => reserved, + }.merge super + end + end + + # 32-bit Mach-O file header structure + class MachHeader < MachOStructure + # @return [Integer] the magic number + field :magic, :uint32 + + # @return [Integer] the CPU type of the Mach-O + field :cputype, :uint32 + + # @return [Integer] the CPU subtype of the Mach-O + field :cpusubtype, :uint32, :mask => CPU_SUBTYPE_MASK + + # @return [Integer] the file type of the Mach-O + field :filetype, :uint32 + + # @return [Integer] the number of load commands in the Mach-O + field :ncmds, :uint32 + + # @return [Integer] the size of all load commands, in bytes, in the Mach-O + field :sizeofcmds, :uint32 + + # @return [Integer] the header flags associated with the Mach-O + field :flags, :uint32 + + # @example + # puts "this mach-o has position-independent execution" if header.flag?(:MH_PIE) + # @param flag [Symbol] a mach header flag symbol + # @return [Boolean] true if `flag` is present in the header's flag section + def flag?(flag) + flag = MH_FLAGS[flag] + + return false if flag.nil? + + flags & flag == flag + end + + # @return [Boolean] whether or not the file is of type `MH_OBJECT` + def object? + filetype == Headers::MH_OBJECT + end + + # @return [Boolean] whether or not the file is of type `MH_EXECUTE` + def executable? + filetype == Headers::MH_EXECUTE + end + + # @return [Boolean] whether or not the file is of type `MH_FVMLIB` + def fvmlib? + filetype == Headers::MH_FVMLIB + end + + # @return [Boolean] whether or not the file is of type `MH_CORE` + def core? + filetype == Headers::MH_CORE + end + + # @return [Boolean] whether or not the file is of type `MH_PRELOAD` + def preload? + filetype == Headers::MH_PRELOAD + end + + # @return [Boolean] whether or not the file is of type `MH_DYLIB` + def dylib? + filetype == Headers::MH_DYLIB + end + + # @return [Boolean] whether or not the file is of type `MH_DYLINKER` + def dylinker? + filetype == Headers::MH_DYLINKER + end + + # @return [Boolean] whether or not the file is of type `MH_BUNDLE` + def bundle? + filetype == Headers::MH_BUNDLE + end + + # @return [Boolean] whether or not the file is of type `MH_DSYM` + def dsym? + filetype == Headers::MH_DSYM + end + + # @return [Boolean] whether or not the file is of type `MH_KEXT_BUNDLE` + def kext? + filetype == Headers::MH_KEXT_BUNDLE + end + + # @return [Boolean] whether or not the file is of type `MH_FILESET` + def fileset? + filetype == Headers::MH_FILESET + end + + # @return [Boolean] true if the Mach-O has 32-bit magic, false otherwise + def magic32? + Utils.magic32?(magic) + end + + # @return [Boolean] true if the Mach-O has 64-bit magic, false otherwise + def magic64? + Utils.magic64?(magic) + end + + # @return [Integer] the file's internal alignment + def alignment + magic32? ? 4 : 8 + end + + # @return [Hash] a hash representation of this {MachHeader} + def to_h + { + "magic" => magic, + "magic_sym" => MH_MAGICS[magic], + "cputype" => cputype, + "cputype_sym" => CPU_TYPES[cputype], + "cpusubtype" => cpusubtype, + "cpusubtype_sym" => CPU_SUBTYPES[cputype][cpusubtype], + "filetype" => filetype, + "filetype_sym" => MH_FILETYPES[filetype], + "ncmds" => ncmds, + "sizeofcmds" => sizeofcmds, + "flags" => flags, + "alignment" => alignment, + }.merge super + end + end + + # 64-bit Mach-O file header structure + class MachHeader64 < MachHeader + # @return [void] + field :reserved, :uint32 + + # @return [Hash] a hash representation of this {MachHeader64} + def to_h + { + "reserved" => reserved, + }.merge super + end + end + + # Prelinked kernel/"kernelcache" header structure + class PrelinkedKernelHeader < MachOStructure + # @return [Integer] the magic number for a compressed header ({COMPRESSED_MAGIC}) + field :signature, :uint32, :endian => :big + + # @return [Integer] the type of compression used + field :compress_type, :uint32, :endian => :big + + # @return [Integer] a checksum for the uncompressed data + field :adler32, :uint32, :endian => :big + + # @return [Integer] the size of the uncompressed data, in bytes + field :uncompressed_size, :uint32, :endian => :big + + # @return [Integer] the size of the compressed data, in bytes + field :compressed_size, :uint32, :endian => :big + + # @return [Integer] the version of the prelink format + field :prelink_version, :uint32, :endian => :big + + # @return [void] + field :reserved, :string, :size => 40, :unpack => "L>10" + + # @return [void] + field :platform_name, :string, :size => 64 + + # @return [void] + field :root_path, :string, :size => 256 + + # @return [Boolean] whether this prelinked kernel supports KASLR + def kaslr? + prelink_version >= 1 + end + + # @return [Boolean] whether this prelinked kernel is compressed with LZSS + def lzss? + compress_type == COMP_TYPE_LZSS + end + + # @return [Boolean] whether this prelinked kernel is compressed with LZVN + def lzvn? + compress_type == COMP_TYPE_FASTLIB + end + + # @return [Hash] a hash representation of this {PrelinkedKernelHeader} + def to_h + { + "signature" => signature, + "compress_type" => compress_type, + "adler32" => adler32, + "uncompressed_size" => uncompressed_size, + "compressed_size" => compressed_size, + "prelink_version" => prelink_version, + "reserved" => reserved, + "platform_name" => platform_name, + "root_path" => root_path, + }.merge super + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/ruby-macho-4.0.0/lib/macho/load_commands.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/ruby-macho-4.0.0/lib/macho/load_commands.rb new file mode 100644 index 0000000000..c420c8bd99 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/ruby-macho-4.0.0/lib/macho/load_commands.rb @@ -0,0 +1,1378 @@ +# frozen_string_literal: true + +module MachO + # Classes and constants for parsing load commands in Mach-O binaries. + module LoadCommands + # load commands added after OS X 10.1 need to be bitwise ORed with + # LC_REQ_DYLD to be recognized by the dynamic linker (dyld) + # @api private + LC_REQ_DYLD = 0x80000000 + + # association of load commands to symbol representations + # @api private + LOAD_COMMANDS = { + 0x1 => :LC_SEGMENT, + 0x2 => :LC_SYMTAB, + 0x3 => :LC_SYMSEG, + 0x4 => :LC_THREAD, + 0x5 => :LC_UNIXTHREAD, + 0x6 => :LC_LOADFVMLIB, + 0x7 => :LC_IDFVMLIB, + 0x8 => :LC_IDENT, + 0x9 => :LC_FVMFILE, + 0xa => :LC_PREPAGE, + 0xb => :LC_DYSYMTAB, + 0xc => :LC_LOAD_DYLIB, + 0xd => :LC_ID_DYLIB, + 0xe => :LC_LOAD_DYLINKER, + 0xf => :LC_ID_DYLINKER, + 0x10 => :LC_PREBOUND_DYLIB, + 0x11 => :LC_ROUTINES, + 0x12 => :LC_SUB_FRAMEWORK, + 0x13 => :LC_SUB_UMBRELLA, + 0x14 => :LC_SUB_CLIENT, + 0x15 => :LC_SUB_LIBRARY, + 0x16 => :LC_TWOLEVEL_HINTS, + 0x17 => :LC_PREBIND_CKSUM, + (LC_REQ_DYLD | 0x18) => :LC_LOAD_WEAK_DYLIB, + 0x19 => :LC_SEGMENT_64, + 0x1a => :LC_ROUTINES_64, + 0x1b => :LC_UUID, + (LC_REQ_DYLD | 0x1c) => :LC_RPATH, + 0x1d => :LC_CODE_SIGNATURE, + 0x1e => :LC_SEGMENT_SPLIT_INFO, + (LC_REQ_DYLD | 0x1f) => :LC_REEXPORT_DYLIB, + 0x20 => :LC_LAZY_LOAD_DYLIB, + 0x21 => :LC_ENCRYPTION_INFO, + 0x22 => :LC_DYLD_INFO, + (LC_REQ_DYLD | 0x22) => :LC_DYLD_INFO_ONLY, + (LC_REQ_DYLD | 0x23) => :LC_LOAD_UPWARD_DYLIB, + 0x24 => :LC_VERSION_MIN_MACOSX, + 0x25 => :LC_VERSION_MIN_IPHONEOS, + 0x26 => :LC_FUNCTION_STARTS, + 0x27 => :LC_DYLD_ENVIRONMENT, + (LC_REQ_DYLD | 0x28) => :LC_MAIN, + 0x29 => :LC_DATA_IN_CODE, + 0x2a => :LC_SOURCE_VERSION, + 0x2b => :LC_DYLIB_CODE_SIGN_DRS, + 0x2c => :LC_ENCRYPTION_INFO_64, + 0x2d => :LC_LINKER_OPTION, + 0x2e => :LC_LINKER_OPTIMIZATION_HINT, + 0x2f => :LC_VERSION_MIN_TVOS, + 0x30 => :LC_VERSION_MIN_WATCHOS, + 0x31 => :LC_NOTE, + 0x32 => :LC_BUILD_VERSION, + (LC_REQ_DYLD | 0x33) => :LC_DYLD_EXPORTS_TRIE, + (LC_REQ_DYLD | 0x34) => :LC_DYLD_CHAINED_FIXUPS, + (LC_REQ_DYLD | 0x35) => :LC_FILESET_ENTRY, + }.freeze + + # association of symbol representations to load command constants + # @api private + LOAD_COMMAND_CONSTANTS = LOAD_COMMANDS.invert.freeze + + # load commands responsible for loading dylibs + # @api private + DYLIB_LOAD_COMMANDS = %i[ + LC_LOAD_DYLIB + LC_LOAD_WEAK_DYLIB + LC_REEXPORT_DYLIB + LC_LAZY_LOAD_DYLIB + LC_LOAD_UPWARD_DYLIB + ].freeze + + # load commands that can be created manually via {LoadCommand.create} + # @api private + CREATABLE_LOAD_COMMANDS = DYLIB_LOAD_COMMANDS + %i[ + LC_ID_DYLIB + LC_RPATH + LC_LOAD_DYLINKER + ].freeze + + # association of load command symbols to string representations of classes + # @api private + LC_STRUCTURES = { + :LC_SEGMENT => "SegmentCommand", + :LC_SYMTAB => "SymtabCommand", + # "obsolete" + :LC_SYMSEG => "SymsegCommand", + # seems obsolete, but not documented as such + :LC_THREAD => "ThreadCommand", + :LC_UNIXTHREAD => "ThreadCommand", + # "obsolete" + :LC_LOADFVMLIB => "FvmlibCommand", + # "obsolete" + :LC_IDFVMLIB => "FvmlibCommand", + # "obsolete" + :LC_IDENT => "IdentCommand", + # "reserved for internal use only" + :LC_FVMFILE => "FvmfileCommand", + # "reserved for internal use only", no public struct + :LC_PREPAGE => "LoadCommand", + :LC_DYSYMTAB => "DysymtabCommand", + :LC_LOAD_DYLIB => "DylibCommand", + :LC_ID_DYLIB => "DylibCommand", + :LC_LOAD_DYLINKER => "DylinkerCommand", + :LC_ID_DYLINKER => "DylinkerCommand", + :LC_PREBOUND_DYLIB => "PreboundDylibCommand", + :LC_ROUTINES => "RoutinesCommand", + :LC_SUB_FRAMEWORK => "SubFrameworkCommand", + :LC_SUB_UMBRELLA => "SubUmbrellaCommand", + :LC_SUB_CLIENT => "SubClientCommand", + :LC_SUB_LIBRARY => "SubLibraryCommand", + :LC_TWOLEVEL_HINTS => "TwolevelHintsCommand", + :LC_PREBIND_CKSUM => "PrebindCksumCommand", + :LC_LOAD_WEAK_DYLIB => "DylibCommand", + :LC_SEGMENT_64 => "SegmentCommand64", + :LC_ROUTINES_64 => "RoutinesCommand64", + :LC_UUID => "UUIDCommand", + :LC_RPATH => "RpathCommand", + :LC_CODE_SIGNATURE => "LinkeditDataCommand", + :LC_SEGMENT_SPLIT_INFO => "LinkeditDataCommand", + :LC_REEXPORT_DYLIB => "DylibCommand", + :LC_LAZY_LOAD_DYLIB => "DylibCommand", + :LC_ENCRYPTION_INFO => "EncryptionInfoCommand", + :LC_DYLD_INFO => "DyldInfoCommand", + :LC_DYLD_INFO_ONLY => "DyldInfoCommand", + :LC_LOAD_UPWARD_DYLIB => "DylibCommand", + :LC_VERSION_MIN_MACOSX => "VersionMinCommand", + :LC_VERSION_MIN_IPHONEOS => "VersionMinCommand", + :LC_FUNCTION_STARTS => "LinkeditDataCommand", + :LC_DYLD_ENVIRONMENT => "DylinkerCommand", + :LC_MAIN => "EntryPointCommand", + :LC_DATA_IN_CODE => "LinkeditDataCommand", + :LC_SOURCE_VERSION => "SourceVersionCommand", + :LC_DYLIB_CODE_SIGN_DRS => "LinkeditDataCommand", + :LC_ENCRYPTION_INFO_64 => "EncryptionInfoCommand64", + :LC_LINKER_OPTION => "LinkerOptionCommand", + :LC_LINKER_OPTIMIZATION_HINT => "LinkeditDataCommand", + :LC_VERSION_MIN_TVOS => "VersionMinCommand", + :LC_VERSION_MIN_WATCHOS => "VersionMinCommand", + :LC_NOTE => "NoteCommand", + :LC_BUILD_VERSION => "BuildVersionCommand", + :LC_DYLD_EXPORTS_TRIE => "LinkeditDataCommand", + :LC_DYLD_CHAINED_FIXUPS => "LinkeditDataCommand", + :LC_FILESET_ENTRY => "FilesetEntryCommand", + }.freeze + + # association of segment name symbols to names + # @api private + SEGMENT_NAMES = { + :SEG_PAGEZERO => "__PAGEZERO", + :SEG_TEXT => "__TEXT", + :SEG_TEXT_EXEC => "__TEXT_EXEC", + :SEG_DATA => "__DATA", + :SEG_DATA_CONST => "__DATA_CONST", + :SEG_OBJC => "__OBJC", + :SEG_OBJC_CONST => "__OBJC_CONST", + :SEG_ICON => "__ICON", + :SEG_LINKEDIT => "__LINKEDIT", + :SEG_LINKINFO => "__LINKINFO", + :SEG_UNIXSTACK => "__UNIXSTACK", + :SEG_IMPORT => "__IMPORT", + :SEG_KLD => "__KLD", + :SEG_KLDDATA => "__KLDDATA", + :SEG_HIB => "__HIB", + :SEG_VECTORS => "__VECTORS", + :SEG_LAST => "__LAST", + :SEG_LASTDATA_CONST => "__LASTDATA_CONST", + :SEG_PRELINK_TEXT => "__PRELINK_TEXT", + :SEG_PRELINK_INFO => "__PRELINK_INFO", + :SEG_CTF => "__CTF", + :SEG_AUTH => "__AUTH", + :SEG_AUTH_CONST => "__AUTH_CONST", + }.freeze + + # association of segment flag symbols to values + # @api private + SEGMENT_FLAGS = { + :SG_HIGHVM => 0x1, + :SG_FVMLIB => 0x2, + :SG_NORELOC => 0x4, + :SG_PROTECTED_VERSION_1 => 0x8, + :SG_READ_ONLY => 0x10, + }.freeze + + # The top-level Mach-O load command structure. + # + # This is the most generic load command -- only the type ID and size are + # represented. Used when a more specific class isn't available or isn't implemented. + class LoadCommand < MachOStructure + # @return [MachO::MachOView, nil] the raw view associated with the load command, + # or nil if the load command was created via {create}. + field :view, :view + + # @return [Integer] the load command's type ID + field :cmd, :uint32 + + # @return [Integer] the size of the load command, in bytes + field :cmdsize, :uint32 + + # Instantiates a new LoadCommand given a view into its origin Mach-O + # @param view [MachO::MachOView] the load command's raw view + # @return [LoadCommand] the new load command + # @api private + def self.new_from_bin(view) + bin = view.raw_data.slice(view.offset, bytesize) + format = Utils.specialize_format(self.format, view.endianness) + + new(view, *bin.unpack(format)) + end + + # Creates a new (viewless) command corresponding to the symbol provided + # @param cmd_sym [Symbol] the symbol of the load command being created + # @param args [Array] the arguments for the load command being created + def self.create(cmd_sym, *args) + raise LoadCommandNotCreatableError, cmd_sym unless CREATABLE_LOAD_COMMANDS.include?(cmd_sym) + + klass = LoadCommands.const_get LC_STRUCTURES[cmd_sym] + cmd = LOAD_COMMAND_CONSTANTS[cmd_sym] + + # cmd will be filled in, view and cmdsize will be left unpopulated + klass_arity = klass.min_args - 3 + + raise LoadCommandCreationArityError.new(cmd_sym, klass_arity, args.size) if klass_arity > args.size + + klass.new(nil, cmd, nil, *args) + end + + # @return [Boolean] whether the load command can be serialized + def serializable? + CREATABLE_LOAD_COMMANDS.include?(LOAD_COMMANDS[cmd]) + end + + # @param context [SerializationContext] the context + # to serialize into + # @return [String, nil] the serialized fields of the load command, or nil + # if the load command can't be serialized + # @api private + def serialize(context) + raise LoadCommandNotSerializableError, LOAD_COMMANDS[cmd] unless serializable? + + format = Utils.specialize_format(self.class.format, context.endianness) + [cmd, self.class.bytesize].pack(format) + end + + # @return [Integer] the load command's offset in the source file + # @deprecated use {#view} instead + def offset + view.offset + end + + # @return [Symbol, nil] a symbol representation of the load command's + # type ID, or nil if the ID doesn't correspond to a known load command class + def type + LOAD_COMMANDS[cmd] + end + + alias to_sym type + + # @return [String] a string representation of the load command's + # identifying number + def to_s + type.to_s + end + + # @return [Hash] a hash representation of this load command + # @note Children should override this to include additional information. + def to_h + { + "view" => view.to_h, + "cmd" => cmd, + "cmdsize" => cmdsize, + "type" => type, + }.merge super + end + + # Represents a Load Command string. A rough analogue to the lc_str + # struct used internally by OS X. This class allows ruby-macho to + # pretend that strings stored in LCs are immediately available without + # explicit operations on the raw Mach-O data. + class LCStr + # @param lc [LoadCommand] the load command + # @param lc_str [Integer, String] the offset to the beginning of the + # string, or the string itself if not being initialized with a view. + # @raise [MachO::LCStrMalformedError] if the string is malformed + # @todo devise a solution such that the `lc_str` parameter is not + # interpreted differently depending on `lc.view`. The current behavior + # is a hack to allow viewless load command creation. + # @api private + def initialize(lc, lc_str) + view = lc.view + + if view + lc_str_abs = view.offset + lc_str + lc_end = view.offset + lc.cmdsize - 1 + raw_string = view.raw_data.slice(lc_str_abs..lc_end) + @string, null_byte, _padding = raw_string.partition("\x00") + + raise LCStrMalformedError, lc if null_byte.empty? + + @string_offset = lc_str + else + @string = lc_str + @string_offset = 0 + end + end + + # @return [String] a string representation of the LCStr + def to_s + @string + end + + # @return [Integer] the offset to the beginning of the string in the + # load command + def to_i + @string_offset + end + + # @return [Hash] a hash representation of this {LCStr}. + def to_h + { + "string" => to_s, + "offset" => to_i, + } + end + end + + # Represents the contextual information needed by a load command to + # serialize itself correctly into a binary string. + class SerializationContext + # @return [Symbol] the endianness of the serialized load command + attr_reader :endianness + + # @return [Integer] the constant alignment value used to pad the + # serialized load command + attr_reader :alignment + + # @param macho [MachO::MachOFile] the file to contextualize + # @return [SerializationContext] the + # resulting context + def self.context_for(macho) + new(macho.endianness, macho.alignment) + end + + # @param endianness [Symbol] the endianness of the context + # @param alignment [Integer] the alignment of the context + # @api private + def initialize(endianness, alignment) + @endianness = endianness + @alignment = alignment + end + end + end + + # A load command containing a single 128-bit unique random number + # identifying an object produced by static link editor. Corresponds to + # LC_UUID. + class UUIDCommand < LoadCommand + # @return [Array] the UUID + field :uuid, :string, :size => 16, :unpack => "C16" + + # @return [String] a string representation of the UUID + def uuid_string + hexes = uuid.map { |elem| "%02x" % { :elem => elem } } + segs = [ + hexes[0..3].join, hexes[4..5].join, hexes[6..7].join, + hexes[8..9].join, hexes[10..15].join + ] + + segs.join("-") + end + + # @return [String] an alias for uuid_string + def to_s + uuid_string + end + + # @return [Hash] returns a hash representation of this {UUIDCommand} + def to_h + { + "uuid" => uuid, + "uuid_string" => uuid_string, + }.merge super + end + end + + # A load command indicating that part of this file is to be mapped into + # the task's address space. Corresponds to LC_SEGMENT. + class SegmentCommand < LoadCommand + # @return [String] the name of the segment + field :segname, :string, :padding => :null, :size => 16, :to_s => true + + # @return [Integer] the memory address of the segment + field :vmaddr, :uint32 + + # @return [Integer] the memory size of the segment + field :vmsize, :uint32 + + # @return [Integer] the file offset of the segment + field :fileoff, :uint32 + + # @return [Integer] the amount to map from the file + field :filesize, :uint32 + + # @return [Integer] the maximum VM protection + field :maxprot, :int32 + + # @return [Integer] the initial VM protection + field :initprot, :int32 + + # @return [Integer] the number of sections in the segment + field :nsects, :uint32 + + # @return [Integer] any flags associated with the segment + field :flags, :uint32 + + # All sections referenced within this segment. + # @return [Array] if the Mach-O is 32-bit + # @return [Array] if the Mach-O is 64-bit + def sections + klass = case self + when SegmentCommand64 + MachO::Sections::Section64 + when SegmentCommand + MachO::Sections::Section + end + + offset = view.offset + self.class.bytesize + length = nsects * klass.bytesize + + bins = view.raw_data[offset, length] + bins.unpack("a#{klass.bytesize}" * nsects).map do |bin| + klass.new_from_bin(view.endianness, bin) + end + end + + # @example + # puts "this segment relocated in/to it" if sect.flag?(:SG_NORELOC) + # @param flag [Symbol] a segment flag symbol + # @return [Boolean] true if `flag` is present in the segment's flag field + def flag?(flag) + flag = SEGMENT_FLAGS[flag] + + return false if flag.nil? + + flags & flag == flag + end + + # Guesses the alignment of the segment. + # @return [Integer] the guessed alignment, as a power of 2 + # @note See `guess_align` in `cctools/misc/lipo.c` + def guess_align + return Sections::MAX_SECT_ALIGN if vmaddr.zero? + + align = 0 + segalign = 1 + + while (segalign & vmaddr).zero? + segalign <<= 1 + align += 1 + end + + return 2 if align < 2 + return Sections::MAX_SECT_ALIGN if align > Sections::MAX_SECT_ALIGN + + align + end + + # @return [Hash] a hash representation of this {SegmentCommand} + def to_h + { + "segname" => segname, + "vmaddr" => vmaddr, + "vmsize" => vmsize, + "fileoff" => fileoff, + "filesize" => filesize, + "maxprot" => maxprot, + "initprot" => initprot, + "nsects" => nsects, + "flags" => flags, + "sections" => sections.map(&:to_h), + }.merge super + end + end + + # A load command indicating that part of this file is to be mapped into + # the task's address space. Corresponds to LC_SEGMENT_64. + class SegmentCommand64 < SegmentCommand + # @return [Integer] the memory address of the segment + field :vmaddr, :uint64 + + # @return [Integer] the memory size of the segment + field :vmsize, :uint64 + + # @return [Integer] the file offset of the segment + field :fileoff, :uint64 + + # @return [Integer] the amount to map from the file + field :filesize, :uint64 + end + + # A load command representing some aspect of shared libraries, depending + # on filetype. Corresponds to LC_ID_DYLIB, LC_LOAD_DYLIB, + # LC_LOAD_WEAK_DYLIB, and LC_REEXPORT_DYLIB. + class DylibCommand < LoadCommand + # @return [LCStr] the library's path + # name as an LCStr + field :name, :lcstr, :to_s => true + + # @return [Integer] the library's build time stamp + field :timestamp, :uint32 + + # @return [Integer] the library's current version number + field :current_version, :uint32 + + # @return [Integer] the library's compatibility version number + field :compatibility_version, :uint32 + + # @param context [SerializationContext] + # the context + # @return [String] the serialized fields of the load command + # @api private + def serialize(context) + format = Utils.specialize_format(self.class.format, context.endianness) + string_payload, string_offsets = Utils.pack_strings(self.class.bytesize, + context.alignment, + :name => name.to_s) + cmdsize = self.class.bytesize + string_payload.bytesize + [cmd, cmdsize, string_offsets[:name], timestamp, current_version, + compatibility_version].pack(format) + string_payload + end + + # @return [Hash] a hash representation of this {DylibCommand} + def to_h + { + "name" => name.to_h, + "timestamp" => timestamp, + "current_version" => current_version, + "compatibility_version" => compatibility_version, + }.merge super + end + end + + # A load command representing some aspect of the dynamic linker, depending + # on filetype. Corresponds to LC_ID_DYLINKER, LC_LOAD_DYLINKER, and + # LC_DYLD_ENVIRONMENT. + class DylinkerCommand < LoadCommand + # @return [LCStr] the dynamic linker's + # path name as an LCStr + field :name, :lcstr, :to_s => true + + # @param context [SerializationContext] + # the context + # @return [String] the serialized fields of the load command + # @api private + def serialize(context) + format = Utils.specialize_format(self.class.format, context.endianness) + string_payload, string_offsets = Utils.pack_strings(self.class.bytesize, + context.alignment, + :name => name.to_s) + cmdsize = self.class.bytesize + string_payload.bytesize + [cmd, cmdsize, string_offsets[:name]].pack(format) + string_payload + end + + # @return [Hash] a hash representation of this {DylinkerCommand} + def to_h + { + "name" => name.to_h, + }.merge super + end + end + + # A load command used to indicate dynamic libraries used in prebinding. + # Corresponds to LC_PREBOUND_DYLIB. + class PreboundDylibCommand < LoadCommand + # @return [LCStr] the library's path + # name as an LCStr + field :name, :lcstr, :to_s => true + + # @return [Integer] the number of modules in the library + field :nmodules, :uint32 + + # @return [Integer] a bit vector of linked modules + field :linked_modules, :uint32 + + # @return [Hash] a hash representation of this {PreboundDylibCommand} + def to_h + { + "name" => name.to_h, + "nmodules" => nmodules, + "linked_modules" => linked_modules, + }.merge super + end + end + + # A load command used to represent threads. + # @note cctools-870 and onwards have all fields of thread_command commented + # out except the common ones (cmd, cmdsize) + class ThreadCommand < LoadCommand + end + + # A load command containing the address of the dynamic shared library + # initialization routine and an index into the module table for the module + # that defines the routine. Corresponds to LC_ROUTINES. + class RoutinesCommand < LoadCommand + # @return [Integer] the address of the initialization routine + field :init_address, :uint32 + + # @return [Integer] the index into the module table that the init routine + # is defined in + field :init_module, :uint32 + + # @return [void] + field :reserved1, :uint32 + + # @return [void] + field :reserved2, :uint32 + + # @return [void] + field :reserved3, :uint32 + + # @return [void] + field :reserved4, :uint32 + + # @return [void] + field :reserved5, :uint32 + + # @return [void] + field :reserved6, :uint32 + + # @return [Hash] a hash representation of this {RoutinesCommand} + def to_h + { + "init_address" => init_address, + "init_module" => init_module, + "reserved1" => reserved1, + "reserved2" => reserved2, + "reserved3" => reserved3, + "reserved4" => reserved4, + "reserved5" => reserved5, + "reserved6" => reserved6, + }.merge super + end + end + + # A load command containing the address of the dynamic shared library + # initialization routine and an index into the module table for the module + # that defines the routine. Corresponds to LC_ROUTINES_64. + class RoutinesCommand64 < RoutinesCommand + # @return [Integer] the address of the initialization routine + field :init_address, :uint64 + + # @return [Integer] the index into the module table that the init routine + # is defined in + field :init_module, :uint64 + + # @return [void] + field :reserved1, :uint64 + + # @return [void] + field :reserved2, :uint64 + + # @return [void] + field :reserved3, :uint64 + + # @return [void] + field :reserved4, :uint64 + + # @return [void] + field :reserved5, :uint64 + + # @return [void] + field :reserved6, :uint64 + end + + # A load command signifying membership of a subframework containing the name + # of an umbrella framework. Corresponds to LC_SUB_FRAMEWORK. + class SubFrameworkCommand < LoadCommand + # @return [LCStr] the umbrella framework name as an LCStr + field :umbrella, :lcstr, :to_s => true + + # @return [Hash] a hash representation of this {SubFrameworkCommand} + def to_h + { + "umbrella" => umbrella.to_h, + }.merge super + end + end + + # A load command signifying membership of a subumbrella containing the name + # of an umbrella framework. Corresponds to LC_SUB_UMBRELLA. + class SubUmbrellaCommand < LoadCommand + # @return [LCStr] the subumbrella framework name as an LCStr + field :sub_umbrella, :lcstr, :to_s => true + + # @return [Hash] a hash representation of this {SubUmbrellaCommand} + def to_h + { + "sub_umbrella" => sub_umbrella.to_h, + }.merge super + end + end + + # A load command signifying a sublibrary of a shared library. Corresponds + # to LC_SUB_LIBRARY. + class SubLibraryCommand < LoadCommand + # @return [LCStr] the sublibrary name as an LCStr + field :sub_library, :lcstr, :to_s => true + + # @return [Hash] a hash representation of this {SubLibraryCommand} + def to_h + { + "sub_library" => sub_library.to_h, + }.merge super + end + end + + # A load command signifying a shared library that is a subframework of + # an umbrella framework. Corresponds to LC_SUB_CLIENT. + class SubClientCommand < LoadCommand + # @return [LCStr] the subclient name as an LCStr + field :sub_client, :lcstr, :to_s => true + + # @return [Hash] a hash representation of this {SubClientCommand} + def to_h + { + "sub_client" => sub_client.to_h, + }.merge super + end + end + + # A load command containing the offsets and sizes of the link-edit 4.3BSD + # "stab" style symbol table information. Corresponds to LC_SYMTAB. + class SymtabCommand < LoadCommand + # @return [Integer] the symbol table's offset + field :symoff, :uint32 + + # @return [Integer] the number of symbol table entries + field :nsyms, :uint32 + + # @return [Integer] the string table's offset + field :stroff, :uint32 + + # @return [Integer] the string table size in bytes + field :strsize, :uint32 + + # @return [Hash] a hash representation of this {SymtabCommand} + def to_h + { + "symoff" => symoff, + "nsyms" => nsyms, + "stroff" => stroff, + "strsize" => strsize, + }.merge super + end + end + + # A load command containing symbolic information needed to support data + # structures used by the dynamic link editor. Corresponds to LC_DYSYMTAB. + class DysymtabCommand < LoadCommand + # @return [Integer] the index to local symbols + field :ilocalsym, :uint32 + + # @return [Integer] the number of local symbols + field :nlocalsym, :uint32 + + # @return [Integer] the index to externally defined symbols + field :iextdefsym, :uint32 + + # @return [Integer] the number of externally defined symbols + field :nextdefsym, :uint32 + + # @return [Integer] the index to undefined symbols + field :iundefsym, :uint32 + + # @return [Integer] the number of undefined symbols + field :nundefsym, :uint32 + + # @return [Integer] the file offset to the table of contents + field :tocoff, :uint32 + + # @return [Integer] the number of entries in the table of contents + field :ntoc, :uint32 + + # @return [Integer] the file offset to the module table + field :modtaboff, :uint32 + + # @return [Integer] the number of entries in the module table + field :nmodtab, :uint32 + + # @return [Integer] the file offset to the referenced symbol table + field :extrefsymoff, :uint32 + + # @return [Integer] the number of entries in the referenced symbol table + field :nextrefsyms, :uint32 + + # @return [Integer] the file offset to the indirect symbol table + field :indirectsymoff, :uint32 + + # @return [Integer] the number of entries in the indirect symbol table + field :nindirectsyms, :uint32 + + # @return [Integer] the file offset to the external relocation entries + field :extreloff, :uint32 + + # @return [Integer] the number of external relocation entries + field :nextrel, :uint32 + + # @return [Integer] the file offset to the local relocation entries + field :locreloff, :uint32 + + # @return [Integer] the number of local relocation entries + field :nlocrel, :uint32 + + # @return [Hash] a hash representation of this {DysymtabCommand} + def to_h + { + "ilocalsym" => ilocalsym, + "nlocalsym" => nlocalsym, + "iextdefsym" => iextdefsym, + "nextdefsym" => nextdefsym, + "iundefsym" => iundefsym, + "nundefsym" => nundefsym, + "tocoff" => tocoff, + "ntoc" => ntoc, + "modtaboff" => modtaboff, + "nmodtab" => nmodtab, + "extrefsymoff" => extrefsymoff, + "nextrefsyms" => nextrefsyms, + "indirectsymoff" => indirectsymoff, + "nindirectsyms" => nindirectsyms, + "extreloff" => extreloff, + "nextrel" => nextrel, + "locreloff" => locreloff, + "nlocrel" => nlocrel, + }.merge super + end + end + + # A load command containing the offset and number of hints in the two-level + # namespace lookup hints table. Corresponds to LC_TWOLEVEL_HINTS. + class TwolevelHintsCommand < LoadCommand + # @return [Integer] the offset to the hint table + field :htoffset, :uint32 + + # @return [Integer] the number of hints in the hint table + field :nhints, :uint32 + + # @return [TwolevelHintsTable] + # the hint table + field :table, :two_level_hints_table + + # @return [Hash] a hash representation of this {TwolevelHintsCommand} + def to_h + { + "htoffset" => htoffset, + "nhints" => nhints, + "table" => table.hints.map(&:to_h), + }.merge super + end + + # A representation of the two-level namespace lookup hints table exposed + # by a {TwolevelHintsCommand} (`LC_TWOLEVEL_HINTS`). + class TwolevelHintsTable + # @return [Array] all hints in the table + attr_reader :hints + + # @param view [MachO::MachOView] the view into the current Mach-O + # @param htoffset [Integer] the offset of the hints table + # @param nhints [Integer] the number of two-level hints in the table + # @api private + def initialize(view, htoffset, nhints) + format = Utils.specialize_format("L=#{nhints}", view.endianness) + raw_table = view.raw_data[htoffset, nhints * 4] + blobs = raw_table.unpack(format) + + @hints = blobs.map { |b| TwolevelHint.new(b) } + end + + # An individual two-level namespace lookup hint. + class TwolevelHint + # @return [Integer] the index into the sub-images + attr_reader :isub_image + + # @return [Integer] the index into the table of contents + attr_reader :itoc + + # @param blob [Integer] the 32-bit number containing the lookup hint + # @api private + def initialize(blob) + @isub_image = blob >> 24 + @itoc = blob & 0x00FFFFFF + end + + # @return [Hash] a hash representation of this {TwolevelHint} + def to_h + { + "isub_image" => isub_image, + "itoc" => itoc, + } + end + end + end + end + + # A load command containing the value of the original checksum for prebound + # files, or zero. Corresponds to LC_PREBIND_CKSUM. + class PrebindCksumCommand < LoadCommand + # @return [Integer] the checksum or 0 + field :cksum, :uint32 + + # @return [Hash] a hash representation of this {PrebindCksumCommand} + def to_h + { + "cksum" => cksum, + }.merge super + end + end + + # A load command representing an rpath, which specifies a path that should + # be added to the current run path used to find @rpath prefixed dylibs. + # Corresponds to LC_RPATH. + class RpathCommand < LoadCommand + # @return [LCStr] the path to add to the run path as an LCStr + field :path, :lcstr, :to_s => true + + # @param context [SerializationContext] the context + # @return [String] the serialized fields of the load command + # @api private + def serialize(context) + format = Utils.specialize_format(self.class.format, context.endianness) + string_payload, string_offsets = Utils.pack_strings(self.class.bytesize, + context.alignment, + :path => path.to_s) + cmdsize = self.class.bytesize + string_payload.bytesize + [cmd, cmdsize, string_offsets[:path]].pack(format) + string_payload + end + + # @return [Hash] a hash representation of this {RpathCommand} + def to_h + { + "path" => path.to_h, + }.merge super + end + end + + # A load command representing the offsets and sizes of a blob of data in + # the __LINKEDIT segment. Corresponds to LC_CODE_SIGNATURE, + # LC_SEGMENT_SPLIT_INFO, LC_FUNCTION_STARTS, LC_DATA_IN_CODE, + # LC_DYLIB_CODE_SIGN_DRS, LC_LINKER_OPTIMIZATION_HINT, LC_DYLD_EXPORTS_TRIE, + # or LC_DYLD_CHAINED_FIXUPS. + class LinkeditDataCommand < LoadCommand + # @return [Integer] offset to the data in the __LINKEDIT segment + field :dataoff, :uint32 + + # @return [Integer] size of the data in the __LINKEDIT segment + field :datasize, :uint32 + + # @return [Hash] a hash representation of this {LinkeditDataCommand} + def to_h + { + "dataoff" => dataoff, + "datasize" => datasize, + }.merge super + end + end + + # A load command representing the offset to and size of an encrypted + # segment. Corresponds to LC_ENCRYPTION_INFO. + class EncryptionInfoCommand < LoadCommand + # @return [Integer] the offset to the encrypted segment + field :cryptoff, :uint32 + + # @return [Integer] the size of the encrypted segment + field :cryptsize, :uint32 + + # @return [Integer] the encryption system, or 0 if not encrypted yet + field :cryptid, :uint32 + + # @return [Hash] a hash representation of this {EncryptionInfoCommand} + def to_h + { + "cryptoff" => cryptoff, + "cryptsize" => cryptsize, + "cryptid" => cryptid, + }.merge super + end + end + + # A load command representing the offset to and size of an encrypted + # segment. Corresponds to LC_ENCRYPTION_INFO_64. + class EncryptionInfoCommand64 < EncryptionInfoCommand + # @return [Integer] 64-bit padding value + field :pad, :uint32 + + # @return [Hash] a hash representation of this {EncryptionInfoCommand64} + def to_h + { + "pad" => pad, + }.merge super + end + end + + # A load command containing the minimum OS version on which the binary + # was built to run. Corresponds to LC_VERSION_MIN_MACOSX and + # LC_VERSION_MIN_IPHONEOS. + class VersionMinCommand < LoadCommand + # @return [Integer] the version X.Y.Z packed as x16.y8.z8 + field :version, :uint32 + + # @return [Integer] the SDK version X.Y.Z packed as x16.y8.z8 + field :sdk, :uint32 + + # A string representation of the binary's minimum OS version. + # @return [String] a string representing the minimum OS version. + def version_string + binary = "%032b" % { :version => version } + segs = [ + binary[0..15], binary[16..23], binary[24..31] + ].map { |s| s.to_i(2) } + + segs.join(".") + end + + # A string representation of the binary's SDK version. + # @return [String] a string representing the SDK version. + def sdk_string + binary = "%032b" % { :sdk => sdk } + segs = [ + binary[0..15], binary[16..23], binary[24..31] + ].map { |s| s.to_i(2) } + + segs.join(".") + end + + # @return [Hash] a hash representation of this {VersionMinCommand} + def to_h + { + "version" => version, + "version_string" => version_string, + "sdk" => sdk, + "sdk_string" => sdk_string, + }.merge super + end + end + + # A load command containing the minimum OS version on which + # the binary was built for its platform. + # Corresponds to LC_BUILD_VERSION. + class BuildVersionCommand < LoadCommand + # @return [Integer] + field :platform, :uint32 + + # @return [Integer] the minimum OS version X.Y.Z packed as x16.y8.z8 + field :minos, :uint32 + + # @return [Integer] the SDK version X.Y.Z packed as x16.y8.z8 + field :sdk, :uint32 + + # @return [ToolEntries] tool entries + field :tool_entries, :tool_entries + + # A string representation of the binary's minimum OS version. + # @return [String] a string representing the minimum OS version. + def minos_string + binary = "%032b" % { :minos => minos } + segs = [ + binary[0..15], binary[16..23], binary[24..31] + ].map { |s| s.to_i(2) } + + segs.join(".") + end + + # A string representation of the binary's SDK version. + # @return [String] a string representing the SDK version. + def sdk_string + binary = "%032b" % { :sdk => sdk } + segs = [ + binary[0..15], binary[16..23], binary[24..31] + ].map { |s| s.to_i(2) } + + segs.join(".") + end + + # @return [Hash] a hash representation of this {BuildVersionCommand} + def to_h + { + "platform" => platform, + "minos" => minos, + "minos_string" => minos_string, + "sdk" => sdk, + "sdk_string" => sdk_string, + "tool_entries" => tool_entries.tools.map(&:to_h), + }.merge super + end + + # A representation of the tool versions exposed + # by a {BuildVersionCommand} (`LC_BUILD_VERSION`). + class ToolEntries + # @return [Array] all tools + attr_reader :tools + + # @param view [MachO::MachOView] the view into the current Mach-O + # @param ntools [Integer] the number of tools + # @api private + def initialize(view, ntools) + format = Utils.specialize_format("L=#{ntools * 2}", view.endianness) + raw_table = view.raw_data[view.offset + 24, ntools * 8] + blobs = raw_table.unpack(format).each_slice(2).to_a + + @tools = blobs.map { |b| Tool.new(*b) } + end + + # An individual tool. + class Tool + # @return [Integer] the enum for the tool + attr_reader :tool + + # @return [Integer] the tool's version number + attr_reader :version + + # @param tool [Integer] 32-bit integer + # @param version [Integer] 32-bit integer + # @api private + def initialize(tool, version) + @tool = tool + @version = version + end + + # @return [Hash] a hash representation of this {Tool} + def to_h + { + "tool" => tool, + "version" => version, + } + end + end + end + end + + # A load command containing the file offsets and sizes of the new + # compressed form of the information dyld needs to load the image. + # Corresponds to LC_DYLD_INFO and LC_DYLD_INFO_ONLY. + class DyldInfoCommand < LoadCommand + # @return [Integer] the file offset to the rebase information + field :rebase_off, :uint32 + + # @return [Integer] the size of the rebase information + field :rebase_size, :uint32 + + # @return [Integer] the file offset to the binding information + field :bind_off, :uint32 + + # @return [Integer] the size of the binding information + field :bind_size, :uint32 + + # @return [Integer] the file offset to the weak binding information + field :weak_bind_off, :uint32 + + # @return [Integer] the size of the weak binding information + field :weak_bind_size, :uint32 + + # @return [Integer] the file offset to the lazy binding information + field :lazy_bind_off, :uint32 + + # @return [Integer] the size of the lazy binding information + field :lazy_bind_size, :uint32 + + # @return [Integer] the file offset to the export information + field :export_off, :uint32 + + # @return [Integer] the size of the export information + field :export_size, :uint32 + + # @return [Hash] a hash representation of this {DyldInfoCommand} + def to_h + { + "rebase_off" => rebase_off, + "rebase_size" => rebase_size, + "bind_off" => bind_off, + "bind_size" => bind_size, + "weak_bind_off" => weak_bind_off, + "weak_bind_size" => weak_bind_size, + "lazy_bind_off" => lazy_bind_off, + "lazy_bind_size" => lazy_bind_size, + "export_off" => export_off, + "export_size" => export_size, + }.merge super + end + end + + # A load command containing linker options embedded in object files. + # Corresponds to LC_LINKER_OPTION. + class LinkerOptionCommand < LoadCommand + # @return [Integer] the number of strings + field :count, :uint32 + + # @return [Hash] a hash representation of this {LinkerOptionCommand} + def to_h + { + "count" => count, + }.merge super + end + end + + # A load command specifying the offset of main(). Corresponds to LC_MAIN. + class EntryPointCommand < LoadCommand + # @return [Integer] the file (__TEXT) offset of main() + field :entryoff, :uint64 + + # @return [Integer] if not 0, the initial stack size. + field :stacksize, :uint64 + + # @return [Hash] a hash representation of this {EntryPointCommand} + def to_h + { + "entryoff" => entryoff, + "stacksize" => stacksize, + }.merge super + end + end + + # A load command specifying the version of the sources used to build the + # binary. Corresponds to LC_SOURCE_VERSION. + class SourceVersionCommand < LoadCommand + # @return [Integer] the version packed as a24.b10.c10.d10.e10 + field :version, :uint64 + + # A string representation of the sources used to build the binary. + # @return [String] a string representation of the version + def version_string + binary = "%064b" % { :version => version } + segs = [ + binary[0..23], binary[24..33], binary[34..43], binary[44..53], + binary[54..63] + ].map { |s| s.to_i(2) } + + segs.join(".") + end + + # @return [Hash] a hash representation of this {SourceVersionCommand} + def to_h + { + "version" => version, + "version_string" => version_string, + }.merge super + end + end + + # An obsolete load command containing the offset and size of the (GNU style) + # symbol table information. Corresponds to LC_SYMSEG. + class SymsegCommand < LoadCommand + # @return [Integer] the offset to the symbol segment + field :offset, :uint32 + + # @return [Integer] the size of the symbol segment in bytes + field :size, :uint32 + + # @return [Hash] a hash representation of this {SymsegCommand} + def to_h + { + "offset" => offset, + "size" => size, + }.merge super + end + end + + # An obsolete load command containing a free format string table. Each + # string is null-terminated and the command is zero-padded to a multiple of + # 4. Corresponds to LC_IDENT. + class IdentCommand < LoadCommand + end + + # An obsolete load command containing the path to a file to be loaded into + # memory. Corresponds to LC_FVMFILE. + class FvmfileCommand < LoadCommand + # @return [LCStr] the pathname of the file being loaded + field :name, :lcstr, :to_s => true + + # @return [Integer] the virtual address being loaded at + field :header_addr, :uint32 + + # @return [Hash] a hash representation of this {FvmfileCommand} + def to_h + { + "name" => name.to_h, + "header_addr" => header_addr, + }.merge super + end + end + + # An obsolete load command containing the path to a library to be loaded + # into memory. Corresponds to LC_LOADFVMLIB and LC_IDFVMLIB. + class FvmlibCommand < LoadCommand + # @return [LCStr] the library's target pathname + field :name, :lcstr, :to_s => true + + # @return [Integer] the library's minor version number + field :minor_version, :uint32 + + # @return [Integer] the library's header address + field :header_addr, :uint32 + + # @return [Hash] a hash representation of this {FvmlibCommand} + def to_h + { + "name" => name.to_h, + "minor_version" => minor_version, + "header_addr" => header_addr, + }.merge super + end + end + + # A load command containing an owner name and offset/size for an arbitrary data region. + # Corresponds to LC_NOTE. + class NoteCommand < LoadCommand + # @return [String] the name of the owner for this note + field :data_owner, :string, :padding => :null, :size => 16, :to_s => true + + # @return [Integer] the offset, within the file, of the note + field :offset, :uint64 + + # @return [Integer] the size, in bytes, of the note + field :size, :uint64 + + # @return [Hash] a hash representation of this {NoteCommand} + def to_h + { + "data_owner" => data_owner, + "offset" => offset, + "size" => size, + }.merge super + end + end + + # A load command containing a description of a Mach-O that is a constituent of a fileset. + # Each entry is further described by its own Mach header. + # Corresponds to LC_FILESET_ENTRY. + class FilesetEntryCommand < LoadCommand + # @return [Integer] the virtual memory address of the entry + field :vmaddr, :uint64 + + # @return [Integer] the file offset of the entry + field :fileoff, :uint64 + + # @return [LCStr] the entry's ID + field :entry_id, :lcstr, :to_s => true + + # @return [void] + field :reserved, :uint32 + + # @return [Hash] a hash representation of this {FilesetEntryCommand} + def to_h + { + "vmaddr" => vmaddr, + "fileoff" => fileoff, + "entry_id" => entry_id, + "reserved" => reserved, + }.merge super + end + + # @return [SegmentCommand64, nil] the matching segment command or nil if nothing matches + def segment + view.macho_file.command(:LC_SEGMENT_64).select { |cmd| cmd.fileoff == fileoff }.first + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/ruby-macho-4.0.0/lib/macho/macho_file.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/ruby-macho-4.0.0/lib/macho/macho_file.rb new file mode 100644 index 0000000000..f48bfa5eb2 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/ruby-macho-4.0.0/lib/macho/macho_file.rb @@ -0,0 +1,652 @@ +# frozen_string_literal: true + +require "forwardable" + +module MachO + # Represents a Mach-O file, which contains a header and load commands + # as well as binary executable instructions. Mach-O binaries are + # architecture specific. + # @see https://en.wikipedia.org/wiki/Mach-O + # @see FatFile + class MachOFile + extend Forwardable + + # @return [String, nil] the filename loaded from, or nil if loaded from a binary + # string + attr_accessor :filename + + # @return [Hash] any parser options that the instance was created with + attr_reader :options + + # @return [Symbol] the endianness of the file, :big or :little + attr_reader :endianness + + # @return [Headers::MachHeader] if the Mach-O is 32-bit + # @return [Headers::MachHeader64] if the Mach-O is 64-bit + attr_reader :header + + # @return [Array] an array of the file's load + # commands + # @note load commands are provided in order of ascending offset. + attr_reader :load_commands + + # Creates a new instance from a binary string. + # @param bin [String] a binary string containing raw Mach-O data + # @param opts [Hash] options to control the parser with + # @option opts [Boolean] :permissive whether to ignore unknown load commands + # @option opts [Boolean] :decompress whether to decompress, if capable + # @return [MachOFile] a new MachOFile + # @note The `:decompress` option relies on non-default dependencies. Compression + # is only used in niche Mach-Os, so leaving this disabled is a reasonable default for + # virtually all normal uses. + def self.new_from_bin(bin, **opts) + instance = allocate + instance.initialize_from_bin(bin, opts) + + instance + end + + # Creates a new instance from data read from the given filename. + # @param filename [String] the Mach-O file to load from + # @param opts [Hash] options to control the parser with + # @option opts [Boolean] :permissive whether to ignore unknown load commands + # @option opts [Boolean] :decompress whether to decompress, if capable + # @raise [ArgumentError] if the given file does not exist + # @note The `:decompress` option relies on non-default dependencies. Compression + # is only used in niche Mach-Os, so leaving this disabled is a reasonable default for + # virtually all normal uses. + def initialize(filename, **opts) + raise ArgumentError, "#{filename}: no such file" unless File.file?(filename) + + @filename = filename + @options = opts + @raw_data = File.binread(@filename) + populate_fields + end + + # Initializes a new MachOFile instance from a binary string with the given options. + # @see MachO::MachOFile.new_from_bin + # @api private + def initialize_from_bin(bin, opts) + @filename = nil + @options = opts + @raw_data = bin + populate_fields + end + + # The file's raw Mach-O data. + # @return [String] the raw Mach-O data + def serialize + @raw_data + end + + # @!method magic + # @return (see MachO::Headers::MachHeader#magic) + # @!method ncmds + # @return (see MachO::Headers::MachHeader#ncmds) + # @!method sizeofcmds + # @return (see MachO::Headers::MachHeader#sizeofcmds) + # @!method flags + # @return (see MachO::Headers::MachHeader#flags) + # @!method object? + # @return (see MachO::Headers::MachHeader#object?) + # @!method executable? + # @return (see MachO::Headers::MachHeader#executable?) + # @!method fvmlib? + # @return (see MachO::Headers::MachHeader#fvmlib?) + # @!method core? + # @return (see MachO::Headers::MachHeader#core?) + # @!method preload? + # @return (see MachO::Headers::MachHeader#preload?) + # @!method dylib? + # @return (see MachO::Headers::MachHeader#dylib?) + # @!method dylinker? + # @return (see MachO::Headers::MachHeader#dylinker?) + # @!method bundle? + # @return (see MachO::Headers::MachHeader#bundle?) + # @!method dsym? + # @return (see MachO::Headers::MachHeader#dsym?) + # @!method kext? + # @return (see MachO::Headers::MachHeader#kext?) + # @!method magic32? + # @return (see MachO::Headers::MachHeader#magic32?) + # @!method magic64? + # @return (see MachO::Headers::MachHeader#magic64?) + # @!method alignment + # @return (see MachO::Headers::MachHeader#alignment) + def_delegators :header, :magic, :ncmds, :sizeofcmds, :flags, :object?, + :executable?, :fvmlib?, :core?, :preload?, :dylib?, + :dylinker?, :bundle?, :dsym?, :kext?, :magic32?, :magic64?, + :alignment + + # @return [String] a string representation of the file's magic number + def magic_string + Headers::MH_MAGICS[magic] + end + + # @return [Symbol] a string representation of the Mach-O's filetype + def filetype + Headers::MH_FILETYPES[header.filetype] + end + + # @return [Symbol] a symbol representation of the Mach-O's CPU type + def cputype + Headers::CPU_TYPES[header.cputype] + end + + # @return [Symbol] a symbol representation of the Mach-O's CPU subtype + def cpusubtype + Headers::CPU_SUBTYPES[header.cputype][header.cpusubtype] + end + + # All load commands of a given name. + # @example + # file.command("LC_LOAD_DYLIB") + # file[:LC_LOAD_DYLIB] + # @param [String, Symbol] name the load command ID + # @return [Array] an array of load commands + # corresponding to `name` + def command(name) + load_commands.select { |lc| lc.type == name.to_sym } + end + + alias [] command + + # Inserts a load command at the given offset. + # @param offset [Integer] the offset to insert at + # @param lc [LoadCommands::LoadCommand] the load command to insert + # @param options [Hash] + # @option options [Boolean] :repopulate (true) whether or not to repopulate + # the instance fields + # @raise [OffsetInsertionError] if the offset is not in the load command region + # @raise [HeaderPadError] if the new command exceeds the header pad buffer + # @note Calling this method with an arbitrary offset in the load command region + # **will leave the object in an inconsistent state**. + def insert_command(offset, lc, options = {}) + context = LoadCommands::LoadCommand::SerializationContext.context_for(self) + cmd_raw = lc.serialize(context) + fileoff = offset + cmd_raw.bytesize + + raise OffsetInsertionError, offset if offset < header.class.bytesize || fileoff > low_fileoff + + new_sizeofcmds = sizeofcmds + cmd_raw.bytesize + + raise HeaderPadError, @filename if header.class.bytesize + new_sizeofcmds > low_fileoff + + # update Mach-O header fields to account for inserted load command + update_ncmds(ncmds + 1) + update_sizeofcmds(new_sizeofcmds) + + @raw_data.insert(offset, cmd_raw) + @raw_data.slice!(header.class.bytesize + new_sizeofcmds, cmd_raw.bytesize) + + populate_fields if options.fetch(:repopulate, true) + end + + # Replace a load command with another command in the Mach-O, preserving location. + # @param old_lc [LoadCommands::LoadCommand] the load command being replaced + # @param new_lc [LoadCommands::LoadCommand] the load command being added + # @return [void] + # @raise [HeaderPadError] if the new command exceeds the header pad buffer + # @see #insert_command + # @note This is public, but methods like {#dylib_id=} should be preferred. + def replace_command(old_lc, new_lc) + context = LoadCommands::LoadCommand::SerializationContext.context_for(self) + cmd_raw = new_lc.serialize(context) + new_sizeofcmds = sizeofcmds + cmd_raw.bytesize - old_lc.cmdsize + + raise HeaderPadError, @filename if header.class.bytesize + new_sizeofcmds > low_fileoff + + delete_command(old_lc) + insert_command(old_lc.view.offset, new_lc) + end + + # Appends a new load command to the Mach-O. + # @param lc [LoadCommands::LoadCommand] the load command being added + # @param options [Hash] + # @option f [Boolean] :repopulate (true) whether or not to repopulate + # the instance fields + # @return [void] + # @see #insert_command + # @note This is public, but methods like {#add_rpath} should be preferred. + # Setting `repopulate` to false **will leave the instance in an + # inconsistent state** unless {#populate_fields} is called **immediately** + # afterwards. + def add_command(lc, options = {}) + insert_command(header.class.bytesize + sizeofcmds, lc, options) + end + + # Delete a load command from the Mach-O. + # @param lc [LoadCommands::LoadCommand] the load command being deleted + # @param options [Hash] + # @option options [Boolean] :repopulate (true) whether or not to repopulate + # the instance fields + # @return [void] + # @note This is public, but methods like {#delete_rpath} should be preferred. + # Setting `repopulate` to false **will leave the instance in an + # inconsistent state** unless {#populate_fields} is called **immediately** + # afterwards. + def delete_command(lc, options = {}) + @raw_data.slice!(lc.view.offset, lc.cmdsize) + + # update Mach-O header fields to account for deleted load command + update_ncmds(ncmds - 1) + update_sizeofcmds(sizeofcmds - lc.cmdsize) + + # pad the space after the load commands to preserve offsets + @raw_data.insert(header.class.bytesize + sizeofcmds - lc.cmdsize, Utils.nullpad(lc.cmdsize)) + + populate_fields if options.fetch(:repopulate, true) + end + + # Populate the instance's fields with the raw Mach-O data. + # @return [void] + # @note This method is public, but should (almost) never need to be called. + # The exception to this rule is when methods like {#add_command} and + # {#delete_command} have been called with `repopulate = false`. + def populate_fields + @header = populate_mach_header + @load_commands = populate_load_commands + end + + # All load commands responsible for loading dylibs. + # @return [Array] an array of DylibCommands + def dylib_load_commands + load_commands.select { |lc| LoadCommands::DYLIB_LOAD_COMMANDS.include?(lc.type) } + end + + # All segment load commands in the Mach-O. + # @return [Array] if the Mach-O is 32-bit + # @return [Array] if the Mach-O is 64-bit + def segments + if magic32? + command(:LC_SEGMENT) + else + command(:LC_SEGMENT_64) + end + end + + # The segment alignment for the Mach-O. Guesses conservatively. + # @return [Integer] the alignment, as a power of 2 + # @note This is **not** the same as {#alignment}! + # @note See `get_align` and `get_align_64` in `cctools/misc/lipo.c` + def segment_alignment + # special cases: 12 for x86/64/PPC/PP64, 14 for ARM/ARM64 + return 12 if %i[i386 x86_64 ppc ppc64].include?(cputype) + return 14 if %i[arm arm64].include?(cputype) + + cur_align = Sections::MAX_SECT_ALIGN + + segments.each do |segment| + if filetype == :object + # start with the smallest alignment, and work our way up + align = magic32? ? 2 : 3 + segment.sections.each do |section| + align = section.align unless section.align <= align + end + else + align = segment.guess_align + end + cur_align = align if align < cur_align + end + + cur_align + end + + # The Mach-O's dylib ID, or `nil` if not a dylib. + # @example + # file.dylib_id # => 'libBar.dylib' + # @return [String, nil] the Mach-O's dylib ID + def dylib_id + return unless dylib? + + dylib_id_cmd = command(:LC_ID_DYLIB).first + + dylib_id_cmd.name.to_s + end + + # Changes the Mach-O's dylib ID to `new_id`. Does nothing if not a dylib. + # @example + # file.change_dylib_id("libFoo.dylib") + # @param new_id [String] the dylib's new ID + # @param _options [Hash] + # @return [void] + # @raise [ArgumentError] if `new_id` is not a String + # @note `_options` is currently unused and is provided for signature + # compatibility with {MachO::FatFile#change_dylib_id} + def change_dylib_id(new_id, _options = {}) + raise ArgumentError, "new ID must be a String" unless new_id.is_a?(String) + return unless dylib? + + old_lc = command(:LC_ID_DYLIB).first + raise DylibIdMissingError unless old_lc + + new_lc = LoadCommands::LoadCommand.create(:LC_ID_DYLIB, new_id, + old_lc.timestamp, + old_lc.current_version, + old_lc.compatibility_version) + + replace_command(old_lc, new_lc) + end + + alias dylib_id= change_dylib_id + + # All shared libraries linked to the Mach-O. + # @return [Array] an array of all shared libraries + def linked_dylibs + # Some linkers produce multiple `LC_LOAD_DYLIB` load commands for the same + # library, but at this point we're really only interested in a list of + # unique libraries this Mach-O file links to, thus: `uniq`. (This is also + # for consistency with `FatFile` that merges this list across all archs.) + dylib_load_commands.map(&:name).map(&:to_s).uniq + end + + # Changes the shared library `old_name` to `new_name` + # @example + # file.change_install_name("abc.dylib", "def.dylib") + # @param old_name [String] the shared library's old name + # @param new_name [String] the shared library's new name + # @param _options [Hash] + # @return [void] + # @raise [DylibUnknownError] if no shared library has the old name + # @note `_options` is currently unused and is provided for signature + # compatibility with {MachO::FatFile#change_install_name} + def change_install_name(old_name, new_name, _options = {}) + old_lc = dylib_load_commands.find { |d| d.name.to_s == old_name } + raise DylibUnknownError, old_name if old_lc.nil? + + new_lc = LoadCommands::LoadCommand.create(old_lc.type, new_name, + old_lc.timestamp, + old_lc.current_version, + old_lc.compatibility_version) + + replace_command(old_lc, new_lc) + end + + alias change_dylib change_install_name + + # All runtime paths searched by the dynamic linker for the Mach-O. + # @return [Array] an array of all runtime paths + def rpaths + command(:LC_RPATH).map(&:path).map(&:to_s) + end + + # Changes the runtime path `old_path` to `new_path` + # @example + # file.change_rpath("/usr/lib", "/usr/local/lib") + # @param old_path [String] the old runtime path + # @param new_path [String] the new runtime path + # @param options [Hash] + # @option options [Boolean] :uniq (false) if true, change duplicate + # rpaths simultaneously. + # @return [void] + # @raise [RpathUnknownError] if no such old runtime path exists + def change_rpath(old_path, new_path, options = {}) + old_lc = command(:LC_RPATH).find { |r| r.path.to_s == old_path } + raise RpathUnknownError, old_path if old_lc.nil? + + new_lc = LoadCommands::LoadCommand.create(:LC_RPATH, new_path) + + delete_rpath(old_path, options) + insert_command(old_lc.view.offset, new_lc) + end + + # Add the given runtime path to the Mach-O. + # @example + # file.rpaths # => ["/lib"] + # file.add_rpath("/usr/lib") + # file.rpaths # => ["/lib", "/usr/lib"] + # @param path [String] the new runtime path + # @param _options [Hash] + # @return [void] + # @raise [RpathExistsError] if the runtime path already exists + # @note `_options` is currently unused and is provided for signature + # compatibility with {MachO::FatFile#add_rpath} + def add_rpath(path, _options = {}) + raise RpathExistsError, path if rpaths.include?(path) + + rpath_cmd = LoadCommands::LoadCommand.create(:LC_RPATH, path) + add_command(rpath_cmd) + end + + # Delete the given runtime path from the Mach-O. + # @example + # file.rpaths # => ["/lib"] + # file.delete_rpath("/lib") + # file.rpaths # => [] + # @param path [String] the runtime path to delete + # @param options [Hash] + # @option options [Boolean] :uniq (false) if true, also delete + # duplicates of the requested path. If false, delete the first + # instance (by offset) of the requested path, unless :last is true. + # Incompatible with :last. + # @option options [Boolean] :last (false) if true, delete the last + # instance (by offset) of the requested path. Incompatible with :uniq. + # @return void + # @raise [RpathUnknownError] if no such runtime path exists + # @raise [ArgumentError] if both :uniq and :last are true + def delete_rpath(path, options = {}) + uniq = options.fetch(:uniq, false) + last = options.fetch(:last, false) + raise ArgumentError, "Cannot set both :uniq and :last to true" if uniq && last + + search_method = uniq || last ? :select : :find + rpath_cmds = command(:LC_RPATH).public_send(search_method) { |r| r.path.to_s == path } + rpath_cmds = rpath_cmds.last if last + + # Cast rpath_cmds into an Array so we can handle the uniq and non-uniq cases the same way + rpath_cmds = Array(rpath_cmds) + raise RpathUnknownError, path if rpath_cmds.empty? + + # delete the commands in reverse order, offset descending. + rpath_cmds.reverse_each { |cmd| delete_command(cmd) } + end + + # Write all Mach-O data to the given filename. + # @param filename [String] the file to write to + # @return [void] + def write(filename) + File.binwrite(filename, @raw_data) + end + + # Write all Mach-O data to the file used to initialize the instance. + # @return [void] + # @raise [MachOError] if the instance was initialized without a file + # @note Overwrites all data in the file! + def write! + raise MachOError, "no initial file to write to" if @filename.nil? + + File.binwrite(@filename, @raw_data) + end + + # @return [Hash] a hash representation of this {MachOFile} + def to_h + { + "header" => header.to_h, + "load_commands" => load_commands.map(&:to_h), + } + end + + private + + # The file's Mach-O header structure. + # @return [Headers::MachHeader] if the Mach-O is 32-bit + # @return [Headers::MachHeader64] if the Mach-O is 64-bit + # @raise [TruncatedFileError] if the file is too small to have a valid header + # @api private + def populate_mach_header + # the smallest Mach-O header is 28 bytes + raise TruncatedFileError if @raw_data.size < 28 + + magic = @raw_data[0..3].unpack1("N") + populate_prelinked_kernel_header if Utils.compressed_magic?(magic) + + magic = populate_and_check_magic + mh_klass = Utils.magic32?(magic) ? Headers::MachHeader : Headers::MachHeader64 + mh = mh_klass.new_from_bin(endianness, @raw_data[0, mh_klass.bytesize]) + + check_cputype(mh.cputype) + check_cpusubtype(mh.cputype, mh.cpusubtype) + check_filetype(mh.filetype) + + mh + end + + # Read a compressed Mach-O header and check its validity, as well as whether we're able + # to parse it. + # @return [void] + # @raise [CompressedMachOError] if we weren't asked to perform decompression + # @raise [DecompressionError] if decompression is impossible or fails + # @api private + def populate_prelinked_kernel_header + raise CompressedMachOError unless options.fetch(:decompress, false) + + @plh = Headers::PrelinkedKernelHeader.new_from_bin :big, @raw_data[0, Headers::PrelinkedKernelHeader.bytesize] + + raise DecompressionError, "unsupported compression type: LZSS" if @plh.lzss? + raise DecompressionError, "unknown compression type: 0x#{plh.compress_type.to_s 16}" unless @plh.lzvn? + + decompress_macho_lzvn + end + + # Attempt to decompress a Mach-O file from the data specified in a prelinked kernel header. + # @return [void] + # @raise [DecompressionError] if decompression is impossible or fails + # @api private + # @note This method rewrites the internal state of {MachOFile} to pretend as if it was never + # compressed to begin with, allowing all other APIs to transparently act on compressed Mach-Os. + def decompress_macho_lzvn + begin + require "lzfse" + rescue LoadError + raise DecompressionError, "LZVN required but the optional 'lzfse' gem is not installed" + end + + # From this point onwards, the internal buffer of this MachOFile refers to the decompressed + # contents specified by the prelinked kernel header. + begin + @raw_data = LZFSE.lzvn_decompress @raw_data.slice(Headers::PrelinkedKernelHeader.bytesize, @plh.compressed_size) + # Sanity checks. + raise DecompressionError if @raw_data.size != @plh.uncompressed_size + # TODO: check the adler32 CRC in @plh + rescue LZFSE::DecodeError + raise DecompressionError, "LZVN decompression failed" + end + end + + # Read just the file's magic number and check its validity. + # @return [Integer] the magic + # @raise [MagicError] if the magic is not valid Mach-O magic + # @raise [FatBinaryError] if the magic is for a Fat file + # @api private + def populate_and_check_magic + magic = @raw_data[0..3].unpack1("N") + + raise MagicError, magic unless Utils.magic?(magic) + raise FatBinaryError if Utils.fat_magic?(magic) + + @endianness = Utils.little_magic?(magic) ? :little : :big + + magic + end + + # Check the file's CPU type. + # @param cputype [Integer] the CPU type + # @raise [CPUTypeError] if the CPU type is unknown + # @api private + def check_cputype(cputype) + raise CPUTypeError, cputype unless Headers::CPU_TYPES.key?(cputype) + end + + # Check the file's CPU type/subtype pair. + # @param cpusubtype [Integer] the CPU subtype + # @raise [CPUSubtypeError] if the CPU sub-type is unknown + # @api private + def check_cpusubtype(cputype, cpusubtype) + # Only check sub-type w/o capability bits (see `populate_mach_header`). + raise CPUSubtypeError.new(cputype, cpusubtype) unless Headers::CPU_SUBTYPES[cputype].key?(cpusubtype) + end + + # Check the file's type. + # @param filetype [Integer] the file type + # @raise [FiletypeError] if the file type is unknown + # @api private + def check_filetype(filetype) + raise FiletypeError, filetype unless Headers::MH_FILETYPES.key?(filetype) + end + + # All load commands in the file. + # @return [Array] an array of load commands + # @raise [LoadCommandError] if an unknown load command is encountered + # @api private + def populate_load_commands + permissive = options.fetch(:permissive, false) + offset = header.class.bytesize + load_commands = [] + + header.ncmds.times do + fmt = Utils.specialize_format("L=", endianness) + cmd = @raw_data.slice(offset, 4).unpack1(fmt) + cmd_sym = LoadCommands::LOAD_COMMANDS[cmd] + + raise LoadCommandError, cmd unless cmd_sym || permissive + + # If we're here, then either cmd_sym represents a valid load + # command *or* we're in permissive mode. + klass = if (klass_str = LoadCommands::LC_STRUCTURES[cmd_sym]) + LoadCommands.const_get klass_str + else + LoadCommands::LoadCommand + end + + view = MachOView.new(self, @raw_data, endianness, offset) + command = klass.new_from_bin(view) + + load_commands << command + offset += command.cmdsize + end + + load_commands + end + + # The low file offset (offset to first section data). + # @return [Integer] the offset + # @api private + def low_fileoff + offset = @raw_data.size + + segments.each do |seg| + seg.sections.each do |sect| + next if sect.empty? + next if sect.type?(:S_ZEROFILL) + next if sect.type?(:S_THREAD_LOCAL_ZEROFILL) + next unless sect.offset < offset + + offset = sect.offset + end + end + + offset + end + + # Updates the number of load commands in the raw data. + # @param ncmds [Integer] the new number of commands + # @return [void] + # @api private + def update_ncmds(ncmds) + fmt = Utils.specialize_format("L=", endianness) + ncmds_raw = [ncmds].pack(fmt) + @raw_data[16..19] = ncmds_raw + end + + # Updates the size of all load commands in the raw data. + # @param size [Integer] the new size, in bytes + # @return [void] + # @api private + def update_sizeofcmds(size) + fmt = Utils.specialize_format("L=", endianness) + size_raw = [size].pack(fmt) + @raw_data[20..23] = size_raw + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/ruby-macho-4.0.0/lib/macho/sections.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/ruby-macho-4.0.0/lib/macho/sections.rb new file mode 100644 index 0000000000..0b48808de2 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/ruby-macho-4.0.0/lib/macho/sections.rb @@ -0,0 +1,216 @@ +# frozen_string_literal: true + +module MachO + # Classes and constants for parsing sections in Mach-O binaries. + module Sections + # type mask + SECTION_TYPE_MASK = 0x000000ff + + # attributes mask + SECTION_ATTRIBUTES_MASK = 0xffffff00 + + # user settable attributes mask + SECTION_ATTRIBUTES_USR_MASK = 0xff000000 + + # system settable attributes mask + SECTION_ATTRIBUTES_SYS_MASK = 0x00ffff00 + + # maximum specifiable section alignment, as a power of 2 + # @note see `MAXSECTALIGN` macro in `cctools/misc/lipo.c` + MAX_SECT_ALIGN = 15 + + # association of section type symbols to values + # @api private + SECTION_TYPES = { + :S_REGULAR => 0x0, + :S_ZEROFILL => 0x1, + :S_CSTRING_LITERALS => 0x2, + :S_4BYTE_LITERALS => 0x3, + :S_8BYTE_LITERALS => 0x4, + :S_LITERAL_POINTERS => 0x5, + :S_NON_LAZY_SYMBOL_POINTERS => 0x6, + :S_LAZY_SYMBOL_POINTERS => 0x7, + :S_SYMBOL_STUBS => 0x8, + :S_MOD_INIT_FUNC_POINTERS => 0x9, + :S_MOD_TERM_FUNC_POINTERS => 0xa, + :S_COALESCED => 0xb, + :S_GB_ZEROFILE => 0xc, + :S_INTERPOSING => 0xd, + :S_16BYTE_LITERALS => 0xe, + :S_DTRACE_DOF => 0xf, + :S_LAZY_DYLIB_SYMBOL_POINTERS => 0x10, + :S_THREAD_LOCAL_REGULAR => 0x11, + :S_THREAD_LOCAL_ZEROFILL => 0x12, + :S_THREAD_LOCAL_VARIABLES => 0x13, + :S_THREAD_LOCAL_VARIABLE_POINTERS => 0x14, + :S_THREAD_LOCAL_INIT_FUNCTION_POINTERS => 0x15, + :S_INIT_FUNC_OFFSETS => 0x16, + }.freeze + + # association of section attribute symbols to values + # @api private + SECTION_ATTRIBUTES = { + :S_ATTR_PURE_INSTRUCTIONS => 0x80000000, + :S_ATTR_NO_TOC => 0x40000000, + :S_ATTR_STRIP_STATIC_SYMS => 0x20000000, + :S_ATTR_NO_DEAD_STRIP => 0x10000000, + :S_ATTR_LIVE_SUPPORT => 0x08000000, + :S_ATTR_SELF_MODIFYING_CODE => 0x04000000, + :S_ATTR_DEBUG => 0x02000000, + :S_ATTR_SOME_INSTRUCTIONS => 0x00000400, + :S_ATTR_EXT_RELOC => 0x00000200, + :S_ATTR_LOC_RELOC => 0x00000100, + }.freeze + + # association of section flag symbols to values + # @api private + SECTION_FLAGS = { + **SECTION_TYPES, + **SECTION_ATTRIBUTES, + }.freeze + + # association of section name symbols to names + # @api private + SECTION_NAMES = { + :SECT_TEXT => "__text", + :SECT_FVMLIB_INIT0 => "__fvmlib_init0", + :SECT_FVMLIB_INIT1 => "__fvmlib_init1", + :SECT_DATA => "__data", + :SECT_BSS => "__bss", + :SECT_COMMON => "__common", + :SECT_OBJC_SYMBOLS => "__symbol_table", + :SECT_OBJC_MODULES => "__module_info", + :SECT_OBJC_STRINGS => "__selector_strs", + :SECT_OBJC_REFS => "__selector_refs", + :SECT_ICON_HEADER => "__header", + :SECT_ICON_TIFF => "__tiff", + }.freeze + + # Represents a section of a segment for 32-bit architectures. + class Section < MachOStructure + # @return [String] the name of the section, including null pad bytes + field :sectname, :string, :padding => :null, :size => 16 + + # @return [String] the name of the segment's section, including null + # pad bytes + field :segname, :string, :padding => :null, :size => 16 + + # @return [Integer] the memory address of the section + field :addr, :uint32 + + # @return [Integer] the size, in bytes, of the section + field :size, :uint32 + + # @return [Integer] the file offset of the section + field :offset, :uint32 + + # @return [Integer] the section alignment (power of 2) of the section + field :align, :uint32 + + # @return [Integer] the file offset of the section's relocation entries + field :reloff, :uint32 + + # @return [Integer] the number of relocation entries + field :nreloc, :uint32 + + # @return [Integer] flags for type and attributes of the section + field :flags, :uint32 + + # @return [void] reserved (for offset or index) + field :reserved1, :uint32 + + # @return [void] reserved (for count or sizeof) + field :reserved2, :uint32 + + # @return [String] the section's name + def section_name + sectname + end + + # @return [String] the parent segment's name + def segment_name + segname + end + + # @return [Boolean] whether the section is empty (i.e, {size} is 0) + def empty? + size.zero? + end + + # @return [Integer] the raw numeric type of this section + def type + flags & SECTION_TYPE_MASK + end + + # @example + # puts "this section is regular" if sect.type?(:S_REGULAR) + # @param type_sym [Symbol] a section type symbol + # @return [Boolean] whether this section is of the given type + def type?(type_sym) + type == SECTION_TYPES[type_sym] + end + + # @return [Integer] the raw numeric attributes of this section + def attributes + flags & SECTION_ATTRIBUTES_MASK + end + + # @example + # puts "pure instructions" if sect.attribute?(:S_ATTR_PURE_INSTRUCTIONS) + # @param attr_sym [Symbol] a section attribute symbol + # @return [Boolean] whether this section is of the given type + def attribute?(attr_sym) + !!(attributes & SECTION_ATTRIBUTES[attr_sym]) + end + + # @deprecated Use {#type?} or {#attribute?} instead. + # @example + # puts "this section is regular" if sect.flag?(:S_REGULAR) + # @param flag [Symbol] a section flag symbol + # @return [Boolean] whether the flag is present in the section's {flags} + def flag?(flag) + flag = SECTION_FLAGS[flag] + + return false if flag.nil? + + flags & flag == flag + end + + # @return [Hash] a hash representation of this {Section} + def to_h + { + "sectname" => sectname, + "segname" => segname, + "addr" => addr, + "size" => size, + "offset" => offset, + "align" => align, + "reloff" => reloff, + "nreloc" => nreloc, + "flags" => flags, + "reserved1" => reserved1, + "reserved2" => reserved2, + }.merge super + end + end + + # Represents a section of a segment for 64-bit architectures. + class Section64 < Section + # @return [Integer] the memory address of the section + field :addr, :uint64 + + # @return [Integer] the size, in bytes, of the section + field :size, :uint64 + + # @return [void] reserved + field :reserved3, :uint32 + + # @return [Hash] a hash representation of this {Section64} + def to_h + { + "reserved3" => reserved3, + }.merge super + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/ruby-macho-4.0.0/lib/macho/structure.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/ruby-macho-4.0.0/lib/macho/structure.rb new file mode 100644 index 0000000000..06949a9376 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/ruby-macho-4.0.0/lib/macho/structure.rb @@ -0,0 +1,284 @@ +# frozen_string_literal: true + +module MachO + # A general purpose pseudo-structure. Described in detail in docs/machostructure-dsl.md. + # @abstract + class MachOStructure + # Constants used for parsing MachOStructure fields + module Fields + # 1. All fields with empty strings and zeros aren't used + # to calculate the format and sizeof variables. + # 2. All fields with nil should provide those values manually + # via the :size parameter. + + # association of field types to byte size + # @api private + BYTE_SIZE = { + # Binary slices + :string => nil, + :null_padded_string => nil, + :int32 => 4, + :uint32 => 4, + :uint64 => 8, + # Classes + :view => 0, + :lcstr => 4, + :two_level_hints_table => 0, + :tool_entries => 4, + }.freeze + + # association of field types with ruby format codes + # Binary format codes can be found here: + # https://docs.ruby-lang.org/en/2.6.0/String.html#method-i-unpack + # + # The equals sign is used to manually change endianness using + # the Utils#specialize_format() method. + # @api private + FORMAT_CODE = { + # Binary slices + :string => "a", + :null_padded_string => "Z", + :int32 => "l=", + :uint32 => "L=", + :uint64 => "Q=", + # Classes + :view => "", + :lcstr => "L=", + :two_level_hints_table => "", + :tool_entries => "L=", + }.freeze + + # A list of classes that must get initialized + # To add a new class append it here and add the init method to the def_class_reader method + # @api private + CLASSES_TO_INIT = %i[lcstr tool_entries two_level_hints_table].freeze + + # A list of fields that don't require arguments in the initializer + # Used to calculate MachOStructure#min_args + # @api private + NO_ARG_REQUIRED = %i[two_level_hints_table].freeze + end + + # map of field names to indices + @field_idxs = {} + + # array of fields sizes + @size_list = [] + + # array of field format codes + @fmt_list = [] + + # minimum number of required arguments + @min_args = 0 + + # @param args [Array[Value]] list of field parameters + def initialize(*args) + raise ArgumentError, "Invalid number of arguments" if args.size < self.class.min_args + + @values = args + end + + # @return [Hash] a hash representation of this {MachOStructure}. + def to_h + { + "structure" => { + "format" => self.class.format, + "bytesize" => self.class.bytesize, + }, + } + end + + class << self + attr_reader :min_args + + # @param endianness [Symbol] either `:big` or `:little` + # @param bin [String] the string to be unpacked into the new structure + # @return [MachO::MachOStructure] the resulting structure + # @api private + def new_from_bin(endianness, bin) + format = Utils.specialize_format(self.format, endianness) + + new(*bin.unpack(format)) + end + + def format + @format ||= @fmt_list.join + end + + def bytesize + @bytesize ||= @size_list.sum + end + + private + + # @param subclass [Class] subclass type + # @api private + def inherited(subclass) # rubocop:disable Lint/MissingSuper + # Clone all class instance variables + field_idxs = @field_idxs.dup + size_list = @size_list.dup + fmt_list = @fmt_list.dup + min_args = @min_args.dup + + # Add those values to the inheriting class + subclass.class_eval do + @field_idxs = field_idxs + @size_list = size_list + @fmt_list = fmt_list + @min_args = min_args + end + end + + # @param name [Symbol] name of internal field + # @param type [Symbol] type of field in terms of binary size + # @param options [Hash] set of additonal options + # Expected options + # :size [Integer] size in bytes + # :mask [Integer] bitmask + # :unpack [String] string format + # :default [Value] default value + # :to_s [Boolean] flag for generating #to_s + # :endian [Symbol] optionally specify :big or :little endian + # :padding [Symbol] optionally specify :null padding + # @api private + def field(name, type, **options) + raise ArgumentError, "Invalid field type #{type}" unless Fields::FORMAT_CODE.key?(type) + + # Get field idx for size_list and fmt_list + idx = if @field_idxs.key?(name) + @field_idxs[name] + else + @min_args += 1 unless options.key?(:default) || Fields::NO_ARG_REQUIRED.include?(type) + @field_idxs[name] = @field_idxs.size + @size_list << nil + @fmt_list << nil + @field_idxs.size - 1 + end + + # Update string type if padding is specified + type = :null_padded_string if type == :string && options[:padding] == :null + + # Add to size_list and fmt_list + @size_list[idx] = Fields::BYTE_SIZE[type] || options[:size] + @fmt_list[idx] = if options[:endian] + Utils.specialize_format(Fields::FORMAT_CODE[type], options[:endian]) + else + Fields::FORMAT_CODE[type] + end + @fmt_list[idx] += options[:size].to_s if options.key?(:size) + + # Generate methods + if Fields::CLASSES_TO_INIT.include?(type) + def_class_reader(name, type, idx) + elsif options.key?(:mask) + def_mask_reader(name, idx, options[:mask]) + elsif options.key?(:unpack) + def_unpack_reader(name, idx, options[:unpack]) + elsif options.key?(:default) + def_default_reader(name, idx, options[:default]) + else + def_reader(name, idx) + end + + def_to_s(name) if options[:to_s] + end + + # + # Method Generators + # + + # Generates a reader method for classes that need to be initialized. + # These classes are defined in the Fields::CLASSES_TO_INIT array. + # @param name [Symbol] name of internal field + # @param type [Symbol] type of field in terms of binary size + # @param idx [Integer] the index of the field value in the @values array + # @api private + def def_class_reader(name, type, idx) + case type + when :lcstr + define_method(name) do + instance_variable_defined?("@#{name}") || + instance_variable_set("@#{name}", LoadCommands::LoadCommand::LCStr.new(self, @values[idx])) + + instance_variable_get("@#{name}") + end + when :two_level_hints_table + define_method(name) do + instance_variable_defined?("@#{name}") || + instance_variable_set("@#{name}", LoadCommands::TwolevelHintsCommand::TwolevelHintsTable.new(view, htoffset, nhints)) + + instance_variable_get("@#{name}") + end + when :tool_entries + define_method(name) do + instance_variable_defined?("@#{name}") || + instance_variable_set("@#{name}", LoadCommands::BuildVersionCommand::ToolEntries.new(view, @values[idx])) + + instance_variable_get("@#{name}") + end + end + end + + # Generates a reader method for fields that need to be bitmasked. + # @param name [Symbol] name of internal field + # @param idx [Integer] the index of the field value in the @values array + # @param mask [Integer] the bitmask + # @api private + def def_mask_reader(name, idx, mask) + define_method(name) do + instance_variable_defined?("@#{name}") || + instance_variable_set("@#{name}", @values[idx] & ~mask) + + instance_variable_get("@#{name}") + end + end + + # Generates a reader method for fields that need further unpacking. + # @param name [Symbol] name of internal field + # @param idx [Integer] the index of the field value in the @values array + # @param unpack [String] the format code used for futher binary unpacking + # @api private + def def_unpack_reader(name, idx, unpack) + define_method(name) do + instance_variable_defined?("@#{name}") || + instance_variable_set("@#{name}", @values[idx].unpack(unpack)) + + instance_variable_get("@#{name}") + end + end + + # Generates a reader method for fields that have default values. + # @param name [Symbol] name of internal field + # @param idx [Integer] the index of the field value in the @values array + # @param default [Value] the default value + # @api private + def def_default_reader(name, idx, default) + define_method(name) do + instance_variable_defined?("@#{name}") || + instance_variable_set("@#{name}", @values.size > idx ? @values[idx] : default) + + instance_variable_get("@#{name}") + end + end + + # Generates an attr_reader like method for a field. + # @param name [Symbol] name of internal field + # @param idx [Integer] the index of the field value in the @values array + # @api private + def def_reader(name, idx) + define_method(name) do + @values[idx] + end + end + + # Generates the to_s method based on the named field. + # @param name [Symbol] name of the field + # @api private + def def_to_s(name) + define_method(:to_s) do + send(name).to_s + end + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/ruby-macho-4.0.0/lib/macho/tools.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/ruby-macho-4.0.0/lib/macho/tools.rb new file mode 100644 index 0000000000..b49a01fdc8 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/ruby-macho-4.0.0/lib/macho/tools.rb @@ -0,0 +1,115 @@ +# frozen_string_literal: true + +module MachO + # A collection of convenient methods for common operations on Mach-O and Fat + # binaries. + module Tools + # @param filename [String] the Mach-O or Fat binary being read + # @return [Array] an array of all dylibs linked to the binary + def self.dylibs(filename) + file = MachO.open(filename) + + file.linked_dylibs + end + + # Changes the dylib ID of a Mach-O or Fat binary, overwriting the source + # file. + # @param filename [String] the Mach-O or Fat binary being modified + # @param new_id [String] the new dylib ID for the binary + # @param options [Hash] + # @option options [Boolean] :strict (true) whether or not to fail loudly + # with an exception if the change cannot be performed + # @return [void] + def self.change_dylib_id(filename, new_id, options = {}) + file = MachO.open(filename) + + file.change_dylib_id(new_id, options) + file.write! + end + + # Changes a shared library install name in a Mach-O or Fat binary, + # overwriting the source file. + # @param filename [String] the Mach-O or Fat binary being modified + # @param old_name [String] the old shared library name + # @param new_name [String] the new shared library name + # @param options [Hash] + # @option options [Boolean] :strict (true) whether or not to fail loudly + # with an exception if the change cannot be performed + # @return [void] + def self.change_install_name(filename, old_name, new_name, options = {}) + file = MachO.open(filename) + + file.change_install_name(old_name, new_name, options) + file.write! + end + + # Changes a runtime path in a Mach-O or Fat binary, overwriting the source + # file. + # @param filename [String] the Mach-O or Fat binary being modified + # @param old_path [String] the old runtime path + # @param new_path [String] the new runtime path + # @param options [Hash] + # @option options [Boolean] :strict (true) whether or not to fail loudly + # with an exception if the change cannot be performed + # @option options [Boolean] :uniq (false) whether or not to change duplicate + # rpaths simultaneously + # @return [void] + def self.change_rpath(filename, old_path, new_path, options = {}) + file = MachO.open(filename) + + file.change_rpath(old_path, new_path, options) + file.write! + end + + # Add a runtime path to a Mach-O or Fat binary, overwriting the source file. + # @param filename [String] the Mach-O or Fat binary being modified + # @param new_path [String] the new runtime path + # @param options [Hash] + # @option options [Boolean] :strict (true) whether or not to fail loudly + # with an exception if the change cannot be performed + # @return [void] + def self.add_rpath(filename, new_path, options = {}) + file = MachO.open(filename) + + file.add_rpath(new_path, options) + file.write! + end + + # Delete a runtime path from a Mach-O or Fat binary, overwriting the source + # file. + # @param filename [String] the Mach-O or Fat binary being modified + # @param old_path [String] the old runtime path + # @param options [Hash] + # @option options [Boolean] :strict (true) whether or not to fail loudly + # with an exception if the change cannot be performed + # @option options [Boolean] :uniq (false) whether or not to delete duplicate + # rpaths simultaneously + # @return [void] + def self.delete_rpath(filename, old_path, options = {}) + file = MachO.open(filename) + + file.delete_rpath(old_path, options) + file.write! + end + + # Merge multiple Mach-Os into one universal (Fat) binary. + # @param filename [String] the fat binary to create + # @param files [Array] the files to merge + # @param fat64 [Boolean] whether to use {Headers::FatArch64}s to represent each slice + # @return [void] + def self.merge_machos(filename, *files, fat64: false) + machos = files.map do |file| + macho = MachO.open(file) + case macho + when MachO::MachOFile + macho + else + macho.machos + end + end.flatten + + fat_macho = MachO::FatFile.new_from_machos(*machos, :fat64 => fat64) + fat_macho.write(filename) + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/ruby-macho-4.0.0/lib/macho/utils.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/ruby-macho-4.0.0/lib/macho/utils.rb new file mode 100644 index 0000000000..5e6e97bae5 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/ruby-macho-4.0.0/lib/macho/utils.rb @@ -0,0 +1,132 @@ +# frozen_string_literal: true + +module MachO + # A collection of utility functions used throughout ruby-macho. + module Utils + # Rounds a value to the next multiple of the given round. + # @param value [Integer] the number being rounded + # @param round [Integer] the number being rounded with + # @return [Integer] the rounded value + # @see http://www.opensource.apple.com/source/cctools/cctools-870/libstuff/rnd.c + def self.round(value, round) + round -= 1 + value += round + value &= ~round + value + end + + # Returns the number of bytes needed to pad the given size to the given + # alignment. + # @param size [Integer] the unpadded size + # @param alignment [Integer] the number to alignment the size with + # @return [Integer] the number of pad bytes required + def self.padding_for(size, alignment) + round(size, alignment) - size + end + + # Returns a string of null bytes of the requested (non-negative) size + # @param size [Integer] the size of the nullpad + # @return [String] the null string (or empty string, for `size = 0`) + # @raise [ArgumentError] if a non-positive nullpad is requested + def self.nullpad(size) + raise ArgumentError, "size < 0: #{size}" if size.negative? + + "\x00" * size + end + + # Converts an abstract (native-endian) String#unpack format to big or + # little. + # @param format [String] the format string being converted + # @param endianness [Symbol] either `:big` or `:little` + # @return [String] the converted string + def self.specialize_format(format, endianness) + modifier = endianness == :big ? ">" : "<" + format.tr("=", modifier) + end + + # Packs tagged strings into an aligned payload. + # @param fixed_offset [Integer] the baseline offset for the first packed + # string + # @param alignment [Integer] the alignment value to use for packing + # @param strings [Hash] the labeled strings to pack + # @return [Array] the packed string and labeled offsets + def self.pack_strings(fixed_offset, alignment, strings = {}) + offsets = {} + next_offset = fixed_offset + payload = +"" + + strings.each do |key, string| + offsets[key] = next_offset + payload << string + payload << Utils.nullpad(1) + next_offset += string.bytesize + 1 + end + + payload << Utils.nullpad(padding_for(fixed_offset + payload.bytesize, alignment)) + [payload.freeze, offsets] + end + + # Compares the given number to valid Mach-O magic numbers. + # @param num [Integer] the number being checked + # @return [Boolean] whether `num` is a valid Mach-O magic number + def self.magic?(num) + Headers::MH_MAGICS.key?(num) + end + + # Compares the given number to valid Fat magic numbers. + # @param num [Integer] the number being checked + # @return [Boolean] whether `num` is a valid Fat magic number + def self.fat_magic?(num) + [Headers::FAT_MAGIC, Headers::FAT_MAGIC_64].include? num + end + + # Compares the given number to valid 32-bit Fat magic numbers. + # @param num [Integer] the number being checked + # @return [Boolean] whether `num` is a valid 32-bit fat magic number + def self.fat_magic32?(num) + num == Headers::FAT_MAGIC + end + + # Compares the given number to valid 64-bit Fat magic numbers. + # @param num [Integer] the number being checked + # @return [Boolean] whether `num` is a valid 64-bit fat magic number + def self.fat_magic64?(num) + num == Headers::FAT_MAGIC_64 + end + + # Compares the given number to valid 32-bit Mach-O magic numbers. + # @param num [Integer] the number being checked + # @return [Boolean] whether `num` is a valid 32-bit magic number + def self.magic32?(num) + [Headers::MH_MAGIC, Headers::MH_CIGAM].include? num + end + + # Compares the given number to valid 64-bit Mach-O magic numbers. + # @param num [Integer] the number being checked + # @return [Boolean] whether `num` is a valid 64-bit magic number + def self.magic64?(num) + [Headers::MH_MAGIC_64, Headers::MH_CIGAM_64].include? num + end + + # Compares the given number to valid little-endian magic numbers. + # @param num [Integer] the number being checked + # @return [Boolean] whether `num` is a valid little-endian magic number + def self.little_magic?(num) + [Headers::MH_CIGAM, Headers::MH_CIGAM_64].include? num + end + + # Compares the given number to valid big-endian magic numbers. + # @param num [Integer] the number being checked + # @return [Boolean] whether `num` is a valid big-endian magic number + def self.big_magic?(num) + [Headers::MH_MAGIC, Headers::MH_MAGIC_64].include? num + end + + # Compares the given number to the known magic number for a compressed Mach-O slice. + # @param num [Integer] the number being checked + # @return [Boolean] whether `num` is a valid compressed header magic number + def self.compressed_magic?(num) + num == Headers::COMPRESSED_MAGIC + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/ruby-macho-4.0.0/lib/macho/view.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/ruby-macho-4.0.0/lib/macho/view.rb new file mode 100644 index 0000000000..3b1c36d954 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/ruby-macho-4.0.0/lib/macho/view.rb @@ -0,0 +1,42 @@ +# frozen_string_literal: true + +module MachO + # A representation of some unspecified Mach-O data. + class MachOView + # @return [MachOFile] that this view belongs to + attr_reader :macho_file + + # @return [String] the raw Mach-O data + attr_reader :raw_data + + # @return [Symbol] the endianness of the data (`:big` or `:little`) + attr_reader :endianness + + # @return [Integer] the offset of the relevant data (in {#raw_data}) + attr_reader :offset + + # Creates a new MachOView. + # @param macho_file [MachOFile] the file this view slice is from + # @param raw_data [String] the raw Mach-O data + # @param endianness [Symbol] the endianness of the data + # @param offset [Integer] the offset of the relevant data + def initialize(macho_file, raw_data, endianness, offset) + @macho_file = macho_file + @raw_data = raw_data + @endianness = endianness + @offset = offset + end + + # @return [Hash] a hash representation of this {MachOView}. + def to_h + { + "endianness" => endianness, + "offset" => offset, + } + end + + def inspect + "#<#{self.class}:0x#{(object_id << 1).to_s(16)} @endianness=#{@endianness.inspect}, @offset=#{@offset.inspect}, length=#{@raw_data.length}>" + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/sorbet-runtime.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/sorbet-runtime.rb new file mode 100644 index 0000000000..c2ad5678d0 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/sorbet-runtime.rb @@ -0,0 +1,116 @@ +# frozen_string_literal: true +# typed: true + +# This file is hand-crafted to encode the dependencies. They load the whole type +# system since there is such a high chance of it being used, using an autoloader +# wouldn't buy us any startup time saving. + +# Namespaces without any implementation +module T; end +module T::Helpers; end +module T::Private; end +module T::Private::Abstract; end +module T::Private::Types; end + +# Each section is a group that I believe need a fixed ordering. There is also +# an ordering between groups. + +# These are pre-reqs for almost everything in here. +require_relative 'types/configuration' +require_relative 'types/_types' +require_relative 'types/private/decl_state' +require_relative 'types/private/class_utils' +require_relative 'types/private/runtime_levels' +require_relative 'types/private/methods/_methods' +require_relative 'types/sig' +require_relative 'types/helpers' +require_relative 'types/private/final' +require_relative 'types/private/sealed' + +# The types themselves. First base classes +require_relative 'types/types/base' +require_relative 'types/types/typed_enumerable' +# Everything else +require_relative 'types/types/class_of' +require_relative 'types/types/enum' +require_relative 'types/types/fixed_array' +require_relative 'types/types/fixed_hash' +require_relative 'types/types/intersection' +require_relative 'types/types/noreturn' +require_relative 'types/types/proc' +require_relative 'types/types/attached_class' +require_relative 'types/types/self_type' +require_relative 'types/types/simple' +require_relative 'types/types/t_enum' +require_relative 'types/types/type_parameter' +require_relative 'types/types/typed_array' +require_relative 'types/types/typed_enumerator' +require_relative 'types/types/typed_enumerator_lazy' +require_relative 'types/types/typed_hash' +require_relative 'types/types/typed_range' +require_relative 'types/types/typed_set' +require_relative 'types/types/union' +require_relative 'types/types/untyped' +require_relative 'types/private/types/not_typed' +require_relative 'types/private/types/void' +require_relative 'types/private/types/string_holder' +require_relative 'types/private/types/type_alias' + +require_relative 'types/types/type_variable' +require_relative 'types/types/type_member' +require_relative 'types/types/type_template' + +# Call validation +require_relative 'types/private/methods/modes' +require_relative 'types/private/methods/call_validation' + +# Signature validation +require_relative 'types/private/methods/signature_validation' +require_relative 'types/abstract_utils' +require_relative 'types/private/abstract/validate' + +# Catch all. Sort of built by `cd extn; find types -type f | grep -v test | sort` +require_relative 'types/generic' +require_relative 'types/interface_wrapper' +require_relative 'types/private/abstract/declare' +require_relative 'types/private/abstract/hooks' +require_relative 'types/private/casts' +require_relative 'types/private/methods/decl_builder' +require_relative 'types/private/methods/signature' +require_relative 'types/private/retry' +require_relative 'types/utils' +require_relative 'types/boolean' + +# Props dependencies +require_relative 'types/private/abstract/data' +require_relative 'types/private/mixins/mixins' +require_relative 'types/props/_props' +require_relative 'types/props/custom_type' +require_relative 'types/props/decorator' +require_relative 'types/props/errors' +require_relative 'types/props/plugin' +require_relative 'types/props/utils' +require_relative 'types/enum' +# Props that run sigs statically so have to be after all the others :( +require_relative 'types/props/private/setter_factory' +require_relative 'types/props/private/apply_default' +require_relative 'types/props/has_lazily_specialized_methods' +require_relative 'types/props/optional' +require_relative 'types/props/weak_constructor' +require_relative 'types/props/constructor' +require_relative 'types/props/pretty_printable' +require_relative 'types/props/private/serde_transform' +require_relative 'types/props/private/deserializer_generator' +require_relative 'types/props/private/serializer_generator' +require_relative 'types/props/serializable' +require_relative 'types/props/type_validation' +require_relative 'types/props/private/parser' +require_relative 'types/props/generated_code_validation' + +require_relative 'types/struct' +require_relative 'types/non_forcing_constants' + +require_relative 'types/compatibility_patches' + +# Sorbet Compiler support module +require_relative 'types/private/compiler' diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/_types.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/_types.rb new file mode 100644 index 0000000000..9d7897400c --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/_types.rb @@ -0,0 +1,316 @@ +# frozen_string_literal: true +# typed: true +# This is where we define the shortcuts, so we can't use them here + +# _____ +# |_ _| _ _ __ ___ ___ +# | || | | | '_ \ / _ \/ __| +# | || |_| | |_) | __/\__ \ +# |_| \__, | .__/ \___||___/ +# |___/|_| +# +# Docs at https://sorbet.org/docs/sigs +# +# Types that you can pass to `sig`: +# +# - a Ruby class +# +# - [, , ...] -- to specify a "tuple"; a fixed-size array with known types for each member +# +# - {key: , key2: , ...} -- to speicfy a "shape"; a fixed-size hash +# with known keys and type values +# +# - Any of the `T.foo` methods below + +module T + # T.any(, , ...) -- matches any of the types listed + def self.any(type_a, type_b, *types) + type_a = T::Utils.coerce(type_a) + type_b = T::Utils.coerce(type_b) + types = types.map {|t| T::Utils.coerce(t)} if !types.empty? + T::Types::Union::Private::Pool.union_of_types(type_a, type_b, types) + end + + # Shorthand for T.any(type, NilClass) + def self.nilable(type) + T::Types::Union::Private::Pool.union_of_types(T::Utils.coerce(type), T::Utils::Nilable::NIL_TYPE) + end + + # Matches any object. In the static checker, T.untyped allows any + # method calls or operations. + def self.untyped + T::Types::Untyped::Private::INSTANCE + end + + # Indicates a function never returns (e.g. "Kernel#raise") + def self.noreturn + T::Types::NoReturn::Private::INSTANCE + end + + # T.all(, , ...) -- matches an object that has all of the types listed + def self.all(type_a, type_b, *types) + T::Types::Intersection.new([type_a, type_b] + types) + end + + # Matches any of the listed values + # @deprecated Use T::Enum instead. + def self.deprecated_enum(values) + T::Types::Enum.new(values) + end + + # Creates a proc type + def self.proc + T::Private::Methods.start_proc + end + + # Matches `self`: + def self.self_type + T::Types::SelfType::Private::INSTANCE + end + + # Matches the instance type in a singleton-class context + def self.attached_class + T::Types::AttachedClassType::Private::INSTANCE + end + + # Matches any class that subclasses or includes the provided class + # or module + def self.class_of(klass) + T::Types::ClassOf.new(klass) + end + + ## END OF THE METHODS TO PASS TO `sig`. + + # Constructs a type alias. Used to create a short name for a larger type. In Ruby this returns a + # wrapper that contains a proc that is evaluated to get the underlying type. This syntax however + # is needed for support by the static checker. + # + # @example + # NilableString = T.type_alias {T.nilable(String)} + # + # sig {params(arg: NilableString, default: String).returns(String)} + # def or_else(arg, default) + # arg || default + # end + # + # The name of the type alias is not preserved; Error messages will + # be printed with reference to the underlying type. + # + # TODO Remove `type` parameter. This was left in to make life easier while migrating. + def self.type_alias(type=nil, &blk) + if blk + T::Private::Types::TypeAlias.new(blk) + else + T::Utils.coerce(type) + end + end + + # References a type parameter which was previously defined with + # `type_parameters`. + # + # This is used for generic methods. + # + # @example + # sig + # .type_parameters(:U) + # .params( + # blk: T.proc.params(arg0: Elem).returns(T.type_parameter(:U)), + # ) + # .returns(T::Array[T.type_parameter(:U)]) + # def map(&blk); end + def self.type_parameter(name) + T::Types::TypeParameter.new(name) + end + + # Tells the typechecker that `value` is of type `type`. Use this to get additional checking after + # an expression that the typechecker is unable to analyze. If `checked` is true, raises an + # exception at runtime if the value doesn't match the type. + # + # Compared to `T.let`, `T.cast` is _trusted_ by static system. + def self.cast(value, type, checked: true) + return value unless checked + + Private::Casts.cast(value, type, "T.cast") + end + + # Tells the typechecker to declare a variable of type `type`. Use + # like: + # + # seconds = T.let(0.0, Float) + # + # Compared to `T.cast`, `T.let` is _checked_ by static system. + # + # If `checked` is true, raises an exception at runtime if the value + # doesn't match the type. + def self.let(value, type, checked: true) + return value unless checked + + Private::Casts.cast(value, type, "T.let") + end + + # Tells the type checker to treat `self` in the current block as `type`. + # Useful for blocks that are captured and executed later with instance_exec. + # Use like: + # + # seconds = lambda do + # T.bind(self, NewBinding) + # ... + # end + # + # `T.bind` behaves like `T.cast` in that it is assumed to be true statically. + # + # If `checked` is true, raises an exception at runtime if the value + # doesn't match the type (this is the default). + def self.bind(value, type, checked: true) + return value unless checked + + Private::Casts.cast(value, type, "T.bind") + end + + # Tells the typechecker to ensure that `value` is of type `type` (if not, the typechecker will + # fail). Use this for debugging typechecking errors, or to ensure that type information is + # statically known and being checked appropriately. If `checked` is true, raises an exception at + # runtime if the value doesn't match the type. + def self.assert_type!(value, type, checked: true) + return value unless checked + + Private::Casts.cast(value, type, "T.assert_type!") + end + + # For the static type checker, strips all type information from a value + # and returns the same value, but statically-typed as `T.untyped`. + # Can be used to tell the static checker to "trust you" by discarding type information + # you know to be incorrect. Use with care! + # (This has no effect at runtime.) + # + # We can't actually write this sig because we ourselves are inside + # the `T::` module and doing this would create a bootstrapping + # cycle. However, we also don't actually need to do so; An untyped + # identity method works just as well here. + # + # `sig {params(value: T.untyped).returns(T.untyped)}` + def self.unsafe(value) + value + end + + # A convenience method to `raise` when the argument is `nil` and return it + # otherwise. + # + # Intended to be used as: + # + # needs_foo(T.must(maybe_gives_foo)) + # + # Equivalent to: + # + # foo = maybe_gives_foo + # raise "nil" if foo.nil? + # needs_foo(foo) + # + # Intended to be used to promise sorbet that a given nilable value happens + # to contain a non-nil value at this point. + # + # `sig {params(arg: T.nilable(A)).returns(A)}` + def self.must(arg) + return arg if arg + return arg if arg == false + + begin + raise TypeError.new("Passed `nil` into T.must") + rescue TypeError => e # raise into rescue to ensure e.backtrace is populated + T::Configuration.inline_type_error_handler(e, {kind: 'T.must', value: arg, type: nil}) + end + end + + # A way to ask Sorbet to show what type it thinks an expression has. + # This can be useful for debugging and checking assumptions. + # In the runtime, merely returns the value passed in. + def self.reveal_type(value) + value + end + + # A way to ask Sorbet to prove that a certain branch of control flow never + # happens. Commonly used to assert that a case or if statement exhausts all + # possible cases. + def self.absurd(value) + msg = "Control flow reached T.absurd." + + case value + when Kernel + msg += " Got value: #{value}" + end + + begin + raise TypeError.new(msg) + rescue TypeError => e # raise into rescue to ensure e.backtrace is populated + T::Configuration.inline_type_error_handler(e, {kind: 'T.absurd', value: value, type: nil}) + end + end + + ### Generic classes ### + + module Array + def self.[](type) + if type.is_a?(T::Types::Untyped) + T::Types::TypedArray::Untyped.new + else + T::Types::TypedArray.new(type) + end + end + end + + module Hash + def self.[](keys, values) + if keys.is_a?(T::Types::Untyped) && values.is_a?(T::Types::Untyped) + T::Types::TypedHash::Untyped.new + else + T::Types::TypedHash.new(keys: keys, values: values) + end + end + end + + module Enumerable + def self.[](type) + if type.is_a?(T::Types::Untyped) + T::Types::TypedEnumerable::Untyped.new + else + T::Types::TypedEnumerable.new(type) + end + end + end + + module Enumerator + def self.[](type) + if type.is_a?(T::Types::Untyped) + T::Types::TypedEnumerator::Untyped.new + else + T::Types::TypedEnumerator.new(type) + end + end + + module Lazy + def self.[](type) + if type.is_a?(T::Types::Untyped) + T::Types::TypedEnumeratorLazy::Untyped.new + else + T::Types::TypedEnumeratorLazy.new(type) + end + end + end + end + + module Range + def self.[](type) + T::Types::TypedRange.new(type) + end + end + + module Set + def self.[](type) + if type.is_a?(T::Types::Untyped) + T::Types::TypedSet::Untyped.new + else + T::Types::TypedSet.new(type) + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/abstract_utils.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/abstract_utils.rb new file mode 100644 index 0000000000..721bd4e0a7 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/abstract_utils.rb @@ -0,0 +1,50 @@ +# frozen_string_literal: true +# typed: true + +module T::AbstractUtils + Methods = T::Private::Methods + + # Returns whether a module is declared as abstract. After the module is finished being declared, + # this is equivalent to whether it has any abstract methods that haven't been implemented + # (because we validate that and raise an error otherwise). + # + # Note that checking `mod.is_a?(Abstract::Hooks)` is not a safe substitute for this method; when + # a class extends `Abstract::Hooks`, all of its subclasses, including the eventual concrete + # ones, will still have `Abstract::Hooks` as an ancestor. + def self.abstract_module?(mod) + !T::Private::Abstract::Data.get(mod, :abstract_type).nil? + end + + def self.abstract_method?(method) + signature = Methods.signature_for_method(method) + signature&.mode == Methods::Modes.abstract + end + + # Given a module, returns the set of methods declared as abstract (in itself or ancestors) + # that have not been implemented. + def self.abstract_methods_for(mod) + declared_methods = declared_abstract_methods_for(mod) + declared_methods.select do |declared_method| + actual_method = mod.instance_method(declared_method.name) + # Note that in the case where an abstract method is overridden by another abstract method, + # this method will return them both. This is intentional to ensure we validate the final + # implementation against all declarations of an abstract method (they might not all have the + # same signature). + abstract_method?(actual_method) + end + end + + # Given a module, returns the set of methods declared as abstract (in itself or ancestors) + # regardless of whether they have been implemented. + def self.declared_abstract_methods_for(mod) + methods = [] + mod.ancestors.each do |ancestor| + ancestor_methods = ancestor.private_instance_methods(false) + ancestor.instance_methods(false) + ancestor_methods.each do |method_name| + method = ancestor.instance_method(method_name) + methods << method if abstract_method?(method) + end + end + methods + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/boolean.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/boolean.rb new file mode 100644 index 0000000000..8763d8707d --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/boolean.rb @@ -0,0 +1,8 @@ +# typed: strict +# frozen_string_literal: true + +module T + # T::Boolean is a type alias helper for the common `T.any(TrueClass, FalseClass)`. + # Defined separately from _types.rb because it has a dependency on T::Types::Union. + Boolean = T.type_alias {T.any(TrueClass, FalseClass)} +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/compatibility_patches.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/compatibility_patches.rb new file mode 100644 index 0000000000..070b182aae --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/compatibility_patches.rb @@ -0,0 +1,93 @@ +# frozen_string_literal: true +# typed: ignore + +# Work around an interaction bug with sorbet-runtime and rspec-mocks, +# which occurs when using message expectations (*_any_instance_of, +# expect, allow) and and_call_original. +# +# When a sig is defined, sorbet-runtime will replace the sigged method +# with a wrapper that, upon first invocation, re-wraps the method with a faster +# implementation. +# +# When expect_any_instance_of is used, rspec stores a reference to the first wrapper, +# to be restored later. +# +# The first wrapper is invoked as part of the test and sorbet-runtime replaces +# the method definition with the second wrapper. +# +# But when mocks are cleaned up, rspec restores back to the first wrapper. +# Upon subsequent invocations, the first wrapper is called, and sorbet-runtime +# throws a runtime error, since this is an unexpected state. +# +# We work around this by forcing re-wrapping before rspec stores a reference +# to the method. +if defined? ::RSpec::Mocks + module T + module CompatibilityPatches + module RSpecCompatibility + module RecorderExtensions + def observe!(method_name) + method = @klass.instance_method(method_name.to_sym) + T::Private::Methods.maybe_run_sig_block_for_method(method) + super(method_name) + end + end + ::RSpec::Mocks::AnyInstance::Recorder.prepend(RecorderExtensions) if defined?(::RSpec::Mocks::AnyInstance::Recorder) + + module MethodDoubleExtensions + def initialize(object, method_name, proxy) + if ::Kernel.instance_method(:respond_to?).bind(object).call(method_name, true) + method = ::RSpec::Support.method_handle_for(object, method_name) + T::Private::Methods.maybe_run_sig_block_for_method(method) + end + super(object, method_name, proxy) + end + end + ::RSpec::Mocks::MethodDouble.prepend(MethodDoubleExtensions) if defined?(::RSpec::Mocks::MethodDouble) + end + end + end +end + +# Work around for sorbet-runtime wrapped methods. +# +# When a sig is defined, sorbet-runtime will replace the sigged method +# with a wrapper. Those wrapper methods look like `foo(*args, &blk)` +# so that wrappers can handle and pass on all the arguments supplied. +# +# However, that creates a problem with runtime reflection on the methods, +# since when a sigged method is introspected, it will always return its +# `arity` as `-1`, its `parameters` as `[[:rest, :args], [:block, :blk]]`, +# and its `source_location` as `[, ]`. +# +# This might be a problem for some applications that rely on getting the +# correct information from these methods. +# +# This compatibility module, when prepended to the `Method` class, would fix +# the return values of `arity`, `parameters` and `source_location`. +# +# @example +# require 'sorbet-runtime' +# ::Method.prepend(T::CompatibilityPatches::MethodExtensions) +module T + module CompatibilityPatches + module MethodExtensions + def arity + arity = super + return arity if arity != -1 || self.is_a?(Proc) + sig = T::Private::Methods.signature_for_method(self) + sig ? sig.method.arity : arity + end + + def source_location + sig = T::Private::Methods.signature_for_method(self) + sig ? sig.method.source_location : super + end + + def parameters + sig = T::Private::Methods.signature_for_method(self) + sig ? sig.method.parameters : super + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/configuration.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/configuration.rb new file mode 100644 index 0000000000..c012b6e8b6 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/configuration.rb @@ -0,0 +1,591 @@ +# typed: true +# frozen_string_literal: true + +module T::Configuration + # Cache this comparisonn to avoid two allocations all over the place. + AT_LEAST_RUBY_2_7 = Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('2.7') + + # Announces to Sorbet that we are currently in a test environment, so it + # should treat any sigs which are marked `.checked(:tests)` as if they were + # just a normal sig. + # + # If this method is not called, sigs marked `.checked(:tests)` will not be + # checked. In fact, such methods won't even be wrapped--the runtime will put + # back the original method. + # + # Note: Due to the way sigs are evaluated and methods are wrapped, this + # method MUST be called before any code calls `sig`. This method raises if + # it has been called too late. + def self.enable_checking_for_sigs_marked_checked_tests + T::Private::RuntimeLevels.enable_checking_in_tests + end + + # Announce to Sorbet that we would like the final checks to be enabled when + # including and extending modules. Iff this is not called, then the following + # example will not raise an error. + # + # ```ruby + # module M + # extend T::Sig + # sig(:final) {void} + # def foo; end + # end + # class C + # include M + # def foo; end + # end + # ``` + def self.enable_final_checks_on_hooks + T::Private::Methods.set_final_checks_on_hooks(true) + end + + # Undo the effects of a previous call to + # `enable_final_checks_on_hooks`. + def self.reset_final_checks_on_hooks + T::Private::Methods.set_final_checks_on_hooks(false) + end + + @include_value_in_type_errors = true + # Whether to include values in TypeError messages. + # + # Including values is useful for debugging, but can potentially leak + # sensitive information to logs. + # + # @return [T::Boolean] + def self.include_value_in_type_errors? + @include_value_in_type_errors + end + + # Configure if type errors excludes the value of the problematic type. + # + # The default is to include values in type errors: + # TypeError: Expected type Integer, got String with value "foo" + # + # When values are excluded from type errors: + # TypeError: Expected type Integer, got String + def self.exclude_value_in_type_errors + @include_value_in_type_errors = false + end + + # Opposite of exclude_value_in_type_errors. + # (Including values in type errors is the default) + def self.include_value_in_type_errors + @include_value_in_type_errors = true + end + + # Whether VM-defined prop serialization/deserialization routines can be enabled. + # + # @return [T::Boolean] + def self.can_enable_vm_prop_serde? + T::Props::Private::DeserializerGenerator.respond_to?(:generate2) + end + + @use_vm_prop_serde = false + # Whether to use VM-defined prop serialization/deserialization routines. + # + # The default is to use runtime codegen inside sorbet-runtime itself. + # + # @return [T::Boolean] + def self.use_vm_prop_serde? + @use_vm_prop_serde || false + end + + # Enable using VM-defined prop serialization/deserialization routines. + # + # This method is likely to break things outside of Stripe's systems. + def self.enable_vm_prop_serde + if !can_enable_vm_prop_serde? + hard_assert_handler('Ruby VM is not setup to use VM-defined prop serde') + end + @use_vm_prop_serde = true + end + + # Disable using VM-defined prop serialization/deserialization routines. + def self.disable_vm_prop_serde + @use_vm_prop_serde = false + end + + # Configure the default checked level for a sig with no explicit `.checked` + # builder. When unset, the default checked level is `:always`. + # + # Note: setting this option is potentially dangerous! Sorbet can't check all + # code statically. The runtime checks complement the checks that Sorbet does + # statically, so that methods don't have to guard themselves from being + # called incorrectly by untyped code. + # + # @param [:never, :compiled, :tests, :always] default_checked_level + def self.default_checked_level=(default_checked_level) + T::Private::RuntimeLevels.default_checked_level = default_checked_level + end + + @inline_type_error_handler = nil + # Set a handler to handle `TypeError`s raised by any in-line type assertions, + # including `T.must`, `T.let`, `T.cast`, and `T.assert_type!`. + # + # By default, any `TypeError`s detected by this gem will be raised. Setting + # inline_type_error_handler to an object that implements :call (e.g. proc or + # lambda) allows users to customize the behavior when a `TypeError` is + # raised on any inline type assertion. + # + # @param [Lambda, Proc, Object, nil] value Proc that handles the error (pass + # nil to reset to default behavior) + # + # Parameters passed to value.call: + # + # @param [TypeError] error TypeError that was raised + # @param [Hash] opts A hash containing contextual information on the error: + # @option opts [String] :kind One of: + # ['T.cast', 'T.let', 'T.bind', 'T.assert_type!', 'T.must', 'T.absurd'] + # @option opts [Object, nil] :type Expected param/return value type + # @option opts [Object] :value Actual param/return value + # + # @example + # T::Configuration.inline_type_error_handler = lambda do |error, opts| + # puts error.message + # end + def self.inline_type_error_handler=(value) + validate_lambda_given!(value) + @inline_type_error_handler = value + end + + private_class_method def self.inline_type_error_handler_default(error, opts) + raise error + end + + def self.inline_type_error_handler(error, opts={}) + if @inline_type_error_handler + # Backwards compatibility before `inline_type_error_handler` took a second arg + if @inline_type_error_handler.arity == 1 + @inline_type_error_handler.call(error) + else + @inline_type_error_handler.call(error, opts) + end + else + inline_type_error_handler_default(error, opts) + end + nil + end + + @sig_builder_error_handler = nil + # Set a handler to handle errors that occur when the builder methods in the + # body of a sig are executed. The sig builder methods are inside a proc so + # that they can be lazily evaluated the first time the method being sig'd is + # called. + # + # By default, improper use of the builder methods within the body of a sig + # cause an ArgumentError to be raised. Setting sig_builder_error_handler to an + # object that implements :call (e.g. proc or lambda) allows users to + # customize the behavior when a sig can't be built for some reason. + # + # @param [Lambda, Proc, Object, nil] value Proc that handles the error (pass + # nil to reset to default behavior) + # + # Parameters passed to value.call: + # + # @param [StandardError] error The error that was raised + # @param [Thread::Backtrace::Location] location Location of the error + # + # @example + # T::Configuration.sig_builder_error_handler = lambda do |error, location| + # puts error.message + # end + def self.sig_builder_error_handler=(value) + validate_lambda_given!(value) + @sig_builder_error_handler = value + end + + private_class_method def self.sig_builder_error_handler_default(error, location) + raise ArgumentError.new("#{location.path}:#{location.lineno}: Error interpreting `sig`:\n #{error.message}\n\n") + end + + def self.sig_builder_error_handler(error, location) + if @sig_builder_error_handler + @sig_builder_error_handler.call(error, location) + else + sig_builder_error_handler_default(error, location) + end + nil + end + + @sig_validation_error_handler = nil + # Set a handler to handle sig validation errors. + # + # Sig validation errors include things like abstract checks, override checks, + # and type compatibility of arguments. They happen after a sig has been + # successfully built, but the built sig is incompatible with other sigs in + # some way. + # + # By default, sig validation errors cause an exception to be raised. + # Setting sig_validation_error_handler to an object that implements :call + # (e.g. proc or lambda) allows users to customize the behavior when a method + # signature's build fails. + # + # @param [Lambda, Proc, Object, nil] value Proc that handles the error (pass + # nil to reset to default behavior) + # + # Parameters passed to value.call: + # + # @param [StandardError] error The error that was raised + # @param [Hash] opts A hash containing contextual information on the error: + # @option opts [Method, UnboundMethod] :method Method on which the signature build failed + # @option opts [T::Private::Methods::Declaration] :declaration Method + # signature declaration struct + # @option opts [T::Private::Methods::Signature, nil] :signature Signature + # that failed (nil if sig build failed before Signature initialization) + # @option opts [T::Private::Methods::Signature, nil] :super_signature Super + # method's signature (nil if method is not an override or super method + # does not have a method signature) + # + # @example + # T::Configuration.sig_validation_error_handler = lambda do |error, opts| + # puts error.message + # end + def self.sig_validation_error_handler=(value) + validate_lambda_given!(value) + @sig_validation_error_handler = value + end + + private_class_method def self.sig_validation_error_handler_default(error, opts) + raise error + end + + def self.sig_validation_error_handler(error, opts={}) + if @sig_validation_error_handler + @sig_validation_error_handler.call(error, opts) + else + sig_validation_error_handler_default(error, opts) + end + nil + end + + @call_validation_error_handler = nil + # Set a handler for type errors that result from calling a method. + # + # By default, errors from calling a method cause an exception to be raised. + # Setting call_validation_error_handler to an object that implements :call + # (e.g. proc or lambda) allows users to customize the behavior when a method + # is called with invalid parameters, or returns an invalid value. + # + # @param [Lambda, Proc, Object, nil] value Proc that handles the error + # report (pass nil to reset to default behavior) + # + # Parameters passed to value.call: + # + # @param [T::Private::Methods::Signature] signature Signature that failed + # @param [Hash] opts A hash containing contextual information on the error: + # @option opts [String] :message Error message + # @option opts [String] :kind One of: + # ['Parameter', 'Block parameter', 'Return value'] + # @option opts [Symbol] :name Param or block param name (nil for return + # value) + # @option opts [Object] :type Expected param/return value type + # @option opts [Object] :value Actual param/return value + # @option opts [Thread::Backtrace::Location] :location Location of the + # caller + # + # @example + # T::Configuration.call_validation_error_handler = lambda do |signature, opts| + # puts opts[:message] + # end + def self.call_validation_error_handler=(value) + validate_lambda_given!(value) + @call_validation_error_handler = value + end + + private_class_method def self.call_validation_error_handler_default(signature, opts) + raise TypeError.new(opts[:pretty_message]) + end + + def self.call_validation_error_handler(signature, opts={}) + if @call_validation_error_handler + @call_validation_error_handler.call(signature, opts) + else + call_validation_error_handler_default(signature, opts) + end + nil + end + + @log_info_handler = nil + # Set a handler for logging + # + # @param [Lambda, Proc, Object, nil] value Proc that handles the error + # report (pass nil to reset to default behavior) + # + # Parameters passed to value.call: + # + # @param [String] str Message to be logged + # @param [Hash] extra A hash containing additional parameters to be passed along to the logger. + # + # @example + # T::Configuration.log_info_handler = lambda do |str, extra| + # puts "#{str}, context: #{extra}" + # end + def self.log_info_handler=(value) + validate_lambda_given!(value) + @log_info_handler = value + end + + private_class_method def self.log_info_handler_default(str, extra) + puts "#{str}, extra: #{extra}" + end + + def self.log_info_handler(str, extra) + if @log_info_handler + @log_info_handler.call(str, extra) + else + log_info_handler_default(str, extra) + end + end + + @soft_assert_handler = nil + # Set a handler for soft assertions + # + # These generally shouldn't stop execution of the program, but rather inform + # some party of the assertion to action on later. + # + # @param [Lambda, Proc, Object, nil] value Proc that handles the error + # report (pass nil to reset to default behavior) + # + # Parameters passed to value.call: + # + # @param [String] str Assertion message + # @param [Hash] extra A hash containing additional parameters to be passed along to the handler. + # + # @example + # T::Configuration.soft_assert_handler = lambda do |str, extra| + # puts "#{str}, context: #{extra}" + # end + def self.soft_assert_handler=(value) + validate_lambda_given!(value) + @soft_assert_handler = value + end + + private_class_method def self.soft_assert_handler_default(str, extra) + puts "#{str}, extra: #{extra}" + end + + def self.soft_assert_handler(str, extra) + if @soft_assert_handler + @soft_assert_handler.call(str, extra) + else + soft_assert_handler_default(str, extra) + end + end + + @hard_assert_handler = nil + # Set a handler for hard assertions + # + # These generally should stop execution of the program, and optionally inform + # some party of the assertion. + # + # @param [Lambda, Proc, Object, nil] value Proc that handles the error + # report (pass nil to reset to default behavior) + # + # Parameters passed to value.call: + # + # @param [String] str Assertion message + # @param [Hash] extra A hash containing additional parameters to be passed along to the handler. + # + # @example + # T::Configuration.hard_assert_handler = lambda do |str, extra| + # raise "#{str}, context: #{extra}" + # end + def self.hard_assert_handler=(value) + validate_lambda_given!(value) + @hard_assert_handler = value + end + + private_class_method def self.hard_assert_handler_default(str, _) + raise str + end + + def self.hard_assert_handler(str, extra={}) + if @hard_assert_handler + @hard_assert_handler.call(str, extra) + else + hard_assert_handler_default(str, extra) + end + end + + @scalar_types = nil + # Set a list of class strings that are to be considered scalar. + # (pass nil to reset to default behavior) + # + # @param [String] values Class name. + # + # @example + # T::Configuration.scalar_types = ["NilClass", "TrueClass", "FalseClass", ...] + def self.scalar_types=(values) + if values.nil? + @scalar_types = values + else + bad_values = values.reject {|v| v.class == String} + unless bad_values.empty? + raise ArgumentError.new("Provided values must all be class name strings.") + end + + @scalar_types = values.each_with_object({}) {|x, acc| acc[x] = true}.freeze + end + end + + @default_scalar_types = { + "NilClass" => true, + "TrueClass" => true, + "FalseClass" => true, + "Integer" => true, + "Float" => true, + "String" => true, + "Symbol" => true, + "Time" => true, + "T::Enum" => true, + }.freeze + + def self.scalar_types + @scalar_types || @default_scalar_types + end + + # Guard against overrides of `name` or `to_s` + MODULE_NAME = Module.instance_method(:name) + private_constant :MODULE_NAME + + @default_module_name_mangler = if T::Configuration::AT_LEAST_RUBY_2_7 + ->(type) {MODULE_NAME.bind_call(type)} + else + ->(type) {MODULE_NAME.bind(type).call} + end + + @module_name_mangler = nil + + def self.module_name_mangler + @module_name_mangler || @default_module_name_mangler + end + + # Set to override the default behavior for converting types + # to names in generated code. Used by the runtime implementation + # associated with `--stripe-packages` mode. + # + # @param [Lambda, Proc, nil] handler Proc that converts a type (Class/Module) + # to a String (pass nil to reset to default behavior) + def self.module_name_mangler=(handler) + @module_name_mangler = handler + end + + @sensitivity_and_pii_handler = nil + # Set to a PII handler function. This will be called with the `sensitivity:` + # annotations on things that use `T::Props` and can modify them ahead-of-time. + # + # @param [Lambda, Proc, nil] handler Proc that takes a hash mapping symbols to the + # prop values. Pass nil to avoid changing `sensitivity:` annotations. + def self.normalize_sensitivity_and_pii_handler=(handler) + @sensitivity_and_pii_handler = handler + end + + def self.normalize_sensitivity_and_pii_handler + @sensitivity_and_pii_handler + end + + @redaction_handler = nil + # Set to a redaction handling function. This will be called when the + # `_redacted` version of a prop reader is used. By default this is set to + # `nil` and will raise an exception when the redacted version of a prop is + # accessed. + # + # @param [Lambda, Proc, nil] handler Proc that converts a value into its + # redacted version according to the spec passed as the second argument. + def self.redaction_handler=(handler) + @redaction_handler = handler + end + + def self.redaction_handler + @redaction_handler + end + + @class_owner_finder = nil + # Set to a function which can get the 'owner' of a class. This is + # used in reporting deserialization errors + # + # @param [Lambda, Proc, nil] handler Proc that takes a class and + # produces its owner, or `nil` if it does not have one. + def self.class_owner_finder=(handler) + @class_owner_finder = handler + end + + def self.class_owner_finder + @class_owner_finder + end + + # Temporarily disable ruby warnings while executing the given block. This is + # useful when doing something that would normally cause a warning to be + # emitted in Ruby verbose mode ($VERBOSE = true). + # + # @yield + # + def self.without_ruby_warnings + if $VERBOSE + begin + original_verbose = $VERBOSE + $VERBOSE = false + yield + ensure + $VERBOSE = original_verbose + end + else + yield + end + end + + @legacy_t_enum_migration_mode = false + def self.enable_legacy_t_enum_migration_mode + @legacy_t_enum_migration_mode = true + end + def self.disable_legacy_t_enum_migration_mode + @legacy_t_enum_migration_mode = false + end + def self.legacy_t_enum_migration_mode? + @legacy_t_enum_migration_mode || false + end + + @prop_freeze_handler = ->(instance, prop_name) {} + + def self.prop_freeze_handler=(handler) + @prop_freeze_handler = handler + end + + def self.prop_freeze_handler + @prop_freeze_handler + end + + @sealed_violation_whitelist = nil + # @param [Array] sealed_violation_whitelist An array of Regexp to validate + # whether inheriting /including a sealed module outside the defining module + # should be allowed. Useful to whitelist benign violations, like shim files + # generated for an autoloader. + def self.sealed_violation_whitelist=(sealed_violation_whitelist) + if !@sealed_violation_whitelist.nil? + raise ArgumentError.new("Cannot overwrite sealed_violation_whitelist after setting it") + end + + case sealed_violation_whitelist + when Array + sealed_violation_whitelist.each do |x| + case x + when Regexp then nil + else raise TypeError.new("sealed_violation_whitelist accepts an Array of Regexp") + end + end + else + raise TypeError.new("sealed_violation_whitelist= accepts an Array of Regexp") + end + + @sealed_violation_whitelist = sealed_violation_whitelist + end + def self.sealed_violation_whitelist + @sealed_violation_whitelist + end + + private_class_method def self.validate_lambda_given!(value) + if !value.nil? && !value.respond_to?(:call) + raise ArgumentError.new("Provided value must respond to :call") + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/enum.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/enum.rb new file mode 100644 index 0000000000..c2de09abaf --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/enum.rb @@ -0,0 +1,377 @@ +# frozen_string_literal: true +# typed: strict + +# Enumerations allow for type-safe declarations of a fixed set of values. +# +# Every value is a singleton instance of the class (i.e. `Suit::SPADE.is_a?(Suit) == true`). +# +# Each value has a corresponding serialized value. By default this is the constant's name converted +# to lowercase (e.g. `Suit::Club.serialize == 'club'`); however a custom value may be passed to the +# constructor. Enum will `freeze` the serialized value. +# +# @example Declaring an Enum: +# class Suit < T::Enum +# enums do +# CLUB = new +# SPADE = new +# DIAMOND = new +# HEART = new +# end +# end +# +# @example Custom serialization value: +# class Status < T::Enum +# enums do +# READY = new('rdy') +# ... +# end +# end +# +# @example Accessing values: +# Suit::SPADE +# +# @example Converting from serialized value to enum instance: +# Suit.deserialize('club') == Suit::CLUB +# +# @example Using enums in type signatures: +# sig {params(suit: Suit).returns(Boolean)} +# def is_red?(suit); ...; end +# +# WARNING: Enum instances are singletons that are shared among all their users. Their internals +# should be kept immutable to avoid unpredictable action at a distance. +class T::Enum + extend T::Sig + extend T::Props::CustomType + + # TODO(jez) Might want to restrict this, or make subclasses provide this type + SerializedVal = T.type_alias {T.untyped} + private_constant :SerializedVal + + ### Enum class methods ### + sig {returns(T::Array[T.attached_class])} + def self.values + if @values.nil? + raise "Attempting to access values of #{self.class} before it has been initialized." \ + " Enums are not initialized until the 'enums do' block they are defined in has finished running." + end + @values + end + + # This exists for compatibility with the interface of `Hash` & mostly to support + # the HashEachMethods Rubocop. + sig {params(blk: T.nilable(T.proc.params(arg0: T.attached_class).void)).returns(T.any(T::Enumerator[T.attached_class], T::Array[T.attached_class]))} + def self.each_value(&blk) + if blk + values.each(&blk) + else + values.each + end + end + + # Convert from serialized value to enum instance + # + # Note: It would have been nice to make this method final before people started overriding it. + # Note: Failed CriticalMethodsNoRuntimeTypingTest + sig {params(serialized_val: SerializedVal).returns(T.nilable(T.attached_class)).checked(:never)} + def self.try_deserialize(serialized_val) + if @mapping.nil? + raise "Attempting to access serialization map of #{self.class} before it has been initialized." \ + " Enums are not initialized until the 'enums do' block they are defined in has finished running." + end + @mapping[serialized_val] + end + + # Convert from serialized value to enum instance. + # + # Note: It would have been nice to make this method final before people started overriding it. + # Note: Failed CriticalMethodsNoRuntimeTypingTest + # + # @return [self] + # @raise [KeyError] if serialized value does not match any instance. + sig {overridable.params(serialized_val: SerializedVal).returns(T.attached_class).checked(:never)} + def self.from_serialized(serialized_val) + res = try_deserialize(serialized_val) + if res.nil? + raise KeyError.new("Enum #{self} key not found: #{serialized_val.inspect}") + end + res + end + + # Note: It would have been nice to make this method final before people started overriding it. + # @return [Boolean] Does the given serialized value correspond with any of this enum's values. + sig {overridable.params(serialized_val: SerializedVal).returns(T::Boolean).checked(:never)} + def self.has_serialized?(serialized_val) + if @mapping.nil? + raise "Attempting to access serialization map of #{self.class} before it has been initialized." \ + " Enums are not initialized until the 'enums do' block they are defined in has finished running." + end + @mapping.include?(serialized_val) + end + + # Note: Failed CriticalMethodsNoRuntimeTypingTest + sig {override.params(instance: T.nilable(T::Enum)).returns(SerializedVal).checked(:never)} + def self.serialize(instance) + # This is needed otherwise if a Chalk::ODM::Document with a property of the shape + # T::Hash[T.nilable(MyEnum), Integer] and a value that looks like {nil => 0} is + # serialized, we throw the error on L102. + return nil if instance.nil? + + if self == T::Enum + raise "Cannot call T::Enum.serialize directly. You must call on a specific child class." + end + if instance.class != self + raise "Cannot call #serialize on a value that is not an instance of #{self}." + end + instance.serialize + end + + # Note: Failed CriticalMethodsNoRuntimeTypingTest + sig {override.params(mongo_value: SerializedVal).returns(T.attached_class).checked(:never)} + def self.deserialize(mongo_value) + if self == T::Enum + raise "Cannot call T::Enum.deserialize directly. You must call on a specific child class." + end + self.from_serialized(mongo_value) + end + + ### Enum instance methods ### + + sig {returns(T.self_type)} + def dup + self + end + + sig {returns(T.self_type).checked(:tests)} + def clone + self + end + + # Note: Failed CriticalMethodsNoRuntimeTypingTest + sig {returns(SerializedVal).checked(:never)} + def serialize + assert_bound! + @serialized_val + end + + sig {params(args: T.untyped).returns(T.untyped)} + def to_json(*args) + serialize.to_json(*args) + end + + sig {params(args: T.untyped).returns(T.untyped)} + def as_json(*args) + serialized_val = serialize + return serialized_val unless serialized_val.respond_to?(:as_json) + serialized_val.as_json(*args) + end + + sig {returns(String)} + def to_s + inspect + end + + sig {returns(String)} + def inspect + "#<#{self.class.name}::#{@const_name || '__UNINITIALIZED__'}>" + end + + sig {params(other: BasicObject).returns(T.nilable(Integer))} + def <=>(other) + case other + when self.class + self.serialize <=> other.serialize + else + nil + end + end + + # NB: Do not call this method. This exists to allow for a safe migration path in places where enum + # values are compared directly against string values. + # + # Ruby's string has a weird quirk where `'my_string' == obj` calls obj.==('my_string') if obj + # responds to the `to_str` method. It does not actually call `to_str` however. + # + # See https://ruby-doc.org/core-2.4.0/String.html#method-i-3D-3D + sig {returns(String)} + def to_str + msg = 'Implicit conversion of Enum instances to strings is not allowed. Call #serialize instead.' + if T::Configuration.legacy_t_enum_migration_mode? + T::Configuration.soft_assert_handler( + msg, + storytime: {class: self.class.name}, + ) + serialize.to_s + else + raise NoMethodError.new(msg) + end + end + + sig {params(other: BasicObject).returns(T::Boolean).checked(:never)} + def ==(other) + case other + when String + if T::Configuration.legacy_t_enum_migration_mode? + comparison_assertion_failed(:==, other) + self.serialize == other + else + false + end + else + super(other) + end + end + + sig {params(other: BasicObject).returns(T::Boolean).checked(:never)} + def ===(other) + case other + when String + if T::Configuration.legacy_t_enum_migration_mode? + comparison_assertion_failed(:===, other) + self.serialize == other + else + false + end + else + super(other) + end + end + + sig {params(method: Symbol, other: T.untyped).void} + private def comparison_assertion_failed(method, other) + T::Configuration.soft_assert_handler( + 'Enum to string comparison not allowed. Compare to the Enum instance directly instead. See go/enum-migration', + storytime: { + class: self.class.name, + self: self.inspect, + other: other, + other_class: other.class.name, + method: method, + } + ) + end + + ### Private implementation ### + + sig {params(serialized_val: SerializedVal).void} + def initialize(serialized_val=nil) + raise 'T::Enum is abstract' if self.class == T::Enum + if !self.class.started_initializing? + raise "Must instantiate all enum values of #{self.class} inside 'enums do'." + end + if self.class.fully_initialized? + raise "Cannot instantiate a new enum value of #{self.class} after it has been initialized." + end + + serialized_val = serialized_val.frozen? ? serialized_val : serialized_val.dup.freeze + @serialized_val = T.let(serialized_val, T.nilable(SerializedVal)) + @const_name = T.let(nil, T.nilable(Symbol)) + self.class._register_instance(self) + end + + sig {returns(NilClass).checked(:never)} + private def assert_bound! + if @const_name.nil? + raise "Attempting to access Enum value on #{self.class} before it has been initialized." \ + " Enums are not initialized until the 'enums do' block they are defined in has finished running." + end + end + + sig {params(const_name: Symbol).void} + def _bind_name(const_name) + @const_name = const_name + @serialized_val = const_to_serialized_val(const_name) if @serialized_val.nil? + freeze + end + + sig {params(const_name: Symbol).returns(String)} + private def const_to_serialized_val(const_name) + # Historical note: We convert to lowercase names because the majority of existing calls to + # `make_accessible` were arrays of lowercase strings. Doing this conversion allowed for the + # least amount of repetition in migrated declarations. + -const_name.to_s.downcase.freeze + end + + sig {returns(T::Boolean)} + def self.started_initializing? + unless defined?(@started_initializing) + @started_initializing = T.let(false, T.nilable(T::Boolean)) + end + T.must(@started_initializing) + end + + sig {returns(T::Boolean)} + def self.fully_initialized? + unless defined?(@fully_initialized) + @fully_initialized = T.let(false, T.nilable(T::Boolean)) + end + T.must(@fully_initialized) + end + + # Maintains the order in which values are defined + sig {params(instance: T.untyped).void} + def self._register_instance(instance) + @values ||= [] + @values << T.cast(instance, T.attached_class) + end + + # Entrypoint for allowing people to register new enum values. + # All enum values must be defined within this block. + sig {params(blk: T.proc.void).void} + def self.enums(&blk) + raise "enums cannot be defined for T::Enum" if self == T::Enum + raise "Enum #{self} was already initialized" if fully_initialized? + raise "Enum #{self} is still initializing" if started_initializing? + + @started_initializing = true + + @values = T.let(nil, T.nilable(T::Array[T.attached_class])) + + yield + + @mapping = T.let(nil, T.nilable(T::Hash[SerializedVal, T.attached_class])) + @mapping = {} + + # Freeze the Enum class and bind the constant names into each of the instances. + self.constants(false).each do |const_name| + instance = self.const_get(const_name, false) + if !instance.is_a?(self) + raise "Invalid constant #{self}::#{const_name} on enum. " \ + "All constants defined for an enum must be instances itself (e.g. `Foo = new`)." + end + + instance._bind_name(const_name) + serialized = instance.serialize + if @mapping.include?(serialized) + raise "Enum values must have unique serializations. Value '#{serialized}' is repeated on #{self}." + end + @mapping[serialized] = instance + end + @values.freeze + @mapping.freeze + + orphaned_instances = T.must(@values) - @mapping.values + if !orphaned_instances.empty? + raise "Enum values must be assigned to constants: #{orphaned_instances.map {|v| v.instance_variable_get('@serialized_val')}}" + end + + @fully_initialized = true + end + + sig {params(child_class: Module).void} + def self.inherited(child_class) + super + + raise "Inheriting from children of T::Enum is prohibited" if self != T::Enum + end + + # Marshal support + sig {params(_level: Integer).returns(String)} + def _dump(_level) + Marshal.dump(serialize) + end + + sig {params(args: String).returns(T.attached_class)} + def self._load(args) + deserialize(Marshal.load(args)) # rubocop:disable Security/MarshalLoad + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/generic.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/generic.rb new file mode 100644 index 0000000000..58def7aa1a --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/generic.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true +# typed: true + +# Use as a mixin with extend (`extend T::Generic`). +module T::Generic + include T::Helpers + include Kernel + + ### Class/Module Helpers ### + + def [](*types) + self + end + + def type_member(variance=:invariant, &blk) + T::Types::TypeMember.new(variance) + end + + def type_template(variance=:invariant, &blk) + T::Types::TypeTemplate.new(variance) + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/helpers.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/helpers.rb new file mode 100644 index 0000000000..e9b3675c34 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/helpers.rb @@ -0,0 +1,65 @@ +# frozen_string_literal: true +# typed: true + +# Use as a mixin with extend (`extend T::Helpers`). +# Docs at https://sorbet.org/docs/ +module T::Helpers + extend T::Sig + + Private = T::Private + + ### Class/Module Helpers ### + + def abstract! + if defined?(super) + # This is to play nicely with Rails' AbstractController::Base, + # which also defines an `abstract!` method. + # https://api.rubyonrails.org/classes/AbstractController/Base.html#method-c-abstract-21 + super + end + + Private::Abstract::Declare.declare_abstract(self, type: :abstract) + end + + def interface! + Private::Abstract::Declare.declare_abstract(self, type: :interface) + end + + def final! + Private::Final.declare(self) + end + + def sealed! + Private::Sealed.declare(self, Kernel.caller(1..1)&.first&.split(':')&.first) + end + + # Causes a mixin to also mix in class methods from the named module. + # + # Nearly equivalent to + # + # def self.included(other) + # other.extend(mod) + # end + # + # Except that it is statically analyzed by sorbet. + def mixes_in_class_methods(mod, *mods) + Private::Mixins.declare_mixes_in_class_methods(self, [mod].concat(mods)) + end + + # Specify an inclusion or inheritance requirement for `self`. + # + # Example: + # + # module MyHelper + # extend T::Helpers + # + # requires_ancestor { Kernel } + # end + # + # class MyClass < BasicObject # error: `MyClass` must include `Kernel` (required by `MyHelper`) + # include MyHelper + # end + # + # TODO: implement the checks in sorbet-runtime. + def requires_ancestor(&block); end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/interface_wrapper.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/interface_wrapper.rb new file mode 100644 index 0000000000..580d4b0df5 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/interface_wrapper.rb @@ -0,0 +1,162 @@ +# frozen_string_literal: true +# typed: false + +# Wraps an object, exposing only the methods defined on a given class/module. The idea is that, in +# the absence of a static type checker that would prevent you from calling non-Bar methods on a +# variable of type Bar, we can use these wrappers as a way of enforcing it at runtime. +# +# Once we ship static type checking, we should get rid of this entirely. +class T::InterfaceWrapper + extend T::Sig + + module Helpers + def wrap_instance(obj) + T::InterfaceWrapper.wrap_instance(obj, self) + end + + def wrap_instances(arr) + T::InterfaceWrapper.wrap_instances(arr, self) + end + end + + private_class_method :new # use `wrap_instance` + + def self.wrap_instance(obj, interface_mod) + wrapper = wrapped_dynamic_cast(obj, interface_mod) + if wrapper.nil? + raise "#{obj.class} cannot be cast to #{interface_mod}" + end + wrapper + end + + sig do + params( + arr: Array, + interface_mod: T.untyped + ) + .returns(Array) + end + def self.wrap_instances(arr, interface_mod) + arr.map {|instance| self.wrap_instance(instance, interface_mod)} + end + + def initialize(target_obj, interface_mod) + if target_obj.is_a?(T::InterfaceWrapper) + # wrapped_dynamic_cast should guarantee this never happens. + raise "Unexpected: wrapping a wrapper. Please report this bug at https://github.com/sorbet/sorbet/issues" + end + + if !target_obj.is_a?(interface_mod) + # wrapped_dynamic_cast should guarantee this never happens. + raise "Unexpected: `is_a?` failed. Please report this bug at https://github.com/sorbet/sorbet/issues" + end + + if target_obj.class == interface_mod + # wrapped_dynamic_cast should guarantee this never happens. + raise "Unexpected: exact class match. Please report this bug at https://github.com/sorbet/sorbet/issues" + end + + @target_obj = target_obj + @interface_mod = interface_mod + self_methods = self.class.self_methods + + # If perf becomes an issue, we can define these on an anonymous subclass, and keep a cache + # so we only need to do it once per unique `interface_mod` + T::Utils.methods_excluding_object(interface_mod).each do |method_name| + if self_methods.include?(method_name) + raise "interface_mod has a method that conflicts with #{self.class}: #{method_name}" + end + + define_singleton_method(method_name) do |*args, &blk| + target_obj.send(method_name, *args, &blk) + end + + if singleton_class.respond_to?(:ruby2_keywords, true) + singleton_class.send(:ruby2_keywords, method_name) + end + + if target_obj.singleton_class.public_method_defined?(method_name) + # no-op, it's already public + elsif target_obj.singleton_class.protected_method_defined?(method_name) + singleton_class.send(:protected, method_name) + elsif target_obj.singleton_class.private_method_defined?(method_name) + singleton_class.send(:private, method_name) + else + raise "This should never happen. Report this bug at https://github.com/sorbet/sorbet/issues" + end + end + end + + def kind_of?(other) + is_a?(other) + end + + def is_a?(other) + if !other.is_a?(Module) + raise TypeError.new("class or module required") + end + + # This makes is_a? return true for T::InterfaceWrapper (and its ancestors), + # as well as for @interface_mod and its ancestors. + self.class <= other || @interface_mod <= other + end + + # Prefixed because we're polluting the namespace of the interface we're wrapping, and we don't + # want anyone else (besides dynamic_cast) calling it. + def __target_obj_DO_NOT_USE # rubocop:disable Naming/MethodName + @target_obj + end + + # Prefixed because we're polluting the namespace of the interface we're wrapping, and we don't + # want anyone else (besides wrapped_dynamic_cast) calling it. + def __interface_mod_DO_NOT_USE # rubocop:disable Naming/MethodName + @interface_mod + end + + # "Cast" an object to another type. If `obj` is an InterfaceWrapper, returns the the wrapped + # object if that matches `type`. Otherwise, returns `obj` if it matches `type`. Otherwise, + # returns nil. + # + # @param obj [Object] object to cast + # @param mod [Module] type to cast `obj` to + # + # @example + # if (impl = T::InterfaceWrapper.dynamic_cast(iface, MyImplementation)) + # impl.do_things + # end + def self.dynamic_cast(obj, mod) + if obj.is_a?(T::InterfaceWrapper) + target_obj = obj.__target_obj_DO_NOT_USE + target_obj.is_a?(mod) ? target_obj : nil + elsif obj.is_a?(mod) + obj + else + nil + end + end + + # Like dynamic_cast, but puts the result in its own wrapper if necessary. + # + # @param obj [Object] object to cast + # @param mod [Module] type to cast `obj` to + def self.wrapped_dynamic_cast(obj, mod) + # Avoid unwrapping and creating an equivalent wrapper. + if obj.is_a?(T::InterfaceWrapper) && obj.__interface_mod_DO_NOT_USE == mod + return obj + end + + cast_obj = dynamic_cast(obj, mod) + if cast_obj.nil? + nil + elsif cast_obj.class == mod + # Nothing to wrap, they want the full class + cast_obj + else + new(cast_obj, mod) + end + end + + def self.self_methods + @self_methods ||= self.instance_methods(false).to_set + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/non_forcing_constants.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/non_forcing_constants.rb new file mode 100644 index 0000000000..96445357cb --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/non_forcing_constants.rb @@ -0,0 +1,65 @@ +# frozen_string_literal: true +# typed: strict + +module T::NonForcingConstants + # NOTE: This method is documented on the RBI in Sorbet's payload, so that it + # shows up in the hover/completion documentation via LSP. + T::Sig::WithoutRuntime.sig {params(val: BasicObject, klass: String, package: T.nilable(String)).returns(T::Boolean)} + def self.non_forcing_is_a?(val, klass, package: nil) + method_name = "T::NonForcingConstants.non_forcing_is_a?" + if klass.empty? + raise ArgumentError.new("The string given to `#{method_name}` must not be empty") + end + + # We don't treat packages differently at runtime, but the static + # type-checker still needs to have the package and constant + # separated out. This just re-assembles the string as needed + if !package.nil? + klass = "::#{package}::#{klass}" + end + + current_klass = T.let(nil, T.nilable(Module)) + current_prefix = T.let(nil, T.nilable(String)) + + parts = klass.split('::') + parts.each do |part| + if current_klass.nil? + # First iteration + if part != "" && package.nil? + # if we've supplied a package, we're probably running in + # package mode, which means absolute references are + # meaningless + raise ArgumentError.new("The string given to `#{method_name}` must be an absolute constant reference that starts with `::`") + end + + current_klass = Object + current_prefix = '' + + # if this had a :: prefix, then there's no more loading to + # do---skip to the next one + next if part == "" + end + + if current_klass.autoload?(part) + # There's an autoload registered for that constant, which means it's not + # yet loaded. `value` can't be an instance of something not yet loaded. + return false + end + + # Sorbet guarantees that the string is an absolutely resolved name. + search_inheritance_chain = false + if !current_klass.const_defined?(part, search_inheritance_chain) + return false + end + + current_klass = current_klass.const_get(part) + current_prefix = "#{current_prefix}::#{part}" + + if !Module.===(current_klass) + raise ArgumentError.new("#{current_prefix} is not a class or module") + end + end + + current_klass.===(val) + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/abstract/data.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/abstract/data.rb new file mode 100644 index 0000000000..2692858ddf --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/abstract/data.rb @@ -0,0 +1,36 @@ +# frozen_string_literal: true +# typed: true + +# We need to associate data with abstract modules. We could add instance methods to them that +# access ivars, but those methods will unnecessarily pollute the module namespace, and they'd +# have access to other private state and methods that they don't actually need. We also need to +# associate data with arbitrary classes/modules that implement abstract mixins, where we don't +# control the interface at all. So, we access data via these `get` and `set` methods. +# +# Using instance_variable_get/set here is gross, but the alternative is to use a hash keyed on +# `mod`, and we can't trust that arbitrary modules can be added to those, because there are lurky +# modules that override the `hash` method with something completely broken. +module T::Private::Abstract::Data + def self.get(mod, key) + mod.instance_variable_get("@opus_abstract__#{key}") if key?(mod, key) + end + + def self.set(mod, key, value) + mod.instance_variable_set("@opus_abstract__#{key}", value) + end + + def self.key?(mod, key) + mod.instance_variable_defined?("@opus_abstract__#{key}") + end + + # Works like `setdefault` in Python. If key has already been set, return its value. If not, + # insert `key` with a value of `default` and return `default`. + def self.set_default(mod, key, default) + if self.key?(mod, key) + self.get(mod, key) + else + self.set(mod, key, default) + default + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/abstract/declare.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/abstract/declare.rb new file mode 100644 index 0000000000..ce8ddf9531 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/abstract/declare.rb @@ -0,0 +1,53 @@ +# frozen_string_literal: true +# typed: true + +module T::Private::Abstract::Declare + Abstract = T::Private::Abstract + AbstractUtils = T::AbstractUtils + + def self.declare_abstract(mod, type:) + if AbstractUtils.abstract_module?(mod) + raise "#{mod} is already declared as abstract" + end + if T::Private::Final.final_module?(mod) + raise "#{mod} was already declared as final and cannot be declared as abstract" + end + + Abstract::Data.set(mod, :can_have_abstract_methods, true) + Abstract::Data.set(mod.singleton_class, :can_have_abstract_methods, true) + Abstract::Data.set(mod, :abstract_type, type) + + mod.extend(Abstract::Hooks) + mod.extend(T::InterfaceWrapper::Helpers) + + if mod.is_a?(Class) + if type == :interface + # Since `interface!` is just `abstract!` with some extra validation, we could technically + # allow this, but it's unclear there are good use cases, and it might be confusing. + raise "Classes can't be interfaces. Use `abstract!` instead of `interface!`." + end + + if mod.instance_method(:initialize).owner == mod + raise "You must call `abstract!` *before* defining an initialize method" + end + + # Don't need to silence warnings via without_ruby_warnings when calling + # define_method because of the guard above + + mod.send(:define_method, :initialize) do |*args, &blk| + if self.class == mod + raise "#{mod} is declared as abstract; it cannot be instantiated" + end + super(*args, &blk) + end + + # Ruby doesn not emit "method redefined" warnings for aliased methods + # (more robust than undef_method that would create a small window in which the method doesn't exist) + mod.send(:alias_method, :initialize, :initialize) + + if mod.respond_to?(:ruby2_keywords, true) + mod.send(:ruby2_keywords, :initialize) + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/abstract/hooks.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/abstract/hooks.rb new file mode 100644 index 0000000000..fae9593ae8 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/abstract/hooks.rb @@ -0,0 +1,42 @@ +# frozen_string_literal: true +# typed: true + +module T::Private::Abstract::Hooks + # This will become the self.extend_object method on a module that extends Abstract::Hooks. + # It gets called when *that* module gets extended in another class/module (similar to the + # `extended` hook, but this gets calls before the ancestors of `other` get modified, which + # is important for our validation). + private def extend_object(other) + T::Private::Abstract::Data.set(self, :last_used_by, other) + super + end + + # This will become the self.append_features method on a module that extends Abstract::Hooks. + # It gets called when *that* module gets included in another class/module (similar to the + # `included` hook, but this gets calls before the ancestors of `other` get modified, which + # is important for our validation). + private def append_features(other) + T::Private::Abstract::Data.set(self, :last_used_by, other) + super + end + + # This will become the self.inherited method on a class that extends Abstract::Hooks. + # It gets called when *that* class gets inherited by another class. + private def inherited(other) + super + # `self` may not actually be abstract -- it could be a concrete class that inherited from an + # abstract class. We only need to check this in `inherited` because, for modules being included + # or extended, the concrete ones won't have these hooks at all. This is just an optimization. + return if !T::AbstractUtils.abstract_module?(self) + + T::Private::Abstract::Data.set(self, :last_used_by, other) + end + + # This will become the self.prepended method on a module that extends Abstract::Hooks. + # It will get called when *that* module gets prepended in another class/module. + private def prepended(other) + # Prepending abstract methods is weird. You'd only be able to override them via other prepended + # modules, or in subclasses. Punt until we have a use case. + Kernel.raise "Prepending abstract mixins is not currently supported." + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/abstract/validate.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/abstract/validate.rb new file mode 100644 index 0000000000..ba0b57775c --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/abstract/validate.rb @@ -0,0 +1,128 @@ +# frozen_string_literal: true +# typed: true + +module T::Private::Abstract::Validate + Abstract = T::Private::Abstract + AbstractUtils = T::AbstractUtils + Methods = T::Private::Methods + SignatureValidation = T::Private::Methods::SignatureValidation + + def self.validate_abstract_module(mod) + type = Abstract::Data.get(mod, :abstract_type) + validate_interface(mod) if type == :interface + end + + # Validates a class/module with an abstract class/module as an ancestor. This must be called + # after all methods on `mod` have been defined. + def self.validate_subclass(mod) + can_have_abstract_methods = !T::Private::Abstract::Data.get(mod, :can_have_abstract_methods) + unimplemented_methods = [] + + T::AbstractUtils.declared_abstract_methods_for(mod).each do |abstract_method| + implementation_method = mod.instance_method(abstract_method.name) + if AbstractUtils.abstract_method?(implementation_method) + # Note that when we end up here, implementation_method might not be the same as + # abstract_method; the latter could've been overridden by another abstract method. In either + # case, if we have a concrete definition in an ancestor, that will end up as the effective + # implementation (see CallValidation.wrap_method_if_needed), so that's what we'll validate + # against. + implementation_method = T.unsafe(nil) + mod.ancestors.each do |ancestor| + if ancestor.instance_methods.include?(abstract_method.name) + method = ancestor.instance_method(abstract_method.name) + T::Private::Methods.maybe_run_sig_block_for_method(method) + if !T::AbstractUtils.abstract_method?(method) + implementation_method = method + break + end + end + end + if !implementation_method + # There's no implementation + if can_have_abstract_methods + unimplemented_methods << describe_method(abstract_method) + end + next # Nothing to validate + end + end + + implementation_signature = Methods.signature_for_method(implementation_method) + # When a signature exists and the method is defined directly on `mod`, we skip the validation + # here, because it will have already been done when the method was defined (by + # T::Private::Methods._on_method_added). + next if implementation_signature&.owner == mod + + # We validate the remaining cases here: (a) methods defined directly on `mod` without a + # signature and (b) methods from ancestors (note that these ancestors can come before or + # after the abstract module in the inheritance chain -- the former coming from + # walking `mod.ancestors` above). + abstract_signature = Methods.signature_for_method(abstract_method) + # We allow implementation methods to be defined without a signature. + # In that case, get its untyped signature. + implementation_signature ||= Methods::Signature.new_untyped( + method: implementation_method, + mode: Methods::Modes.override + ) + SignatureValidation.validate_override_shape(implementation_signature, abstract_signature) + SignatureValidation.validate_override_types(implementation_signature, abstract_signature) + end + + method_type = mod.singleton_class? ? "class" : "instance" + if !unimplemented_methods.empty? + raise "Missing implementation for abstract #{method_type} method(s) in #{mod}:\n" \ + "#{unimplemented_methods.join("\n")}\n" \ + "If #{mod} is meant to be an abstract class/module, you can call " \ + "`abstract!` or `interface!`. Otherwise, you must implement the method(s)." + end + end + + private_class_method def self.validate_interface_all_abstract(mod, method_names) + violations = method_names.map do |method_name| + method = mod.instance_method(method_name) + if !AbstractUtils.abstract_method?(method) + describe_method(method, show_owner: false) + end + end.compact + + if !violations.empty? + raise "`#{mod}` is declared as an interface, but the following methods are not declared " \ + "with `abstract`:\n#{violations.join("\n")}" + end + end + + private_class_method def self.validate_interface(mod) + interface_methods = T::Utils.methods_excluding_object(mod) + validate_interface_all_abstract(mod, interface_methods) + validate_interface_all_public(mod, interface_methods) + end + + private_class_method def self.validate_interface_all_public(mod, method_names) + violations = method_names.map do |method_name| + if !mod.public_method_defined?(method_name) + describe_method(mod.instance_method(method_name), show_owner: false) + end + end.compact + + if !violations.empty? + raise "All methods on an interface must be public. If you intend to have non-public " \ + "methods, declare your class/module using `abstract!` instead of `interface!`. " \ + "The following methods on `#{mod}` are not public: \n#{violations.join("\n")}" + end + end + + private_class_method def self.describe_method(method, show_owner: true) + loc = if method.source_location + method.source_location.join(':') + else + "" + end + + owner = if show_owner + " declared in #{method.owner}" + else + "" + end + + " * `#{method.name}`#{owner} at #{loc}" + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/casts.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/casts.rb new file mode 100644 index 0000000000..9b5145fdd9 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/casts.rb @@ -0,0 +1,41 @@ +# frozen_string_literal: true +# typed: false + +module T::Private + module Casts + def self.cast(value, type, cast_method) + begin + error = T::Utils.coerce(type).error_message_for_obj(value) + return value unless error + + caller_loc = T.must(caller_locations(2..2)).first + + suffix = "Caller: #{T.must(caller_loc).path}:#{T.must(caller_loc).lineno}" + + raise TypeError.new("#{cast_method}: #{error}\n#{suffix}") + rescue TypeError => e # raise into rescue to ensure e.backtrace is populated + T::Configuration.inline_type_error_handler(e, {kind: cast_method, value: value, type: type}) + value + end + end + + # there's a lot of shared logic with the above one, but factoring + # it out like this makes it easier to hopefully one day delete + # this one + def self.cast_recursive(value, type, cast_method) + begin + error = T::Utils.coerce(type).error_message_for_obj_recursive(value) + return value unless error + + caller_loc = T.must(caller_locations(2..2)).first + + suffix = "Caller: #{T.must(caller_loc).path}:#{T.must(caller_loc).lineno}" + + raise TypeError.new("#{cast_method}: #{error}\n#{suffix}") + rescue TypeError => e # raise into rescue to ensure e.backtrace is populated + T::Configuration.inline_type_error_handler(e, {kind: cast_method, value: value, type: type}) + value + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/class_utils.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/class_utils.rb new file mode 100644 index 0000000000..9842ae62b0 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/class_utils.rb @@ -0,0 +1,127 @@ +# frozen_string_literal: true +# typed: false + +# Cut down version of Chalk::Tools::ClassUtils with only :replace_method functionality. +# Extracted to a separate namespace so the type system can be used standalone. +module T::Private::ClassUtils + class ReplacedMethod + def initialize(mod, old_method, new_method, overwritten, visibility) + if old_method.name != new_method.name + raise "Method names must match. old=#{old_method.name} new=#{new_method.name}" + end + @mod = mod + @old_method = old_method + @new_method = new_method + @overwritten = overwritten + @name = old_method.name + @visibility = visibility + @restored = false + end + + def restore + # The check below would also catch this, but this makes the failure mode much clearer + if @restored + raise "Method '#{@name}' on '#{@mod}' was already restored" + end + + if @mod.instance_method(@name) != @new_method + raise "Trying to restore #{@mod}##{@name} but the method has changed since the call to replace_method" + end + + @restored = true + + if @overwritten + # The original method was overwritten. Overwrite again to restore it. + T::Configuration.without_ruby_warnings do + @mod.send(:define_method, @old_method.name, @old_method) + end + else + # The original method was in an ancestor. Restore it by removing the overriding method. + @mod.send(:remove_method, @old_method.name) + end + + # Restore the visibility. Note that we need to do this even when we call remove_method + # above, because the module may have set custom visibility for a method it inherited. + @mod.send(@visibility, @old_method.name) + + nil + end + + def bind(obj) + @old_method.bind(obj) + end + + def to_s + @old_method.to_s + end + end + + # `name` must be an instance method (for class methods, pass in mod.singleton_class) + private_class_method def self.visibility_method_name(mod, name) + if mod.public_method_defined?(name) + :public + elsif mod.protected_method_defined?(name) + :protected + elsif mod.private_method_defined?(name) + :private + else + raise NameError.new("undefined method `#{name}` for `#{mod}`") + end + end + + def self.def_with_visibility(mod, name, visibility, method=nil, &block) + mod.module_exec do + # Start a visibility (public/protected/private) region, so that + # all of the method redefinitions happen with the right visibility + # from the beginning. This ensures that any other code that is + # triggered by `method_added`, sees the redefined method with the + # right visibility. + send(visibility) + + if method + define_method(name, method) + else + define_method(name, &block) + end + + if block && block.arity < 0 && respond_to?(:ruby2_keywords, true) + ruby2_keywords(name) + end + end + end + + # Replaces a method, either by overwriting it (if it is defined directly on `mod`) or by + # overriding it (if it is defined by one of mod's ancestors). Returns a ReplacedMethod instance + # on which you can call `bind(...).call(...)` to call the original method, or `restore` to + # restore the original method (by overwriting or removing the override). + def self.replace_method(mod, name, &blk) + original_method = mod.instance_method(name) + original_visibility = visibility_method_name(mod, name) + original_owner = original_method.owner + + mod.ancestors.each do |ancestor| + break if ancestor == mod + if ancestor == original_owner + # If we get here, that means the method we're trying to replace exists on a *prepended* + # mixin, which means in order to supersede it, we'd need to create a method on a new + # module that we'd prepend before `ancestor`. The problem with that approach is there'd + # be no way to remove that new module after prepending it, so we'd be left with these + # empty anonymous modules in the ancestor chain after calling `restore`. + # + # That's not necessarily a deal breaker, but for now, we're keeping it as unsupported. + raise "You're trying to replace `#{name}` on `#{mod}`, but that method exists in a " \ + "prepended module (#{ancestor}), which we don't currently support." + end + end + + overwritten = original_owner == mod + T::Configuration.without_ruby_warnings do + T::Private::DeclState.current.without_on_method_added do + def_with_visibility(mod, name, original_visibility, &blk) + end + end + new_method = mod.instance_method(name) + + ReplacedMethod.new(mod, original_method, new_method, overwritten, original_visibility) + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/compiler.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/compiler.rb new file mode 100644 index 0000000000..fed86b40f3 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/compiler.rb @@ -0,0 +1,24 @@ +# frozen_string_literal: true +# typed: true + +module T::Private + module Compiler + # If this code ever runs, the caller is running interpreted (or the + # compiler didn't see the call to `running_compiled?` statically.) + # + # The Sorbet Compiler replaces calls to this method unconditionally (no + # runtime guards) to return `true` when compiling a file. + def self.running_compiled? + false + end + + # Returns `nil` because the compiler isn't running. + # + # The Sorbet Compiler replaces calls to this method unconditionally (no + # runtime guards) to return a String showing the Sorbet Compiler's version + # string. + def self.compiler_version + nil + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/decl_state.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/decl_state.rb new file mode 100644 index 0000000000..8eeae57e4c --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/decl_state.rb @@ -0,0 +1,30 @@ +# frozen_string_literal: true +# typed: true + +class T::Private::DeclState + def self.current + Thread.current[:opus_types__decl_state] ||= self.new + end + + def self.current=(other) + Thread.current[:opus_types__decl_state] = other + end + + attr_accessor :active_declaration + attr_accessor :skip_on_method_added + + def reset! + self.active_declaration = nil + end + + def without_on_method_added + begin + # explicit 'self' is needed here + old_value = self.skip_on_method_added + self.skip_on_method_added = true + yield + ensure + self.skip_on_method_added = old_value + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/final.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/final.rb new file mode 100644 index 0000000000..9ca747248e --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/final.rb @@ -0,0 +1,50 @@ +# frozen_string_literal: true +# typed: false + +module T::Private::Final + module NoInherit + def inherited(arg) + super(arg) + raise "#{self} was declared as final and cannot be inherited" + end + end + + module NoIncludeExtend + def included(arg) + super(arg) + raise "#{self} was declared as final and cannot be included" + end + + def extended(arg) + super(arg) + raise "#{self} was declared as final and cannot be extended" + end + end + + def self.declare(mod) + if !mod.is_a?(Module) + raise "#{mod} is not a class or module and cannot be declared as final with `final!`" + end + if final_module?(mod) + raise "#{mod} was already declared as final and cannot be re-declared as final" + end + if T::AbstractUtils.abstract_module?(mod) + raise "#{mod} was already declared as abstract and cannot be declared as final" + end + if T::Private::Sealed.sealed_module?(mod) + raise "#{mod} was already declared as sealed and cannot be declared as final" + end + mod.extend(mod.is_a?(Class) ? NoInherit : NoIncludeExtend) + mark_as_final_module(mod) + mark_as_final_module(mod.singleton_class) + T::Private::Methods.install_hooks(mod) + end + + def self.final_module?(mod) + mod.instance_variable_defined?(:@sorbet_final_module) + end + + private_class_method def self.mark_as_final_module(mod) + mod.instance_variable_set(:@sorbet_final_module, true) + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/methods/_methods.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/methods/_methods.rb new file mode 100644 index 0000000000..1720892a95 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/methods/_methods.rb @@ -0,0 +1,581 @@ +# frozen_string_literal: true +# typed: false + +module T::Private::Methods + @installed_hooks = {} + @signatures_by_method = {} + @sig_wrappers = {} + @sigs_that_raised = {} + # stores method names that were declared final without regard for where. + # enables early rejection of names that we know can't induce final method violations. + @was_ever_final_names = {} + # maps from a module's object_id to the set of final methods declared in that module. + # we also overload entries slightly: if the value is nil, that means that the + # module has final methods somewhere along its ancestor chain, but does not itself + # have any final methods. + # + # we need the latter information to know whether we need to check along the ancestor + # chain for final method violations. we need the former information because we + # care about exactly where a final method is defined (e.g. including the same module + # twice is permitted). we could do this with two tables, but it seems slightly + # cleaner with a single table. + # Effectively T::Hash[Module, T.nilable(Set))] + @modules_with_final = Hash.new {|hash, key| hash[key] = nil} + # this stores the old [included, extended] hooks for Module and inherited hook for Class that we override when + # enabling final checks for when those hooks are called. the 'hooks' here don't have anything to do with the 'hooks' + # in installed_hooks. + @old_hooks = nil + + ARG_NOT_PROVIDED = Object.new + PROC_TYPE = Object.new + + DeclarationBlock = Struct.new(:mod, :loc, :blk, :final, :raw) + + def self.declare_sig(mod, loc, arg, &blk) + T::Private::DeclState.current.active_declaration = _declare_sig_internal(mod, loc, arg, &blk) + + nil + end + + # See tests for how to use this. But you shouldn't be using this. + def self._declare_sig(mod, arg=nil, &blk) + _declare_sig_internal(mod, caller_locations(1, 1).first, arg, raw: true, &blk) + end + + private_class_method def self._declare_sig_internal(mod, loc, arg, raw: false, &blk) + install_hooks(mod) + + if T::Private::DeclState.current.active_declaration + T::Private::DeclState.current.reset! + raise "You called sig twice without declaring a method in between" + end + + if !arg.nil? && arg != :final + raise "Invalid argument to `sig`: #{arg}" + end + + DeclarationBlock.new(mod, loc, blk, arg == :final, raw) + end + + def self._with_declared_signature(mod, declblock, &blk) + # If declblock is provided, this code is equivalent to the check in + # _declare_sig_internal, above. + # If declblock is not provided and we have an active declaration, we are + # obviously doing something wrong. + if T::Private::DeclState.current.active_declaration + T::Private::DeclState.current.reset! + raise "You called sig twice without declaring a method in between" + end + if declblock + T::Private::DeclState.current.active_declaration = declblock + end + mod.module_exec(&blk) + end + + def self.start_proc + DeclBuilder.new(PROC_TYPE, false) + end + + def self.finalize_proc(decl) + decl.finalized = true + + if decl.mode != Modes.standard + raise "Procs cannot have override/abstract modifiers" + end + if decl.mod != PROC_TYPE + raise "You are passing a DeclBuilder as a type. Did you accidentally use `self` inside a `sig` block?" + end + if decl.returns == ARG_NOT_PROVIDED + raise "Procs must specify a return type" + end + if decl.on_failure != ARG_NOT_PROVIDED + raise "Procs cannot use .on_failure" + end + + if decl.params == ARG_NOT_PROVIDED + decl.params = {} + end + + T::Types::Proc.new(decl.params, decl.returns) + end + + # Returns the signature for a method whose definition was preceded by `sig`. + # + # @param method [UnboundMethod] + # @return [T::Private::Methods::Signature] + def self.signature_for_method(method) + signature_for_key(method_to_key(method)) + end + + private_class_method def self.signature_for_key(key) + maybe_run_sig_block_for_key(key) + + # If a subclass Sub inherits a method `foo` from Base, then + # Sub.instance_method(:foo) != Base.instance_method(:foo) even though they resolve to the + # same method. Similarly, Foo.method(:bar) != Foo.singleton_class.instance_method(:bar). + # So, we always do the look up by the method on the owner (Base in this example). + @signatures_by_method[key] + end + + # when target includes a module with instance methods source_method_names, ensure there is zero intersection between + # the final instance methods of target and source_method_names. so, for every m in source_method_names, check if there + # is already a method defined on one of target_ancestors with the same name that is final. + # + # we assume that source_method_names has already been filtered to only include method + # names that were declared final at one point. + def self._check_final_ancestors(target, target_ancestors, source_method_names, source) + source_ancestors = nil + # use reverse_each to check farther-up ancestors first, for better error messages. + target_ancestors.reverse_each do |ancestor| + final_methods = @modules_with_final.fetch(ancestor.object_id, nil) + # In this case, either ancestor didn't have any final methods anywhere in its + # ancestor chain, or ancestor did have final methods somewhere in its ancestor + # chain, but no final methods defined in ancestor itself. Either way, there + # are no final methods to check here, so we can move on to the next ancestor. + next unless final_methods + source_method_names.each do |method_name| + next unless final_methods.include?(method_name) + + # If we get here, we are defining a method that some ancestor declared as + # final. however, we permit a final method to be defined multiple + # times if it is the same final method being defined each time. + if source + if !source_ancestors + source_ancestors = source.ancestors + # filter out things without actual final methods just to make sure that + # the below checks (which should be uncommon) go as quickly as possible. + source_ancestors.select! do |a| + @modules_with_final.fetch(a.object_id, nil) + end + end + # final-ness means that there should be no more than one index for which + # the below block returns true. + defining_ancestor_idx = source_ancestors.index do |a| + @modules_with_final.fetch(a.object_id).include?(method_name) + end + next if defining_ancestor_idx && source_ancestors[defining_ancestor_idx] == ancestor + end + + definition_file, definition_line = T::Private::Methods.signature_for_method(ancestor.instance_method(method_name)).method.source_location + is_redefined = target == ancestor + caller_loc = caller_locations&.find {|l| !l.to_s.match?(%r{sorbet-runtime[^/]*/lib/})} + extra_info = "\n" + if caller_loc + extra_info = (is_redefined ? "Redefined" : "Overridden") + " here: #{caller_loc.path}:#{caller_loc.lineno}\n" + end + + error_message = "The method `#{method_name}` on #{ancestor} was declared as final and cannot be " + + (is_redefined ? "redefined" : "overridden in #{target}") + pretty_message = "#{error_message}\n" \ + "Made final here: #{definition_file}:#{definition_line}\n" \ + "#{extra_info}" + + begin + raise pretty_message + rescue => e + # sig_validation_error_handler raises by default; on the off chance that + # it doesn't raise, we need to ensure that the rest of signature building + # sees a consistent state. This sig failed to validate, so we should get + # rid of it. If we don't do this, errors of the form "You called sig + # twice without declaring a method in between" will non-deterministically + # crop up in tests. + T::Private::DeclState.current.reset! + T::Configuration.sig_validation_error_handler(e, {}) + end + end + end + end + + def self.add_module_with_final_method(mod, method_name, is_singleton_method) + m = is_singleton_method ? mod.singleton_class : mod + mid = m.object_id + methods = @modules_with_final[mid] + if methods.nil? + methods = {} + @modules_with_final[mid] = methods + end + methods[method_name] = true + nil + end + + def self.note_module_deals_with_final(mod) + # Side-effectfully initialize the value if it's not already there + @modules_with_final[mod.object_id] + @modules_with_final[mod.singleton_class.object_id] + end + + # Only public because it needs to get called below inside the replace_method blocks below. + def self._on_method_added(hook_mod, method_name, is_singleton_method: false) + if T::Private::DeclState.current.skip_on_method_added + return + end + + current_declaration = T::Private::DeclState.current.active_declaration + mod = is_singleton_method ? hook_mod.singleton_class : hook_mod + + if T::Private::Final.final_module?(mod) && (current_declaration.nil? || !current_declaration.final) + raise "#{mod} was declared as final but its method `#{method_name}` was not declared as final" + end + # Don't compute mod.ancestors if we don't need to bother checking final-ness. + if @was_ever_final_names.include?(method_name) && @modules_with_final.include?(mod.object_id) + _check_final_ancestors(mod, mod.ancestors, [method_name], nil) + # We need to fetch the active declaration again, as _check_final_ancestors + # may have reset it (see the comment in that method for details). + current_declaration = T::Private::DeclState.current.active_declaration + end + + if current_declaration.nil? + return + end + T::Private::DeclState.current.reset! + + if method_name == :method_added || method_name == :singleton_method_added + raise( + "Putting a `sig` on `#{method_name}` is not supported" \ + " (sorbet-runtime uses this method internally to perform `sig` validation logic)" + ) + end + + original_method = mod.instance_method(method_name) + sig_block = lambda do + T::Private::Methods.run_sig(hook_mod, method_name, original_method, current_declaration) + end + + # Always replace the original method with this wrapper, + # which is called only on the *first* invocation. + # This wrapper is very slow, so it will subsequently re-wrap with a much faster wrapper + # (or unwrap back to the original method). + key = method_owner_and_name_to_key(mod, method_name) + unless current_declaration.raw + T::Private::ClassUtils.replace_method(mod, method_name) do |*args, &blk| + method_sig = T::Private::Methods.maybe_run_sig_block_for_key(key) + method_sig ||= T::Private::Methods._handle_missing_method_signature( + self, + original_method, + __callee__, + ) + + # Should be the same logic as CallValidation.wrap_method_if_needed but we + # don't want that extra layer of indirection in the callstack + if method_sig.mode == T::Private::Methods::Modes.abstract + # We're in an interface method, keep going up the chain + if defined?(super) + super(*args, &blk) + else + raise NotImplementedError.new("The method `#{method_sig.method_name}` on #{mod} is declared as `abstract`. It does not have an implementation.") + end + # Note, this logic is duplicated (intentionally, for micro-perf) at `CallValidation.wrap_method_if_needed`, + # make sure to keep changes in sync. + elsif method_sig.check_level == :always || (method_sig.check_level == :tests && T::Private::RuntimeLevels.check_tests?) + CallValidation.validate_call(self, original_method, method_sig, args, blk) + elsif T::Configuration::AT_LEAST_RUBY_2_7 + original_method.bind_call(self, *args, &blk) + else + original_method.bind(self).call(*args, &blk) + end + end + end + + @sig_wrappers[key] = sig_block + if current_declaration.final + @was_ever_final_names[method_name] = true + # use hook_mod, not mod, because for example, we want class C to be marked as having final if we def C.foo as + # final. change this to mod to see some final_method tests fail. + note_module_deals_with_final(hook_mod) + add_module_with_final_method(hook_mod, method_name, is_singleton_method) + end + end + + def self._handle_missing_method_signature(receiver, original_method, callee) + method_sig = T::Private::Methods.signature_for_method(original_method) + if !method_sig + raise "`sig` not present for method `#{callee}` on #{receiver.inspect} but you're trying to run it anyways. " \ + "This should only be executed if you used `alias_method` to grab a handle to a method after `sig`ing it, but that clearly isn't what you are doing. " \ + "Maybe look to see if an exception was thrown in your `sig` lambda or somehow else your `sig` wasn't actually applied to the method." + end + + if receiver.class <= original_method.owner + receiving_class = receiver.class + elsif receiver.singleton_class <= original_method.owner + receiving_class = receiver.singleton_class + elsif receiver.is_a?(Module) && receiver <= original_method.owner + receiving_class = receiver + else + raise "#{receiver} is not related to #{original_method} - how did we get here?" + end + + # Check for a case where `alias` or `alias_method` was called for a + # method which had already had a `sig` applied. In that case, we want + # to avoid hitting this slow path again, by moving to a faster validator + # just like we did or will for the original method. + # + # If this isn't an `alias` or `alias_method` case, we're probably in the + # middle of some metaprogramming using a Method object, e.g. a pattern like + # `arr.map(&method(:foo))`. There's nothing really we can do to optimize + # that here. + receiving_method = receiving_class.instance_method(callee) + if receiving_method != original_method && receiving_method.original_name == original_method.name + aliasing_mod = receiving_method.owner + method_sig = method_sig.as_alias(callee) + unwrap_method(aliasing_mod, method_sig, original_method) + end + + method_sig + end + + # Executes the `sig` block, and converts the resulting Declaration + # to a Signature. + def self.run_sig(hook_mod, method_name, original_method, declaration_block) + current_declaration = + begin + run_builder(declaration_block) + rescue DeclBuilder::BuilderError => e + T::Configuration.sig_builder_error_handler(e, declaration_block.loc) + nil + end + + signature = + if current_declaration + build_sig(hook_mod, method_name, original_method, current_declaration, declaration_block.loc) + else + Signature.new_untyped(method: original_method) + end + + unwrap_method(signature.method.owner, signature, original_method) + signature + end + + def self.run_builder(declaration_block) + builder = DeclBuilder.new(declaration_block.mod, declaration_block.raw) + builder + .instance_exec(&declaration_block.blk) + .finalize! + .decl + end + + def self.build_sig(hook_mod, method_name, original_method, current_declaration, loc) + begin + # We allow `sig` in the current module's context (normal case) and + if hook_mod != current_declaration.mod && + # inside `class << self`, and + hook_mod.singleton_class != current_declaration.mod && + # on `self` at the top level of a file + current_declaration.mod != TOP_SELF + raise "A method (#{method_name}) is being added on a different class/module (#{hook_mod}) than the " \ + "last call to `sig` (#{current_declaration.mod}). Make sure each call " \ + "to `sig` is immediately followed by a method definition on the same " \ + "class/module." + end + + signature = Signature.new( + method: original_method, + method_name: method_name, + raw_arg_types: current_declaration.params, + raw_return_type: current_declaration.returns, + bind: current_declaration.bind, + mode: current_declaration.mode, + check_level: current_declaration.checked, + on_failure: current_declaration.on_failure, + override_allow_incompatible: current_declaration.override_allow_incompatible, + defined_raw: current_declaration.raw, + ) + + SignatureValidation.validate(signature) + signature + rescue => e + super_method = original_method&.super_method + super_signature = signature_for_method(super_method) if super_method + + T::Configuration.sig_validation_error_handler( + e, + method: original_method, + declaration: current_declaration, + signature: signature, + super_signature: super_signature + ) + + Signature.new_untyped(method: original_method) + end + end + + def self.unwrap_method(mod, signature, original_method) + maybe_wrapped_method = CallValidation.wrap_method_if_needed(mod, signature, original_method) + @signatures_by_method[method_to_key(maybe_wrapped_method)] = signature + end + + def self.has_sig_block_for_method(method) + has_sig_block_for_key(method_to_key(method)) + end + + private_class_method def self.has_sig_block_for_key(key) + @sig_wrappers.key?(key) + end + + def self.maybe_run_sig_block_for_method(method) + maybe_run_sig_block_for_key(method_to_key(method)) + end + + # Only public so that it can be accessed in the closure for _on_method_added + def self.maybe_run_sig_block_for_key(key) + run_sig_block_for_key(key) if has_sig_block_for_key(key) + end + + def self.run_sig_block_for_method(method) + run_sig_block_for_key(method_to_key(method)) + end + + private_class_method def self.run_sig_block_for_key(key) + blk = @sig_wrappers[key] + if !blk + sig = @signatures_by_method[key] + if sig + # We already ran the sig block, perhaps in another thread. + return sig + else + raise "No `sig` wrapper for #{key_to_method(key)}" + end + end + + begin + sig = blk.call + rescue + @sigs_that_raised[key] = true + raise + end + if @sigs_that_raised[key] + raise "A previous invocation of #{key_to_method(key)} raised, and the current one succeeded. Please don't do that." + end + + @sig_wrappers.delete(key) + sig + end + + def self.run_all_sig_blocks + loop do + break if @sig_wrappers.empty? + key, = @sig_wrappers.first + run_sig_block_for_key(key) + end + end + + def self.all_checked_tests_sigs + @signatures_by_method.values.select {|sig| sig.check_level == :tests} + end + + # the module target is adding the methods from the module source to itself. we need to check that for all instance + # methods M on source, M is not defined on any of target's ancestors. + def self._hook_impl(target, singleton_class, source) + # we do not need to call add_was_ever_final here, because we have already marked + # any such methods when source was originally defined. + if !@modules_with_final.include?(target.object_id) + if !@modules_with_final.include?(source.object_id) + return + end + note_module_deals_with_final(target) + install_hooks(target) + return + end + + methods = source.instance_methods + methods.select! do |method_name| + @was_ever_final_names.include?(method_name) + end + if methods.empty? + return + end + + target_ancestors = singleton_class ? target.singleton_class.ancestors : target.ancestors + _check_final_ancestors(target, target_ancestors, methods, source) + end + + def self.set_final_checks_on_hooks(enable) + is_enabled = !@old_hooks.nil? + if enable == is_enabled + return + end + if is_enabled + @old_hooks.each(&:restore) + @old_hooks = nil + else + old_included = T::Private::ClassUtils.replace_method(Module, :included) do |arg| + old_included.bind(self).call(arg) + ::T::Private::Methods._hook_impl(arg, false, self) + end + old_extended = T::Private::ClassUtils.replace_method(Module, :extended) do |arg| + old_extended.bind(self).call(arg) + ::T::Private::Methods._hook_impl(arg, true, self) + end + old_inherited = T::Private::ClassUtils.replace_method(Class, :inherited) do |arg| + old_inherited.bind(self).call(arg) + ::T::Private::Methods._hook_impl(arg, false, self) + end + @old_hooks = [old_included, old_extended, old_inherited] + end + end + + module MethodHooks + def method_added(name) + super(name) + ::T::Private::Methods._on_method_added(self, name, is_singleton_method: false) + end + end + + module SingletonMethodHooks + def singleton_method_added(name) + super(name) + ::T::Private::Methods._on_method_added(self, name, is_singleton_method: true) + end + end + + def self.install_hooks(mod) + return if @installed_hooks.include?(mod) + @installed_hooks[mod] = true + + if mod == TOP_SELF + # self at the top-level of a file is weirdly special in Ruby + # The Ruby VM on startup creates an `Object.new` and stashes it. + # Unlike when we're using sig inside a module, `self` is actually a + # normal object, not an instance of Module. + # + # Thus we can't ask things like mod.singleton_class? (since that's + # defined only on Module, not on Object) and even if we could, the places + # where we need to install the hooks are special. + mod.extend(SingletonMethodHooks) # def self.foo; end (at top level) + Object.extend(MethodHooks) # def foo; end (at top level) + return + end + + # See https://github.com/sorbet/sorbet/pull/3964 for an explanation of why this + # check (which theoretically should not be needed) is actually needed. + if !mod.is_a?(Module) + return + end + + if mod.singleton_class? + mod.include(SingletonMethodHooks) + else + mod.extend(MethodHooks) + end + mod.extend(SingletonMethodHooks) + end + + # use this directly if you don't want/need to box up the method into an object to pass to method_to_key. + private_class_method def self.method_owner_and_name_to_key(owner, name) + "#{owner.object_id}##{name}" + end + + private_class_method def self.method_to_key(method) + method_owner_and_name_to_key(method.owner, method.name) + end + + private_class_method def self.key_to_method(key) + id, name = key.split("#") + obj = ObjectSpace._id2ref(id.to_i) + obj.instance_method(name) + end +end + +# This has to be here, and can't be nested inside `T::Private::Methods`, +# because the value of `self` depends on lexical (nesting) scope, and we +# specifically need a reference to the file-level self, i.e. `main:Object` +T::Private::Methods::TOP_SELF = self diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/methods/call_validation.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/methods/call_validation.rb new file mode 100644 index 0000000000..1bfe488aed --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/methods/call_validation.rb @@ -0,0 +1,217 @@ +# frozen_string_literal: true +# typed: false + +module T::Private::Methods::CallValidation + CallValidation = T::Private::Methods::CallValidation + Modes = T::Private::Methods::Modes + + # Wraps a method with a layer of validation for the given type signature. + # This wrapper is meant to be fast, and is applied by a previous wrapper, + # which was placed by `_on_method_added`. + # + # @param method_sig [T::Private::Methods::Signature] + # @return [UnboundMethod] the new wrapper method (or the original one if we didn't wrap it) + def self.wrap_method_if_needed(mod, method_sig, original_method) + original_visibility = visibility_method_name(mod, method_sig.method_name) + if method_sig.mode == T::Private::Methods::Modes.abstract + T::Private::ClassUtils.replace_method(mod, method_sig.method_name) do |*args, &blk| + # TODO: write a cop to ensure that abstract methods have an empty body + # + # We allow abstract methods to be implemented by things further down the ancestor chain. + # So, if a super method exists, call it. + if defined?(super) + super(*args, &blk) + else + raise NotImplementedError.new( + "The method `#{method_sig.method_name}` on #{mod} is declared as `abstract`. It does not have an implementation." + ) + end + end + # Do nothing in this case; this method was not wrapped in _on_method_added. + elsif method_sig.defined_raw + # Note, this logic is duplicated (intentionally, for micro-perf) at `Methods._on_method_added`, + # make sure to keep changes in sync. + # This is a trapdoor point for each method: + # if a given method is wrapped, it stays wrapped; and if not, it's never wrapped. + # (Therefore, we need the `@wrapped_tests_with_validation` check in `T::RuntimeLevels`.) + elsif method_sig.check_level == :always || (method_sig.check_level == :tests && T::Private::RuntimeLevels.check_tests?) + create_validator_method(mod, original_method, method_sig, original_visibility) + else + T::Configuration.without_ruby_warnings do + # get all the shims out of the way and put back the original method + T::Private::DeclState.current.without_on_method_added do + T::Private::ClassUtils.def_with_visibility(mod, method_sig.method_name, original_visibility, original_method) + end + end + end + # Return the newly created method (or the original one if we didn't replace it) + mod.instance_method(method_sig.method_name) + end + + @is_allowed_to_have_fast_path = true + def self.is_allowed_to_have_fast_path + @is_allowed_to_have_fast_path + end + + def self.disable_fast_path + @is_allowed_to_have_fast_path = false + end + + def self.create_validator_method(mod, original_method, method_sig, original_visibility) + has_fixed_arity = method_sig.kwarg_types.empty? && !method_sig.has_rest && !method_sig.has_keyrest && + original_method.parameters.all? {|(kind, _name)| kind == :req} + ok_for_fast_path = has_fixed_arity && !method_sig.bind && method_sig.arg_types.length < 5 && is_allowed_to_have_fast_path + + all_args_are_simple = ok_for_fast_path && method_sig.arg_types.all? {|_name, type| type.is_a?(T::Types::Simple)} + simple_method = all_args_are_simple && method_sig.return_type.is_a?(T::Types::Simple) + simple_procedure = all_args_are_simple && method_sig.return_type.is_a?(T::Private::Types::Void) + + T::Configuration.without_ruby_warnings do + T::Private::DeclState.current.without_on_method_added do + if simple_method + create_validator_method_fast(mod, original_method, method_sig, original_visibility) + elsif simple_procedure + create_validator_procedure_fast(mod, original_method, method_sig, original_visibility) + elsif ok_for_fast_path && method_sig.return_type.is_a?(T::Private::Types::Void) + create_validator_procedure_medium(mod, original_method, method_sig, original_visibility) + elsif ok_for_fast_path + create_validator_method_medium(mod, original_method, method_sig, original_visibility) + else + create_validator_slow(mod, original_method, method_sig, original_visibility) + end + end + mod.send(original_visibility, method_sig.method_name) + end + end + + def self.create_validator_slow(mod, original_method, method_sig, original_visibility) + T::Private::ClassUtils.def_with_visibility(mod, method_sig.method_name, original_visibility) do |*args, &blk| + CallValidation.validate_call(self, original_method, method_sig, args, blk) + end + end + + def self.validate_call(instance, original_method, method_sig, args, blk) + # This method is called for every `sig`. It's critical to keep it fast and + # reduce number of allocations that happen here. + + if method_sig.bind + message = method_sig.bind.error_message_for_obj(instance) + if message + CallValidation.report_error( + method_sig, + message, + 'Bind', + nil, + method_sig.bind, + instance + ) + end + end + + # NOTE: We don't bother validating for missing or extra kwargs; + # the method call itself will take care of that. + method_sig.each_args_value_type(args) do |name, arg, type| + message = type.error_message_for_obj(arg) + if message + CallValidation.report_error( + method_sig, + message, + 'Parameter', + name, + type, + arg, + caller_offset: 2 + ) + end + end + + if method_sig.block_type + message = method_sig.block_type.error_message_for_obj(blk) + if message + CallValidation.report_error( + method_sig, + message, + 'Block parameter', + method_sig.block_name, + method_sig.block_type, + blk + ) + end + end + + # The following line breaks are intentional to show nice pry message + + + + + + + + + + + # PRY note: + # this code is sig validation code. + # Please issue `finish` to step out of it + + return_value = T::Configuration::AT_LEAST_RUBY_2_7 ? original_method.bind_call(instance, *args, &blk) : original_method.bind(instance).call(*args, &blk) + + # The only type that is allowed to change the return value is `.void`. + # It ignores what you returned and changes it to be a private singleton. + if method_sig.return_type.is_a?(T::Private::Types::Void) + T::Private::Types::Void::VOID + else + message = method_sig.return_type.error_message_for_obj(return_value) + if message + CallValidation.report_error( + method_sig, + message, + 'Return value', + nil, + method_sig.return_type, + return_value, + ) + end + return_value + end + end + + def self.report_error(method_sig, error_message, kind, name, type, value, caller_offset: 0) + caller_loc = T.must(caller_locations(3 + caller_offset, 1))[0] + definition_file, definition_line = method_sig.method.source_location + + pretty_message = "#{kind}#{name ? " '#{name}'" : ''}: #{error_message}\n" \ + "Caller: #{caller_loc.path}:#{caller_loc.lineno}\n" \ + "Definition: #{definition_file}:#{definition_line}" + + T::Configuration.call_validation_error_handler( + method_sig, + message: error_message, + pretty_message: pretty_message, + kind: kind, + name: name, + type: type, + value: value, + location: caller_loc + ) + end + + # `name` must be an instance method (for class methods, pass in mod.singleton_class) + private_class_method def self.visibility_method_name(mod, name) + if mod.public_method_defined?(name) + :public + elsif mod.protected_method_defined?(name) + :protected + elsif mod.private_method_defined?(name) + :private + else + raise NameError.new("undefined method `#{name}` for `#{mod}`") + end + end +end + +if T::Configuration::AT_LEAST_RUBY_2_7 + require_relative './call_validation_2_7' +else + require_relative './call_validation_2_6' +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/methods/call_validation_2_6.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/methods/call_validation_2_6.rb new file mode 100644 index 0000000000..ff7fcb46b3 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/methods/call_validation_2_6.rb @@ -0,0 +1,1203 @@ +# frozen_string_literal: true +# typed: false + +# DO NOT EDIT. This file is autogenerated. To regenerate, run: +# +# bazel test //gems/sorbet-runtime:update_call_validation + +module T::Private::Methods::CallValidation + def self.create_validator_method_fast(mod, original_method, method_sig, original_visibility) + if method_sig.return_type.is_a?(T::Private::Types::Void) + raise 'Should have used create_validator_procedure_fast' + end + # trampoline to reduce stack frame size + if method_sig.arg_types.empty? + create_validator_method_fast0(mod, original_method, method_sig, original_visibility, method_sig.return_type.raw_type) + elsif method_sig.arg_types.length == 1 + create_validator_method_fast1(mod, original_method, method_sig, original_visibility, method_sig.return_type.raw_type, + method_sig.arg_types[0][1].raw_type) + elsif method_sig.arg_types.length == 2 + create_validator_method_fast2(mod, original_method, method_sig, original_visibility, method_sig.return_type.raw_type, + method_sig.arg_types[0][1].raw_type, + method_sig.arg_types[1][1].raw_type) + elsif method_sig.arg_types.length == 3 + create_validator_method_fast3(mod, original_method, method_sig, original_visibility, method_sig.return_type.raw_type, + method_sig.arg_types[0][1].raw_type, + method_sig.arg_types[1][1].raw_type, + method_sig.arg_types[2][1].raw_type) + elsif method_sig.arg_types.length == 4 + create_validator_method_fast4(mod, original_method, method_sig, original_visibility, method_sig.return_type.raw_type, + method_sig.arg_types[0][1].raw_type, + method_sig.arg_types[1][1].raw_type, + method_sig.arg_types[2][1].raw_type, + method_sig.arg_types[3][1].raw_type) + else + raise 'should not happen' + end + end + + def self.create_validator_method_fast0(mod, original_method, method_sig, original_visibility, return_type) + T::Private::ClassUtils.def_with_visibility(mod, method_sig.method_name, original_visibility) do |&blk| + # This method is a manually sped-up version of more general code in `validate_call` + # The following line breaks are intentional to show nice pry message + + + + + + + + + + + # PRY note: + # this code is sig validation code. + # Please issue `finish` to step out of it + + return_value = original_method.bind(self).call(&blk) + unless return_value.is_a?(return_type) + message = method_sig.return_type.error_message_for_obj(return_value) + if message + CallValidation.report_error( + method_sig, + message, + 'Return value', + nil, + method_sig.return_type, + return_value, + caller_offset: -1 + ) + end + end + return_value + end + end + + def self.create_validator_method_fast1(mod, original_method, method_sig, original_visibility, return_type, arg0_type) + T::Private::ClassUtils.def_with_visibility(mod, method_sig.method_name, original_visibility) do |arg0, &blk| + # This method is a manually sped-up version of more general code in `validate_call` + unless arg0.is_a?(arg0_type) + CallValidation.report_error( + method_sig, + method_sig.arg_types[0][1].error_message_for_obj(arg0), + 'Parameter', + method_sig.arg_types[0][0], + arg0_type, + arg0, + caller_offset: -1 + ) + end + + # The following line breaks are intentional to show nice pry message + + + + + + + + + + + # PRY note: + # this code is sig validation code. + # Please issue `finish` to step out of it + + return_value = original_method.bind(self).call(arg0, &blk) + unless return_value.is_a?(return_type) + message = method_sig.return_type.error_message_for_obj(return_value) + if message + CallValidation.report_error( + method_sig, + message, + 'Return value', + nil, + method_sig.return_type, + return_value, + caller_offset: -1 + ) + end + end + return_value + end + end + + def self.create_validator_method_fast2(mod, original_method, method_sig, original_visibility, return_type, arg0_type, arg1_type) + T::Private::ClassUtils.def_with_visibility(mod, method_sig.method_name, original_visibility) do |arg0, arg1, &blk| + # This method is a manually sped-up version of more general code in `validate_call` + unless arg0.is_a?(arg0_type) + CallValidation.report_error( + method_sig, + method_sig.arg_types[0][1].error_message_for_obj(arg0), + 'Parameter', + method_sig.arg_types[0][0], + arg0_type, + arg0, + caller_offset: -1 + ) + end + + unless arg1.is_a?(arg1_type) + CallValidation.report_error( + method_sig, + method_sig.arg_types[1][1].error_message_for_obj(arg1), + 'Parameter', + method_sig.arg_types[1][0], + arg1_type, + arg1, + caller_offset: -1 + ) + end + + # The following line breaks are intentional to show nice pry message + + + + + + + + + + + # PRY note: + # this code is sig validation code. + # Please issue `finish` to step out of it + + return_value = original_method.bind(self).call(arg0, arg1, &blk) + unless return_value.is_a?(return_type) + message = method_sig.return_type.error_message_for_obj(return_value) + if message + CallValidation.report_error( + method_sig, + message, + 'Return value', + nil, + method_sig.return_type, + return_value, + caller_offset: -1 + ) + end + end + return_value + end + end + + def self.create_validator_method_fast3(mod, original_method, method_sig, original_visibility, return_type, arg0_type, arg1_type, arg2_type) + T::Private::ClassUtils.def_with_visibility(mod, method_sig.method_name, original_visibility) do |arg0, arg1, arg2, &blk| + # This method is a manually sped-up version of more general code in `validate_call` + unless arg0.is_a?(arg0_type) + CallValidation.report_error( + method_sig, + method_sig.arg_types[0][1].error_message_for_obj(arg0), + 'Parameter', + method_sig.arg_types[0][0], + arg0_type, + arg0, + caller_offset: -1 + ) + end + + unless arg1.is_a?(arg1_type) + CallValidation.report_error( + method_sig, + method_sig.arg_types[1][1].error_message_for_obj(arg1), + 'Parameter', + method_sig.arg_types[1][0], + arg1_type, + arg1, + caller_offset: -1 + ) + end + + unless arg2.is_a?(arg2_type) + CallValidation.report_error( + method_sig, + method_sig.arg_types[2][1].error_message_for_obj(arg2), + 'Parameter', + method_sig.arg_types[2][0], + arg2_type, + arg2, + caller_offset: -1 + ) + end + + # The following line breaks are intentional to show nice pry message + + + + + + + + + + + # PRY note: + # this code is sig validation code. + # Please issue `finish` to step out of it + + return_value = original_method.bind(self).call(arg0, arg1, arg2, &blk) + unless return_value.is_a?(return_type) + message = method_sig.return_type.error_message_for_obj(return_value) + if message + CallValidation.report_error( + method_sig, + message, + 'Return value', + nil, + method_sig.return_type, + return_value, + caller_offset: -1 + ) + end + end + return_value + end + end + + def self.create_validator_method_fast4(mod, original_method, method_sig, original_visibility, return_type, arg0_type, arg1_type, arg2_type, arg3_type) + T::Private::ClassUtils.def_with_visibility(mod, method_sig.method_name, original_visibility) do |arg0, arg1, arg2, arg3, &blk| + # This method is a manually sped-up version of more general code in `validate_call` + unless arg0.is_a?(arg0_type) + CallValidation.report_error( + method_sig, + method_sig.arg_types[0][1].error_message_for_obj(arg0), + 'Parameter', + method_sig.arg_types[0][0], + arg0_type, + arg0, + caller_offset: -1 + ) + end + + unless arg1.is_a?(arg1_type) + CallValidation.report_error( + method_sig, + method_sig.arg_types[1][1].error_message_for_obj(arg1), + 'Parameter', + method_sig.arg_types[1][0], + arg1_type, + arg1, + caller_offset: -1 + ) + end + + unless arg2.is_a?(arg2_type) + CallValidation.report_error( + method_sig, + method_sig.arg_types[2][1].error_message_for_obj(arg2), + 'Parameter', + method_sig.arg_types[2][0], + arg2_type, + arg2, + caller_offset: -1 + ) + end + + unless arg3.is_a?(arg3_type) + CallValidation.report_error( + method_sig, + method_sig.arg_types[3][1].error_message_for_obj(arg3), + 'Parameter', + method_sig.arg_types[3][0], + arg3_type, + arg3, + caller_offset: -1 + ) + end + + # The following line breaks are intentional to show nice pry message + + + + + + + + + + + # PRY note: + # this code is sig validation code. + # Please issue `finish` to step out of it + + return_value = original_method.bind(self).call(arg0, arg1, arg2, arg3, &blk) + unless return_value.is_a?(return_type) + message = method_sig.return_type.error_message_for_obj(return_value) + if message + CallValidation.report_error( + method_sig, + message, + 'Return value', + nil, + method_sig.return_type, + return_value, + caller_offset: -1 + ) + end + end + return_value + end + end + + def self.create_validator_procedure_fast(mod, original_method, method_sig, original_visibility) + # trampoline to reduce stack frame size + if method_sig.arg_types.empty? + create_validator_procedure_fast0(mod, original_method, method_sig, original_visibility) + elsif method_sig.arg_types.length == 1 + create_validator_procedure_fast1(mod, original_method, method_sig, original_visibility, + method_sig.arg_types[0][1].raw_type) + elsif method_sig.arg_types.length == 2 + create_validator_procedure_fast2(mod, original_method, method_sig, original_visibility, + method_sig.arg_types[0][1].raw_type, + method_sig.arg_types[1][1].raw_type) + elsif method_sig.arg_types.length == 3 + create_validator_procedure_fast3(mod, original_method, method_sig, original_visibility, + method_sig.arg_types[0][1].raw_type, + method_sig.arg_types[1][1].raw_type, + method_sig.arg_types[2][1].raw_type) + elsif method_sig.arg_types.length == 4 + create_validator_procedure_fast4(mod, original_method, method_sig, original_visibility, + method_sig.arg_types[0][1].raw_type, + method_sig.arg_types[1][1].raw_type, + method_sig.arg_types[2][1].raw_type, + method_sig.arg_types[3][1].raw_type) + else + raise 'should not happen' + end + end + + def self.create_validator_procedure_fast0(mod, original_method, method_sig, original_visibility) + T::Private::ClassUtils.def_with_visibility(mod, method_sig.method_name, original_visibility) do |&blk| + # This method is a manually sped-up version of more general code in `validate_call` + # The following line breaks are intentional to show nice pry message + + + + + + + + + + + # PRY note: + # this code is sig validation code. + # Please issue `finish` to step out of it + + original_method.bind(self).call(&blk) + T::Private::Types::Void::VOID + end + end + + def self.create_validator_procedure_fast1(mod, original_method, method_sig, original_visibility, arg0_type) + T::Private::ClassUtils.def_with_visibility(mod, method_sig.method_name, original_visibility) do |arg0, &blk| + # This method is a manually sped-up version of more general code in `validate_call` + unless arg0.is_a?(arg0_type) + CallValidation.report_error( + method_sig, + method_sig.arg_types[0][1].error_message_for_obj(arg0), + 'Parameter', + method_sig.arg_types[0][0], + arg0_type, + arg0, + caller_offset: -1 + ) + end + + # The following line breaks are intentional to show nice pry message + + + + + + + + + + + # PRY note: + # this code is sig validation code. + # Please issue `finish` to step out of it + + original_method.bind(self).call(arg0, &blk) + T::Private::Types::Void::VOID + end + end + + def self.create_validator_procedure_fast2(mod, original_method, method_sig, original_visibility, arg0_type, arg1_type) + T::Private::ClassUtils.def_with_visibility(mod, method_sig.method_name, original_visibility) do |arg0, arg1, &blk| + # This method is a manually sped-up version of more general code in `validate_call` + unless arg0.is_a?(arg0_type) + CallValidation.report_error( + method_sig, + method_sig.arg_types[0][1].error_message_for_obj(arg0), + 'Parameter', + method_sig.arg_types[0][0], + arg0_type, + arg0, + caller_offset: -1 + ) + end + + unless arg1.is_a?(arg1_type) + CallValidation.report_error( + method_sig, + method_sig.arg_types[1][1].error_message_for_obj(arg1), + 'Parameter', + method_sig.arg_types[1][0], + arg1_type, + arg1, + caller_offset: -1 + ) + end + + # The following line breaks are intentional to show nice pry message + + + + + + + + + + + # PRY note: + # this code is sig validation code. + # Please issue `finish` to step out of it + + original_method.bind(self).call(arg0, arg1, &blk) + T::Private::Types::Void::VOID + end + end + + def self.create_validator_procedure_fast3(mod, original_method, method_sig, original_visibility, arg0_type, arg1_type, arg2_type) + T::Private::ClassUtils.def_with_visibility(mod, method_sig.method_name, original_visibility) do |arg0, arg1, arg2, &blk| + # This method is a manually sped-up version of more general code in `validate_call` + unless arg0.is_a?(arg0_type) + CallValidation.report_error( + method_sig, + method_sig.arg_types[0][1].error_message_for_obj(arg0), + 'Parameter', + method_sig.arg_types[0][0], + arg0_type, + arg0, + caller_offset: -1 + ) + end + + unless arg1.is_a?(arg1_type) + CallValidation.report_error( + method_sig, + method_sig.arg_types[1][1].error_message_for_obj(arg1), + 'Parameter', + method_sig.arg_types[1][0], + arg1_type, + arg1, + caller_offset: -1 + ) + end + + unless arg2.is_a?(arg2_type) + CallValidation.report_error( + method_sig, + method_sig.arg_types[2][1].error_message_for_obj(arg2), + 'Parameter', + method_sig.arg_types[2][0], + arg2_type, + arg2, + caller_offset: -1 + ) + end + + # The following line breaks are intentional to show nice pry message + + + + + + + + + + + # PRY note: + # this code is sig validation code. + # Please issue `finish` to step out of it + + original_method.bind(self).call(arg0, arg1, arg2, &blk) + T::Private::Types::Void::VOID + end + end + + def self.create_validator_procedure_fast4(mod, original_method, method_sig, original_visibility, arg0_type, arg1_type, arg2_type, arg3_type) + T::Private::ClassUtils.def_with_visibility(mod, method_sig.method_name, original_visibility) do |arg0, arg1, arg2, arg3, &blk| + # This method is a manually sped-up version of more general code in `validate_call` + unless arg0.is_a?(arg0_type) + CallValidation.report_error( + method_sig, + method_sig.arg_types[0][1].error_message_for_obj(arg0), + 'Parameter', + method_sig.arg_types[0][0], + arg0_type, + arg0, + caller_offset: -1 + ) + end + + unless arg1.is_a?(arg1_type) + CallValidation.report_error( + method_sig, + method_sig.arg_types[1][1].error_message_for_obj(arg1), + 'Parameter', + method_sig.arg_types[1][0], + arg1_type, + arg1, + caller_offset: -1 + ) + end + + unless arg2.is_a?(arg2_type) + CallValidation.report_error( + method_sig, + method_sig.arg_types[2][1].error_message_for_obj(arg2), + 'Parameter', + method_sig.arg_types[2][0], + arg2_type, + arg2, + caller_offset: -1 + ) + end + + unless arg3.is_a?(arg3_type) + CallValidation.report_error( + method_sig, + method_sig.arg_types[3][1].error_message_for_obj(arg3), + 'Parameter', + method_sig.arg_types[3][0], + arg3_type, + arg3, + caller_offset: -1 + ) + end + + # The following line breaks are intentional to show nice pry message + + + + + + + + + + + # PRY note: + # this code is sig validation code. + # Please issue `finish` to step out of it + + original_method.bind(self).call(arg0, arg1, arg2, arg3, &blk) + T::Private::Types::Void::VOID + end + end + + def self.create_validator_method_medium(mod, original_method, method_sig, original_visibility) + if method_sig.return_type.is_a?(T::Private::Types::Void) + raise 'Should have used create_validator_procedure_medium' + end + # trampoline to reduce stack frame size + if method_sig.arg_types.empty? + create_validator_method_medium0(mod, original_method, method_sig, original_visibility, method_sig.return_type) + elsif method_sig.arg_types.length == 1 + create_validator_method_medium1(mod, original_method, method_sig, original_visibility, method_sig.return_type, + method_sig.arg_types[0][1]) + elsif method_sig.arg_types.length == 2 + create_validator_method_medium2(mod, original_method, method_sig, original_visibility, method_sig.return_type, + method_sig.arg_types[0][1], + method_sig.arg_types[1][1]) + elsif method_sig.arg_types.length == 3 + create_validator_method_medium3(mod, original_method, method_sig, original_visibility, method_sig.return_type, + method_sig.arg_types[0][1], + method_sig.arg_types[1][1], + method_sig.arg_types[2][1]) + elsif method_sig.arg_types.length == 4 + create_validator_method_medium4(mod, original_method, method_sig, original_visibility, method_sig.return_type, + method_sig.arg_types[0][1], + method_sig.arg_types[1][1], + method_sig.arg_types[2][1], + method_sig.arg_types[3][1]) + else + raise 'should not happen' + end + end + + def self.create_validator_method_medium0(mod, original_method, method_sig, original_visibility, return_type) + T::Private::ClassUtils.def_with_visibility(mod, method_sig.method_name, original_visibility) do |&blk| + # This method is a manually sped-up version of more general code in `validate_call` + # The following line breaks are intentional to show nice pry message + + + + + + + + + + + # PRY note: + # this code is sig validation code. + # Please issue `finish` to step out of it + + return_value = original_method.bind(self).call(&blk) + unless return_type.valid?(return_value) + message = method_sig.return_type.error_message_for_obj(return_value) + if message + CallValidation.report_error( + method_sig, + message, + 'Return value', + nil, + method_sig.return_type, + return_value, + caller_offset: -1 + ) + end + end + return_value + end + end + + def self.create_validator_method_medium1(mod, original_method, method_sig, original_visibility, return_type, arg0_type) + T::Private::ClassUtils.def_with_visibility(mod, method_sig.method_name, original_visibility) do |arg0, &blk| + # This method is a manually sped-up version of more general code in `validate_call` + unless arg0_type.valid?(arg0) + CallValidation.report_error( + method_sig, + method_sig.arg_types[0][1].error_message_for_obj(arg0), + 'Parameter', + method_sig.arg_types[0][0], + arg0_type, + arg0, + caller_offset: -1 + ) + end + + # The following line breaks are intentional to show nice pry message + + + + + + + + + + + # PRY note: + # this code is sig validation code. + # Please issue `finish` to step out of it + + return_value = original_method.bind(self).call(arg0, &blk) + unless return_type.valid?(return_value) + message = method_sig.return_type.error_message_for_obj(return_value) + if message + CallValidation.report_error( + method_sig, + message, + 'Return value', + nil, + method_sig.return_type, + return_value, + caller_offset: -1 + ) + end + end + return_value + end + end + + def self.create_validator_method_medium2(mod, original_method, method_sig, original_visibility, return_type, arg0_type, arg1_type) + T::Private::ClassUtils.def_with_visibility(mod, method_sig.method_name, original_visibility) do |arg0, arg1, &blk| + # This method is a manually sped-up version of more general code in `validate_call` + unless arg0_type.valid?(arg0) + CallValidation.report_error( + method_sig, + method_sig.arg_types[0][1].error_message_for_obj(arg0), + 'Parameter', + method_sig.arg_types[0][0], + arg0_type, + arg0, + caller_offset: -1 + ) + end + + unless arg1_type.valid?(arg1) + CallValidation.report_error( + method_sig, + method_sig.arg_types[1][1].error_message_for_obj(arg1), + 'Parameter', + method_sig.arg_types[1][0], + arg1_type, + arg1, + caller_offset: -1 + ) + end + + # The following line breaks are intentional to show nice pry message + + + + + + + + + + + # PRY note: + # this code is sig validation code. + # Please issue `finish` to step out of it + + return_value = original_method.bind(self).call(arg0, arg1, &blk) + unless return_type.valid?(return_value) + message = method_sig.return_type.error_message_for_obj(return_value) + if message + CallValidation.report_error( + method_sig, + message, + 'Return value', + nil, + method_sig.return_type, + return_value, + caller_offset: -1 + ) + end + end + return_value + end + end + + def self.create_validator_method_medium3(mod, original_method, method_sig, original_visibility, return_type, arg0_type, arg1_type, arg2_type) + T::Private::ClassUtils.def_with_visibility(mod, method_sig.method_name, original_visibility) do |arg0, arg1, arg2, &blk| + # This method is a manually sped-up version of more general code in `validate_call` + unless arg0_type.valid?(arg0) + CallValidation.report_error( + method_sig, + method_sig.arg_types[0][1].error_message_for_obj(arg0), + 'Parameter', + method_sig.arg_types[0][0], + arg0_type, + arg0, + caller_offset: -1 + ) + end + + unless arg1_type.valid?(arg1) + CallValidation.report_error( + method_sig, + method_sig.arg_types[1][1].error_message_for_obj(arg1), + 'Parameter', + method_sig.arg_types[1][0], + arg1_type, + arg1, + caller_offset: -1 + ) + end + + unless arg2_type.valid?(arg2) + CallValidation.report_error( + method_sig, + method_sig.arg_types[2][1].error_message_for_obj(arg2), + 'Parameter', + method_sig.arg_types[2][0], + arg2_type, + arg2, + caller_offset: -1 + ) + end + + # The following line breaks are intentional to show nice pry message + + + + + + + + + + + # PRY note: + # this code is sig validation code. + # Please issue `finish` to step out of it + + return_value = original_method.bind(self).call(arg0, arg1, arg2, &blk) + unless return_type.valid?(return_value) + message = method_sig.return_type.error_message_for_obj(return_value) + if message + CallValidation.report_error( + method_sig, + message, + 'Return value', + nil, + method_sig.return_type, + return_value, + caller_offset: -1 + ) + end + end + return_value + end + end + + def self.create_validator_method_medium4(mod, original_method, method_sig, original_visibility, return_type, arg0_type, arg1_type, arg2_type, arg3_type) + T::Private::ClassUtils.def_with_visibility(mod, method_sig.method_name, original_visibility) do |arg0, arg1, arg2, arg3, &blk| + # This method is a manually sped-up version of more general code in `validate_call` + unless arg0_type.valid?(arg0) + CallValidation.report_error( + method_sig, + method_sig.arg_types[0][1].error_message_for_obj(arg0), + 'Parameter', + method_sig.arg_types[0][0], + arg0_type, + arg0, + caller_offset: -1 + ) + end + + unless arg1_type.valid?(arg1) + CallValidation.report_error( + method_sig, + method_sig.arg_types[1][1].error_message_for_obj(arg1), + 'Parameter', + method_sig.arg_types[1][0], + arg1_type, + arg1, + caller_offset: -1 + ) + end + + unless arg2_type.valid?(arg2) + CallValidation.report_error( + method_sig, + method_sig.arg_types[2][1].error_message_for_obj(arg2), + 'Parameter', + method_sig.arg_types[2][0], + arg2_type, + arg2, + caller_offset: -1 + ) + end + + unless arg3_type.valid?(arg3) + CallValidation.report_error( + method_sig, + method_sig.arg_types[3][1].error_message_for_obj(arg3), + 'Parameter', + method_sig.arg_types[3][0], + arg3_type, + arg3, + caller_offset: -1 + ) + end + + # The following line breaks are intentional to show nice pry message + + + + + + + + + + + # PRY note: + # this code is sig validation code. + # Please issue `finish` to step out of it + + return_value = original_method.bind(self).call(arg0, arg1, arg2, arg3, &blk) + unless return_type.valid?(return_value) + message = method_sig.return_type.error_message_for_obj(return_value) + if message + CallValidation.report_error( + method_sig, + message, + 'Return value', + nil, + method_sig.return_type, + return_value, + caller_offset: -1 + ) + end + end + return_value + end + end + + def self.create_validator_procedure_medium(mod, original_method, method_sig, original_visibility) + # trampoline to reduce stack frame size + if method_sig.arg_types.empty? + create_validator_procedure_medium0(mod, original_method, method_sig, original_visibility) + elsif method_sig.arg_types.length == 1 + create_validator_procedure_medium1(mod, original_method, method_sig, original_visibility, + method_sig.arg_types[0][1]) + elsif method_sig.arg_types.length == 2 + create_validator_procedure_medium2(mod, original_method, method_sig, original_visibility, + method_sig.arg_types[0][1], + method_sig.arg_types[1][1]) + elsif method_sig.arg_types.length == 3 + create_validator_procedure_medium3(mod, original_method, method_sig, original_visibility, + method_sig.arg_types[0][1], + method_sig.arg_types[1][1], + method_sig.arg_types[2][1]) + elsif method_sig.arg_types.length == 4 + create_validator_procedure_medium4(mod, original_method, method_sig, original_visibility, + method_sig.arg_types[0][1], + method_sig.arg_types[1][1], + method_sig.arg_types[2][1], + method_sig.arg_types[3][1]) + else + raise 'should not happen' + end + end + + def self.create_validator_procedure_medium0(mod, original_method, method_sig, original_visibility) + T::Private::ClassUtils.def_with_visibility(mod, method_sig.method_name, original_visibility) do |&blk| + # This method is a manually sped-up version of more general code in `validate_call` + # The following line breaks are intentional to show nice pry message + + + + + + + + + + + # PRY note: + # this code is sig validation code. + # Please issue `finish` to step out of it + + original_method.bind(self).call(&blk) + T::Private::Types::Void::VOID + end + end + + def self.create_validator_procedure_medium1(mod, original_method, method_sig, original_visibility, arg0_type) + T::Private::ClassUtils.def_with_visibility(mod, method_sig.method_name, original_visibility) do |arg0, &blk| + # This method is a manually sped-up version of more general code in `validate_call` + unless arg0_type.valid?(arg0) + CallValidation.report_error( + method_sig, + method_sig.arg_types[0][1].error_message_for_obj(arg0), + 'Parameter', + method_sig.arg_types[0][0], + arg0_type, + arg0, + caller_offset: -1 + ) + end + + # The following line breaks are intentional to show nice pry message + + + + + + + + + + + # PRY note: + # this code is sig validation code. + # Please issue `finish` to step out of it + + original_method.bind(self).call(arg0, &blk) + T::Private::Types::Void::VOID + end + end + + def self.create_validator_procedure_medium2(mod, original_method, method_sig, original_visibility, arg0_type, arg1_type) + T::Private::ClassUtils.def_with_visibility(mod, method_sig.method_name, original_visibility) do |arg0, arg1, &blk| + # This method is a manually sped-up version of more general code in `validate_call` + unless arg0_type.valid?(arg0) + CallValidation.report_error( + method_sig, + method_sig.arg_types[0][1].error_message_for_obj(arg0), + 'Parameter', + method_sig.arg_types[0][0], + arg0_type, + arg0, + caller_offset: -1 + ) + end + + unless arg1_type.valid?(arg1) + CallValidation.report_error( + method_sig, + method_sig.arg_types[1][1].error_message_for_obj(arg1), + 'Parameter', + method_sig.arg_types[1][0], + arg1_type, + arg1, + caller_offset: -1 + ) + end + + # The following line breaks are intentional to show nice pry message + + + + + + + + + + + # PRY note: + # this code is sig validation code. + # Please issue `finish` to step out of it + + original_method.bind(self).call(arg0, arg1, &blk) + T::Private::Types::Void::VOID + end + end + + def self.create_validator_procedure_medium3(mod, original_method, method_sig, original_visibility, arg0_type, arg1_type, arg2_type) + T::Private::ClassUtils.def_with_visibility(mod, method_sig.method_name, original_visibility) do |arg0, arg1, arg2, &blk| + # This method is a manually sped-up version of more general code in `validate_call` + unless arg0_type.valid?(arg0) + CallValidation.report_error( + method_sig, + method_sig.arg_types[0][1].error_message_for_obj(arg0), + 'Parameter', + method_sig.arg_types[0][0], + arg0_type, + arg0, + caller_offset: -1 + ) + end + + unless arg1_type.valid?(arg1) + CallValidation.report_error( + method_sig, + method_sig.arg_types[1][1].error_message_for_obj(arg1), + 'Parameter', + method_sig.arg_types[1][0], + arg1_type, + arg1, + caller_offset: -1 + ) + end + + unless arg2_type.valid?(arg2) + CallValidation.report_error( + method_sig, + method_sig.arg_types[2][1].error_message_for_obj(arg2), + 'Parameter', + method_sig.arg_types[2][0], + arg2_type, + arg2, + caller_offset: -1 + ) + end + + # The following line breaks are intentional to show nice pry message + + + + + + + + + + + # PRY note: + # this code is sig validation code. + # Please issue `finish` to step out of it + + original_method.bind(self).call(arg0, arg1, arg2, &blk) + T::Private::Types::Void::VOID + end + end + + def self.create_validator_procedure_medium4(mod, original_method, method_sig, original_visibility, arg0_type, arg1_type, arg2_type, arg3_type) + T::Private::ClassUtils.def_with_visibility(mod, method_sig.method_name, original_visibility) do |arg0, arg1, arg2, arg3, &blk| + # This method is a manually sped-up version of more general code in `validate_call` + unless arg0_type.valid?(arg0) + CallValidation.report_error( + method_sig, + method_sig.arg_types[0][1].error_message_for_obj(arg0), + 'Parameter', + method_sig.arg_types[0][0], + arg0_type, + arg0, + caller_offset: -1 + ) + end + + unless arg1_type.valid?(arg1) + CallValidation.report_error( + method_sig, + method_sig.arg_types[1][1].error_message_for_obj(arg1), + 'Parameter', + method_sig.arg_types[1][0], + arg1_type, + arg1, + caller_offset: -1 + ) + end + + unless arg2_type.valid?(arg2) + CallValidation.report_error( + method_sig, + method_sig.arg_types[2][1].error_message_for_obj(arg2), + 'Parameter', + method_sig.arg_types[2][0], + arg2_type, + arg2, + caller_offset: -1 + ) + end + + unless arg3_type.valid?(arg3) + CallValidation.report_error( + method_sig, + method_sig.arg_types[3][1].error_message_for_obj(arg3), + 'Parameter', + method_sig.arg_types[3][0], + arg3_type, + arg3, + caller_offset: -1 + ) + end + + # The following line breaks are intentional to show nice pry message + + + + + + + + + + + # PRY note: + # this code is sig validation code. + # Please issue `finish` to step out of it + + original_method.bind(self).call(arg0, arg1, arg2, arg3, &blk) + T::Private::Types::Void::VOID + end + end + +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/methods/call_validation_2_7.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/methods/call_validation_2_7.rb new file mode 100644 index 0000000000..26c261746a --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/methods/call_validation_2_7.rb @@ -0,0 +1,1203 @@ +# frozen_string_literal: true +# typed: false + +# DO NOT EDIT. This file is autogenerated. To regenerate, run: +# +# bazel test //gems/sorbet-runtime:update_call_validation + +module T::Private::Methods::CallValidation + def self.create_validator_method_fast(mod, original_method, method_sig, original_visibility) + if method_sig.return_type.is_a?(T::Private::Types::Void) + raise 'Should have used create_validator_procedure_fast' + end + # trampoline to reduce stack frame size + if method_sig.arg_types.empty? + create_validator_method_fast0(mod, original_method, method_sig, original_visibility, method_sig.return_type.raw_type) + elsif method_sig.arg_types.length == 1 + create_validator_method_fast1(mod, original_method, method_sig, original_visibility, method_sig.return_type.raw_type, + method_sig.arg_types[0][1].raw_type) + elsif method_sig.arg_types.length == 2 + create_validator_method_fast2(mod, original_method, method_sig, original_visibility, method_sig.return_type.raw_type, + method_sig.arg_types[0][1].raw_type, + method_sig.arg_types[1][1].raw_type) + elsif method_sig.arg_types.length == 3 + create_validator_method_fast3(mod, original_method, method_sig, original_visibility, method_sig.return_type.raw_type, + method_sig.arg_types[0][1].raw_type, + method_sig.arg_types[1][1].raw_type, + method_sig.arg_types[2][1].raw_type) + elsif method_sig.arg_types.length == 4 + create_validator_method_fast4(mod, original_method, method_sig, original_visibility, method_sig.return_type.raw_type, + method_sig.arg_types[0][1].raw_type, + method_sig.arg_types[1][1].raw_type, + method_sig.arg_types[2][1].raw_type, + method_sig.arg_types[3][1].raw_type) + else + raise 'should not happen' + end + end + + def self.create_validator_method_fast0(mod, original_method, method_sig, original_visibility, return_type) + T::Private::ClassUtils.def_with_visibility(mod, method_sig.method_name, original_visibility) do |&blk| + # This method is a manually sped-up version of more general code in `validate_call` + # The following line breaks are intentional to show nice pry message + + + + + + + + + + + # PRY note: + # this code is sig validation code. + # Please issue `finish` to step out of it + + return_value = original_method.bind_call(self, &blk) + unless return_value.is_a?(return_type) + message = method_sig.return_type.error_message_for_obj(return_value) + if message + CallValidation.report_error( + method_sig, + message, + 'Return value', + nil, + method_sig.return_type, + return_value, + caller_offset: -1 + ) + end + end + return_value + end + end + + def self.create_validator_method_fast1(mod, original_method, method_sig, original_visibility, return_type, arg0_type) + T::Private::ClassUtils.def_with_visibility(mod, method_sig.method_name, original_visibility) do |arg0, &blk| + # This method is a manually sped-up version of more general code in `validate_call` + unless arg0.is_a?(arg0_type) + CallValidation.report_error( + method_sig, + method_sig.arg_types[0][1].error_message_for_obj(arg0), + 'Parameter', + method_sig.arg_types[0][0], + arg0_type, + arg0, + caller_offset: -1 + ) + end + + # The following line breaks are intentional to show nice pry message + + + + + + + + + + + # PRY note: + # this code is sig validation code. + # Please issue `finish` to step out of it + + return_value = original_method.bind_call(self, arg0, &blk) + unless return_value.is_a?(return_type) + message = method_sig.return_type.error_message_for_obj(return_value) + if message + CallValidation.report_error( + method_sig, + message, + 'Return value', + nil, + method_sig.return_type, + return_value, + caller_offset: -1 + ) + end + end + return_value + end + end + + def self.create_validator_method_fast2(mod, original_method, method_sig, original_visibility, return_type, arg0_type, arg1_type) + T::Private::ClassUtils.def_with_visibility(mod, method_sig.method_name, original_visibility) do |arg0, arg1, &blk| + # This method is a manually sped-up version of more general code in `validate_call` + unless arg0.is_a?(arg0_type) + CallValidation.report_error( + method_sig, + method_sig.arg_types[0][1].error_message_for_obj(arg0), + 'Parameter', + method_sig.arg_types[0][0], + arg0_type, + arg0, + caller_offset: -1 + ) + end + + unless arg1.is_a?(arg1_type) + CallValidation.report_error( + method_sig, + method_sig.arg_types[1][1].error_message_for_obj(arg1), + 'Parameter', + method_sig.arg_types[1][0], + arg1_type, + arg1, + caller_offset: -1 + ) + end + + # The following line breaks are intentional to show nice pry message + + + + + + + + + + + # PRY note: + # this code is sig validation code. + # Please issue `finish` to step out of it + + return_value = original_method.bind_call(self, arg0, arg1, &blk) + unless return_value.is_a?(return_type) + message = method_sig.return_type.error_message_for_obj(return_value) + if message + CallValidation.report_error( + method_sig, + message, + 'Return value', + nil, + method_sig.return_type, + return_value, + caller_offset: -1 + ) + end + end + return_value + end + end + + def self.create_validator_method_fast3(mod, original_method, method_sig, original_visibility, return_type, arg0_type, arg1_type, arg2_type) + T::Private::ClassUtils.def_with_visibility(mod, method_sig.method_name, original_visibility) do |arg0, arg1, arg2, &blk| + # This method is a manually sped-up version of more general code in `validate_call` + unless arg0.is_a?(arg0_type) + CallValidation.report_error( + method_sig, + method_sig.arg_types[0][1].error_message_for_obj(arg0), + 'Parameter', + method_sig.arg_types[0][0], + arg0_type, + arg0, + caller_offset: -1 + ) + end + + unless arg1.is_a?(arg1_type) + CallValidation.report_error( + method_sig, + method_sig.arg_types[1][1].error_message_for_obj(arg1), + 'Parameter', + method_sig.arg_types[1][0], + arg1_type, + arg1, + caller_offset: -1 + ) + end + + unless arg2.is_a?(arg2_type) + CallValidation.report_error( + method_sig, + method_sig.arg_types[2][1].error_message_for_obj(arg2), + 'Parameter', + method_sig.arg_types[2][0], + arg2_type, + arg2, + caller_offset: -1 + ) + end + + # The following line breaks are intentional to show nice pry message + + + + + + + + + + + # PRY note: + # this code is sig validation code. + # Please issue `finish` to step out of it + + return_value = original_method.bind_call(self, arg0, arg1, arg2, &blk) + unless return_value.is_a?(return_type) + message = method_sig.return_type.error_message_for_obj(return_value) + if message + CallValidation.report_error( + method_sig, + message, + 'Return value', + nil, + method_sig.return_type, + return_value, + caller_offset: -1 + ) + end + end + return_value + end + end + + def self.create_validator_method_fast4(mod, original_method, method_sig, original_visibility, return_type, arg0_type, arg1_type, arg2_type, arg3_type) + T::Private::ClassUtils.def_with_visibility(mod, method_sig.method_name, original_visibility) do |arg0, arg1, arg2, arg3, &blk| + # This method is a manually sped-up version of more general code in `validate_call` + unless arg0.is_a?(arg0_type) + CallValidation.report_error( + method_sig, + method_sig.arg_types[0][1].error_message_for_obj(arg0), + 'Parameter', + method_sig.arg_types[0][0], + arg0_type, + arg0, + caller_offset: -1 + ) + end + + unless arg1.is_a?(arg1_type) + CallValidation.report_error( + method_sig, + method_sig.arg_types[1][1].error_message_for_obj(arg1), + 'Parameter', + method_sig.arg_types[1][0], + arg1_type, + arg1, + caller_offset: -1 + ) + end + + unless arg2.is_a?(arg2_type) + CallValidation.report_error( + method_sig, + method_sig.arg_types[2][1].error_message_for_obj(arg2), + 'Parameter', + method_sig.arg_types[2][0], + arg2_type, + arg2, + caller_offset: -1 + ) + end + + unless arg3.is_a?(arg3_type) + CallValidation.report_error( + method_sig, + method_sig.arg_types[3][1].error_message_for_obj(arg3), + 'Parameter', + method_sig.arg_types[3][0], + arg3_type, + arg3, + caller_offset: -1 + ) + end + + # The following line breaks are intentional to show nice pry message + + + + + + + + + + + # PRY note: + # this code is sig validation code. + # Please issue `finish` to step out of it + + return_value = original_method.bind_call(self, arg0, arg1, arg2, arg3, &blk) + unless return_value.is_a?(return_type) + message = method_sig.return_type.error_message_for_obj(return_value) + if message + CallValidation.report_error( + method_sig, + message, + 'Return value', + nil, + method_sig.return_type, + return_value, + caller_offset: -1 + ) + end + end + return_value + end + end + + def self.create_validator_procedure_fast(mod, original_method, method_sig, original_visibility) + # trampoline to reduce stack frame size + if method_sig.arg_types.empty? + create_validator_procedure_fast0(mod, original_method, method_sig, original_visibility) + elsif method_sig.arg_types.length == 1 + create_validator_procedure_fast1(mod, original_method, method_sig, original_visibility, + method_sig.arg_types[0][1].raw_type) + elsif method_sig.arg_types.length == 2 + create_validator_procedure_fast2(mod, original_method, method_sig, original_visibility, + method_sig.arg_types[0][1].raw_type, + method_sig.arg_types[1][1].raw_type) + elsif method_sig.arg_types.length == 3 + create_validator_procedure_fast3(mod, original_method, method_sig, original_visibility, + method_sig.arg_types[0][1].raw_type, + method_sig.arg_types[1][1].raw_type, + method_sig.arg_types[2][1].raw_type) + elsif method_sig.arg_types.length == 4 + create_validator_procedure_fast4(mod, original_method, method_sig, original_visibility, + method_sig.arg_types[0][1].raw_type, + method_sig.arg_types[1][1].raw_type, + method_sig.arg_types[2][1].raw_type, + method_sig.arg_types[3][1].raw_type) + else + raise 'should not happen' + end + end + + def self.create_validator_procedure_fast0(mod, original_method, method_sig, original_visibility) + T::Private::ClassUtils.def_with_visibility(mod, method_sig.method_name, original_visibility) do |&blk| + # This method is a manually sped-up version of more general code in `validate_call` + # The following line breaks are intentional to show nice pry message + + + + + + + + + + + # PRY note: + # this code is sig validation code. + # Please issue `finish` to step out of it + + original_method.bind_call(self, &blk) + T::Private::Types::Void::VOID + end + end + + def self.create_validator_procedure_fast1(mod, original_method, method_sig, original_visibility, arg0_type) + T::Private::ClassUtils.def_with_visibility(mod, method_sig.method_name, original_visibility) do |arg0, &blk| + # This method is a manually sped-up version of more general code in `validate_call` + unless arg0.is_a?(arg0_type) + CallValidation.report_error( + method_sig, + method_sig.arg_types[0][1].error_message_for_obj(arg0), + 'Parameter', + method_sig.arg_types[0][0], + arg0_type, + arg0, + caller_offset: -1 + ) + end + + # The following line breaks are intentional to show nice pry message + + + + + + + + + + + # PRY note: + # this code is sig validation code. + # Please issue `finish` to step out of it + + original_method.bind_call(self, arg0, &blk) + T::Private::Types::Void::VOID + end + end + + def self.create_validator_procedure_fast2(mod, original_method, method_sig, original_visibility, arg0_type, arg1_type) + T::Private::ClassUtils.def_with_visibility(mod, method_sig.method_name, original_visibility) do |arg0, arg1, &blk| + # This method is a manually sped-up version of more general code in `validate_call` + unless arg0.is_a?(arg0_type) + CallValidation.report_error( + method_sig, + method_sig.arg_types[0][1].error_message_for_obj(arg0), + 'Parameter', + method_sig.arg_types[0][0], + arg0_type, + arg0, + caller_offset: -1 + ) + end + + unless arg1.is_a?(arg1_type) + CallValidation.report_error( + method_sig, + method_sig.arg_types[1][1].error_message_for_obj(arg1), + 'Parameter', + method_sig.arg_types[1][0], + arg1_type, + arg1, + caller_offset: -1 + ) + end + + # The following line breaks are intentional to show nice pry message + + + + + + + + + + + # PRY note: + # this code is sig validation code. + # Please issue `finish` to step out of it + + original_method.bind_call(self, arg0, arg1, &blk) + T::Private::Types::Void::VOID + end + end + + def self.create_validator_procedure_fast3(mod, original_method, method_sig, original_visibility, arg0_type, arg1_type, arg2_type) + T::Private::ClassUtils.def_with_visibility(mod, method_sig.method_name, original_visibility) do |arg0, arg1, arg2, &blk| + # This method is a manually sped-up version of more general code in `validate_call` + unless arg0.is_a?(arg0_type) + CallValidation.report_error( + method_sig, + method_sig.arg_types[0][1].error_message_for_obj(arg0), + 'Parameter', + method_sig.arg_types[0][0], + arg0_type, + arg0, + caller_offset: -1 + ) + end + + unless arg1.is_a?(arg1_type) + CallValidation.report_error( + method_sig, + method_sig.arg_types[1][1].error_message_for_obj(arg1), + 'Parameter', + method_sig.arg_types[1][0], + arg1_type, + arg1, + caller_offset: -1 + ) + end + + unless arg2.is_a?(arg2_type) + CallValidation.report_error( + method_sig, + method_sig.arg_types[2][1].error_message_for_obj(arg2), + 'Parameter', + method_sig.arg_types[2][0], + arg2_type, + arg2, + caller_offset: -1 + ) + end + + # The following line breaks are intentional to show nice pry message + + + + + + + + + + + # PRY note: + # this code is sig validation code. + # Please issue `finish` to step out of it + + original_method.bind_call(self, arg0, arg1, arg2, &blk) + T::Private::Types::Void::VOID + end + end + + def self.create_validator_procedure_fast4(mod, original_method, method_sig, original_visibility, arg0_type, arg1_type, arg2_type, arg3_type) + T::Private::ClassUtils.def_with_visibility(mod, method_sig.method_name, original_visibility) do |arg0, arg1, arg2, arg3, &blk| + # This method is a manually sped-up version of more general code in `validate_call` + unless arg0.is_a?(arg0_type) + CallValidation.report_error( + method_sig, + method_sig.arg_types[0][1].error_message_for_obj(arg0), + 'Parameter', + method_sig.arg_types[0][0], + arg0_type, + arg0, + caller_offset: -1 + ) + end + + unless arg1.is_a?(arg1_type) + CallValidation.report_error( + method_sig, + method_sig.arg_types[1][1].error_message_for_obj(arg1), + 'Parameter', + method_sig.arg_types[1][0], + arg1_type, + arg1, + caller_offset: -1 + ) + end + + unless arg2.is_a?(arg2_type) + CallValidation.report_error( + method_sig, + method_sig.arg_types[2][1].error_message_for_obj(arg2), + 'Parameter', + method_sig.arg_types[2][0], + arg2_type, + arg2, + caller_offset: -1 + ) + end + + unless arg3.is_a?(arg3_type) + CallValidation.report_error( + method_sig, + method_sig.arg_types[3][1].error_message_for_obj(arg3), + 'Parameter', + method_sig.arg_types[3][0], + arg3_type, + arg3, + caller_offset: -1 + ) + end + + # The following line breaks are intentional to show nice pry message + + + + + + + + + + + # PRY note: + # this code is sig validation code. + # Please issue `finish` to step out of it + + original_method.bind_call(self, arg0, arg1, arg2, arg3, &blk) + T::Private::Types::Void::VOID + end + end + + def self.create_validator_method_medium(mod, original_method, method_sig, original_visibility) + if method_sig.return_type.is_a?(T::Private::Types::Void) + raise 'Should have used create_validator_procedure_medium' + end + # trampoline to reduce stack frame size + if method_sig.arg_types.empty? + create_validator_method_medium0(mod, original_method, method_sig, original_visibility, method_sig.return_type) + elsif method_sig.arg_types.length == 1 + create_validator_method_medium1(mod, original_method, method_sig, original_visibility, method_sig.return_type, + method_sig.arg_types[0][1]) + elsif method_sig.arg_types.length == 2 + create_validator_method_medium2(mod, original_method, method_sig, original_visibility, method_sig.return_type, + method_sig.arg_types[0][1], + method_sig.arg_types[1][1]) + elsif method_sig.arg_types.length == 3 + create_validator_method_medium3(mod, original_method, method_sig, original_visibility, method_sig.return_type, + method_sig.arg_types[0][1], + method_sig.arg_types[1][1], + method_sig.arg_types[2][1]) + elsif method_sig.arg_types.length == 4 + create_validator_method_medium4(mod, original_method, method_sig, original_visibility, method_sig.return_type, + method_sig.arg_types[0][1], + method_sig.arg_types[1][1], + method_sig.arg_types[2][1], + method_sig.arg_types[3][1]) + else + raise 'should not happen' + end + end + + def self.create_validator_method_medium0(mod, original_method, method_sig, original_visibility, return_type) + T::Private::ClassUtils.def_with_visibility(mod, method_sig.method_name, original_visibility) do |&blk| + # This method is a manually sped-up version of more general code in `validate_call` + # The following line breaks are intentional to show nice pry message + + + + + + + + + + + # PRY note: + # this code is sig validation code. + # Please issue `finish` to step out of it + + return_value = original_method.bind_call(self, &blk) + unless return_type.valid?(return_value) + message = method_sig.return_type.error_message_for_obj(return_value) + if message + CallValidation.report_error( + method_sig, + message, + 'Return value', + nil, + method_sig.return_type, + return_value, + caller_offset: -1 + ) + end + end + return_value + end + end + + def self.create_validator_method_medium1(mod, original_method, method_sig, original_visibility, return_type, arg0_type) + T::Private::ClassUtils.def_with_visibility(mod, method_sig.method_name, original_visibility) do |arg0, &blk| + # This method is a manually sped-up version of more general code in `validate_call` + unless arg0_type.valid?(arg0) + CallValidation.report_error( + method_sig, + method_sig.arg_types[0][1].error_message_for_obj(arg0), + 'Parameter', + method_sig.arg_types[0][0], + arg0_type, + arg0, + caller_offset: -1 + ) + end + + # The following line breaks are intentional to show nice pry message + + + + + + + + + + + # PRY note: + # this code is sig validation code. + # Please issue `finish` to step out of it + + return_value = original_method.bind_call(self, arg0, &blk) + unless return_type.valid?(return_value) + message = method_sig.return_type.error_message_for_obj(return_value) + if message + CallValidation.report_error( + method_sig, + message, + 'Return value', + nil, + method_sig.return_type, + return_value, + caller_offset: -1 + ) + end + end + return_value + end + end + + def self.create_validator_method_medium2(mod, original_method, method_sig, original_visibility, return_type, arg0_type, arg1_type) + T::Private::ClassUtils.def_with_visibility(mod, method_sig.method_name, original_visibility) do |arg0, arg1, &blk| + # This method is a manually sped-up version of more general code in `validate_call` + unless arg0_type.valid?(arg0) + CallValidation.report_error( + method_sig, + method_sig.arg_types[0][1].error_message_for_obj(arg0), + 'Parameter', + method_sig.arg_types[0][0], + arg0_type, + arg0, + caller_offset: -1 + ) + end + + unless arg1_type.valid?(arg1) + CallValidation.report_error( + method_sig, + method_sig.arg_types[1][1].error_message_for_obj(arg1), + 'Parameter', + method_sig.arg_types[1][0], + arg1_type, + arg1, + caller_offset: -1 + ) + end + + # The following line breaks are intentional to show nice pry message + + + + + + + + + + + # PRY note: + # this code is sig validation code. + # Please issue `finish` to step out of it + + return_value = original_method.bind_call(self, arg0, arg1, &blk) + unless return_type.valid?(return_value) + message = method_sig.return_type.error_message_for_obj(return_value) + if message + CallValidation.report_error( + method_sig, + message, + 'Return value', + nil, + method_sig.return_type, + return_value, + caller_offset: -1 + ) + end + end + return_value + end + end + + def self.create_validator_method_medium3(mod, original_method, method_sig, original_visibility, return_type, arg0_type, arg1_type, arg2_type) + T::Private::ClassUtils.def_with_visibility(mod, method_sig.method_name, original_visibility) do |arg0, arg1, arg2, &blk| + # This method is a manually sped-up version of more general code in `validate_call` + unless arg0_type.valid?(arg0) + CallValidation.report_error( + method_sig, + method_sig.arg_types[0][1].error_message_for_obj(arg0), + 'Parameter', + method_sig.arg_types[0][0], + arg0_type, + arg0, + caller_offset: -1 + ) + end + + unless arg1_type.valid?(arg1) + CallValidation.report_error( + method_sig, + method_sig.arg_types[1][1].error_message_for_obj(arg1), + 'Parameter', + method_sig.arg_types[1][0], + arg1_type, + arg1, + caller_offset: -1 + ) + end + + unless arg2_type.valid?(arg2) + CallValidation.report_error( + method_sig, + method_sig.arg_types[2][1].error_message_for_obj(arg2), + 'Parameter', + method_sig.arg_types[2][0], + arg2_type, + arg2, + caller_offset: -1 + ) + end + + # The following line breaks are intentional to show nice pry message + + + + + + + + + + + # PRY note: + # this code is sig validation code. + # Please issue `finish` to step out of it + + return_value = original_method.bind_call(self, arg0, arg1, arg2, &blk) + unless return_type.valid?(return_value) + message = method_sig.return_type.error_message_for_obj(return_value) + if message + CallValidation.report_error( + method_sig, + message, + 'Return value', + nil, + method_sig.return_type, + return_value, + caller_offset: -1 + ) + end + end + return_value + end + end + + def self.create_validator_method_medium4(mod, original_method, method_sig, original_visibility, return_type, arg0_type, arg1_type, arg2_type, arg3_type) + T::Private::ClassUtils.def_with_visibility(mod, method_sig.method_name, original_visibility) do |arg0, arg1, arg2, arg3, &blk| + # This method is a manually sped-up version of more general code in `validate_call` + unless arg0_type.valid?(arg0) + CallValidation.report_error( + method_sig, + method_sig.arg_types[0][1].error_message_for_obj(arg0), + 'Parameter', + method_sig.arg_types[0][0], + arg0_type, + arg0, + caller_offset: -1 + ) + end + + unless arg1_type.valid?(arg1) + CallValidation.report_error( + method_sig, + method_sig.arg_types[1][1].error_message_for_obj(arg1), + 'Parameter', + method_sig.arg_types[1][0], + arg1_type, + arg1, + caller_offset: -1 + ) + end + + unless arg2_type.valid?(arg2) + CallValidation.report_error( + method_sig, + method_sig.arg_types[2][1].error_message_for_obj(arg2), + 'Parameter', + method_sig.arg_types[2][0], + arg2_type, + arg2, + caller_offset: -1 + ) + end + + unless arg3_type.valid?(arg3) + CallValidation.report_error( + method_sig, + method_sig.arg_types[3][1].error_message_for_obj(arg3), + 'Parameter', + method_sig.arg_types[3][0], + arg3_type, + arg3, + caller_offset: -1 + ) + end + + # The following line breaks are intentional to show nice pry message + + + + + + + + + + + # PRY note: + # this code is sig validation code. + # Please issue `finish` to step out of it + + return_value = original_method.bind_call(self, arg0, arg1, arg2, arg3, &blk) + unless return_type.valid?(return_value) + message = method_sig.return_type.error_message_for_obj(return_value) + if message + CallValidation.report_error( + method_sig, + message, + 'Return value', + nil, + method_sig.return_type, + return_value, + caller_offset: -1 + ) + end + end + return_value + end + end + + def self.create_validator_procedure_medium(mod, original_method, method_sig, original_visibility) + # trampoline to reduce stack frame size + if method_sig.arg_types.empty? + create_validator_procedure_medium0(mod, original_method, method_sig, original_visibility) + elsif method_sig.arg_types.length == 1 + create_validator_procedure_medium1(mod, original_method, method_sig, original_visibility, + method_sig.arg_types[0][1]) + elsif method_sig.arg_types.length == 2 + create_validator_procedure_medium2(mod, original_method, method_sig, original_visibility, + method_sig.arg_types[0][1], + method_sig.arg_types[1][1]) + elsif method_sig.arg_types.length == 3 + create_validator_procedure_medium3(mod, original_method, method_sig, original_visibility, + method_sig.arg_types[0][1], + method_sig.arg_types[1][1], + method_sig.arg_types[2][1]) + elsif method_sig.arg_types.length == 4 + create_validator_procedure_medium4(mod, original_method, method_sig, original_visibility, + method_sig.arg_types[0][1], + method_sig.arg_types[1][1], + method_sig.arg_types[2][1], + method_sig.arg_types[3][1]) + else + raise 'should not happen' + end + end + + def self.create_validator_procedure_medium0(mod, original_method, method_sig, original_visibility) + T::Private::ClassUtils.def_with_visibility(mod, method_sig.method_name, original_visibility) do |&blk| + # This method is a manually sped-up version of more general code in `validate_call` + # The following line breaks are intentional to show nice pry message + + + + + + + + + + + # PRY note: + # this code is sig validation code. + # Please issue `finish` to step out of it + + original_method.bind_call(self, &blk) + T::Private::Types::Void::VOID + end + end + + def self.create_validator_procedure_medium1(mod, original_method, method_sig, original_visibility, arg0_type) + T::Private::ClassUtils.def_with_visibility(mod, method_sig.method_name, original_visibility) do |arg0, &blk| + # This method is a manually sped-up version of more general code in `validate_call` + unless arg0_type.valid?(arg0) + CallValidation.report_error( + method_sig, + method_sig.arg_types[0][1].error_message_for_obj(arg0), + 'Parameter', + method_sig.arg_types[0][0], + arg0_type, + arg0, + caller_offset: -1 + ) + end + + # The following line breaks are intentional to show nice pry message + + + + + + + + + + + # PRY note: + # this code is sig validation code. + # Please issue `finish` to step out of it + + original_method.bind_call(self, arg0, &blk) + T::Private::Types::Void::VOID + end + end + + def self.create_validator_procedure_medium2(mod, original_method, method_sig, original_visibility, arg0_type, arg1_type) + T::Private::ClassUtils.def_with_visibility(mod, method_sig.method_name, original_visibility) do |arg0, arg1, &blk| + # This method is a manually sped-up version of more general code in `validate_call` + unless arg0_type.valid?(arg0) + CallValidation.report_error( + method_sig, + method_sig.arg_types[0][1].error_message_for_obj(arg0), + 'Parameter', + method_sig.arg_types[0][0], + arg0_type, + arg0, + caller_offset: -1 + ) + end + + unless arg1_type.valid?(arg1) + CallValidation.report_error( + method_sig, + method_sig.arg_types[1][1].error_message_for_obj(arg1), + 'Parameter', + method_sig.arg_types[1][0], + arg1_type, + arg1, + caller_offset: -1 + ) + end + + # The following line breaks are intentional to show nice pry message + + + + + + + + + + + # PRY note: + # this code is sig validation code. + # Please issue `finish` to step out of it + + original_method.bind_call(self, arg0, arg1, &blk) + T::Private::Types::Void::VOID + end + end + + def self.create_validator_procedure_medium3(mod, original_method, method_sig, original_visibility, arg0_type, arg1_type, arg2_type) + T::Private::ClassUtils.def_with_visibility(mod, method_sig.method_name, original_visibility) do |arg0, arg1, arg2, &blk| + # This method is a manually sped-up version of more general code in `validate_call` + unless arg0_type.valid?(arg0) + CallValidation.report_error( + method_sig, + method_sig.arg_types[0][1].error_message_for_obj(arg0), + 'Parameter', + method_sig.arg_types[0][0], + arg0_type, + arg0, + caller_offset: -1 + ) + end + + unless arg1_type.valid?(arg1) + CallValidation.report_error( + method_sig, + method_sig.arg_types[1][1].error_message_for_obj(arg1), + 'Parameter', + method_sig.arg_types[1][0], + arg1_type, + arg1, + caller_offset: -1 + ) + end + + unless arg2_type.valid?(arg2) + CallValidation.report_error( + method_sig, + method_sig.arg_types[2][1].error_message_for_obj(arg2), + 'Parameter', + method_sig.arg_types[2][0], + arg2_type, + arg2, + caller_offset: -1 + ) + end + + # The following line breaks are intentional to show nice pry message + + + + + + + + + + + # PRY note: + # this code is sig validation code. + # Please issue `finish` to step out of it + + original_method.bind_call(self, arg0, arg1, arg2, &blk) + T::Private::Types::Void::VOID + end + end + + def self.create_validator_procedure_medium4(mod, original_method, method_sig, original_visibility, arg0_type, arg1_type, arg2_type, arg3_type) + T::Private::ClassUtils.def_with_visibility(mod, method_sig.method_name, original_visibility) do |arg0, arg1, arg2, arg3, &blk| + # This method is a manually sped-up version of more general code in `validate_call` + unless arg0_type.valid?(arg0) + CallValidation.report_error( + method_sig, + method_sig.arg_types[0][1].error_message_for_obj(arg0), + 'Parameter', + method_sig.arg_types[0][0], + arg0_type, + arg0, + caller_offset: -1 + ) + end + + unless arg1_type.valid?(arg1) + CallValidation.report_error( + method_sig, + method_sig.arg_types[1][1].error_message_for_obj(arg1), + 'Parameter', + method_sig.arg_types[1][0], + arg1_type, + arg1, + caller_offset: -1 + ) + end + + unless arg2_type.valid?(arg2) + CallValidation.report_error( + method_sig, + method_sig.arg_types[2][1].error_message_for_obj(arg2), + 'Parameter', + method_sig.arg_types[2][0], + arg2_type, + arg2, + caller_offset: -1 + ) + end + + unless arg3_type.valid?(arg3) + CallValidation.report_error( + method_sig, + method_sig.arg_types[3][1].error_message_for_obj(arg3), + 'Parameter', + method_sig.arg_types[3][0], + arg3_type, + arg3, + caller_offset: -1 + ) + end + + # The following line breaks are intentional to show nice pry message + + + + + + + + + + + # PRY note: + # this code is sig validation code. + # Please issue `finish` to step out of it + + original_method.bind_call(self, arg0, arg1, arg2, arg3, &blk) + T::Private::Types::Void::VOID + end + end + +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/methods/decl_builder.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/methods/decl_builder.rb new file mode 100644 index 0000000000..b48b1d5b68 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/methods/decl_builder.rb @@ -0,0 +1,232 @@ +# frozen_string_literal: true +# typed: true + +module T::Private::Methods + Declaration = Struct.new(:mod, :params, :returns, :bind, :mode, :checked, :finalized, :on_failure, :override_allow_incompatible, :type_parameters, :raw) + + class DeclBuilder + attr_reader :decl + + class BuilderError < StandardError; end + + private def check_live! + if decl.finalized + raise BuilderError.new("You can't modify a signature declaration after it has been used.") + end + end + + def initialize(mod, raw) + # TODO RUBYPLAT-1278 - with ruby 2.5, use kwargs here + @decl = Declaration.new( + mod, + ARG_NOT_PROVIDED, # params + ARG_NOT_PROVIDED, # returns + ARG_NOT_PROVIDED, # bind + Modes.standard, # mode + ARG_NOT_PROVIDED, # checked + false, # finalized + ARG_NOT_PROVIDED, # on_failure + nil, # override_allow_incompatible + ARG_NOT_PROVIDED, # type_parameters + raw + ) + end + + def params(**params) + check_live! + if !decl.params.equal?(ARG_NOT_PROVIDED) + raise BuilderError.new("You can't call .params twice") + end + + if params.empty? + raise BuilderError.new("params expects keyword arguments") + end + decl.params = params + + self + end + + def returns(type) + check_live! + if decl.returns.is_a?(T::Private::Types::Void) + raise BuilderError.new("You can't call .returns after calling .void.") + end + if !decl.returns.equal?(ARG_NOT_PROVIDED) + raise BuilderError.new("You can't call .returns multiple times in a signature.") + end + + decl.returns = type + + self + end + + def void + check_live! + if !decl.returns.equal?(ARG_NOT_PROVIDED) + raise BuilderError.new("You can't call .void after calling .returns.") + end + + decl.returns = T::Private::Types::Void.new + + self + end + + def bind(type) + check_live! + if !decl.bind.equal?(ARG_NOT_PROVIDED) + raise BuilderError.new("You can't call .bind multiple times in a signature.") + end + + decl.bind = type + + self + end + + def checked(level) + check_live! + + if !decl.checked.equal?(ARG_NOT_PROVIDED) + raise BuilderError.new("You can't call .checked multiple times in a signature.") + end + if (level == :never || level == :compiled) && !decl.on_failure.equal?(ARG_NOT_PROVIDED) + raise BuilderError.new("You can't use .checked(:#{level}) with .on_failure because .on_failure will have no effect.") + end + if !T::Private::RuntimeLevels::LEVELS.include?(level) + raise BuilderError.new("Invalid `checked` level '#{level}'. Use one of: #{T::Private::RuntimeLevels::LEVELS}.") + end + + decl.checked = level + + self + end + + def on_failure(*args) + check_live! + + if !decl.on_failure.equal?(ARG_NOT_PROVIDED) + raise BuilderError.new("You can't call .on_failure multiple times in a signature.") + end + if decl.checked == :never || decl.checked == :compiled + raise BuilderError.new("You can't use .on_failure with .checked(:#{decl.checked}) because .on_failure will have no effect.") + end + + decl.on_failure = args + + self + end + + def abstract + check_live! + + case decl.mode + when Modes.standard + decl.mode = Modes.abstract + when Modes.abstract + raise BuilderError.new(".abstract cannot be repeated in a single signature") + else + raise BuilderError.new("`.abstract` cannot be combined with `.override` or `.overridable`.") + end + + self + end + + def final + check_live! + raise BuilderError.new("The syntax for declaring a method final is `sig(:final) {...}`, not `sig {final. ...}`") + end + + def override(allow_incompatible: false) + check_live! + + case decl.mode + when Modes.standard + decl.mode = Modes.override + decl.override_allow_incompatible = allow_incompatible + when Modes.override, Modes.overridable_override + raise BuilderError.new(".override cannot be repeated in a single signature") + when Modes.overridable + decl.mode = Modes.overridable_override + else + raise BuilderError.new("`.override` cannot be combined with `.abstract`.") + end + + self + end + + def overridable + check_live! + + case decl.mode + when Modes.abstract + raise BuilderError.new("`.overridable` cannot be combined with `.#{decl.mode}`") + when Modes.override + decl.mode = Modes.overridable_override + when Modes.standard + decl.mode = Modes.overridable + when Modes.overridable, Modes.overridable_override + raise BuilderError.new(".overridable cannot be repeated in a single signature") + end + + self + end + + # Declares valid type paramaters which can be used with `T.type_parameter` in + # this `sig`. + # + # This is used for generic methods. Example usage: + # + # sig do + # type_parameters(:U) + # .params(blk: T.proc.params(arg0: Elem).returns(T.type_parameter(:U))) + # .returns(T::Array[T.type_parameter(:U)]) + # end + # def map(&blk); end + def type_parameters(*names) + check_live! + + names.each do |name| + raise BuilderError.new("not a symbol: #{name}") unless name.is_a?(Symbol) + end + + if !decl.type_parameters.equal?(ARG_NOT_PROVIDED) + raise BuilderError.new("You can't call .type_parameters multiple times in a signature.") + end + + decl.type_parameters = names + + self + end + + def finalize! + check_live! + + if decl.returns.equal?(ARG_NOT_PROVIDED) + raise BuilderError.new("You must provide a return type; use the `.returns` or `.void` builder methods.") + end + + if decl.bind.equal?(ARG_NOT_PROVIDED) + decl.bind = nil + end + if decl.checked.equal?(ARG_NOT_PROVIDED) + default_checked_level = T::Private::RuntimeLevels.default_checked_level + if (default_checked_level == :never || default_checked_level == :compiled) && !decl.on_failure.equal?(ARG_NOT_PROVIDED) + raise BuilderError.new("To use .on_failure you must additionally call .checked(:tests) or .checked(:always), otherwise, the .on_failure has no effect.") + end + decl.checked = default_checked_level + end + if decl.on_failure.equal?(ARG_NOT_PROVIDED) + decl.on_failure = nil + end + if decl.params.equal?(ARG_NOT_PROVIDED) + decl.params = {} + end + if decl.type_parameters.equal?(ARG_NOT_PROVIDED) + decl.type_parameters = {} + end + + decl.finalized = true + + self + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/methods/modes.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/methods/modes.rb new file mode 100644 index 0000000000..53d9a93195 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/methods/modes.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true +# typed: true + +module T::Private::Methods::Modes + def self.standard + 'standard' + end + def self.abstract + 'abstract' + end + def self.overridable + 'overridable' + end + def self.override + 'override' + end + def self.overridable_override + 'overridable_override' + end + def self.untyped + 'untyped' + end + MODES = [self.standard, self.abstract, self.overridable, self.override, self.overridable_override, self.untyped].freeze + + OVERRIDABLE_MODES = [self.override, self.overridable, self.overridable_override, self.untyped, self.abstract].freeze + OVERRIDE_MODES = [self.override, self.overridable_override].freeze + NON_OVERRIDE_MODES = MODES - OVERRIDE_MODES +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/methods/signature.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/methods/signature.rb new file mode 100644 index 0000000000..bd15977bd5 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/methods/signature.rb @@ -0,0 +1,225 @@ +# frozen_string_literal: true +# typed: true + +class T::Private::Methods::Signature + attr_reader :method, :method_name, :arg_types, :kwarg_types, :block_type, :block_name, + :rest_type, :rest_name, :keyrest_type, :keyrest_name, :bind, + :return_type, :mode, :req_arg_count, :req_kwarg_names, :has_rest, :has_keyrest, + :check_level, :parameters, :on_failure, :override_allow_incompatible, + :defined_raw + + def self.new_untyped(method:, mode: T::Private::Methods::Modes.untyped, parameters: method.parameters) + # Using `Untyped` ensures we'll get an error if we ever try validation on these. + not_typed = T::Private::Types::NotTyped.new + raw_return_type = not_typed + # Map missing parameter names to "argN" positionally + parameters = parameters.each_with_index.map do |(param_kind, param_name), index| + [param_kind, param_name || "arg#{index}"] + end + raw_arg_types = parameters.map do |_param_kind, param_name| + [param_name, not_typed] + end.to_h + + self.new( + method: method, + method_name: method.name, + raw_arg_types: raw_arg_types, + raw_return_type: raw_return_type, + bind: nil, + mode: mode, + check_level: :never, + parameters: parameters, + on_failure: nil, + ) + end + + def initialize(method:, method_name:, raw_arg_types:, raw_return_type:, bind:, mode:, check_level:, on_failure:, parameters: method.parameters, override_allow_incompatible: false, defined_raw: false) + @method = method + @method_name = method_name + @arg_types = [] + @kwarg_types = {} + @block_type = nil + @block_name = nil + @rest_type = nil + @rest_name = nil + @keyrest_type = nil + @keyrest_name = nil + @return_type = T::Utils.coerce(raw_return_type) + @bind = bind ? T::Utils.coerce(bind) : bind + @mode = mode + @check_level = check_level + @req_arg_count = 0 + @req_kwarg_names = [] + @has_rest = false + @has_keyrest = false + @parameters = parameters + @on_failure = on_failure + @override_allow_incompatible = override_allow_incompatible + @defined_raw = defined_raw + + declared_param_names = raw_arg_types.keys + # If sig params are declared but there is a single parameter with a missing name + # **and** the method ends with a "=", assume it is a writer method generated + # by attr_writer or attr_accessor + writer_method = declared_param_names != [nil] && parameters == [[:req]] && method_name[-1] == "=" + # For writer methods, map the single parameter to the method name without the "=" at the end + parameters = [[:req, method_name[0...-1].to_sym]] if writer_method + param_names = parameters.map {|_, name| name} + missing_names = param_names - declared_param_names + extra_names = declared_param_names - param_names + if !missing_names.empty? + raise "The declaration for `#{method.name}` is missing parameter(s): #{missing_names.join(', ')}" + end + if !extra_names.empty? + raise "The declaration for `#{method.name}` has extra parameter(s): #{extra_names.join(', ')}" + end + + if parameters.size != raw_arg_types.size + raise "The declaration for `#{method.name}` has arguments with duplicate names" + end + + parameters.zip(raw_arg_types) do |(param_kind, param_name), (type_name, raw_type)| + if type_name != param_name + hint = "" + # Ruby reorders params so that required keyword arguments + # always precede optional keyword arguments. We can't tell + # whether the culprit is the Ruby reordering or user error, so + # we error but include a note + if param_kind == :keyreq && parameters.any? {|k, _| k == :key} + hint = "\n\nNote: Any required keyword arguments must precede any optional keyword " \ + "arguments. If your method declaration matches your `def`, try reordering any " \ + "optional keyword parameters to the end of the method list." + end + + raise "Parameter `#{type_name}` is declared out of order (declared as arg number " \ + "#{declared_param_names.index(type_name) + 1}, defined in the method as arg number " \ + "#{param_names.index(type_name) + 1}).#{hint}\nMethod: #{method_desc}" + end + + type = T::Utils.coerce(raw_type) + + case param_kind + when :req + if @arg_types.length > @req_arg_count + # Note that this is actually is supported by Ruby, but it would add complexity to + # support it here, and I'm happy to discourage its use anyway. + # + # If you are seeing this error and surprised by it, it's possible that you have + # overridden the method described in the error message. For example, Rails defines + # def self.update!(id = :all, attributes) + # on AR models. If you have also defined `self.update!` on an AR model you might + # see this error. The simplest resolution is to rename your method. + raise "Required params after optional params are not supported in method declarations. Method: #{method_desc}" + end + @arg_types << [param_name, type] + @req_arg_count += 1 + when :opt + @arg_types << [param_name, type] + when :key, :keyreq + @kwarg_types[param_name] = type + if param_kind == :keyreq + @req_kwarg_names << param_name + end + when :block + @block_name = param_name + @block_type = type + when :rest + @has_rest = true + @rest_name = param_name + @rest_type = type + when :keyrest + @has_keyrest = true + @keyrest_name = param_name + @keyrest_type = type + else + raise "Unexpected param_kind: `#{param_kind}`. Method: #{method_desc}" + end + end + end + + attr_writer :method_name + protected :method_name= + + def as_alias(alias_name) + new_sig = clone + new_sig.method_name = alias_name + new_sig + end + + def arg_count + @arg_types.length + end + + def kwarg_names + @kwarg_types.keys + end + + def owner + @method.owner + end + + def dsl_method + "#{@mode}_method" + end + + # @return [Hash] a mapping like `{arg_name: [val, type], ...}`, for only those args actually present. + def each_args_value_type(args) + # Manually split out args and kwargs based on ruby's behavior. Do not try to implement this by + # getting ruby to determine the kwargs for you (e.g., by defining this method to take *args and + # **kwargs). That won't work, because ruby's behavior for determining kwargs is dependent on the + # the other parameters in the method definition, and our method definition here doesn't (and + # can't) match the definition of the method we're validating. In addition, Ruby has a bug that + # causes forwarding **kwargs to do the wrong thing: see https://bugs.ruby-lang.org/issues/10708 + # and https://bugs.ruby-lang.org/issues/11860. + args_length = args.length + if (args_length > @req_arg_count) && (!@kwarg_types.empty? || @has_keyrest) && args[-1].is_a?(Hash) + kwargs = args[-1] + args_length -= 1 + else + kwargs = EMPTY_HASH + end + + arg_types = @arg_types + + if @has_rest + rest_count = args_length - @arg_types.length + rest_count = 0 if rest_count.negative? + + arg_types += [[@rest_name, @rest_type]] * rest_count + + elsif (args_length < @req_arg_count) || (args_length > @arg_types.length) + expected_str = @req_arg_count.to_s + if @arg_types.length != @req_arg_count + expected_str += "..#{@arg_types.length}" + end + raise ArgumentError.new("wrong number of arguments (given #{args_length}, expected #{expected_str})") + end + + begin + it = 0 + while it < args_length + yield arg_types[it][0], args[it], arg_types[it][1] + it += 1 + end + end + + kwargs.each do |name, val| + type = @kwarg_types[name] + if !type && @has_keyrest + type = @keyrest_type + end + yield name, val, type if type + end + end + + def method_desc + loc = if @method.source_location + @method.source_location.join(':') + else + "" + end + "#{@method} at #{loc}" + end + + EMPTY_HASH = {}.freeze +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/methods/signature_validation.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/methods/signature_validation.rb new file mode 100644 index 0000000000..16188e0bf3 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/methods/signature_validation.rb @@ -0,0 +1,225 @@ +# frozen_string_literal: true +# typed: true + +module T::Private::Methods::SignatureValidation + Methods = T::Private::Methods + Modes = Methods::Modes + + def self.validate(signature) + if signature.method_name == :initialize && signature.method.owner.is_a?(Class) + # Constructors are special. They look like overrides in terms of a super_method existing, + # but in practice, you never call them polymorphically. Conceptually, they're standard + # methods (this is consistent with how they're treated in other languages, e.g. Java) + if signature.mode != Modes.standard + raise "`initialize` should not use `.abstract` or `.implementation` or any other inheritance modifiers." + end + return + end + + super_method = signature.method.super_method + + if super_method && super_method.owner != signature.method.owner + Methods.maybe_run_sig_block_for_method(super_method) + super_signature = Methods.signature_for_method(super_method) + + # If the super_method has any kwargs we can't build a + # Signature for it, so we'll just skip validation in that case. + if !super_signature && !super_method.parameters.select {|kind, _| kind == :rest || kind == :kwrest}.empty? + nil + else + # super_signature can be nil when we're overriding a method (perhaps a builtin) that didn't use + # one of the method signature helpers. Use an untyped signature so we can still validate + # everything but types. + # + # We treat these signatures as overridable, that way people can use `.override` with + # overrides of builtins. In the future we could try to distinguish when the method is a + # builtin and treat non-builtins as non-overridable (so you'd be forced to declare them with + # `.overridable`). + # + super_signature ||= Methods::Signature.new_untyped(method: super_method) + + validate_override_mode(signature, super_signature) + validate_override_shape(signature, super_signature) + validate_override_types(signature, super_signature) + end + else + validate_non_override_mode(signature) + end + end + + private_class_method def self.pretty_mode(signature) + if signature.mode == Modes.overridable_override + '.overridable.override' + else + ".#{signature.mode}" + end + end + + def self.validate_override_mode(signature, super_signature) + case signature.mode + when *Modes::OVERRIDE_MODES + # Peaceful + when *Modes::NON_OVERRIDE_MODES + if super_signature.mode == Modes.standard + # Peaceful + elsif super_signature.mode == Modes.abstract + raise "You must use `.override` when overriding the abstract method `#{signature.method_name}`.\n" \ + " Abstract definition: #{method_loc_str(super_signature.method)}\n" \ + " Implementation definition: #{method_loc_str(signature.method)}\n" + elsif super_signature.mode != Modes.untyped + raise "You must use `.override` when overriding the existing method `#{signature.method_name}`.\n" \ + " Parent definition: #{method_loc_str(super_signature.method)}\n" \ + " Child definition: #{method_loc_str(signature.method)}\n" + end + else + raise "Unexpected mode: #{signature.mode}. Please report this bug at https://github.com/sorbet/sorbet/issues" + end + end + + def self.validate_non_override_mode(signature) + case signature.mode + when Modes.override + if signature.method_name == :each && signature.method.owner < Enumerable + # Enumerable#each is the only method in Sorbet's RBI payload that defines an abstract method. + # Enumerable#each does not actually exist at runtime, but it is required to be implemented by + # any class which includes Enumerable. We want to declare Enumerable#each as abstract so that + # people can call it anything which implements the Enumerable interface, and so that it's a + # static error to forget to implement it. + # + # This is a one-off hack, and we should think carefully before adding more methods here. + nil + else + raise "You marked `#{signature.method_name}` as #{pretty_mode(signature)}, but that method doesn't already exist in this class/module to be overriden.\n" \ + " Either check for typos and for missing includes or super classes to make the parent method shows up\n" \ + " ... or remove #{pretty_mode(signature)} here: #{method_loc_str(signature.method)}\n" + end + when Modes.standard, *Modes::NON_OVERRIDE_MODES + # Peaceful + nil + else + raise "Unexpected mode: #{signature.mode}. Please report this bug at https://github.com/sorbet/sorbet/issues" + end + + # Given a singleton class, we can check if it belongs to a + # module by looking at its superclass; given `module M`, + # `M.singleton_class.superclass == Module`, which is not true + # for any class. + owner = signature.method.owner + if (signature.mode == Modes.abstract || Modes::OVERRIDABLE_MODES.include?(signature.mode)) && + owner.singleton_class? && owner.superclass == Module + raise "Defining an overridable class method (via #{pretty_mode(signature)}) " \ + "on a module is not allowed. Class methods on " \ + "modules do not get inherited and thus cannot be overridden." + end + end + + def self.validate_override_shape(signature, super_signature) + return if signature.override_allow_incompatible + return if super_signature.mode == Modes.untyped + + method_name = signature.method_name + mode_verb = super_signature.mode == Modes.abstract ? 'implements' : 'overrides' + + if !signature.has_rest && signature.arg_count < super_signature.arg_count + raise "Your definition of `#{method_name}` must accept at least #{super_signature.arg_count} " \ + "positional arguments to be compatible with the method it #{mode_verb}: " \ + "#{base_override_loc_str(signature, super_signature)}" + end + + if !signature.has_rest && super_signature.has_rest + raise "Your definition of `#{method_name}` must have `*#{super_signature.rest_name}` " \ + "to be compatible with the method it #{mode_verb}: " \ + "#{base_override_loc_str(signature, super_signature)}" + end + + if signature.req_arg_count > super_signature.req_arg_count + raise "Your definition of `#{method_name}` must have no more than #{super_signature.req_arg_count} " \ + "required argument(s) to be compatible with the method it #{mode_verb}: " \ + "#{base_override_loc_str(signature, super_signature)}" + end + + if !signature.has_keyrest + # O(nm), but n and m are tiny here + missing_kwargs = super_signature.kwarg_names - signature.kwarg_names + if !missing_kwargs.empty? + raise "Your definition of `#{method_name}` is missing these keyword arg(s): #{missing_kwargs} " \ + "which are defined in the method it #{mode_verb}: " \ + "#{base_override_loc_str(signature, super_signature)}" + end + end + + if !signature.has_keyrest && super_signature.has_keyrest + raise "Your definition of `#{method_name}` must have `**#{super_signature.keyrest_name}` " \ + "to be compatible with the method it #{mode_verb}: " \ + "#{base_override_loc_str(signature, super_signature)}" + end + + # O(nm), but n and m are tiny here + extra_req_kwargs = signature.req_kwarg_names - super_signature.req_kwarg_names + if !extra_req_kwargs.empty? + raise "Your definition of `#{method_name}` has extra required keyword arg(s) " \ + "#{extra_req_kwargs} relative to the method it #{mode_verb}, making it incompatible: " \ + "#{base_override_loc_str(signature, super_signature)}" + end + + if super_signature.block_name && !signature.block_name + raise "Your definition of `#{method_name}` must accept a block parameter to be compatible " \ + "with the method it #{mode_verb}: " \ + "#{base_override_loc_str(signature, super_signature)}" + end + end + + def self.validate_override_types(signature, super_signature) + return if signature.override_allow_incompatible + return if super_signature.mode == Modes.untyped + return unless [signature, super_signature].all? do |sig| + sig.check_level == :always || sig.check_level == :compiled || (sig.check_level == :tests && T::Private::RuntimeLevels.check_tests?) + end + mode_noun = super_signature.mode == Modes.abstract ? 'implementation' : 'override' + + # arg types must be contravariant + super_signature.arg_types.zip(signature.arg_types).each_with_index do |((_super_name, super_type), (name, type)), index| + if !super_type.subtype_of?(type) + raise "Incompatible type for arg ##{index + 1} (`#{name}`) in signature for #{mode_noun} of method " \ + "`#{signature.method_name}`:\n" \ + "* Base: `#{super_type}` (in #{method_loc_str(super_signature.method)})\n" \ + "* #{mode_noun.capitalize}: `#{type}` (in #{method_loc_str(signature.method)})\n" \ + "(The types must be contravariant.)" + end + end + + # kwarg types must be contravariant + super_signature.kwarg_types.each do |name, super_type| + type = signature.kwarg_types[name] + if !super_type.subtype_of?(type) + raise "Incompatible type for arg `#{name}` in signature for #{mode_noun} of method `#{signature.method_name}`:\n" \ + "* Base: `#{super_type}` (in #{method_loc_str(super_signature.method)})\n" \ + "* #{mode_noun.capitalize}: `#{type}` (in #{method_loc_str(signature.method)})\n" \ + "(The types must be contravariant.)" + end + end + + # return types must be covariant + if !signature.return_type.subtype_of?(super_signature.return_type) + raise "Incompatible return type in signature for #{mode_noun} of method `#{signature.method_name}`:\n" \ + "* Base: `#{super_signature.return_type}` (in #{method_loc_str(super_signature.method)})\n" \ + "* #{mode_noun.capitalize}: `#{signature.return_type}` (in #{method_loc_str(signature.method)})\n" \ + "(The types must be covariant.)" + end + end + + private_class_method def self.base_override_loc_str(signature, super_signature) + mode_noun = super_signature.mode == Modes.abstract ? 'Implementation' : 'Override' + "\n * Base definition: in #{method_loc_str(super_signature.method)}" \ + "\n * #{mode_noun}: in #{method_loc_str(signature.method)}" + end + + private_class_method def self.method_loc_str(method) + loc = if method.source_location + method.source_location.join(':') + else + "" + end + "#{method.owner} at #{loc}" + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/mixins/mixins.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/mixins/mixins.rb new file mode 100644 index 0000000000..01eb42bd3a --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/mixins/mixins.rb @@ -0,0 +1,27 @@ +# frozen_string_literal: true +# typed: true + +module T::Private + module MixesInClassMethods + def included(other) + mods = Abstract::Data.get(self, :class_methods_mixins) + mods.each {|mod| other.extend(mod)} + super + end + end + + module Mixins + def self.declare_mixes_in_class_methods(mixin, class_methods) + if mixin.is_a?(Class) + raise "Classes cannot be used as mixins, and so mixes_in_class_methods cannot be used on a Class." + end + + if Abstract::Data.key?(mixin, :class_methods_mixins) + class_methods = Abstract::Data.get(mixin, :class_methods_mixins) + class_methods + end + + mixin.singleton_class.include(MixesInClassMethods) + Abstract::Data.set(mixin, :class_methods_mixins, class_methods) + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/retry.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/retry.rb new file mode 100644 index 0000000000..7b2822d394 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/retry.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: true +# typed: true + +module T::Private::Retry + + # A special singleton used for static analysis of exceptions. + module RETRY + freeze + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/runtime_levels.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/runtime_levels.rb new file mode 100644 index 0000000000..2454b21988 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/runtime_levels.rb @@ -0,0 +1,62 @@ +# frozen_string_literal: true +# typed: true + +# Used in `sig.checked(level)` to determine when runtime type checking +# is enabled on a method. +module T::Private::RuntimeLevels + LEVELS = [ + # Validate every call in every environment + :always, + # Validate in tests, but not in production + :tests, + # Don't even validate in tests, b/c too expensive, + # or b/c we fully trust the static typing + :never, + # Validate the sig when the file is using the Sorbet Compiler. + # Behaves like :never when interpreted. + :compiled, + ].freeze + + @check_tests = false + @wrapped_tests_with_validation = false + + @has_read_default_checked_level = false + @default_checked_level = :always + + def self.check_tests? + # Assume that this code path means that some `sig.checked(:tests)` + # has been wrapped (or not wrapped) already, which is a trapdoor + # for toggling `@check_tests`. + @wrapped_tests_with_validation = true + + @check_tests + end + + def self.enable_checking_in_tests + if !@check_tests && @wrapped_tests_with_validation + all_checked_tests_sigs = T::Private::Methods.all_checked_tests_sigs + locations = all_checked_tests_sigs.map {|sig| sig.method.source_location.join(':')}.join("\n- ") + raise "Toggle `:tests`-level runtime type checking earlier. " \ + "There are already some methods wrapped with `sig.checked(:tests)`:\n" \ + "- #{locations}" + end + + _toggle_checking_tests(true) + end + + def self.default_checked_level + @has_read_default_checked_level = true + @default_checked_level + end + + def self.default_checked_level=(default_checked_level) + if @has_read_default_checked_level + raise "Set the default checked level earlier. There are already some methods whose sig blocks have evaluated which would not be affected by the new default." + end + @default_checked_level = default_checked_level + end + + def self._toggle_checking_tests(checked) + @check_tests = checked + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/sealed.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/sealed.rb new file mode 100644 index 0000000000..62e19fb088 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/sealed.rb @@ -0,0 +1,91 @@ +# frozen_string_literal: true +# typed: false + +module T::Private::Sealed + module NoInherit + def inherited(child) + super + this_line = Kernel.caller.find {|line| !line.match(/in `inherited'$/)} + T::Private::Sealed.validate_inheritance(this_line, self, child, 'inherited') + @sorbet_sealed_module_all_subclasses << child + end + + def sealed_subclasses + @sorbet_sealed_module_all_subclasses_set ||= # rubocop:disable Naming/MemoizedInstanceVariableName + begin + require 'set' + Set.new(@sorbet_sealed_module_all_subclasses).freeze + end + end + end + + module NoIncludeExtend + def included(child) + super + this_line = Kernel.caller.find {|line| !line.match(/in `included'$/)} + T::Private::Sealed.validate_inheritance(this_line, self, child, 'included') + @sorbet_sealed_module_all_subclasses << child + end + + def extended(child) + super + this_line = Kernel.caller.find {|line| !line.match(/in `extended'$/)} + T::Private::Sealed.validate_inheritance(this_line, self, child, 'extended') + @sorbet_sealed_module_all_subclasses << child + end + + def sealed_subclasses + # this will freeze the set so that you can never get into a + # state where you use the subclasses list and then something + # else will add to it + @sorbet_sealed_module_all_subclasses_set ||= # rubocop:disable Naming/MemoizedInstanceVariableName + begin + require 'set' + Set.new(@sorbet_sealed_module_all_subclasses).freeze + end + end + end + + def self.declare(mod, decl_file) + if !mod.is_a?(Module) + raise "#{mod} is not a class or module and cannot be declared `sealed!`" + end + if sealed_module?(mod) + raise "#{mod} was already declared `sealed!` and cannot be re-declared `sealed!`" + end + if T::Private::Final.final_module?(mod) + raise "#{mod} was already declared `final!` and cannot be declared `sealed!`" + end + mod.extend(mod.is_a?(Class) ? NoInherit : NoIncludeExtend) + if !decl_file + raise "Couldn't determine declaration file for sealed class." + end + mod.instance_variable_set(:@sorbet_sealed_module_decl_file, decl_file) + mod.instance_variable_set(:@sorbet_sealed_module_all_subclasses, []) + end + + def self.sealed_module?(mod) + mod.instance_variable_defined?(:@sorbet_sealed_module_decl_file) + end + + def self.validate_inheritance(this_line, parent, child, verb) + this_file = this_line&.split(':')&.first + decl_file = parent.instance_variable_get(:@sorbet_sealed_module_decl_file) if sealed_module?(parent) + + if !this_file + raise "Could not use backtrace to determine file for #{verb} child #{child}" + end + if !decl_file + raise "#{parent} does not seem to be a sealed module (#{verb} by #{child})" + end + + if !this_file.start_with?(decl_file) + whitelist = T::Configuration.sealed_violation_whitelist + if !whitelist.nil? && whitelist.any? {|pattern| this_file =~ pattern} + return + end + + raise "#{parent} was declared sealed and can only be #{verb} in #{decl_file}, not #{this_file}" + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/types/not_typed.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/types/not_typed.rb new file mode 100644 index 0000000000..57196553b6 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/types/not_typed.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true +# typed: true + +# A placeholder for when an untyped thing must provide a type. +# Raises an exception if it is ever used for validation. +class T::Private::Types::NotTyped < T::Types::Base + ERROR_MESSAGE = "Validation is being done on a `NotTyped`. Please report this bug at https://github.com/sorbet/sorbet/issues" + + # overrides Base + def name + "" + end + + # overrides Base + def valid?(obj) + raise ERROR_MESSAGE + end + + # overrides Base + private def subtype_of_single?(other) + raise ERROR_MESSAGE + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/types/string_holder.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/types/string_holder.rb new file mode 100644 index 0000000000..b2295f7730 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/types/string_holder.rb @@ -0,0 +1,26 @@ +# frozen_string_literal: true +# typed: true + +# Holds a string. Useful for showing type aliases in error messages +class T::Private::Types::StringHolder < T::Types::Base + attr_reader :string + + def initialize(string) + @string = string + end + + # overrides Base + def name + string + end + + # overrides Base + def valid?(obj) + false + end + + # overrides Base + private def subtype_of_single?(other) + false + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/types/type_alias.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/types/type_alias.rb new file mode 100644 index 0000000000..de805c9659 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/types/type_alias.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true +# typed: true + +module T::Private::Types + # Wraps a proc for a type alias to defer its evaluation. + class TypeAlias < T::Types::Base + + def initialize(callable) + @callable = callable + end + + def aliased_type + @aliased_type ||= T::Utils.coerce(@callable.call) + end + + # overrides Base + def name + aliased_type.name + end + + # overrides Base + def recursively_valid?(obj) + aliased_type.recursively_valid?(obj) + end + + # overrides Base + def valid?(obj) + aliased_type.valid?(obj) + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/types/void.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/types/void.rb new file mode 100644 index 0000000000..310fc56abc --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/private/types/void.rb @@ -0,0 +1,34 @@ +# frozen_string_literal: true +# typed: true + +# A marking class for when methods return void. +# Should never appear in types directly. +class T::Private::Types::Void < T::Types::Base + ERROR_MESSAGE = "Validation is being done on an `Void`. Please report this bug at https://github.com/sorbet/sorbet/issues" + + # The actual return value of `.void` methods. + # + # Uses `module VOID` because this gives it a readable name when someone + # examines it in Pry or with `#inspect` like: + # + # T::Private::Types::Void::VOID + # + module VOID + freeze + end + + # overrides Base + def name + "" + end + + # overrides Base + def valid?(obj) + raise ERROR_MESSAGE + end + + # overrides Base + private def subtype_of_single?(other) + raise ERROR_MESSAGE + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/props/_props.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/props/_props.rb new file mode 100644 index 0000000000..fae252aa04 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/props/_props.rb @@ -0,0 +1,169 @@ +# frozen_string_literal: true +# typed: true + +# A mixin for defining typed properties (attributes). +# To get serialization methods (to/from JSON-style hashes), add T::Props::Serializable. +# To get a constructor based on these properties, inherit from T::Struct. +module T::Props + extend T::Helpers + + ##### + # CAUTION: This mixin is used in hundreds of classes; we want to keep its surface area as narrow + # as possible and avoid polluting (and possibly conflicting with) the classes that use it. + # + # It currently has *zero* instance methods; let's try to keep it that way. + # For ClassMethods (below), try to add things to T::Props::Decorator instead unless you are sure + # it needs to be exposed here. + ##### + + module ClassMethods + extend T::Sig + extend T::Helpers + + def props + decorator.props + end + def plugins + @plugins ||= [] + end + + def decorator_class + Decorator + end + + def decorator + @decorator ||= decorator_class.new(self) + end + def reload_decorator! + @decorator = decorator_class.new(self) + end + + # Define a new property. See {file:README.md} for some concrete + # examples. + # + # Defining a property defines a method with the same name as the + # property, that returns the current value, and a `prop=` method + # to set its value. Properties will be inherited by subclasses of + # a document class. + # + # @param name [Symbol] The name of this property + # @param cls [Class,T::Types::Base] The type of this + # property. If the type is itself a `Document` subclass, this + # property will be recursively serialized/deserialized. + # @param rules [Hash] Options to control this property's behavior. + # @option rules [T::Boolean,Symbol] :optional If `true`, this property + # is never required to be set before an instance is serialized. + # If `:on_load` (default), when this property is missing or nil, a + # new model cannot be saved, and an existing model can only be + # saved if the property was already missing when it was loaded. + # If `false`, when the property is missing/nil after deserialization, it + # will be set to the default value (as defined by the `default` or + # `factory` option) or will raise if they are not present. + # Deprecated: For `Model`s, if `:optional` is set to the special value + # `:existing`, the property can be saved as nil even if it was + # deserialized with a non-nil value. (Deprecated because there should + # never be a need for this behavior; the new behavior of non-optional + # properties should be sufficient.) + # @option rules [Array] :enum An array of legal values; The + # property is required to take on one of those values. + # @option rules [T::Boolean] :dont_store If true, this property will + # not be saved on the hash resulting from + # {T::Props::Serializable#serialize} + # @option rules [Object] :ifunset A value to be returned if this + # property is requested but has never been set (is set to + # `nil`). It is applied at property-access time, and never saved + # back onto the object or into the database. + # + # ``:ifunset`` is considered **DEPRECATED** and should not be used + # in new code, in favor of just setting a default value. + # @option rules [Model, Symbol, Proc] :foreign A model class that this + # property is a reference to. Passing `:foreign` will define a + # `:"#{name}_"` method, that will load and return the + # corresponding foreign model. + # + # A symbol can be passed to avoid load-order dependencies; It + # will be lazily resolved relative to the enclosing module of the + # defining class. + # + # A callable (proc or method) can be passed to dynamically specify the + # foreign model. This will be passed the object instance so that other + # properties of the object can be used to determine the relevant model + # class. It should return a string/symbol class name or the foreign model + # class directly. + # + # @option rules [Object] :default A default value that will be set + # by `#initialize` if none is provided in the initialization + # hash. This will not affect objects loaded by {.from_hash}. + # @option rules [Proc] :factory A `Proc` that will be called to + # generate an initial value for this prop on `#initialize`, if + # none is provided. + # @option rules [T::Boolean] :immutable If true, this prop cannot be + # modified after an instance is created or loaded from a hash. + # @option rules [T::Boolean] :override It is an error to redeclare a + # `prop` that has already been declared (including on a + # superclass), unless `:override` is set to `true`. + # @option rules [Symbol, Array] :redaction A redaction directive that may + # be passed to Chalk::Tools::RedactionUtils.redact_with_directive to + # sanitize this parameter for display. Will define a + # `:"#{name}_redacted"` method, which will return the value in sanitized + # form. + # + # @return [void] + sig {params(name: Symbol, cls: T.untyped, rules: T.untyped).void} + def prop(name, cls, rules={}) + cls = T::Utils.coerce(cls) if !cls.is_a?(Module) + decorator.prop_defined(name, cls, rules) + end + + # Validates the value of the specified prop. This method allows the caller to + # validate a value for a prop without having to set the data on the instance. + # Throws if invalid. + # + # @param prop [Symbol] + # @param val [Object] + # @return [void] + def validate_prop_value(prop, val) + decorator.validate_prop_value(prop, val) + end + + # Needs to be documented + def plugin(mod) + decorator.plugin(mod) + end + + # Shorthand helper to define a `prop` with `immutable => true` + sig {params(name: Symbol, cls_or_args: T.untyped, args: T::Hash[Symbol, T.untyped]).void} + def const(name, cls_or_args, args={}) + if (cls_or_args.is_a?(Hash) && cls_or_args.key?(:immutable)) || args.key?(:immutable) + Kernel.raise ArgumentError.new("Cannot pass 'immutable' argument when using 'const' keyword to define a prop") + end + + if cls_or_args.is_a?(Hash) + self.prop(name, cls_or_args.merge(immutable: true)) + else + self.prop(name, cls_or_args, args.merge(immutable: true)) + end + end + + def included(child) + decorator.model_inherited(child) + super + end + + def prepended(child) + decorator.model_inherited(child) + super + end + + def extended(child) + decorator.model_inherited(child.singleton_class) + super + end + + def inherited(child) + decorator.model_inherited(child) + super + end + end + mixes_in_class_methods(ClassMethods) +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/props/constructor.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/props/constructor.rb new file mode 100644 index 0000000000..570c068ac4 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/props/constructor.rb @@ -0,0 +1,40 @@ +# frozen_string_literal: true +# typed: false + +module T::Props::Constructor + include T::Props::WeakConstructor +end + +module T::Props::Constructor::DecoratorMethods + extend T::Sig + + # Set values for all props that have no defaults. Override what `WeakConstructor` + # does in order to raise errors on nils instead of ignoring them. + # + # @return [Integer] A count of props that we successfully initialized (which + # we'll use to check for any unrecognized input.) + # + # checked(:never) - O(runtime object construction) + sig {params(instance: T::Props::Constructor, hash: T::Hash[Symbol, T.untyped]).returns(Integer).checked(:never)} + def construct_props_without_defaults(instance, hash) + # Use `each_pair` rather than `count` because, as of Ruby 2.6, the latter delegates to Enumerator + # and therefore allocates for each entry. + result = 0 + props_without_defaults&.each_pair do |p, setter_proc| + begin + val = hash[p] + instance.instance_exec(val, &setter_proc) + if val || hash.key?(p) + result += 1 + end + rescue TypeError, T::Props::InvalidValueError + if !hash.key?(p) + raise ArgumentError.new("Missing required prop `#{p}` for class `#{instance.class.name}`") + else + raise + end + end + end + result + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/props/custom_type.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/props/custom_type.rb new file mode 100644 index 0000000000..0df6a0d863 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/props/custom_type.rb @@ -0,0 +1,108 @@ +# frozen_string_literal: true +# typed: strict + +module T::Props + module CustomType + extend T::Sig + extend T::Helpers + + abstract! + + include Kernel # for `is_a?` + + # Alias for backwards compatibility + sig(:final) do + params( + value: BasicObject, + ) + .returns(T::Boolean) + .checked(:never) + end + def instance?(value) + self.===(value) + end + + # Alias for backwards compatibility + sig(:final) do + params( + value: BasicObject, + ) + .returns(T::Boolean) + .checked(:never) + end + def valid?(value) + instance?(value) + end + + # Given an instance of this type, serialize that into a scalar type + # supported by T::Props. + # + # @param [Object] instance + # @return An instance of one of T::Configuration.scalar_types + sig {abstract.params(instance: T.untyped).returns(T.untyped).checked(:never)} + def serialize(instance); end + + # Given the serialized form of your type, this returns an instance + # of that custom type representing that value. + # + # @param scalar One of T::Configuration.scalar_types + # @return Object + sig {abstract.params(scalar: T.untyped).returns(T.untyped).checked(:never)} + def deserialize(scalar); end + + sig {override.params(_base: Module).void} + def self.included(_base) + super + + raise 'Please use "extend", not "include" to attach this module' + end + + sig(:final) {params(val: Object).returns(T::Boolean).checked(:never)} + def self.scalar_type?(val) + # We don't need to check for val's included modules in + # T::Configuration.scalar_types, because T::Configuration.scalar_types + # are all classes. + klass = T.let(val.class, T.nilable(Class)) + until klass.nil? + return true if T::Configuration.scalar_types.include?(klass.to_s) + klass = klass.superclass + end + false + end + + # We allow custom types to serialize to Arrays, so that we can + # implement set-like fields that store a unique-array, but forbid + # hashes; Custom hash types should be implemented via an emebdded + # T::Struct (or a subclass like Chalk::ODM::Document) or via T. + sig(:final) {params(val: Object).returns(T::Boolean).checked(:never)} + def self.valid_serialization?(val) + case val + when Array + val.each do |v| + return false unless scalar_type?(v) + end + + true + else + scalar_type?(val) + end + end + + sig(:final) do + params(instance: Object) + .returns(T.untyped) + .checked(:never) + end + def self.checked_serialize(instance) + val = T.cast(instance.class, T::Props::CustomType).serialize(instance) + unless valid_serialization?(val) + msg = "#{instance.class} did not serialize to a valid scalar type. It became a: #{val.class}" + if val.is_a?(Hash) + msg += "\nIf you want to store a structured Hash, consider using a T::Struct as your type." + end + raise TypeError.new(msg) + end + val + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/props/decorator.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/props/decorator.rb new file mode 100644 index 0000000000..8013495fd8 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/props/decorator.rb @@ -0,0 +1,671 @@ +# frozen_string_literal: true +# typed: strict + +# NB: This is not actually a decorator. It's just named that way for consistency +# with DocumentDecorator and ModelDecorator (which both seem to have been written +# with an incorrect understanding of the decorator pattern). These "decorators" +# should really just be static methods on private modules (we'd also want/need to +# replace decorator overrides in plugins with class methods that expose the necessary +# functionality). +class T::Props::Decorator + extend T::Sig + + Rules = T.type_alias {T::Hash[Symbol, T.untyped]} + DecoratedInstance = T.type_alias {Object} # Would be T::Props, but that produces circular reference errors in some circumstances + PropType = T.type_alias {T::Types::Base} + PropTypeOrClass = T.type_alias {T.any(PropType, Module)} + + class NoRulesError < StandardError; end + + EMPTY_PROPS = T.let({}.freeze, T::Hash[Symbol, Rules]) + private_constant :EMPTY_PROPS + + sig {params(klass: T.untyped).void.checked(:never)} + def initialize(klass) + @class = T.let(klass, T.all(Module, T::Props::ClassMethods)) + @class.plugins.each do |mod| + T::Props::Plugin::Private.apply_decorator_methods(mod, self) + end + @props = T.let(EMPTY_PROPS, T::Hash[Symbol, Rules]) + end + + # checked(:never) - O(prop accesses) + sig {returns(T::Hash[Symbol, Rules]).checked(:never)} + attr_reader :props + + sig {returns(T::Array[Symbol])} + def all_props + props.keys + end + + # checked(:never) - O(prop accesses) + sig {params(prop: T.any(Symbol, String)).returns(Rules).checked(:never)} + def prop_rules(prop) + props[prop.to_sym] || raise("No such prop: #{prop.inspect}") + end + + # checked(:never) - Rules hash is expensive to check + sig {params(prop: Symbol, rules: Rules).void.checked(:never)} + def add_prop_definition(prop, rules) + override = rules.delete(:override) + + if props.include?(prop) && !override + raise ArgumentError.new("Attempted to redefine prop #{prop.inspect} that's already defined without specifying :override => true: #{prop_rules(prop)}") + elsif !props.include?(prop) && override + raise ArgumentError.new("Attempted to override a prop #{prop.inspect} that doesn't already exist") + end + + @props = @props.merge(prop => rules.freeze).freeze + end + + # Heads up! + # + # There are already too many ad-hoc options on the prop DSL. + # + # We have already done a lot of work to remove unnecessary and confusing + # options. If you're considering adding a new rule key, please come chat with + # the Sorbet team first, as we'd really like to learn more about how to best + # solve the problem you're encountering. + VALID_RULE_KEYS = T.let(%i[ + enum + foreign + ifunset + immutable + override + redaction + sensitivity + without_accessors + clobber_existing_method! + extra + setter_validate + _tnilable + ].map {|k| [k, true]}.to_h.freeze, T::Hash[Symbol, T::Boolean]) + private_constant :VALID_RULE_KEYS + + sig {params(key: Symbol).returns(T::Boolean).checked(:never)} + def valid_rule_key?(key) + !!VALID_RULE_KEYS[key] + end + + # checked(:never) - O(prop accesses) + sig {returns(T.all(Module, T::Props::ClassMethods)).checked(:never)} + def decorated_class + @class + end + + # Accessors + + # Use this to validate that a value will validate for a given prop. Useful for knowing whether a value can be set on a model without setting it. + # + # checked(:never) - potentially O(prop accesses) depending on usage pattern + sig {params(prop: Symbol, val: T.untyped).void.checked(:never)} + def validate_prop_value(prop, val) + # We call `setter_proc` here without binding to an instance, so it'll run + # `instance_variable_set` if validation passes, but nothing will care. + # We only care about the validation. + prop_rules(prop).fetch(:setter_proc).call(val) + end + + # For performance, don't use named params here. + # Passing in rules here is purely a performance optimization. + # Unlike the other methods that take rules, this one calls prop_rules for + # the default, which raises if the prop doesn't exist (this maintains + # preexisting behavior). + # + # Note this path is NOT used by generated setters on instances, + # which are defined using `setter_proc` directly. + # + # checked(:never) - O(prop accesses) + sig do + params( + instance: DecoratedInstance, + prop: Symbol, + val: T.untyped, + rules: Rules + ) + .void + .checked(:never) + end + def prop_set(instance, prop, val, rules=prop_rules(prop)) + instance.instance_exec(val, &rules.fetch(:setter_proc)) + end + alias_method :set, :prop_set + + # Only Models have any custom get logic but we need to call this on + # non-Models since we don't know at code gen time what we have. + sig do + params( + instance: DecoratedInstance, + prop: Symbol, + value: T.untyped + ) + .returns(T.untyped) + .checked(:never) + end + def prop_get_logic(instance, prop, value) + value + end + + # For performance, don't use named params here. + # Passing in rules here is purely a performance optimization. + # + # Note this path is NOT used by generated getters on instances, + # unless `ifunset` is used on the prop, or `prop_get` is overridden. + # + # checked(:never) - O(prop accesses) + sig do + params( + instance: DecoratedInstance, + prop: T.any(String, Symbol), + rules: Rules + ) + .returns(T.untyped) + .checked(:never) + end + def prop_get(instance, prop, rules=prop_rules(prop)) + val = instance.instance_variable_get(rules[:accessor_key]) if instance.instance_variable_defined?(rules[:accessor_key]) + if !val.nil? + val + elsif (d = rules[:ifunset]) + T::Props::Utils.deep_clone_object(d) + else + nil + end + end + + sig do + params( + instance: DecoratedInstance, + prop: T.any(String, Symbol), + rules: Rules + ) + .returns(T.untyped) + .checked(:never) + end + def prop_get_if_set(instance, prop, rules=prop_rules(prop)) + instance.instance_variable_get(rules[:accessor_key]) if instance.instance_variable_defined?(rules[:accessor_key]) + end + alias_method :get, :prop_get_if_set # Alias for backwards compatibility + + # checked(:never) - O(prop accesses) + sig do + params( + instance: DecoratedInstance, + prop: Symbol, + foreign_class: Module, + rules: Rules, + opts: T::Hash[Symbol, T.untyped], + ) + .returns(T.untyped) + .checked(:never) + end + def foreign_prop_get(instance, prop, foreign_class, rules=prop_rules(prop), opts={}) + return if !(value = prop_get(instance, prop, rules)) + T.unsafe(foreign_class).load(value, {}, opts) + end + + # TODO: we should really be checking all the methods on `cls`, not just Object + BANNED_METHOD_NAMES = T.let(Object.instance_methods.each_with_object({}) {|x, acc| acc[x] = true}.freeze, T::Hash[Symbol, TrueClass]) + + # checked(:never) - Rules hash is expensive to check + sig do + params( + name: Symbol, + cls: Module, + rules: Rules, + type: PropTypeOrClass + ) + .void + .checked(:never) + end + def prop_validate_definition!(name, cls, rules, type) + validate_prop_name(name) + + if rules.key?(:pii) + raise ArgumentError.new("The 'pii:' option for props has been renamed " \ + "to 'sensitivity:' (in prop #{@class.name}.#{name})") + end + + if rules.keys.any? {|k| !valid_rule_key?(k)} + raise ArgumentError.new("At least one invalid prop arg supplied in #{self}: #{rules.keys.inspect}") + end + + if !rules[:clobber_existing_method!] && !rules[:without_accessors] && BANNED_METHOD_NAMES.include?(name.to_sym) + raise ArgumentError.new( + "#{name} can't be used as a prop in #{@class} because a method with " \ + "that name already exists (defined by #{@class.instance_method(name).owner} " \ + "at #{@class.instance_method(name).source_location || ''}). " \ + "(If using this name is unavoidable, try `without_accessors: true`.)" + ) + end + + extra = rules[:extra] + if !extra.nil? && !extra.is_a?(Hash) + raise ArgumentError.new("Extra metadata must be a Hash in prop #{@class.name}.#{name}") + end + + nil + end + + SAFE_NAME = T.let(/\A[A-Za-z_][A-Za-z0-9_-]*\z/.freeze, Regexp) + + # Used to validate both prop names and serialized forms + sig {params(name: T.any(Symbol, String)).void} + private def validate_prop_name(name) + if !name.match?(SAFE_NAME) + raise ArgumentError.new("Invalid prop name in #{@class.name}: #{name}") + end + end + + # This converts the type from a T::Type to a regular old ruby class. + sig {params(type: T::Types::Base).returns(Module)} + private def convert_type_to_class(type) + case type + when T::Types::TypedArray, T::Types::FixedArray + Array + when T::Types::TypedHash, T::Types::FixedHash + Hash + when T::Types::TypedSet + Set + when T::Types::Union + # The below unwraps our T.nilable types for T::Props if we can. + # This lets us do things like specify: const T.nilable(String), foreign: Opus::DB::Model::Merchant + non_nil_type = T::Utils.unwrap_nilable(type) + if non_nil_type + convert_type_to_class(non_nil_type) + else + Object + end + when T::Types::Simple + type.raw_type + else + # This isn't allowed unless whitelisted_for_underspecification is + # true, due to the check in prop_validate_definition + Object + end + end + + # Returns `true` when the type of the prop is nilable, or the field is typed + # as `T.untyped`, a `:default` is present in the rules hash, and its value is + # `nil`. The latter case is a workaround for explicitly not supporting the use + # of `T.nilable(T.untyped)`. + # + # checked(:never) - Rules hash is expensive to check + sig do + params( + cls: PropTypeOrClass, + rules: Rules, + ) + .void + .checked(:never) + end + private def prop_nilable?(cls, rules) + # NB: `prop` and `const` do not `T::Utils::coerce the type of the prop if it is a `Module`, + # hence the bare `NilClass` check. + T::Utils::Nilable.is_union_with_nilclass(cls) || ((cls == T.untyped || cls == NilClass) && rules.key?(:default) && rules[:default].nil?) + end + + # checked(:never) - Rules hash is expensive to check + sig do + params( + name: T.any(Symbol, String), + cls: PropTypeOrClass, + rules: Rules, + ) + .void + .checked(:never) + end + def prop_defined(name, cls, rules={}) + cls = T::Utils.resolve_alias(cls) + + if prop_nilable?(cls, rules) + # :_tnilable is introduced internally for performance purpose so that clients do not need to call + # T::Utils::Nilable.is_tnilable(cls) again. + # It is strictly internal: clients should always use T::Props::Utils.required_prop?() or + # T::Props::Utils.optional_prop?() for checking whether a field is required or optional. + rules[:_tnilable] = true + end + + name = name.to_sym + type = cls + if !cls.is_a?(Module) + cls = convert_type_to_class(cls) + end + type_object = smart_coerce(type, enum: rules[:enum]) + + prop_validate_definition!(name, cls, rules, type_object) + + # Retrive the possible underlying object with T.nilable. + type = T::Utils::Nilable.get_underlying_type(type) + + sensitivity_and_pii = {sensitivity: rules[:sensitivity]} + normalize = T::Configuration.normalize_sensitivity_and_pii_handler + if normalize + sensitivity_and_pii = normalize.call(sensitivity_and_pii) + + # We check for Class so this is only applied on concrete + # documents/models; We allow mixins containing props to not + # specify their PII nature, as long as every class into which they + # are ultimately included does. + # + if sensitivity_and_pii[:pii] && @class.is_a?(Class) && !T.unsafe(@class).contains_pii? + raise ArgumentError.new( + 'Cannot include a pii prop in a class that declares `contains_no_pii`' + ) + end + end + + rules = rules.merge( + # TODO: The type of this element is confusing. We should refactor so that + # it can be always `type_object` (a PropType) or always `cls` (a Module) + type: type, + type_object: type_object, + accessor_key: "@#{name}".to_sym, + sensitivity: sensitivity_and_pii[:sensitivity], + pii: sensitivity_and_pii[:pii], + # extra arbitrary metadata attached by the code defining this property + extra: rules[:extra]&.freeze, + ) + + validate_not_missing_sensitivity(name, rules) + + # for backcompat (the `:array` key is deprecated but because the name is + # so generic it's really hard to be sure it's not being relied on anymore) + if type.is_a?(T::Types::TypedArray) + inner = T::Utils::Nilable.get_underlying_type(type.type) + if inner.is_a?(Module) + rules[:array] = inner + end + end + + rules[:setter_proc] = T::Props::Private::SetterFactory.build_setter_proc(@class, name, rules).freeze + + add_prop_definition(name, rules) + + # NB: using `without_accessors` doesn't make much sense unless you also define some other way to + # get at the property (e.g., Chalk::ODM::Document exposes `get` and `set`). + define_getter_and_setter(name, rules) unless rules[:without_accessors] + + handle_foreign_option(name, cls, rules, rules[:foreign]) if rules[:foreign] + handle_redaction_option(name, rules[:redaction]) if rules[:redaction] + end + + # checked(:never) - Rules hash is expensive to check + sig {params(name: Symbol, rules: Rules).void.checked(:never)} + private def define_getter_and_setter(name, rules) + T::Configuration.without_ruby_warnings do + if !rules[:immutable] + if method(:prop_set).owner != T::Props::Decorator + @class.send(:define_method, "#{name}=") do |val| + T.unsafe(self.class).decorator.prop_set(self, name, val, rules) + end + else + # Fast path (~4x faster as of Ruby 2.6) + @class.send(:define_method, "#{name}=", &rules.fetch(:setter_proc)) + end + end + + if method(:prop_get).owner != T::Props::Decorator || rules.key?(:ifunset) + @class.send(:define_method, name) do + T.unsafe(self.class).decorator.prop_get(self, name, rules) + end + else + # Fast path (~30x faster as of Ruby 2.6) + @class.send(:attr_reader, name) # send is used because `attr_reader` is private in 2.4 + end + end + end + + sig do + params(type: PropTypeOrClass, enum: T.untyped) + .returns(T::Types::Base) + end + private def smart_coerce(type, enum:) + # Backwards compatibility for pre-T::Types style + type = T::Utils.coerce(type) + if enum.nil? + type + else + nonnil_type = T::Utils.unwrap_nilable(type) + if nonnil_type + T.unsafe(T.nilable(T.all(nonnil_type, T.deprecated_enum(enum)))) + else + T.unsafe(T.all(T.unsafe(type), T.deprecated_enum(enum))) + end + end + end + + # checked(:never) - Rules hash is expensive to check + sig {params(prop_name: Symbol, rules: Rules).void.checked(:never)} + private def validate_not_missing_sensitivity(prop_name, rules) + if rules[:sensitivity].nil? + if rules[:redaction] + T::Configuration.hard_assert_handler( + "#{@class}##{prop_name} has a 'redaction:' annotation but no " \ + "'sensitivity:' annotation. This is probably wrong, because if a " \ + "prop needs redaction then it is probably sensitive. Add a " \ + "sensitivity annotation like 'sensitivity: Opus::Sensitivity::PII." \ + "whatever', or explicitly override this check with 'sensitivity: []'." + ) + end + # TODO(PRIVACYENG-982) Ideally we'd also check for 'password' and possibly + # other terms, but this interacts badly with ProtoDefinedDocument because + # the proto syntax currently can't declare "sensitivity: []" + if /\bsecret\b/.match?(prop_name) + T::Configuration.hard_assert_handler( + "#{@class}##{prop_name} has the word 'secret' in its name, but no " \ + "'sensitivity:' annotation. This is probably wrong, because if a " \ + "prop is named 'secret' then it is probably sensitive. Add a " \ + "sensitivity annotation like 'sensitivity: Opus::Sensitivity::NonPII." \ + "security_token', or explicitly override this check with " \ + "'sensitivity: []'." + ) + end + end + end + + # Create `#{prop_name}_redacted` method + sig do + params( + prop_name: Symbol, + redaction: T.untyped, + ) + .void + end + private def handle_redaction_option(prop_name, redaction) + redacted_method = "#{prop_name}_redacted" + + @class.send(:define_method, redacted_method) do + value = self.public_send(prop_name) + handler = T::Configuration.redaction_handler + if !handler + raise "Using `redaction:` on a prop requires specifying `T::Configuration.redaction_handler`" + end + handler.call(value, redaction) + end + end + + sig do + params( + option_sym: Symbol, + foreign: T.untyped, + valid_type_msg: String, + ) + .void + end + private def validate_foreign_option(option_sym, foreign, valid_type_msg:) + if foreign.is_a?(Symbol) || foreign.is_a?(String) + raise ArgumentError.new( + "Using a symbol/string for `#{option_sym}` is no longer supported. Instead, use a Proc " \ + "that returns the class, e.g., foreign: -> {Foo}" + ) + end + + if !foreign.is_a?(Proc) && !foreign.is_a?(Array) && !foreign.respond_to?(:load) + raise ArgumentError.new("The `#{option_sym}` option must be #{valid_type_msg}") + end + end + + # checked(:never) - Rules hash is expensive to check + sig do + params( + prop_name: T.any(String, Symbol), + rules: Rules, + foreign: T.untyped, + ) + .void + .checked(:never) + end + private def define_foreign_method(prop_name, rules, foreign) + fk_method = "#{prop_name}_" + + # n.b. there's no clear reason *not* to allow additional options + # here, but we're baking in `allow_direct_mutation` since we + # *haven't* allowed additional options in the past and want to + # default to keeping this interface narrow. + @class.send(:define_method, fk_method) do |allow_direct_mutation: nil| + foreign = T.let(foreign, T.untyped) + if foreign.is_a?(Proc) + resolved_foreign = foreign.call + if !resolved_foreign.respond_to?(:load) + raise ArgumentError.new( + "The `foreign` proc for `#{prop_name}` must return a model class. " \ + "Got `#{resolved_foreign.inspect}` instead." + ) + end + # `foreign` is part of the closure state, so this will persist to future invocations + # of the method, optimizing it so this only runs on the first invocation. + foreign = resolved_foreign + end + opts = if allow_direct_mutation.nil? + {} + else + {allow_direct_mutation: allow_direct_mutation} + end + + T.unsafe(self.class).decorator.foreign_prop_get(self, prop_name, foreign, rules, opts) + end + + force_fk_method = "#{fk_method}!" + @class.send(:define_method, force_fk_method) do |allow_direct_mutation: nil| + loaded_foreign = send(fk_method, allow_direct_mutation: allow_direct_mutation) + if !loaded_foreign + T::Configuration.hard_assert_handler( + 'Failed to load foreign model', + storytime: {method: force_fk_method, class: self.class} + ) + end + loaded_foreign + end + end + + # checked(:never) - Rules hash is expensive to check + sig do + params( + prop_name: Symbol, + prop_cls: Module, + rules: Rules, + foreign: T.untyped, + ) + .void + .checked(:never) + end + private def handle_foreign_option(prop_name, prop_cls, rules, foreign) + validate_foreign_option( + :foreign, foreign, valid_type_msg: "a model class or a Proc that returns one" + ) + + if prop_cls != String + raise ArgumentError.new("`foreign` can only be used with a prop type of String") + end + + if foreign.is_a?(Array) + # We don't support arrays with `foreign` because it's hard to both preserve ordering and + # keep them from being lurky performance hits by issuing a bunch of un-batched DB queries. + # We could potentially address that by porting over something like AmbiguousIDLoader. + raise ArgumentError.new( + "Using an array for `foreign` is no longer supported. Instead, please use a union type of " \ + "token types for the prop type, e.g., T.any(Opus::Autogen::Tokens::FooModelToken, Opus::Autogen::Tokens::BarModelToken)" + ) + end + + unless foreign.is_a?(Proc) + T::Configuration.soft_assert_handler(<<~MESSAGE, storytime: {prop: prop_name, value: foreign}, notify: 'jerry') + Please use a Proc that returns a model class instead of the model class itself as the argument to `foreign`. In other words: + + instead of `prop :foo, String, foreign: FooModel` + use `prop :foo, String, foreign: -> {FooModel}` + + MESSAGE + end + + define_foreign_method(prop_name, rules, foreign) + end + + # TODO: rename this to props_inherited + # + # This gets called when a module or class that extends T::Props gets included, extended, + # prepended, or inherited. + sig {params(child: Module).void.checked(:never)} + def model_inherited(child) + child.extend(T::Props::ClassMethods) + child = T.cast(child, T.all(Module, T::Props::ClassMethods)) + + child.plugins.concat(decorated_class.plugins) + decorated_class.plugins.each do |mod| + # NB: apply_class_methods must not be an instance method on the decorator itself, + # otherwise we'd have to call child.decorator here, which would create the decorator + # before any `decorator_class` override has a chance to take effect (see the comment below). + T::Props::Plugin::Private.apply_class_methods(mod, child) + end + + props.each do |name, rules| + copied_rules = rules.dup + # NB: Calling `child.decorator` here is a timb bomb that's going to give someone a really bad + # time. Any class that defines props and also overrides the `decorator_class` method is going + # to reach this line before its override take effect, turning it into a no-op. + child.decorator.add_prop_definition(name, copied_rules) + + # It's a bit tricky to support `prop_get` hooks added by plugins without + # sacrificing the `attr_reader` fast path or clobbering customized getters + # defined manually on a child. + # + # To make this work, we _do_ clobber getters defined on the child, but only if: + # (a) it's needed in order to support a `prop_get` hook, and + # (b) it's safe because the getter was defined by this file. + # + unless rules[:without_accessors] + if clobber_getter?(child, name) + child.send(:define_method, name) do + T.unsafe(self.class).decorator.prop_get(self, name, rules) + end + end + + if !rules[:immutable] && clobber_setter?(child, name) + child.send(:define_method, "#{name}=") do |val| + T.unsafe(self.class).decorator.prop_set(self, name, val, rules) + end + end + end + end + end + + sig {params(child: T.all(Module, T::Props::ClassMethods), prop: Symbol).returns(T::Boolean).checked(:never)} + private def clobber_getter?(child, prop) + !!(child.decorator.method(:prop_get).owner != method(:prop_get).owner && + child.instance_method(prop).source_location&.first == __FILE__) + end + + sig {params(child: T.all(Module, T::Props::ClassMethods), prop: Symbol).returns(T::Boolean).checked(:never)} + private def clobber_setter?(child, prop) + !!(child.decorator.method(:prop_set).owner != method(:prop_set).owner && + child.instance_method("#{prop}=").source_location&.first == __FILE__) + end + + sig {params(mod: Module).void.checked(:never)} + def plugin(mod) + decorated_class.plugins << mod + T::Props::Plugin::Private.apply_class_methods(mod, decorated_class) + T::Props::Plugin::Private.apply_decorator_methods(mod, self) + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/props/errors.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/props/errors.rb new file mode 100644 index 0000000000..6977f20471 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/props/errors.rb @@ -0,0 +1,8 @@ +# frozen_string_literal: true +# typed: strict + +module T::Props + class Error < StandardError; end + class InvalidValueError < Error; end + class ImmutableProp < Error; end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/props/generated_code_validation.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/props/generated_code_validation.rb new file mode 100644 index 0000000000..91f256799d --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/props/generated_code_validation.rb @@ -0,0 +1,277 @@ +# frozen_string_literal: true +# typed: true + +module T::Props + # Helper to validate generated code, to mitigate security concerns around + # `class_eval`. Not called by default; the expectation is this will be used + # in a test iterating over all T::Props::Serializable subclasses. + # + # We validate the exact expected structure of the generated methods as far + # as we can, and then where cloning produces an arbitrarily nested structure, + # we just validate a lack of side effects. + module GeneratedCodeValidation + extend Private::Parse + + class ValidationError < RuntimeError; end + + def self.validate_deserialize(source) + parsed = parse(source) + + # def %(hash) + # ... + # end + assert_equal(:def, parsed.type) + name, args, body = parsed.children + assert_equal(:__t_props_generated_deserialize, name) + assert_equal(s(:args, s(:arg, :hash)), args) + + assert_equal(:begin, body.type) + init, *prop_clauses, ret = body.children + + # found = % + # ... + # found + assert_equal(:lvasgn, init.type) + init_name, init_val = init.children + assert_equal(:found, init_name) + assert_equal(:int, init_val.type) + assert_equal(s(:lvar, :found), ret) + + prop_clauses.each_with_index do |clause, i| + if i.even? + validate_deserialize_hash_read(clause) + else + validate_deserialize_ivar_set(clause) + end + end + end + + def self.validate_serialize(source) + parsed = parse(source) + + # def %(strict) + # ... + # end + assert_equal(:def, parsed.type) + name, args, body = parsed.children + assert_equal(:__t_props_generated_serialize, name) + assert_equal(s(:args, s(:arg, :strict)), args) + + assert_equal(:begin, body.type) + init, *prop_clauses, ret = body.children + + # h = {} + # ... + # h + assert_equal(s(:lvasgn, :h, s(:hash)), init) + assert_equal(s(:lvar, :h), ret) + + prop_clauses.each do |clause| + validate_serialize_clause(clause) + end + end + + private_class_method def self.validate_serialize_clause(clause) + assert_equal(:if, clause.type) + condition, if_body, else_body = clause.children + + # if @%.nil? + assert_equal(:send, condition.type) + receiver, method = condition.children + assert_equal(:ivar, receiver.type) + assert_equal(:nil?, method) + + unless if_body.nil? + # required_prop_missing_from_serialize(%) if strict + assert_equal(:if, if_body.type) + if_strict_condition, if_strict_body, if_strict_else = if_body.children + assert_equal(s(:lvar, :strict), if_strict_condition) + assert_equal(:send, if_strict_body.type) + on_strict_receiver, on_strict_method, on_strict_arg = if_strict_body.children + assert_equal(nil, on_strict_receiver) + assert_equal(:required_prop_missing_from_serialize, on_strict_method) + assert_equal(:sym, on_strict_arg.type) + assert_equal(nil, if_strict_else) + end + + # h[%] = ... + assert_equal(:send, else_body.type) + receiver, method, h_key, h_val = else_body.children + assert_equal(s(:lvar, :h), receiver) + assert_equal(:[]=, method) + assert_equal(:str, h_key.type) + + validate_lack_of_side_effects(h_val, whitelisted_methods_for_serialize) + end + + private_class_method def self.validate_deserialize_hash_read(clause) + # val = hash[%s] + + assert_equal(:lvasgn, clause.type) + name, val = clause.children + assert_equal(:val, name) + assert_equal(:send, val.type) + receiver, method, arg = val.children + assert_equal(s(:lvar, :hash), receiver) + assert_equal(:[], method) + assert_equal(:str, arg.type) + end + + private_class_method def self.validate_deserialize_ivar_set(clause) + # %s = if val.nil? + # found -= 1 unless hash.key?(%s) + # %s + # else + # %s + # end + + assert_equal(:ivasgn, clause.type) + ivar_name, deser_val = clause.children + unless ivar_name.is_a?(Symbol) + raise ValidationError.new("Unexpected ivar: #{ivar_name}") + end + + assert_equal(:if, deser_val.type) + condition, if_body, else_body = deser_val.children + assert_equal(s(:send, s(:lvar, :val), :nil?), condition) + + assert_equal(:begin, if_body.type) + update_found, handle_nil = if_body.children + assert_equal(:if, update_found.type) + found_condition, found_if_body, found_else_body = update_found.children + assert_equal(:send, found_condition.type) + receiver, method, arg = found_condition.children + assert_equal(s(:lvar, :hash), receiver) + assert_equal(:key?, method) + assert_equal(:str, arg.type) + assert_equal(nil, found_if_body) + assert_equal(s(:op_asgn, s(:lvasgn, :found), :-, s(:int, 1)), found_else_body) + + validate_deserialize_handle_nil(handle_nil) + + if else_body.type == :kwbegin + rescue_expression, = else_body.children + assert_equal(:rescue, rescue_expression.type) + + try, rescue_body = rescue_expression.children + validate_lack_of_side_effects(try, whitelisted_methods_for_deserialize) + + assert_equal(:resbody, rescue_body.type) + exceptions, assignment, handler = rescue_body.children + assert_equal(:array, exceptions.type) + exceptions.children.each {|c| assert_equal(:const, c.type)} + assert_equal(:lvasgn, assignment.type) + assert_equal([:e], assignment.children) + + deserialization_error, val_return = handler.children + + assert_equal(:send, deserialization_error.type) + receiver, method, *args = deserialization_error.children + assert_equal(nil, receiver) + assert_equal(:raise_deserialization_error, method) + args.each {|a| validate_lack_of_side_effects(a, whitelisted_methods_for_deserialize)} + + validate_lack_of_side_effects(val_return, whitelisted_methods_for_deserialize) + else + validate_lack_of_side_effects(else_body, whitelisted_methods_for_deserialize) + end + end + + private_class_method def self.validate_deserialize_handle_nil(node) + case node.type + when :hash, :array, :str, :sym, :int, :float, :true, :false, :nil, :const # rubocop:disable Lint/BooleanSymbol + # Primitives and constants are safe + when :send + receiver, method, arg = node.children + if receiver.nil? + # required_prop_missing_from_deserialize(%) + assert_equal(:required_prop_missing_from_deserialize, method) + assert_equal(:sym, arg.type) + elsif receiver == self_class_decorator + # self.class.decorator.raise_nil_deserialize_error(%) + assert_equal(:raise_nil_deserialize_error, method) + assert_equal(:str, arg.type) + elsif method == :default + # self.class.decorator.props_with_defaults.fetch(%).default + assert_equal(:send, receiver.type) + inner_receiver, inner_method, inner_arg = receiver.children + assert_equal( + s(:send, self_class_decorator, :props_with_defaults), + inner_receiver, + ) + assert_equal(:fetch, inner_method) + assert_equal(:sym, inner_arg.type) + else + raise ValidationError.new("Unexpected receiver in nil handler: #{node.inspect}") + end + else + raise ValidationError.new("Unexpected nil handler: #{node.inspect}") + end + end + + private_class_method def self.self_class_decorator + @self_class_decorator ||= s(:send, s(:send, s(:self), :class), :decorator).freeze + end + + private_class_method def self.validate_lack_of_side_effects(node, whitelisted_methods_by_receiver_type) + case node.type + when :const + # This is ok, because we'll have validated what method has been called + # if applicable + when :hash, :array, :str, :sym, :int, :float, :true, :false, :nil, :self # rubocop:disable Lint/BooleanSymbol + # Primitives & self are ok + when :lvar, :arg, :ivar + # Reading local & instance variables & arguments is ok + unless node.children.all? {|c| c.is_a?(Symbol)} + raise ValidationError.new("Unexpected child for #{node.type}: #{node.inspect}") + end + when :args, :mlhs, :block, :begin, :if + # Blocks etc are read-only if their contents are read-only + node.children.each {|c| validate_lack_of_side_effects(c, whitelisted_methods_by_receiver_type) if c} + when :send + # Sends are riskier so check a whitelist + receiver, method, *args = node.children + if receiver + if receiver.type == :send + key = receiver + else + key = receiver.type + validate_lack_of_side_effects(receiver, whitelisted_methods_by_receiver_type) + end + + if !whitelisted_methods_by_receiver_type[key]&.include?(method) + raise ValidationError.new("Unexpected method #{method} called on #{receiver.inspect}") + end + end + args.each do |arg| + validate_lack_of_side_effects(arg, whitelisted_methods_by_receiver_type) + end + else + raise ValidationError.new("Unexpected node type #{node.type}: #{node.inspect}") + end + end + + private_class_method def self.assert_equal(expected, actual) + if expected != actual + raise ValidationError.new("Expected #{expected}, got #{actual}") + end + end + + # Method calls generated by SerdeTransform + private_class_method def self.whitelisted_methods_for_serialize + @whitelisted_methods_for_serialize ||= { + lvar: %i{dup map transform_values transform_keys each_with_object nil? []= serialize}, + ivar: %i[dup map transform_values transform_keys each_with_object serialize], + const: %i[checked_serialize deep_clone_object], + } + end + + # Method calls generated by SerdeTransform + private_class_method def self.whitelisted_methods_for_deserialize + @whitelisted_methods_for_deserialize ||= { + lvar: %i{dup map transform_values transform_keys each_with_object nil? []= to_f}, + const: %i[deserialize from_hash deep_clone_object], + } + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/props/has_lazily_specialized_methods.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/props/has_lazily_specialized_methods.rb new file mode 100644 index 0000000000..5c1acecb69 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/props/has_lazily_specialized_methods.rb @@ -0,0 +1,140 @@ +# frozen_string_literal: true +# typed: false + +module T::Props + + # Helper for generating methods that replace themselves with a specialized + # version on first use. The main use case is when we want to generate a + # method using the full set of props on a class; we can't do that during + # prop definition because we have no way of knowing whether we are defining + # the last prop. + # + # See go/M8yrvzX2 (Stripe-internal) for discussion of security considerations. + # In outline, while `class_eval` is a bit scary, we believe that as long as + # all inputs are defined in version control (and this is enforced by calling + # `disable_lazy_evaluation!` appropriately), risk isn't significantly higher + # than with build-time codegen. + module HasLazilySpecializedMethods + extend T::Sig + + class SourceEvaluationDisabled < RuntimeError + def initialize + super("Evaluation of lazily-defined methods is disabled") + end + end + + # Disable any future evaluation of lazily-defined methods. + # + # This is intended to be called after startup but before interacting with + # the outside world, to limit attack surface for our `class_eval` use. + # + # Note it does _not_ prevent explicit calls to `eagerly_define_lazy_methods!` + # from working. + sig {void} + def self.disable_lazy_evaluation! + @lazy_evaluation_disabled ||= true + end + + sig {returns(T::Boolean)} + def self.lazy_evaluation_enabled? + !defined?(@lazy_evaluation_disabled) || !@lazy_evaluation_disabled + end + + module DecoratorMethods + extend T::Sig + + sig {returns(T::Hash[Symbol, T.proc.returns(String)]).checked(:never)} + private def lazily_defined_methods + @lazily_defined_methods ||= {} + end + + sig {returns(T::Hash[Symbol, T.untyped]).checked(:never)} + private def lazily_defined_vm_methods + @lazily_defined_vm_methods ||= {} + end + + sig {params(name: Symbol).void} + private def eval_lazily_defined_method!(name) + if !HasLazilySpecializedMethods.lazy_evaluation_enabled? + raise SourceEvaluationDisabled.new + end + + source = lazily_defined_methods.fetch(name).call + + cls = decorated_class + cls.class_eval(source.to_s) + cls.send(:private, name) + end + + sig {params(name: Symbol).void} + private def eval_lazily_defined_vm_method!(name) + if !HasLazilySpecializedMethods.lazy_evaluation_enabled? + raise SourceEvaluationDisabled.new + end + + lazily_defined_vm_methods.fetch(name).call + + cls = decorated_class + cls.send(:private, name) + end + + sig {params(name: Symbol, blk: T.proc.returns(String)).void} + private def enqueue_lazy_method_definition!(name, &blk) + lazily_defined_methods[name] = blk + + cls = decorated_class + if cls.method_defined?(name) + # Ruby does not emit "method redefined" warnings for aliased methods + # (more robust than undef_method that would create a small window in which the method doesn't exist) + cls.send(:alias_method, name, name) + end + cls.send(:define_method, name) do |*args| + self.class.decorator.send(:eval_lazily_defined_method!, name) + send(name, *args) + end + if cls.respond_to?(:ruby2_keywords, true) + cls.send(:ruby2_keywords, name) + end + cls.send(:private, name) + end + + sig {params(name: Symbol, blk: T.untyped).void} + private def enqueue_lazy_vm_method_definition!(name, &blk) + lazily_defined_vm_methods[name] = blk + + cls = decorated_class + cls.send(:define_method, name) do |*args| + self.class.decorator.send(:eval_lazily_defined_vm_method!, name) + send(name, *args) + end + if cls.respond_to?(:ruby2_keywords, true) + cls.send(:ruby2_keywords, name) + end + cls.send(:private, name) + end + + sig {void} + def eagerly_define_lazy_methods! + return if lazily_defined_methods.empty? + + source = lazily_defined_methods.values.map(&:call).map(&:to_s).join("\n\n") + + cls = decorated_class + cls.class_eval(source) + lazily_defined_methods.each_key {|name| cls.send(:private, name)} + lazily_defined_methods.clear + end + + sig {void} + def eagerly_define_lazy_vm_methods! + return if lazily_defined_vm_methods.empty? + + lazily_defined_vm_methods.values.map(&:call) + + cls = decorated_class + lazily_defined_vm_methods.each_key {|name| cls.send(:private, name)} + lazily_defined_vm_methods.clear + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/props/optional.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/props/optional.rb new file mode 100644 index 0000000000..4f482beac3 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/props/optional.rb @@ -0,0 +1,89 @@ +# frozen_string_literal: true +# typed: false + +module T::Props::Optional + include T::Props::Plugin +end + +############################################## + +# NB: This must stay in the same file where T::Props::Optional is defined due to +# T::Props::Decorator#apply_plugin; see https://git.corp.stripe.com/stripe-internal/pay-server/blob/fc7f15593b49875f2d0499ffecfd19798bac05b3/chalk/odm/lib/chalk-odm/document_decorator.rb#L716-L717 +module T::Props::Optional::DecoratorMethods + extend T::Sig + + # Heads up! + # + # There are already too many ad-hoc options on the prop DSL. + # + # We have already done a lot of work to remove unnecessary and confusing + # options. If you're considering adding a new rule key, please come chat with + # the Sorbet team first, as we'd really like to learn more about how to best + # solve the problem you're encountering. + VALID_RULE_KEYS = { + default: true, + factory: true, + }.freeze + private_constant :VALID_RULE_KEYS + + DEFAULT_SETTER_RULE_KEY = :_t_props_private_apply_default + private_constant :DEFAULT_SETTER_RULE_KEY + + def valid_rule_key?(key) + super || VALID_RULE_KEYS[key] + end + + def prop_optional?(prop) + prop_rules(prop)[:fully_optional] + end + + def compute_derived_rules(rules) + rules[:fully_optional] = !T::Props::Utils.need_nil_write_check?(rules) + rules[:need_nil_read_check] = T::Props::Utils.need_nil_read_check?(rules) + end + + # checked(:never) - O(runtime object construction) + sig {returns(T::Hash[Symbol, T::Props::Private::ApplyDefault]).checked(:never)} + attr_reader :props_with_defaults + + # checked(:never) - O(runtime object construction) + sig {returns(T::Hash[Symbol, T::Props::Private::SetterFactory::SetterProc]).checked(:never)} + attr_reader :props_without_defaults + + def add_prop_definition(prop, rules) + compute_derived_rules(rules) + + default_setter = T::Props::Private::ApplyDefault.for(decorated_class, rules) + if default_setter + @props_with_defaults ||= {} + @props_with_defaults[prop] = default_setter + props_without_defaults&.delete(prop) # Handle potential override + + rules[DEFAULT_SETTER_RULE_KEY] = default_setter + else + @props_without_defaults ||= {} + @props_without_defaults[prop] = rules.fetch(:setter_proc) + props_with_defaults&.delete(prop) # Handle potential override + end + + super + end + + def prop_validate_definition!(name, cls, rules, type) + result = super + + if rules.key?(:default) && rules.key?(:factory) + raise ArgumentError.new("Setting both :default and :factory is invalid. See: go/chalk-docs") + end + + result + end + + def has_default?(rules) + rules.include?(DEFAULT_SETTER_RULE_KEY) + end + + def get_default(rules, instance_class) + rules[DEFAULT_SETTER_RULE_KEY]&.default + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/props/plugin.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/props/plugin.rb new file mode 100644 index 0000000000..1423c172ed --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/props/plugin.rb @@ -0,0 +1,37 @@ +# frozen_string_literal: true +# typed: false + +module T::Props::Plugin + include T::Props + extend T::Helpers + + module ClassMethods + def included(child) + super + child.plugin(self) + end + end + mixes_in_class_methods(ClassMethods) + + module Private + # These need to be non-instance methods so we can use them without prematurely creating the + # child decorator in `model_inherited` (see comments there for details). + # + # The dynamic constant access below forces this file to be `typed: false` + def self.apply_class_methods(plugin, target) + if plugin.const_defined?('ClassMethods') + # FIXME: This will break preloading, selective test execution, etc if `mod::ClassMethods` + # is ever defined in a separate file from `mod`. + target.extend(plugin::ClassMethods) + end + end + + def self.apply_decorator_methods(plugin, target) + if plugin.const_defined?('DecoratorMethods') + # FIXME: This will break preloading, selective test execution, etc if `mod::DecoratorMethods` + # is ever defined in a separate file from `mod`. + target.extend(plugin::DecoratorMethods) + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/props/pretty_printable.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/props/pretty_printable.rb new file mode 100644 index 0000000000..e821cd3435 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/props/pretty_printable.rb @@ -0,0 +1,107 @@ +# frozen_string_literal: true +# typed: true + +module T::Props::PrettyPrintable + include T::Props::Plugin + + # Return a string representation of this object and all of its props + def inspect + T.unsafe(T.cast(self, Object).class).decorator.inspect_instance(self) + end + + # Override the PP gem with something that's similar, but gives us a hook + # to do redaction + def pretty_inspect + T.unsafe(T.cast(self, Object).class).decorator.inspect_instance(self, multiline: true) + end + + module DecoratorMethods + extend T::Sig + + sig {params(key: Symbol).returns(T::Boolean).checked(:never)} + def valid_rule_key?(key) + super || key == :inspect + end + + sig do + params(instance: T::Props::PrettyPrintable, multiline: T::Boolean, indent: String) + .returns(String) + end + def inspect_instance(instance, multiline: false, indent: ' ') + components = + inspect_instance_components( + instance, + multiline: multiline, + indent: indent + ) + .reject(&:empty?) + + # Not using #<> here as that makes pry highlight these objects + # as if they were all comments, whereas this makes them look + # like the structured thing they are. + if multiline + "#{components[0]}:\n" + T.must(components[1..-1]).join("\n") + else + "<#{components.join(' ')}>" + end + end + + sig do + params(instance: T::Props::PrettyPrintable, multiline: T::Boolean, indent: String) + .returns(T::Array[String]) + end + private def inspect_instance_components(instance, multiline:, indent:) + pretty_props = T.unsafe(self).all_props.map do |prop| + [prop, inspect_prop_value(instance, prop, multiline: multiline, indent: indent)] + end + + joined_props = join_props_with_pretty_values( + pretty_props, + multiline: multiline, + indent: indent + ) + + [ + T.unsafe(self).decorated_class.to_s, + joined_props, + ] + end + + sig do + params(instance: T::Props::PrettyPrintable, prop: Symbol, multiline: T::Boolean, indent: String) + .returns(String) + .checked(:never) + end + private def inspect_prop_value(instance, prop, multiline:, indent:) + val = T.unsafe(self).get(instance, prop) + rules = T.unsafe(self).prop_rules(prop) + if (custom_inspect = rules[:inspect]) + if T::Utils.arity(custom_inspect) == 1 + custom_inspect.call(val) + else + custom_inspect.call(val, {multiline: multiline, indent: indent}) + end + elsif rules[:sensitivity] && !rules[:sensitivity].empty? && !val.nil? + "" + else + val.inspect + end + end + + sig do + params(pretty_kvs: T::Array[[Symbol, String]], multiline: T::Boolean, indent: String) + .returns(String) + end + private def join_props_with_pretty_values(pretty_kvs, multiline:, indent: ' ') + pairs = pretty_kvs + .sort_by {|k, _v| k.to_s} + .map {|k, v| "#{k}=#{v}"} + + if multiline + indent + pairs.join("\n#{indent}") + else + pairs.join(', ') + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/props/private/apply_default.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/props/private/apply_default.rb new file mode 100644 index 0000000000..b86f506f9a --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/props/private/apply_default.rb @@ -0,0 +1,170 @@ +# frozen_string_literal: true +# typed: strict + +module T::Props + module Private + class ApplyDefault + extend T::Sig + extend T::Helpers + abstract! + + # checked(:never) - O(object construction x prop count) + sig {returns(SetterFactory::SetterProc).checked(:never)} + attr_reader :setter_proc + + # checked(:never) - We do this with `T.let` instead + sig {params(accessor_key: Symbol, setter_proc: SetterFactory::SetterProc).void.checked(:never)} + def initialize(accessor_key, setter_proc) + @accessor_key = T.let(accessor_key, Symbol) + @setter_proc = T.let(setter_proc, SetterFactory::SetterProc) + end + + # checked(:never) - O(object construction x prop count) + sig {abstract.returns(T.untyped).checked(:never)} + def default; end + + # checked(:never) - O(object construction x prop count) + sig {abstract.params(instance: T.all(T::Props::Optional, Object)).void.checked(:never)} + def set_default(instance); end + + NO_CLONE_TYPES = T.let([TrueClass, FalseClass, NilClass, Symbol, Numeric, T::Enum].freeze, T::Array[Module]) + + # checked(:never) - Rules hash is expensive to check + sig {params(cls: Module, rules: T::Hash[Symbol, T.untyped]).returns(T.nilable(ApplyDefault)).checked(:never)} + def self.for(cls, rules) + accessor_key = rules.fetch(:accessor_key) + setter = rules.fetch(:setter_proc) + + if rules.key?(:factory) + ApplyDefaultFactory.new(cls, rules.fetch(:factory), accessor_key, setter) + elsif rules.key?(:default) + default = rules.fetch(:default) + case default + when *NO_CLONE_TYPES + return ApplyPrimitiveDefault.new(default, accessor_key, setter) + when String + if default.frozen? + return ApplyPrimitiveDefault.new(default, accessor_key, setter) + end + when Array + if default.empty? && default.class == Array + return ApplyEmptyArrayDefault.new(accessor_key, setter) + end + when Hash + if default.empty? && default.default.nil? && T.unsafe(default).default_proc.nil? && default.class == Hash + return ApplyEmptyHashDefault.new(accessor_key, setter) + end + end + + ApplyComplexDefault.new(default, accessor_key, setter) + else + nil + end + end + end + + class ApplyFixedDefault < ApplyDefault + abstract! + + # checked(:never) - We do this with `T.let` instead + sig {params(default: BasicObject, accessor_key: Symbol, setter_proc: SetterFactory::SetterProc).void.checked(:never)} + def initialize(default, accessor_key, setter_proc) + # FIXME: Ideally we'd check here that the default is actually a valid + # value for this field, but existing code relies on the fact that we don't. + # + # :( + # + # setter_proc.call(default) + @default = T.let(default, BasicObject) + super(accessor_key, setter_proc) + end + + # checked(:never) - O(object construction x prop count) + sig {override.params(instance: T.all(T::Props::Optional, Object)).void.checked(:never)} + def set_default(instance) + instance.instance_variable_set(@accessor_key, default) + end + end + + class ApplyPrimitiveDefault < ApplyFixedDefault + # checked(:never) - O(object construction x prop count) + sig {override.returns(T.untyped).checked(:never)} + attr_reader :default + end + + class ApplyComplexDefault < ApplyFixedDefault + # checked(:never) - O(object construction x prop count) + sig {override.returns(T.untyped).checked(:never)} + def default + T::Props::Utils.deep_clone_object(@default) + end + end + + # Special case since it's so common, and a literal `[]` is meaningfully + # faster than falling back to ApplyComplexDefault or even calling + # `some_empty_array.dup` + class ApplyEmptyArrayDefault < ApplyDefault + # checked(:never) - O(object construction x prop count) + sig {override.params(instance: T.all(T::Props::Optional, Object)).void.checked(:never)} + def set_default(instance) + instance.instance_variable_set(@accessor_key, []) + end + + # checked(:never) - O(object construction x prop count) + sig {override.returns(T::Array[T.untyped]).checked(:never)} + def default + [] + end + end + + # Special case since it's so common, and a literal `{}` is meaningfully + # faster than falling back to ApplyComplexDefault or even calling + # `some_empty_hash.dup` + class ApplyEmptyHashDefault < ApplyDefault + # checked(:never) - O(object construction x prop count) + sig {override.params(instance: T.all(T::Props::Optional, Object)).void.checked(:never)} + def set_default(instance) + instance.instance_variable_set(@accessor_key, {}) + end + + # checked(:never) - O(object construction x prop count) + sig {override.returns(T::Hash[T.untyped, T.untyped]).checked(:never)} + def default + {} + end + end + + class ApplyDefaultFactory < ApplyDefault + # checked(:never) - We do this with `T.let` instead + sig do + params( + cls: Module, + factory: T.any(Proc, Method), + accessor_key: Symbol, + setter_proc: SetterFactory::SetterProc, + ) + .void + .checked(:never) + end + def initialize(cls, factory, accessor_key, setter_proc) + @class = T.let(cls, Module) + @factory = T.let(factory, T.any(Proc, Method)) + super(accessor_key, setter_proc) + end + + # checked(:never) - O(object construction x prop count) + sig {override.params(instance: T.all(T::Props::Optional, Object)).void.checked(:never)} + def set_default(instance) + # Use the actual setter to validate the factory returns a legitimate + # value every time + instance.instance_exec(default, &@setter_proc) + end + + # checked(:never) - O(object construction x prop count) + sig {override.returns(T.untyped).checked(:never)} + def default + @class.class_exec(&@factory) + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/props/private/deserializer_generator.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/props/private/deserializer_generator.rb new file mode 100644 index 0000000000..2393e1a284 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/props/private/deserializer_generator.rb @@ -0,0 +1,160 @@ +# frozen_string_literal: true +# typed: strict + +module T::Props + module Private + + # Generates a specialized `deserialize` implementation for a subclass of + # T::Props::Serializable. + # + # The basic idea is that we analyze the props and for each prop, generate + # the simplest possible logic as a block of Ruby source, so that we don't + # pay the cost of supporting types like T:::Hash[CustomType, SubstructType] + # when deserializing a simple Integer. Then we join those together, + # with a little shared logic to be able to detect when we get input keys + # that don't match any prop. + module DeserializerGenerator + extend T::Sig + + # Generate a method that takes a T::Hash[String, T.untyped] representing + # serialized props, sets instance variables for each prop found in the + # input, and returns the count of we props set (which we can use to check + # for unexpected input keys with minimal effect on the fast path). + sig do + params( + props: T::Hash[Symbol, T::Hash[Symbol, T.untyped]], + defaults: T::Hash[Symbol, T::Props::Private::ApplyDefault], + ) + .returns(String) + .checked(:never) + end + def self.generate(props, defaults) + stored_props = props.reject {|_, rules| rules[:dont_store]} + parts = stored_props.map do |prop, rules| + # All of these strings should already be validated (directly or + # indirectly) in `validate_prop_name`, so we don't bother with a nice + # error message, but we double check here to prevent a refactoring + # from introducing a security vulnerability. + raise unless T::Props::Decorator::SAFE_NAME.match?(prop.to_s) + + hash_key = rules.fetch(:serialized_form) + raise unless T::Props::Decorator::SAFE_NAME.match?(hash_key) + + ivar_name = rules.fetch(:accessor_key).to_s + raise unless ivar_name.start_with?('@') && T::Props::Decorator::SAFE_NAME.match?(ivar_name[1..-1]) + + transformation = SerdeTransform.generate( + T::Utils::Nilable.get_underlying_type_object(rules.fetch(:type_object)), + SerdeTransform::Mode::DESERIALIZE, + 'val' + ) + transformed_val = if transformation + # Rescuing exactly NoMethodError is intended as a temporary hack + # to preserve the semantics from before codegen. More generally + # we are inconsistent about typechecking on deser and need to decide + # our strategy here. + <<~RUBY + begin + #{transformation} + rescue NoMethodError => e + raise_deserialization_error( + #{prop.inspect}, + val, + e, + ) + val + end + RUBY + else + 'val' + end + + nil_handler = generate_nil_handler( + prop: prop, + serialized_form: hash_key, + default: defaults[prop], + nilable_type: T::Props::Utils.optional_prop?(rules), + raise_on_nil_write: !!rules[:raise_on_nil_write], + ) + + <<~RUBY + val = hash[#{hash_key.inspect}] + #{ivar_name} = if val.nil? + found -= 1 unless hash.key?(#{hash_key.inspect}) + #{nil_handler} + else + #{transformed_val} + end + RUBY + end + + <<~RUBY + def __t_props_generated_deserialize(hash) + found = #{stored_props.size} + #{parts.join("\n\n")} + found + end + RUBY + end + + # This is very similar to what we do in ApplyDefault, but has a few + # key differences that mean we don't just re-use the code: + # + # 1. Where the logic in construction is that we generate a default + # if & only if the prop key isn't present in the input, here we'll + # generate a default even to override an explicit nil, but only + # if the prop is actually required. + # 2. Since we're generating raw Ruby source, we can remove a layer + # of indirection for marginally better performance; this seems worth + # it for the common cases of literals and empty arrays/hashes. + # 3. We need to care about the distinction between `raise_on_nil_write` + # and actually non-nilable, where new-instance construction doesn't. + # + # So we fall back to ApplyDefault only when one of the cases just + # mentioned doesn't apply. + sig do + params( + prop: Symbol, + serialized_form: String, + default: T.nilable(ApplyDefault), + nilable_type: T::Boolean, + raise_on_nil_write: T::Boolean, + ) + .returns(String) + .checked(:never) + end + private_class_method def self.generate_nil_handler( + prop:, + serialized_form:, + default:, + nilable_type:, + raise_on_nil_write: + ) + if !nilable_type + case default + when NilClass + "self.class.decorator.raise_nil_deserialize_error(#{serialized_form.inspect})" + when ApplyPrimitiveDefault + literal = default.default + case literal + when String, Integer, Symbol, Float, TrueClass, FalseClass, NilClass + literal.inspect + else + "self.class.decorator.props_with_defaults.fetch(#{prop.inspect}).default" + end + when ApplyEmptyArrayDefault + '[]' + when ApplyEmptyHashDefault + '{}' + else + "self.class.decorator.props_with_defaults.fetch(#{prop.inspect}).default" + end + elsif raise_on_nil_write + "required_prop_missing_from_deserialize(#{prop.inspect})" + else + 'nil' + end + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/props/private/parser.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/props/private/parser.rb new file mode 100644 index 0000000000..2ccd574118 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/props/private/parser.rb @@ -0,0 +1,32 @@ +# frozen_string_literal: true +# typed: false + +module T::Props + module Private + module Parse + def parse(source) + @current_ruby ||= require_parser(:CurrentRuby) + @current_ruby.parse(source) + end + + def s(type, *children) + @node ||= require_parser(:AST, :Node) + @node.new(type, children) + end + + private def require_parser(*constants) + # This is an optional dependency for sorbet-runtime in general, + # but is required here + require 'parser/current' + + # Hack to work around the static checker thinking the constant is + # undefined + cls = Kernel.const_get(:Parser, true) + while (const = constants.shift) + cls = cls.const_get(const, false) + end + cls + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/props/private/serde_transform.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/props/private/serde_transform.rb new file mode 100644 index 0000000000..e0b37a376d --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/props/private/serde_transform.rb @@ -0,0 +1,186 @@ +# frozen_string_literal: true +# typed: strict + +module T::Props + module Private + module SerdeTransform + extend T::Sig + + class Serialize; end + private_constant :Serialize + class Deserialize; end + private_constant :Deserialize + ModeType = T.type_alias {T.any(Serialize, Deserialize)} + private_constant :ModeType + + module Mode + SERIALIZE = T.let(Serialize.new.freeze, Serialize) + DESERIALIZE = T.let(Deserialize.new.freeze, Deserialize) + end + + NO_TRANSFORM_TYPES = T.let( + [TrueClass, FalseClass, NilClass, Symbol, String].freeze, + T::Array[Module], + ) + private_constant :NO_TRANSFORM_TYPES + + sig do + params( + type: T::Types::Base, + mode: ModeType, + varname: String, + ) + .returns(T.nilable(String)) + .checked(:never) + end + def self.generate(type, mode, varname) + case type + when T::Types::TypedArray + inner = generate(type.type, mode, 'v') + if inner.nil? + "#{varname}.dup" + else + "#{varname}.map {|v| #{inner}}" + end + when T::Types::TypedSet + inner = generate(type.type, mode, 'v') + if inner.nil? + "#{varname}.dup" + else + "Set.new(#{varname}) {|v| #{inner}}" + end + when T::Types::TypedHash + keys = generate(type.keys, mode, 'k') + values = generate(type.values, mode, 'v') + if keys && values + "#{varname}.each_with_object({}) {|(k,v),h| h[#{keys}] = #{values}}" + elsif keys + "#{varname}.transform_keys {|k| #{keys}}" + elsif values + "#{varname}.transform_values {|v| #{values}}" + else + "#{varname}.dup" + end + when T::Types::Simple + raw = type.raw_type + if NO_TRANSFORM_TYPES.any? {|cls| raw <= cls} + nil + elsif raw <= Float + case mode + when Deserialize then "#{varname}.to_f" + when Serialize then nil + else T.absurd(mode) + end + elsif raw <= Numeric + nil + elsif raw < T::Props::Serializable + handle_serializable_subtype(varname, raw, mode) + elsif raw.singleton_class < T::Props::CustomType + handle_custom_type(varname, T.unsafe(raw), mode) + elsif T::Configuration.scalar_types.include?(raw.name) + # It's a bit of a hack that this is separate from NO_TRANSFORM_TYPES + # and doesn't check inheritance (like `T::Props::CustomType.scalar_type?` + # does), but it covers the main use case (pay-server's custom `Boolean` + # module) without either requiring `T::Configuration.scalar_types` to + # accept modules instead of strings (which produces load-order issues + # and subtle behavior changes) or eating the performance cost of doing + # an inheritance check by manually crawling a class hierarchy and doing + # string comparisons. + nil + else + "T::Props::Utils.deep_clone_object(#{varname})" + end + when T::Types::Union + non_nil_type = T::Utils.unwrap_nilable(type) + if non_nil_type + inner = generate(non_nil_type, mode, varname) + if inner.nil? + nil + else + "#{varname}.nil? ? nil : #{inner}" + end + elsif type.types.all? {|t| generate(t, mode, varname).nil?} + # Handle, e.g., T::Boolean + nil + else + # We currently deep_clone_object if the type was T.any(Integer, Float). + # When we get better support for union types (maybe this specific + # union type, because it would be a replacement for + # Chalk::ODM::DeprecatedNumemric), we could opt to special case + # this union to have no specific serde transform (the only reason + # why Float has a special case is because round tripping through + # JSON might normalize Floats to Integers) + "T::Props::Utils.deep_clone_object(#{varname})" + end + when T::Types::Intersection + dynamic_fallback = "T::Props::Utils.deep_clone_object(#{varname})" + + # Transformations for any members of the intersection type where we + # know what we need to do and did not have to fall back to the + # dynamic deep clone method. + # + # NB: This deliberately does include `nil`, which means we know we + # don't need to do any transforming. + inner_known = type.types + .map {|t| generate(t, mode, varname)} + .reject {|t| t == dynamic_fallback} + .uniq + + if inner_known.size != 1 + # If there were no cases where we could tell what we need to do, + # e.g. if this is `T.all(SomethingWeird, WhoKnows)`, just use the + # dynamic fallback. + # + # If there were multiple cases and they weren't consistent, e.g. + # if this is `T.all(String, T::Array[Integer])`, the type is probably + # bogus/uninhabited, but use the dynamic fallback because we still + # don't have a better option, and this isn't the place to raise that + # error. + dynamic_fallback + else + # This is probably something like `T.all(String, SomeMarker)` or + # `T.all(SomeEnum, T.deprecated_enum(SomeEnum::FOO))` and we should + # treat it like String or SomeEnum even if we don't know what to do + # with the rest of the type. + inner_known.first + end + when T::Types::Enum + generate(T::Utils.lift_enum(type), mode, varname) + else + "T::Props::Utils.deep_clone_object(#{varname})" + end + end + + sig {params(varname: String, type: Module, mode: ModeType).returns(String).checked(:never)} + private_class_method def self.handle_serializable_subtype(varname, type, mode) + case mode + when Serialize + "#{varname}.serialize(strict)" + when Deserialize + type_name = T.must(module_name(type)) + "#{type_name}.from_hash(#{varname})" + else + T.absurd(mode) + end + end + + sig {params(varname: String, type: Module, mode: ModeType).returns(String).checked(:never)} + private_class_method def self.handle_custom_type(varname, type, mode) + case mode + when Serialize + "T::Props::CustomType.checked_serialize(#{varname})" + when Deserialize + type_name = T.must(module_name(type)) + "#{type_name}.deserialize(#{varname})" + else + T.absurd(mode) + end + end + + sig {params(type: Module).returns(T.nilable(String)).checked(:never)} + private_class_method def self.module_name(type) + T::Configuration.module_name_mangler.call(type) + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/props/private/serializer_generator.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/props/private/serializer_generator.rb new file mode 100644 index 0000000000..0d49a46e0f --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/props/private/serializer_generator.rb @@ -0,0 +1,76 @@ +# frozen_string_literal: true +# typed: strict + +module T::Props + module Private + + # Generates a specialized `serialize` implementation for a subclass of + # T::Props::Serializable. + # + # The basic idea is that we analyze the props and for each prop, generate + # the simplest possible logic as a block of Ruby source, so that we don't + # pay the cost of supporting types like T:::Hash[CustomType, SubstructType] + # when serializing a simple Integer. Then we join those together, + # with a little shared logic to be able to detect when we get input keys + # that don't match any prop. + module SerializerGenerator + extend T::Sig + + sig do + params( + props: T::Hash[Symbol, T::Hash[Symbol, T.untyped]], + ) + .returns(String) + .checked(:never) + end + def self.generate(props) + stored_props = props.reject {|_, rules| rules[:dont_store]} + parts = stored_props.map do |prop, rules| + # All of these strings should already be validated (directly or + # indirectly) in `validate_prop_name`, so we don't bother with a nice + # error message, but we double check here to prevent a refactoring + # from introducing a security vulnerability. + raise unless T::Props::Decorator::SAFE_NAME.match?(prop.to_s) + + hash_key = rules.fetch(:serialized_form) + raise unless T::Props::Decorator::SAFE_NAME.match?(hash_key) + + ivar_name = rules.fetch(:accessor_key).to_s + raise unless ivar_name.start_with?('@') && T::Props::Decorator::SAFE_NAME.match?(ivar_name[1..-1]) + + transformed_val = SerdeTransform.generate( + T::Utils::Nilable.get_underlying_type_object(rules.fetch(:type_object)), + SerdeTransform::Mode::SERIALIZE, + ivar_name + ) || ivar_name + + nil_asserter = + if rules[:fully_optional] + '' + else + "required_prop_missing_from_serialize(#{prop.inspect}) if strict" + end + + # Don't serialize values that are nil to save space (both the + # nil value itself and the field name in the serialized BSON + # document) + <<~RUBY + if #{ivar_name}.nil? + #{nil_asserter} + else + h[#{hash_key.inspect}] = #{transformed_val} + end + RUBY + end + + <<~RUBY + def __t_props_generated_serialize(strict) + h = {} + #{parts.join("\n\n")} + h + end + RUBY + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/props/private/setter_factory.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/props/private/setter_factory.rb new file mode 100644 index 0000000000..00c76ed1e7 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/props/private/setter_factory.rb @@ -0,0 +1,197 @@ +# frozen_string_literal: true +# typed: strict + +module T::Props + module Private + module SetterFactory + extend T::Sig + + SetterProc = T.type_alias {T.proc.params(val: T.untyped).void} + ValidateProc = T.type_alias {T.proc.params(prop: Symbol, value: T.untyped).void} + + sig do + params( + klass: T.all(Module, T::Props::ClassMethods), + prop: Symbol, + rules: T::Hash[Symbol, T.untyped] + ) + .returns(SetterProc) + .checked(:never) + end + def self.build_setter_proc(klass, prop, rules) + # Our nil check works differently than a simple T.nilable for various + # reasons (including the `raise_on_nil_write` setting and the existence + # of defaults & factories), so unwrap any T.nilable and do a check + # manually. + non_nil_type = T::Utils::Nilable.get_underlying_type_object(rules.fetch(:type_object)) + accessor_key = rules.fetch(:accessor_key) + validate = rules[:setter_validate] + + # It seems like a bug that this affects the behavior of setters, but + # some existing code relies on this behavior + has_explicit_nil_default = rules.key?(:default) && rules.fetch(:default).nil? + + # Use separate methods in order to ensure that we only close over necessary + # variables + if !T::Props::Utils.need_nil_write_check?(rules) || has_explicit_nil_default + if validate.nil? && non_nil_type.is_a?(T::Types::Simple) + simple_nilable_proc(prop, accessor_key, non_nil_type.raw_type, klass) + else + nilable_proc(prop, accessor_key, non_nil_type, klass, validate) + end + else + if validate.nil? && non_nil_type.is_a?(T::Types::Simple) + simple_non_nil_proc(prop, accessor_key, non_nil_type.raw_type, klass) + else + non_nil_proc(prop, accessor_key, non_nil_type, klass, validate) + end + end + end + + sig do + params( + prop: Symbol, + accessor_key: Symbol, + non_nil_type: Module, + klass: T.all(Module, T::Props::ClassMethods), + ) + .returns(SetterProc) + end + private_class_method def self.simple_non_nil_proc(prop, accessor_key, non_nil_type, klass) + proc do |val| + unless val.is_a?(non_nil_type) + T::Props::Private::SetterFactory.raise_pretty_error( + klass, + prop, + T::Utils.coerce(non_nil_type), + val, + ) + end + instance_variable_set(accessor_key, val) + end + end + + sig do + params( + prop: Symbol, + accessor_key: Symbol, + non_nil_type: T::Types::Base, + klass: T.all(Module, T::Props::ClassMethods), + validate: T.nilable(ValidateProc) + ) + .returns(SetterProc) + end + private_class_method def self.non_nil_proc(prop, accessor_key, non_nil_type, klass, validate) + proc do |val| + # this use of recursively_valid? is intentional: unlike for + # methods, we want to make sure data at the 'edge' + # (e.g. models that go into databases or structs serialized + # from disk) are correct, so we use more thorough runtime + # checks there + if non_nil_type.recursively_valid?(val) + validate&.call(prop, val) + else + T::Props::Private::SetterFactory.raise_pretty_error( + klass, + prop, + non_nil_type, + val, + ) + end + instance_variable_set(accessor_key, val) + end + end + + sig do + params( + prop: Symbol, + accessor_key: Symbol, + non_nil_type: Module, + klass: T.all(Module, T::Props::ClassMethods), + ) + .returns(SetterProc) + end + private_class_method def self.simple_nilable_proc(prop, accessor_key, non_nil_type, klass) + proc do |val| + if val.nil? + instance_variable_set(accessor_key, nil) + elsif val.is_a?(non_nil_type) + instance_variable_set(accessor_key, val) + else + T::Props::Private::SetterFactory.raise_pretty_error( + klass, + prop, + T::Utils.coerce(non_nil_type), + val, + ) + instance_variable_set(accessor_key, val) + end + end + end + + sig do + params( + prop: Symbol, + accessor_key: Symbol, + non_nil_type: T::Types::Base, + klass: T.all(Module, T::Props::ClassMethods), + validate: T.nilable(ValidateProc), + ) + .returns(SetterProc) + end + private_class_method def self.nilable_proc(prop, accessor_key, non_nil_type, klass, validate) + proc do |val| + if val.nil? + instance_variable_set(accessor_key, nil) + # this use of recursively_valid? is intentional: unlike for + # methods, we want to make sure data at the 'edge' + # (e.g. models that go into databases or structs serialized + # from disk) are correct, so we use more thorough runtime + # checks there + elsif non_nil_type.recursively_valid?(val) + validate&.call(prop, val) + instance_variable_set(accessor_key, val) + else + T::Props::Private::SetterFactory.raise_pretty_error( + klass, + prop, + non_nil_type, + val, + ) + instance_variable_set(accessor_key, val) + end + end + end + + sig do + params( + klass: T.all(Module, T::Props::ClassMethods), + prop: Symbol, + type: T.any(T::Types::Base, Module), + val: T.untyped, + ) + .void + end + def self.raise_pretty_error(klass, prop, type, val) + base_message = "Can't set #{klass.name}.#{prop} to #{val.inspect} (instance of #{val.class}) - need a #{type}" + + pretty_message = "Parameter '#{prop}': #{base_message}\n" + caller_loc = caller_locations&.find {|l| !l.to_s.include?('sorbet-runtime/lib/types/props')} + if caller_loc + pretty_message += "Caller: #{caller_loc.path}:#{caller_loc.lineno}\n" + end + + T::Configuration.call_validation_error_handler( + nil, + message: base_message, + pretty_message: pretty_message, + kind: 'Parameter', + name: prop, + type: type, + value: val, + location: caller_loc, + ) + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/props/serializable.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/props/serializable.rb new file mode 100644 index 0000000000..2e2ea1b749 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/props/serializable.rb @@ -0,0 +1,374 @@ +# frozen_string_literal: true +# typed: false + +module T::Props::Serializable + include T::Props::Plugin + # Required because we have special handling for `optional: false` + include T::Props::Optional + # Required because we have special handling for extra_props + include T::Props::PrettyPrintable + + # Serializes this object to a hash, suitable for conversion to + # JSON/BSON. + # + # @param strict [T::Boolean] (true) If false, do not raise an + # exception if this object has mandatory props with missing + # values. + # @return [Hash] A serialization of this object. + def serialize(strict=true) + begin + h = __t_props_generated_serialize(strict) + rescue => e + msg = self.class.decorator.message_with_generated_source_context( + e, + :__t_props_generated_serialize, + :generate_serialize_source + ) + if msg + begin + raise e.class.new(msg) + rescue ArgumentError + raise TypeError.new(msg) + end + else + raise + end + end + + h.merge!(@_extra_props) if defined?(@_extra_props) + h + end + + private def __t_props_generated_serialize(strict) + # No-op; will be overridden if there are any props. + # + # To see the definition for class `Foo`, run `Foo.decorator.send(:generate_serialize_source)` + {} + end + + # Populates the property values on this object with the values + # from a hash. In general, prefer to use {.from_hash} to construct + # a new instance, instead of loading into an existing instance. + # + # @param hash [Hash] The hash to take property + # values from. + # @param strict [T::Boolean] (false) If true, raise an exception if + # the hash contains keys that do not correspond to any known + # props on this instance. + # @return [void] + def deserialize(hash, strict=false) + begin + hash_keys_matching_props = __t_props_generated_deserialize(hash) + rescue => e + msg = self.class.decorator.message_with_generated_source_context( + e, + :__t_props_generated_deserialize, + :generate_deserialize_source + ) + if msg + begin + raise e.class.new(msg) + rescue ArgumentError + raise TypeError.new(msg) + end + else + raise + end + end + + if hash.size > hash_keys_matching_props + serialized_forms = self.class.decorator.prop_by_serialized_forms + extra = hash.reject {|k, _| serialized_forms.key?(k)} + + # `extra` could still be empty here if the input matches a `dont_store` prop; + # historically, we just ignore those + if !extra.empty? + if strict + raise "Unknown properties for #{self.class.name}: #{extra.keys.inspect}" + else + @_extra_props = extra + end + end + end + end + + private def __t_props_generated_deserialize(hash) + # No-op; will be overridden if there are any props. + # + # To see the definition for class `Foo`, run `Foo.decorator.send(:generate_deserialize_source)` + 0 + end + + # with() will clone the old object to the new object and merge the specified props to the new object. + def with(changed_props) + with_existing_hash(changed_props, existing_hash: self.serialize) + end + + private def recursive_stringify_keys(obj) + if obj.is_a?(Hash) + new_obj = obj.class.new + obj.each do |k, v| + new_obj[k.to_s] = recursive_stringify_keys(v) + end + elsif obj.is_a?(Array) + new_obj = obj.map {|v| recursive_stringify_keys(v)} + else + new_obj = obj + end + new_obj + end + + private def with_existing_hash(changed_props, existing_hash:) + serialized = existing_hash + new_val = self.class.from_hash(serialized.merge(recursive_stringify_keys(changed_props))) + old_extra = self.instance_variable_get(:@_extra_props) if self.instance_variable_defined?(:@_extra_props) + new_extra = new_val.instance_variable_get(:@_extra_props) if new_val.instance_variable_defined?(:@_extra_props) + if old_extra != new_extra + difference = + if old_extra + new_extra.reject {|k, v| old_extra[k] == v} + else + new_extra + end + raise ArgumentError.new("Unexpected arguments: input(#{changed_props}), unexpected(#{difference})") + end + new_val + end + + # Asserts if this property is missing during strict serialize + private def required_prop_missing_from_serialize(prop) + if defined?(@_required_props_missing_from_deserialize) && + @_required_props_missing_from_deserialize&.include?(prop) + # If the prop was already missing during deserialization, that means the application + # code already had to deal with a nil value, which means we wouldn't be accomplishing + # much by raising here (other than causing an unnecessary breakage). + T::Configuration.log_info_handler( + "chalk-odm: missing required property in serialize", + prop: prop, class: self.class.name, id: self.class.decorator.get_id(self) + ) + else + raise TypeError.new("#{self.class.name}.#{prop} not set for non-optional prop") + end + end + + # Marks this property as missing during deserialize + private def required_prop_missing_from_deserialize(prop) + @_required_props_missing_from_deserialize ||= Set[] + @_required_props_missing_from_deserialize << prop + nil + end + + private def raise_deserialization_error(prop_name, value, orig_error) + T::Configuration.soft_assert_handler( + 'Deserialization error (probably unexpected stored type)', + storytime: { + klass: self.class, + prop: prop_name, + value: value, + error: orig_error.message, + notify: 'djudd' + } + ) + end +end + +############################################## + +# NB: This must stay in the same file where T::Props::Serializable is defined due to +# T::Props::Decorator#apply_plugin; see https://git.corp.stripe.com/stripe-internal/pay-server/blob/fc7f15593b49875f2d0499ffecfd19798bac05b3/chalk/odm/lib/chalk-odm/document_decorator.rb#L716-L717 +module T::Props::Serializable::DecoratorMethods + include T::Props::HasLazilySpecializedMethods::DecoratorMethods + + # Heads up! + # + # There are already too many ad-hoc options on the prop DSL. + # + # We have already done a lot of work to remove unnecessary and confusing + # options. If you're considering adding a new rule key, please come chat with + # the Sorbet team first, as we'd really like to learn more about how to best + # solve the problem you're encountering. + VALID_RULE_KEYS = {dont_store: true, name: true, raise_on_nil_write: true}.freeze + private_constant :VALID_RULE_KEYS + + def valid_rule_key?(key) + super || VALID_RULE_KEYS[key] + end + + def required_props + @class.props.select {|_, v| T::Props::Utils.required_prop?(v)}.keys + end + + def prop_dont_store?(prop) + prop_rules(prop)[:dont_store] + end + def prop_by_serialized_forms + @class.prop_by_serialized_forms + end + + def from_hash(hash, strict=false) + raise ArgumentError.new("#{hash.inspect} provided to from_hash") if !(hash && hash.is_a?(Hash)) + + i = @class.allocate + i.deserialize(hash, strict) + + i + end + + def prop_serialized_form(prop) + prop_rules(prop)[:serialized_form] + end + + def serialized_form_prop(serialized_form) + prop_by_serialized_forms[serialized_form.to_s] || raise("No such serialized form: #{serialized_form.inspect}") + end + + def add_prop_definition(prop, rules) + rules[:serialized_form] = rules.fetch(:name, prop.to_s) + res = super + prop_by_serialized_forms[rules[:serialized_form]] = prop + if T::Configuration.use_vm_prop_serde? + enqueue_lazy_vm_method_definition!(:__t_props_generated_serialize) {generate_serialize2} + enqueue_lazy_vm_method_definition!(:__t_props_generated_deserialize) {generate_deserialize2} + else + enqueue_lazy_method_definition!(:__t_props_generated_serialize) {generate_serialize_source} + enqueue_lazy_method_definition!(:__t_props_generated_deserialize) {generate_deserialize_source} + end + res + end + + private def generate_serialize_source + T::Props::Private::SerializerGenerator.generate(props) + end + + private def generate_deserialize_source + T::Props::Private::DeserializerGenerator.generate( + props, + props_with_defaults || {}, + ) + end + + private def generate_serialize2 + T::Props::Private::SerializerGenerator.generate2(decorated_class, props) + end + + private def generate_deserialize2 + T::Props::Private::DeserializerGenerator.generate2( + decorated_class, + props, + props_with_defaults || {}, + ) + end + + def message_with_generated_source_context(error, generated_method, generate_source_method) + line_label = error.backtrace.find {|l| l.end_with?("in `#{generated_method}'")} + return unless line_label + + line_num = line_label.split(':')[1]&.to_i + return unless line_num + + source_lines = self.send(generate_source_method).split("\n") + previous_blank = source_lines[0...line_num].rindex(&:empty?) || 0 + next_blank = line_num + (source_lines[line_num..-1]&.find_index(&:empty?) || 0) + context = " #{source_lines[(previous_blank + 1)...next_blank].join("\n ")}" + <<~MSG + Error in #{decorated_class.name}##{generated_method}: #{error.message} + at line #{line_num - previous_blank - 1} in: + #{context} + MSG + end + + def raise_nil_deserialize_error(hkey) + msg = "Tried to deserialize a required prop from a nil value. It's "\ + "possible that a nil value exists in the database, so you should "\ + "provide a `default: or factory:` for this prop (see go/optional "\ + "for more details). If this is already the case, you probably "\ + "omitted a required prop from the `fields:` option when doing a "\ + "partial load." + storytime = {prop: hkey, klass: decorated_class.name} + + # Notify the model owner if it exists, and always notify the API owner. + begin + if T::Configuration.class_owner_finder && (owner = T::Configuration.class_owner_finder.call(decorated_class)) + T::Configuration.hard_assert_handler( + msg, + storytime: storytime, + project: owner + ) + end + ensure + T::Configuration.hard_assert_handler(msg, storytime: storytime) + end + end + + def prop_validate_definition!(name, cls, rules, type) + result = super + + if (rules_name = rules[:name]) + unless rules_name.is_a?(String) + raise ArgumentError.new("Invalid name in prop #{@class.name}.#{name}: #{rules_name.inspect}") + end + + validate_prop_name(rules_name) + end + + if !rules[:raise_on_nil_write].nil? && rules[:raise_on_nil_write] != true + raise ArgumentError.new("The value of `raise_on_nil_write` if specified must be `true` (given: #{rules[:raise_on_nil_write]}).") + end + + result + end + + def get_id(instance) + prop = prop_by_serialized_forms['_id'] + if prop + get(instance, prop) + else + nil + end + end + + EMPTY_EXTRA_PROPS = {}.freeze + private_constant :EMPTY_EXTRA_PROPS + + def extra_props(instance) + if instance.instance_variable_defined?(:@_extra_props) + instance.instance_variable_get(:@_extra_props) || EMPTY_EXTRA_PROPS + else + EMPTY_EXTRA_PROPS + end + end + + # overrides T::Props::PrettyPrintable + private def inspect_instance_components(instance, multiline:, indent:) + if (extra_props = extra_props(instance)) && !extra_props.empty? + pretty_kvs = extra_props.map {|k, v| [k.to_sym, v.inspect]} + extra = join_props_with_pretty_values(pretty_kvs, multiline: false) + super + ["@_extra_props=<#{extra}>"] + else + super + end + end +end + +############################################## + +# NB: This must stay in the same file where T::Props::Serializable is defined due to +# T::Props::Decorator#apply_plugin; see https://git.corp.stripe.com/stripe-internal/pay-server/blob/fc7f15593b49875f2d0499ffecfd19798bac05b3/chalk/odm/lib/chalk-odm/document_decorator.rb#L716-L717 +module T::Props::Serializable::ClassMethods + def prop_by_serialized_forms + @prop_by_serialized_forms ||= {} + end + + # Allocate a new instance and call {#deserialize} to load a new + # object from a hash. + # @return [Serializable] + def from_hash(hash, strict=false) + self.decorator.from_hash(hash, strict) + end + + # Equivalent to {.from_hash} with `strict` set to true. + # @return [Serializable] + def from_hash!(hash) + self.decorator.from_hash(hash, true) + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/props/type_validation.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/props/type_validation.rb new file mode 100644 index 0000000000..ae3557783d --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/props/type_validation.rb @@ -0,0 +1,111 @@ +# frozen_string_literal: true +# typed: false + +module T::Props::TypeValidation + include T::Props::Plugin + + BANNED_TYPES = [Object, BasicObject, Kernel].freeze + + class UnderspecifiedType < ArgumentError; end + + module DecoratorMethods + extend T::Sig + + sig {params(key: Symbol).returns(T::Boolean).checked(:never)} + def valid_rule_key?(key) + super || key == :DEPRECATED_underspecified_type + end + + sig do + params( + name: T.any(Symbol, String), + _cls: Module, + rules: T::Hash[Symbol, T.untyped], + type: T.any(T::Types::Base, Module) + ) + .void + end + def prop_validate_definition!(name, _cls, rules, type) + super + + if !rules[:DEPRECATED_underspecified_type] + validate_type(type, field_name: name) + elsif rules[:DEPRECATED_underspecified_type] && find_invalid_subtype(type).nil? + raise ArgumentError.new("DEPRECATED_underspecified_type set unnecessarily for #{@class.name}.#{name} - #{type} is a valid type") + end + end + + sig do + params( + type: T::Types::Base, + field_name: T.any(Symbol, String), + ) + .void + end + private def validate_type(type, field_name:) + if (invalid_subtype = find_invalid_subtype(type)) + raise UnderspecifiedType.new(type_error_message(invalid_subtype, field_name, type)) + end + end + + # Returns an invalid type, if any, found in the given top-level type. + # This might be the type itself, if it is e.g. "Object", or might be + # a subtype like the type of the values of a typed hash. + # + # If the type is fully valid, returns nil. + # + # checked(:never) - called potentially many times recursively + sig {params(type: T::Types::Base).returns(T.nilable(T::Types::Base)).checked(:never)} + private def find_invalid_subtype(type) + case type + when T::Types::TypedEnumerable + find_invalid_subtype(type.type) + when T::Types::FixedHash + type.types.values.map {|subtype| find_invalid_subtype(subtype)}.compact.first + when T::Types::Union, T::Types::FixedArray + # `T.any` is valid if all of the members are valid + type.types.map {|subtype| find_invalid_subtype(subtype)}.compact.first + when T::Types::Intersection + # `T.all` is valid if at least one of the members is valid + invalid = type.types.map {|subtype| find_invalid_subtype(subtype)}.compact + if invalid.length == type.types.length + invalid.first + else + nil + end + when T::Types::Enum, T::Types::ClassOf + nil + when T::Private::Types::TypeAlias + find_invalid_subtype(type.aliased_type) + when T::Types::Simple + # TODO Could we manage to define a whitelist, consisting of something + # like primitives, subdocs, DataInterfaces, and collections/enums/unions + # thereof? + if BANNED_TYPES.include?(type.raw_type) + type + else + nil + end + else + type + end + end + + sig do + params( + type: T::Types::Base, + field_name: T.any(Symbol, String), + orig_type: T::Types::Base, + ) + .returns(String) + end + private def type_error_message(type, field_name, orig_type) + msg_prefix = "#{@class.name}.#{field_name}: #{orig_type} is invalid in prop definition" + if type == orig_type + "#{msg_prefix}. Please choose a more specific type (T.untyped and ~equivalents like Object are banned)." + else + "#{msg_prefix}. Please choose a subtype more specific than #{type} (T.untyped and ~equivalents like Object are banned)." + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/props/utils.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/props/utils.rb new file mode 100644 index 0000000000..33d1abadce --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/props/utils.rb @@ -0,0 +1,59 @@ +# frozen_string_literal: true +# typed: true + +module T::Props::Utils + # Deep copy an object. The object must consist of Ruby primitive + # types and Hashes and Arrays. + def self.deep_clone_object(what, freeze: false) + result = case what + when true + true + when false + false + when Symbol, NilClass, Numeric + what + when Array + what.map {|v| deep_clone_object(v, freeze: freeze)} + when Hash + h = what.class.new + what.each do |k, v| + k.freeze if freeze + h[k] = deep_clone_object(v, freeze: freeze) + end + h + when Regexp + what.dup + when T::Enum + what + else + what.clone + end + freeze ? result.freeze : result + end + + # The prop_rules indicate whether we should check for reading a nil value for the prop/field. + # This is mostly for the compatibility check that we allow existing documents carry some nil prop/field. + def self.need_nil_read_check?(prop_rules) + # . :on_load allows nil read, but we need to check for the read for future writes + prop_rules[:optional] == :on_load || prop_rules[:raise_on_nil_write] + end + + # The prop_rules indicate whether we should check for writing a nil value for the prop/field. + def self.need_nil_write_check?(prop_rules) + need_nil_read_check?(prop_rules) || T::Props::Utils.required_prop?(prop_rules) + end + + def self.required_prop?(prop_rules) + # Clients should never reference :_tnilable as the implementation can change. + !prop_rules[:_tnilable] + end + + def self.optional_prop?(prop_rules) + # Clients should never reference :_tnilable as the implementation can change. + !!prop_rules[:_tnilable] + end + + def self.merge_serialized_optional_rule(prop_rules) + {'_tnilable' => true}.merge(prop_rules.merge('_tnilable' => true)) + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/props/weak_constructor.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/props/weak_constructor.rb new file mode 100644 index 0000000000..3ffe1be695 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/props/weak_constructor.rb @@ -0,0 +1,67 @@ +# frozen_string_literal: true +# typed: false + +module T::Props::WeakConstructor + include T::Props::Optional + extend T::Sig + + # checked(:never) - O(runtime object construction) + sig {params(hash: T::Hash[Symbol, T.untyped]).void.checked(:never)} + def initialize(hash={}) + decorator = self.class.decorator + + hash_keys_matching_props = decorator.construct_props_with_defaults(self, hash) + + decorator.construct_props_without_defaults(self, hash) + + if hash_keys_matching_props < hash.size + raise ArgumentError.new("#{self.class}: Unrecognized properties: #{(hash.keys - decorator.props.keys).join(', ')}") + end + end +end + +module T::Props::WeakConstructor::DecoratorMethods + extend T::Sig + + # Set values for all props that have no defaults. Ignore any not present. + # + # @return [Integer] A count of props that we successfully initialized (which + # we'll use to check for any unrecognized input.) + # + # checked(:never) - O(runtime object construction) + sig {params(instance: T::Props::WeakConstructor, hash: T::Hash[Symbol, T.untyped]).returns(Integer).checked(:never)} + def construct_props_without_defaults(instance, hash) + # Use `each_pair` rather than `count` because, as of Ruby 2.6, the latter delegates to Enumerator + # and therefore allocates for each entry. + result = 0 + props_without_defaults&.each_pair do |p, setter_proc| + if hash.key?(p) + instance.instance_exec(hash[p], &setter_proc) + result += 1 + end + end + result + end + + # Set values for all props that have defaults. Use the default if and only if + # the prop key isn't in the input. + # + # @return [Integer] A count of props that we successfully initialized (which + # we'll use to check for any unrecognized input.) + # + # checked(:never) - O(runtime object construction) + sig {params(instance: T::Props::WeakConstructor, hash: T::Hash[Symbol, T.untyped]).returns(Integer).checked(:never)} + def construct_props_with_defaults(instance, hash) + # Use `each_pair` rather than `count` because, as of Ruby 2.6, the latter delegates to Enumerator + # and therefore allocates for each entry. + result = 0 + props_with_defaults&.each_pair do |p, default_struct| + if hash.key?(p) + instance.instance_exec(hash[p], &default_struct.setter_proc) + result += 1 + else + default_struct.set_default(instance) + end + end + result + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/sig.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/sig.rb new file mode 100644 index 0000000000..3112adf861 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/sig.rb @@ -0,0 +1,30 @@ +# frozen_string_literal: true +# typed: strict + +# Used as a mixin to any class so that you can call `sig`. +# Docs at https://sorbet.org/docs/sigs +module T::Sig + module WithoutRuntime + # At runtime, does nothing, but statically it is treated exactly the same + # as T::Sig#sig. Only use it in cases where you can't use T::Sig#sig. + def self.sig(arg0=nil, &blk); end + + original_verbose = $VERBOSE + $VERBOSE = false + + # At runtime, does nothing, but statically it is treated exactly the same + # as T::Sig#sig. Only use it in cases where you can't use T::Sig#sig. + T::Sig::WithoutRuntime.sig {params(arg0: T.nilable(Symbol), blk: T.proc.bind(T::Private::Methods::DeclBuilder).void).void} + def self.sig(arg0=nil, &blk); end # rubocop:disable Lint/DuplicateMethods + + $VERBOSE = original_verbose + end + + # Declares a method with type signatures and/or + # abstract/override/... helpers. See the documentation URL on + # {T::Helpers} + T::Sig::WithoutRuntime.sig {params(arg0: T.nilable(Symbol), blk: T.proc.bind(T::Private::Methods::DeclBuilder).void).void} + def sig(arg0=nil, &blk) + T::Private::Methods.declare_sig(self, Kernel.caller_locations(1, 1)&.first, arg0, &blk) + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/struct.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/struct.rb new file mode 100644 index 0000000000..79e6b303d3 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/struct.rb @@ -0,0 +1,51 @@ +# frozen_string_literal: true +# typed: true + +class T::InexactStruct + include T::Props + include T::Props::Serializable + include T::Props::Constructor +end + +class T::Struct < T::InexactStruct + def self.inherited(subclass) + super(subclass) + T::Private::ClassUtils.replace_method(subclass.singleton_class, :inherited) do |s| + super(s) + raise "#{self.name} is a subclass of T::Struct and cannot be subclassed" + end + end +end + +class T::ImmutableStruct < T::InexactStruct + extend T::Sig + + def self.inherited(subclass) + super(subclass) + + T::Private::ClassUtils.replace_method(subclass.singleton_class, :inherited) do |s| + super(s) + raise "#{self.name} is a subclass of T::ImmutableStruct and cannot be subclassed" + end + end + + # Matches the one in WeakConstructor, but freezes the object + sig {params(hash: T::Hash[Symbol, T.untyped]).void.checked(:never)} + def initialize(hash={}) + super + + freeze + end + + # Matches the signature in Props, but raises since this is an immutable struct and only const is allowed + sig {params(name: Symbol, cls: T.untyped, rules: T.untyped).void} + def self.prop(name, cls, rules={}) + return super if (cls.is_a?(Hash) && cls[:immutable]) || rules[:immutable] + + raise "Cannot use `prop` in #{self.name} because it is an immutable struct. Use `const` instead" + end + + def with(changed_props) + raise "Cannot use `with` in #{self.class.name} because it is an immutable struct" + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/attached_class.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/attached_class.rb new file mode 100644 index 0000000000..059956a68d --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/attached_class.rb @@ -0,0 +1,37 @@ +# frozen_string_literal: true +# typed: true + +module T::Types + # Modeling AttachedClass properly at runtime would require additional + # tracking, so at runtime we permit all values and rely on the static checker. + # As AttachedClass is modeled statically as a type member on every singleton + # class, this is consistent with the runtime behavior for all type members. + class AttachedClassType < Base + + def initialize(); end + + # overrides Base + def name + "T.attached_class" + end + + # overrides Base + def valid?(obj) + true + end + + # overrides Base + private def subtype_of_single?(other) + case other + when AttachedClassType + true + else + false + end + end + + module Private + INSTANCE = AttachedClassType.new.freeze + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/base.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/base.rb new file mode 100644 index 0000000000..cce89b178a --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/base.rb @@ -0,0 +1,172 @@ +# frozen_string_literal: true +# typed: true + +module T::Types + class Base + def self.method_added(method_name) + super(method_name) + # What is now `subtype_of_single?` used to be named `subtype_of?`. Make sure people don't + # override the wrong thing. + # + # NB: Outside of T::Types, we would enforce this by using `sig` and not declaring the method + # as overridable, but doing so here would result in a dependency cycle. + if method_name == :subtype_of? && self != T::Types::Base + raise "`subtype_of?` should not be overridden. You probably want to override " \ + "`subtype_of_single?` instead." + end + end + + # this will be redefined in certain subclasses + def recursively_valid?(obj) + valid?(obj) + end + + def valid?(obj) + raise NotImplementedError + end + + # @return [T::Boolean] This method must be implemented to return whether the subclass is a subtype + # of `type`. This should only be called by `subtype_of?`, which guarantees that `type` will be + # a "single" type, by which we mean it won't be a Union or an Intersection (c.f. + # `isSubTypeSingle` in sorbet). + private def subtype_of_single?(type) + raise NotImplementedError + end + + # Equality is based on name, so be sure the name reflects all relevant state when implementing. + def name + raise NotImplementedError + end + + # Mirrors ruby_typer::core::Types::isSubType + # See https://git.corp.stripe.com/stripe-internal/ruby-typer/blob/9fc8ed998c04ac0b96592ae6bb3493b8a925c5c1/core/types/subtyping.cc#L912-L950 + # + # This method cannot be overridden (see `method_added` above). + # Subclasses only need to implement `subtype_of_single?`). + def subtype_of?(t2) + t1 = self + + if t2.is_a?(T::Private::Types::TypeAlias) + t2 = t2.aliased_type + end + + if t1.is_a?(T::Private::Types::TypeAlias) + return t1.aliased_type.subtype_of?(t2) + end + + # pairs to cover: 1 (_, _) + # 2 (_, And) + # 3 (_, Or) + # 4 (And, _) + # 5 (And, And) + # 6 (And, Or) + # 7 (Or, _) + # 8 (Or, And) + # 9 (Or, Or) + + # Note: order of cases here matters! + if t1.is_a?(T::Types::Union) # 7, 8, 9 + # this will be incorrect if/when we have Type members + return t1.types.all? {|t1_member| t1_member.subtype_of?(t2)} + end + + if t2.is_a?(T::Types::Intersection) # 2, 5 + # this will be incorrect if/when we have Type members + return t2.types.all? {|t2_member| t1.subtype_of?(t2_member)} + end + + if t2.is_a?(T::Types::Union) + if t1.is_a?(T::Types::Intersection) # 6 + # dropping either of parts eagerly make subtype test be too strict. + # we have to try both cases, when we normally try only one + return t2.types.any? {|t2_member| t1.subtype_of?(t2_member)} || + t1.types.any? {|t1_member| t1_member.subtype_of?(t2)} + end + return t2.types.any? {|t2_member| t1.subtype_of?(t2_member)} # 3 + end + + if t1.is_a?(T::Types::Intersection) # 4 + # this will be incorrect if/when we have Type members + return t1.types.any? {|t1_member| t1_member.subtype_of?(t2)} + end + + # 1; Start with some special cases + if t1.is_a?(T::Private::Types::Void) + return t2.is_a?(T::Private::Types::Void) + end + + if t1.is_a?(T::Types::Untyped) || t2.is_a?(T::Types::Untyped) + return true + end + + # Rest of (1) + subtype_of_single?(t2) + end + + def to_s + name + end + + def describe_obj(obj) + # Would be redundant to print class and value in these common cases. + case obj + when nil, true, false + return "type #{obj.class}" + end + + # In rare cases, obj.inspect may fail, or be undefined, so rescue. + begin + # Default inspect behavior of, eg; `#` is ugly; just print the hash instead, which is more concise/readable. + if obj.method(:inspect).owner == Kernel + "type #{obj.class} with hash #{obj.hash}" + elsif T::Configuration.include_value_in_type_errors? + "type #{obj.class} with value #{T::Utils.string_truncate_middle(obj.inspect, 30, 30)}" + else + "type #{obj.class}" + end + rescue StandardError, SystemStackError + "type #{obj.class} with unprintable value" + end + end + + def error_message_for_obj(obj) + if valid?(obj) + nil + else + error_message(obj) + end + end + + def error_message_for_obj_recursive(obj) + if recursively_valid?(obj) + nil + else + error_message(obj) + end + end + + private def error_message(obj) + "Expected type #{self.name}, got #{describe_obj(obj)}" + end + + def validate!(obj) + err = error_message_for_obj(obj) + raise TypeError.new(err) if err + end + + ### Equality methods (necessary for deduping types with `uniq`) + + def hash + name.hash + end + + # Type equivalence, defined by serializing the type to a string (with + # `#name`) and comparing the resulting strings for equality. + def ==(other) + (T::Utils.resolve_alias(other).class == T::Utils.resolve_alias(self).class) && + other.name == self.name + end + + alias_method :eql?, :== + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/class_of.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/class_of.rb new file mode 100644 index 0000000000..d56f21d4c7 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/class_of.rb @@ -0,0 +1,40 @@ +# frozen_string_literal: true +# typed: true + +module T::Types + # Validates that an object belongs to the specified class. + class ClassOf < Base + attr_reader :type + + def initialize(type) + @type = type + end + + # overrides Base + def name + "T.class_of(#{@type})" + end + + # overrides Base + def valid?(obj) + obj.is_a?(Module) && obj <= @type + end + + # overrides Base + def subtype_of_single?(other) + case other + when ClassOf + @type <= other.type + when Simple + @type.is_a?(other.raw_type) + else + false + end + end + + # overrides Base + def describe_obj(obj) + obj.inspect + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/enum.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/enum.rb new file mode 100644 index 0000000000..97ecfe0c0c --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/enum.rb @@ -0,0 +1,40 @@ +# frozen_string_literal: true +# typed: true + +module T::Types + # validates that the provided value is within a given set/enum + class Enum < Base + extend T::Sig + + attr_reader :values + + def initialize(values) + @values = values + end + + # overrides Base + def valid?(obj) + @values.member?(obj) + end + + # overrides Base + private def subtype_of_single?(other) + case other + when Enum + (other.values - @values).empty? + else + false + end + end + + # overrides Base + def name + "T.deprecated_enum([#{@values.map(&:inspect).join(', ')}])" + end + + # overrides Base + def describe_obj(obj) + obj.inspect + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/fixed_array.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/fixed_array.rb new file mode 100644 index 0000000000..3bed082bcc --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/fixed_array.rb @@ -0,0 +1,86 @@ +# frozen_string_literal: true +# https://jira.corp.stripe.com/browse/RUBYPLAT-1107 +# typed: false + +module T::Types + # Takes a list of types. Validates each item in an array using the type in the same position + # in the list. + class FixedArray < Base + attr_reader :types + + def initialize(types) + @types = types.map {|type| T::Utils.coerce(type)} + end + + # overrides Base + def name + "[#{@types.join(', ')}]" + end + + # overrides Base + def recursively_valid?(obj) + if obj.is_a?(Array) && obj.length == @types.length + i = 0 + while i < @types.length + if !@types[i].recursively_valid?(obj[i]) + return false + end + i += 1 + end + true + else + false + end + end + + # overrides Base + def valid?(obj) + if obj.is_a?(Array) && obj.length == @types.length + i = 0 + while i < @types.length + if !@types[i].valid?(obj[i]) + return false + end + i += 1 + end + true + else + false + end + end + + # overrides Base + private def subtype_of_single?(other) + case other + when FixedArray + # Properly speaking, covariance here is unsound since arrays + # can be mutated, but sorbet implements covariant tuples for + # ease of adoption. + @types.size == other.types.size && @types.zip(other.types).all? do |t1, t2| + t1.subtype_of?(t2) + end + else + false + end + end + + # This gives us better errors, e.g.: + # "Expected [String, Symbol], got [String, String]" + # instead of + # "Expected [String, Symbol], got Array". + # + # overrides Base + def describe_obj(obj) + if obj.is_a?(Array) + if obj.length == @types.length + item_classes = obj.map(&:class).join(', ') + "type [#{item_classes}]" + else + "array of size #{obj.length}" + end + else + super + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/fixed_hash.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/fixed_hash.rb new file mode 100644 index 0000000000..d8fddb3703 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/fixed_hash.rb @@ -0,0 +1,74 @@ +# frozen_string_literal: true +# typed: true + +module T::Types + # Takes a hash of types. Validates each item in a hash using the type in the same position + # in the list. + class FixedHash < Base + attr_reader :types + + def initialize(types) + @types = types.transform_values {|v| T::Utils.coerce(v)} + end + + # overrides Base + def name + serialize_hash(@types) + end + + # overrides Base + def recursively_valid?(obj) + return false unless obj.is_a?(Hash) + return false if @types.any? {|key, type| !type.recursively_valid?(obj[key])} + return false if obj.any? {|key, _| !@types[key]} + true + end + + # overrides Base + def valid?(obj) + return false unless obj.is_a?(Hash) + return false if @types.any? {|key, type| !type.valid?(obj[key])} + return false if obj.any? {|key, _| !@types[key]} + true + end + + # overrides Base + private def subtype_of_single?(other) + case other + when FixedHash + # Using `subtype_of?` here instead of == would be unsound + @types == other.types + else + false + end + end + + # This gives us better errors, e.g.: + # `Expected {a: String}, got {a: TrueClass}` + # instead of + # `Expected {a: String}, got Hash`. + # + # overrides Base + def describe_obj(obj) + if obj.is_a?(Hash) + "type #{serialize_hash(obj.transform_values(&:class))}" + else + super + end + end + + private + + def serialize_hash(hash) + entries = hash.map do |(k, v)| + if Symbol === k && ":#{k}" == k.inspect + "#{k}: #{v}" + else + "#{k.inspect} => #{v}" + end + end + + "{#{entries.join(', ')}}" + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/intersection.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/intersection.rb new file mode 100644 index 0000000000..e55295fe1c --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/intersection.rb @@ -0,0 +1,42 @@ +# frozen_string_literal: true +# typed: true + +module T::Types + # Takes a list of types. Validates that an object matches all of the types. + class Intersection < Base + attr_reader :types + + def initialize(types) + @types = types.flat_map do |type| + type = T::Utils.resolve_alias(type) + if type.is_a?(Intersection) + # Simplify nested intersections (mostly so `name` returns a nicer value) + type.types + else + T::Utils.coerce(type) + end + end.uniq + end + + # overrides Base + def name + "T.all(#{@types.map(&:name).compact.sort.join(', ')})" + end + + # overrides Base + def recursively_valid?(obj) + @types.all? {|type| type.recursively_valid?(obj)} + end + + # overrides Base + def valid?(obj) + @types.all? {|type| type.valid?(obj)} + end + + # overrides Base + private def subtype_of_single?(other) + raise "This should never be reached if you're going through `subtype_of?` (and you should be)" + end + + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/noreturn.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/noreturn.rb new file mode 100644 index 0000000000..c285797480 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/noreturn.rb @@ -0,0 +1,29 @@ +# frozen_string_literal: true +# typed: true + +module T::Types + # The bottom type + class NoReturn < Base + + def initialize; end + + # overrides Base + def name + "T.noreturn" + end + + # overrides Base + def valid?(obj) + false + end + + # overrides Base + private def subtype_of_single?(other) + true + end + + module Private + INSTANCE = NoReturn.new.freeze + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/proc.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/proc.rb new file mode 100644 index 0000000000..aece6a3a2f --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/proc.rb @@ -0,0 +1,51 @@ +# frozen_string_literal: true +# typed: true + +module T::Types + # Defines the type of a proc (a ruby callable). At runtime, only + # validates that the value is a `::Proc`. + # + # At present, we only support fixed-arity procs with no optional or + # keyword arguments. + class Proc < Base + attr_reader :arg_types + attr_reader :returns + + def initialize(arg_types, returns) + @arg_types = {} + arg_types.each do |key, raw_type| + @arg_types[key] = T::Utils.coerce(raw_type) + end + @returns = T::Utils.coerce(returns) + end + + # overrides Base + def name + args = [] + @arg_types.each do |k, v| + args << "#{k}: #{v.name}" + end + "T.proc.params(#{args.join(', ')}).returns(#{returns})" + end + + # overrides Base + def valid?(obj) + obj.is_a?(::Proc) + end + + # overrides Base + private def subtype_of_single?(other) + case other + when self.class + if arg_types.size != other.arg_types.size + return false + end + arg_types.values.zip(other.arg_types.values).all? do |a, b| + b.subtype_of?(a) + end && returns.subtype_of?(other.returns) + else + false + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/self_type.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/self_type.rb new file mode 100644 index 0000000000..e431a3e0f9 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/self_type.rb @@ -0,0 +1,35 @@ +# frozen_string_literal: true +# typed: true + +module T::Types + # Modeling self-types properly at runtime would require additional tracking, + # so at runtime we permit all values and rely on the static checker. + class SelfType < Base + + def initialize(); end + + # overrides Base + def name + "T.self_type" + end + + # overrides Base + def valid?(obj) + true + end + + # overrides Base + private def subtype_of_single?(other) + case other + when SelfType + true + else + false + end + end + + module Private + INSTANCE = SelfType.new.freeze + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/simple.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/simple.rb new file mode 100644 index 0000000000..2789adbb67 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/simple.rb @@ -0,0 +1,94 @@ +# frozen_string_literal: true +# typed: true + +module T::Types + # Validates that an object belongs to the specified class. + class Simple < Base + attr_reader :raw_type + + def initialize(raw_type) + @raw_type = raw_type + end + + # overrides Base + def name + # Memoize to mitigate pathological performance with anonymous modules (https://bugs.ruby-lang.org/issues/11119) + # + # `name` isn't normally a hot path for types, but it is used in initializing a T::Types::Union, + # and so in `T.nilable`, and so in runtime constructions like `x = T.let(nil, T.nilable(Integer))`. + @name ||= @raw_type.name.freeze + end + + # overrides Base + def valid?(obj) + obj.is_a?(@raw_type) + end + + # overrides Base + private def subtype_of_single?(other) + case other + when Simple + @raw_type <= other.raw_type + else + false + end + end + + # overrides Base + private def error_message(obj) + error_message = super(obj) + actual_name = obj.class.name + + return error_message unless name == actual_name + + <<~MSG.strip + #{error_message} + + The expected type and received object type have the same name but refer to different constants. + Expected type is #{name} with object id #{@raw_type.__id__}, but received type is #{actual_name} with object id #{obj.class.__id__}. + + There might be a constant reloading problem in your application. + MSG + end + + def to_nilable + @nilable ||= T::Types::Union.new([self, T::Utils::Nilable::NIL_TYPE]) + end + + module Private + module Pool + @cache = ObjectSpace::WeakMap.new + + def self.type_for_module(mod) + cached = @cache[mod] + return cached if cached + + type = if mod == ::Array + T::Array[T.untyped] + elsif mod == ::Hash + T::Hash[T.untyped, T.untyped] + elsif mod == ::Enumerable + T::Enumerable[T.untyped] + elsif mod == ::Enumerator + T::Enumerator[T.untyped] + elsif mod == ::Range + T::Range[T.untyped] + elsif !Object.autoload?(:Set) && Object.const_defined?(:Set) && mod == ::Set + T::Set[T.untyped] + else + Simple.new(mod) + end + + # Unfortunately, we still need to check if the module is frozen, + # since WeakMap adds a finalizer to the key that is added + # to the map, so that it can clear the map entry when the key is + # garbage collected. + # For a frozen object, though, adding a finalizer is not a valid + # operation, so this still raises if `mod` is frozen. + @cache[mod] = type unless mod.frozen? + type + end + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/t_enum.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/t_enum.rb new file mode 100644 index 0000000000..121368c7b6 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/t_enum.rb @@ -0,0 +1,38 @@ +# frozen_string_literal: true +# typed: true + +module T::Types + # Validates that an object is equal to another T::Enum singleton value. + class TEnum < Base + attr_reader :val + + def initialize(val) + @val = val + end + + # overrides Base + def name + # Strips the #<...> off, just leaving the ... + # Reasoning: the user will have written something like + # T.any(MyEnum::A, MyEnum::B) + # in the type, so we should print what they wrote in errors, not: + # T.any(#, #) + @val.inspect[2..-2] + end + + # overrides Base + def valid?(obj) + @val == obj + end + + # overrides Base + private def subtype_of_single?(other) + case other + when TEnum + @val == other.val + else + false + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/type_member.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/type_member.rb new file mode 100644 index 0000000000..fadd2a7eea --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/type_member.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true +# typed: strict + +module T::Types + class TypeMember < TypeVariable + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/type_parameter.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/type_parameter.rb new file mode 100644 index 0000000000..ea82a07cc3 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/type_parameter.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true +# typed: true + +module T::Types + class TypeParameter < Base + def initialize(name) + raise ArgumentError.new("not a symbol: #{name}") unless name.is_a?(Symbol) + @name = name + end + + def valid?(obj) + true + end + + def subtype_of_single?(type) + true + end + + def name + "T.type_parameter(:#{@name})" + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/type_template.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/type_template.rb new file mode 100644 index 0000000000..8c83de8949 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/type_template.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true +# typed: strict + +module T::Types + class TypeTemplate < TypeVariable + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/type_variable.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/type_variable.rb new file mode 100644 index 0000000000..187119167d --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/type_variable.rb @@ -0,0 +1,34 @@ +# frozen_string_literal: true +# typed: true + +module T::Types + # Since we do type erasure at runtime, this just validates the variance and + # provides some syntax for the static type checker + class TypeVariable < Base + attr_reader :variance + + VALID_VARIANCES = %i[in out invariant].freeze + + def initialize(variance) + case variance + when Hash then raise ArgumentError.new("Pass bounds using a block. Got: #{variance}") + when *VALID_VARIANCES then nil + else + raise TypeError.new("invalid variance #{variance}") + end + @variance = variance + end + + def valid?(obj) + true + end + + def subtype_of_single?(type) + true + end + + def name + Untyped.new.name + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/typed_array.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/typed_array.rb new file mode 100644 index 0000000000..0b5f3541a9 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/typed_array.rb @@ -0,0 +1,39 @@ +# frozen_string_literal: true +# typed: true + +module T::Types + class TypedArray < TypedEnumerable + # overrides Base + def name + "T::Array[#{@type.name}]" + end + + def underlying_class + Array + end + + # overrides Base + def recursively_valid?(obj) + obj.is_a?(Array) && super + end + + # overrides Base + def valid?(obj) + obj.is_a?(Array) + end + + def new(*args) + Array.new(*T.unsafe(args)) + end + + class Untyped < TypedArray + def initialize + super(T.untyped) + end + + def valid?(obj) + obj.is_a?(Array) + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/typed_enumerable.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/typed_enumerable.rb new file mode 100644 index 0000000000..65c2631f0a --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/typed_enumerable.rb @@ -0,0 +1,176 @@ +# frozen_string_literal: true +# typed: true + +module T::Types + # Note: All subclasses of Enumerable should add themselves to the + # `case` statement below in `describe_obj` in order to get better + # error messages. + class TypedEnumerable < Base + attr_reader :type + + def initialize(type) + @type = T::Utils.coerce(type) + end + + def underlying_class + Enumerable + end + + # overrides Base + def name + "T::Enumerable[#{@type.name}]" + end + + # overrides Base + def valid?(obj) + obj.is_a?(Enumerable) + end + + # overrides Base + def recursively_valid?(obj) + return false unless obj.is_a?(Enumerable) + case obj + when Array + begin + it = 0 + while it < obj.count + return false unless @type.recursively_valid?(obj[it]) + it += 1 + end + true + end + when Hash + return false unless @type.is_a?(FixedArray) + types = @type.types + return false if types.count != 2 + key_type = types[0] + value_type = types[1] + obj.each_pair do |key, val| + # Some objects (I'm looking at you Rack::Utils::HeaderHash) don't + # iterate over a [key, value] array, so we can't juse use the @type.recursively_valid?(v) + return false if !key_type.recursively_valid?(key) || !value_type.recursively_valid?(val) + end + true + when Enumerator::Lazy + # Enumerators can be unbounded: see `[:foo, :bar].cycle` + true + when Enumerator + # Enumerators can be unbounded: see `[:foo, :bar].cycle` + true + when Range + # A nil beginning or a nil end does not provide any type information. That is, nil in a range represents + # boundlessness, it does not express a type. For example `(nil...nil)` is not a T::Range[NilClass], its a range + # of unknown types (T::Range[T.untyped]). + # Similarly, `(nil...1)` is not a `T::Range[T.nilable(Integer)]`, it's a boundless range of Integer. + (obj.begin.nil? || @type.recursively_valid?(obj.begin)) && (obj.end.nil? || @type.recursively_valid?(obj.end)) + when Set + obj.each do |item| + return false unless @type.recursively_valid?(item) + end + + true + else + # We don't check the enumerable since it isn't guaranteed to be + # rewindable (e.g. STDIN) and it may be expensive to enumerate + # (e.g. an enumerator that makes an HTTP request)" + true + end + end + + # overrides Base + private def subtype_of_single?(other) + if other.class <= TypedEnumerable && + underlying_class <= other.underlying_class + # Enumerables are covariant because they are read only + # + # Properly speaking, many Enumerable subtypes (e.g. Set) + # should be invariant because they are mutable and support + # both reading and writing. However, Sorbet treats *all* + # Enumerable subclasses as covariant for ease of adoption. + @type.subtype_of?(other.type) + else + false + end + end + + # overrides Base + def describe_obj(obj) + return super unless obj.is_a?(Enumerable) + type_from_instance(obj).name + end + + private def type_from_instances(objs) + return objs.class unless objs.is_a?(Enumerable) + obtained_types = [] + begin + objs.each do |x| + obtained_types << type_from_instance(x) + end + rescue + return T.untyped # all we can do is go with the types we have so far + end + if obtained_types.count > 1 + # Multiple kinds of bad types showed up, we'll suggest a union + # type you might want. + Union.new(obtained_types) + elsif obtained_types.empty? + T.noreturn + else + # Everything was the same bad type, lets just show that + obtained_types.first + end + end + + private def type_from_instance(obj) + if [true, false].include?(obj) + return T::Boolean + elsif !obj.is_a?(Enumerable) + return obj.class + end + + case obj + when Array + T::Array[type_from_instances(obj)] + when Hash + inferred_key = type_from_instances(obj.keys) + inferred_val = type_from_instances(obj.values) + T::Hash[inferred_key, inferred_val] + when Range + # We can't get any information from `NilClass` in ranges (since nil is used to represent boundlessness). + typeable_objects = [obj.begin, obj.end].compact + if typeable_objects.empty? + T::Range[T.untyped] + else + T::Range[type_from_instances(typeable_objects)] + end + when Enumerator::Lazy + T::Enumerator::Lazy[type_from_instances(obj)] + when Enumerator + T::Enumerator[type_from_instances(obj)] + when Set + T::Set[type_from_instances(obj)] + when IO + # Short circuit for anything IO-like (File, etc.). In these cases, + # enumerating the object is a destructive operation and might hang. + obj.class + else + # This is a specialized enumerable type, just return the class. + if T::Configuration::AT_LEAST_RUBY_2_7 + Object.instance_method(:class).bind_call(obj) + else + Object.instance_method(:class).bind(obj).call + end + end + end + + class Untyped < TypedEnumerable + def initialize + super(T.untyped) + end + + def valid?(obj) + obj.is_a?(Enumerable) + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/typed_enumerator.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/typed_enumerator.rb new file mode 100644 index 0000000000..e79341eb94 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/typed_enumerator.rb @@ -0,0 +1,41 @@ +# frozen_string_literal: true +# typed: true + +module T::Types + class TypedEnumerator < TypedEnumerable + attr_reader :type + + def underlying_class + Enumerator + end + + # overrides Base + def name + "T::Enumerator[#{@type.name}]" + end + + # overrides Base + def recursively_valid?(obj) + obj.is_a?(Enumerator) && super + end + + # overrides Base + def valid?(obj) + obj.is_a?(Enumerator) + end + + def new(*args, &blk) + T.unsafe(Enumerator).new(*args, &blk) + end + + class Untyped < TypedEnumerator + def initialize + super(T.untyped) + end + + def valid?(obj) + obj.is_a?(Enumerator) + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/typed_enumerator_lazy.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/typed_enumerator_lazy.rb new file mode 100644 index 0000000000..3569be398a --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/typed_enumerator_lazy.rb @@ -0,0 +1,41 @@ +# frozen_string_literal: true +# typed: true + +module T::Types + class TypedEnumeratorLazy < TypedEnumerable + attr_reader :type + + def underlying_class + Enumerator::Lazy + end + + # overrides Base + def name + "T::Enumerator::Lazy[#{@type.name}]" + end + + # overrides Base + def recursively_valid?(obj) + obj.is_a?(Enumerator::Lazy) && super + end + + # overrides Base + def valid?(obj) + obj.is_a?(Enumerator::Lazy) + end + + def new(*args, &blk) + T.unsafe(Enumerator::Lazy).new(*args, &blk) + end + + class Untyped < TypedEnumeratorLazy + def initialize + super(T.untyped) + end + + def valid?(obj) + obj.is_a?(Enumerator::Lazy) + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/typed_hash.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/typed_hash.rb new file mode 100644 index 0000000000..f48e0c1595 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/typed_hash.rb @@ -0,0 +1,48 @@ +# frozen_string_literal: true +# typed: true + +module T::Types + class TypedHash < TypedEnumerable + # Technically we don't need these, but they are a nice api + attr_reader :keys, :values + + def underlying_class + Hash + end + + def initialize(keys:, values:) + @keys = T::Utils.coerce(keys) + @values = T::Utils.coerce(values) + @type = T::Utils.coerce([keys, values]) + end + + # overrides Base + def name + "T::Hash[#{@keys.name}, #{@values.name}]" + end + + # overrides Base + def recursively_valid?(obj) + obj.is_a?(Hash) && super + end + + # overrides Base + def valid?(obj) + obj.is_a?(Hash) + end + + def new(*args, &blk) + Hash.new(*T.unsafe(args), &blk) + end + + class Untyped < TypedHash + def initialize + super(keys: T.untyped, values: T.untyped) + end + + def valid?(obj) + obj.is_a?(Hash) + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/typed_range.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/typed_range.rb new file mode 100644 index 0000000000..50e2ef9d53 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/typed_range.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true +# typed: true + +module T::Types + class TypedRange < TypedEnumerable + attr_reader :type + + def underlying_class + Hash + end + + # overrides Base + def name + "T::Range[#{@type.name}]" + end + + # overrides Base + def recursively_valid?(obj) + obj.is_a?(Range) && super + end + + # overrides Base + def valid?(obj) + obj.is_a?(Range) + end + + def new(*args) + T.unsafe(Range).new(*args) + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/typed_set.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/typed_set.rb new file mode 100644 index 0000000000..8c1b2caee3 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/typed_set.rb @@ -0,0 +1,53 @@ +# frozen_string_literal: true +# typed: true + +module T::Types + class TypedSet < TypedEnumerable + attr_reader :type + + def underlying_class + Hash + end + + # overrides Base + def name + "T::Set[#{@type.name}]" + end + + # overrides Base + def recursively_valid?(obj) + # Re-implements non_forcing_is_a? + return false if Object.autoload?(:Set) # Set is meant to be autoloaded but not yet loaded, this value can't be a Set + return false unless Object.const_defined?(:Set) # Set is not loaded yet + obj.is_a?(Set) && super + end + + # overrides Base + def valid?(obj) + # Re-implements non_forcing_is_a? + return false if Object.autoload?(:Set) # Set is meant to be autoloaded but not yet loaded, this value can't be a Set + return false unless Object.const_defined?(:Set) # Set is not loaded yet + obj.is_a?(Set) + end + + def new(*args) + # Fine for this to blow up, because hopefully if they're trying to make a + # Set, they don't mind putting (or already have put) a `require 'set'` in + # their program directly. + Set.new(*T.unsafe(args)) + end + + class Untyped < TypedSet + def initialize + super(T.untyped) + end + + def valid?(obj) + # Re-implements non_forcing_is_a? + return false if Object.autoload?(:Set) # Set is meant to be autoloaded but not yet loaded, this value can't be a Set + return false unless Object.const_defined?(:Set) # Set is not loaded yet + obj.is_a?(Set) + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/union.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/union.rb new file mode 100644 index 0000000000..3729dc48de --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/union.rb @@ -0,0 +1,91 @@ +# frozen_string_literal: true +# typed: true + +module T::Types + # Takes a list of types. Validates that an object matches at least one of the types. + class Union < Base + attr_reader :types + + def initialize(types) + @types = types.flat_map do |type| + type = T::Utils.coerce(type) + if type.is_a?(Union) + # Simplify nested unions (mostly so `name` returns a nicer value) + type.types + else + type + end + end.uniq + end + + # overrides Base + def name + type_shortcuts(@types) + end + + private def type_shortcuts(types) + if types.size == 1 + return types[0].name + end + nilable = T::Utils.coerce(NilClass) + trueclass = T::Utils.coerce(TrueClass) + falseclass = T::Utils.coerce(FalseClass) + if types.any? {|t| t == nilable} + remaining_types = types.reject {|t| t == nilable} + "T.nilable(#{type_shortcuts(remaining_types)})" + elsif types.any? {|t| t == trueclass} && types.any? {|t| t == falseclass} + remaining_types = types.reject {|t| t == trueclass || t == falseclass} + type_shortcuts([T::Private::Types::StringHolder.new("T::Boolean")] + remaining_types) + else + names = types.map(&:name).compact.sort + "T.any(#{names.join(', ')})" + end + end + + # overrides Base + def recursively_valid?(obj) + @types.any? {|type| type.recursively_valid?(obj)} + end + + # overrides Base + def valid?(obj) + @types.any? {|type| type.valid?(obj)} + end + + # overrides Base + private def subtype_of_single?(other) + raise "This should never be reached if you're going through `subtype_of?` (and you should be)" + end + + module Private + module Pool + EMPTY_ARRAY = [].freeze + private_constant :EMPTY_ARRAY + + # @param type_a [T::Types::Base] + # @param type_b [T::Types::Base] + # @param types [Array] optional array of additional T::Types::Base instances + def self.union_of_types(type_a, type_b, types=EMPTY_ARRAY) + if types.empty? + # We aren't guaranteed to detect a simple `T.nilable()` type here + # in cases where there are duplicate types, nested unions, etc. + # + # That's ok, because this is an optimization which isn't necessary for + # correctness. + if type_b == T::Utils::Nilable::NIL_TYPE && type_a.is_a?(T::Types::Simple) + type_a.to_nilable + elsif type_a == T::Utils::Nilable::NIL_TYPE && type_b.is_a?(T::Types::Simple) + type_b.to_nilable + else + Union.new([type_a, type_b]) + end + else + # This can't be a `T.nilable()` case unless there are duplicates, + # which is possible but unexpected. + Union.new([type_a, type_b] + types) + end + end + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/untyped.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/untyped.rb new file mode 100644 index 0000000000..a06a633d42 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/types/untyped.rb @@ -0,0 +1,29 @@ +# frozen_string_literal: true +# typed: true + +module T::Types + # A dynamic type, which permits whatever + class Untyped < Base + + def initialize; end + + # overrides Base + def name + "T.untyped" + end + + # overrides Base + def valid?(obj) + true + end + + # overrides Base + private def subtype_of_single?(other) + true + end + + module Private + INSTANCE = Untyped.new.freeze + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/utils.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/utils.rb new file mode 100644 index 0000000000..4aa60fa74b --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/sorbet-runtime-0.5.10461/lib/types/utils.rb @@ -0,0 +1,209 @@ +# frozen_string_literal: true +# typed: true + +module T::Utils + # Used to convert from a type specification to a `T::Types::Base`. + def self.coerce(val) + if val.is_a?(T::Private::Types::TypeAlias) + val.aliased_type + elsif val.is_a?(T::Types::Base) + val + elsif val.is_a?(Module) + T::Types::Simple::Private::Pool.type_for_module(val) + elsif val.is_a?(::Array) + T::Types::FixedArray.new(val) + elsif val.is_a?(::Hash) + T::Types::FixedHash.new(val) + elsif val.is_a?(T::Private::Methods::DeclBuilder) + T::Private::Methods.finalize_proc(val.decl) + elsif val.is_a?(::T::Enum) + T::Types::TEnum.new(val) + elsif val.is_a?(::String) + raise "Invalid String literal for type constraint. Must be an #{T::Types::Base}, a " \ + "class/module, or an array. Got a String with value `#{val}`." + else + raise "Invalid value for type constraint. Must be an #{T::Types::Base}, a " \ + "class/module, or an array. Got a `#{val.class}`." + end + end + + # Dynamically confirm that `value` is recursively a valid value of + # type `type`, including recursively through collections. Note that + # in some cases this runtime check can be very expensive, especially + # with large collections of objects. + def self.check_type_recursive!(value, type) + T::Private::Casts.cast_recursive(value, type, "T.check_type_recursive!") + end + + # Returns the set of all methods (public, protected, private) defined on a module or its + # ancestors, excluding Object and its ancestors. Overrides of methods from Object (and its + # ancestors) are included. + def self.methods_excluding_object(mod) + # We can't just do mod.instance_methods - Object.instance_methods, because that would leave out + # any methods from Object that are overridden in mod. + mod.ancestors.flat_map do |ancestor| + # equivalent to checking Object.ancestors.include?(ancestor) + next [] if Object <= ancestor + ancestor.instance_methods(false) + ancestor.private_instance_methods(false) + end.uniq + end + + # Returns the signature for the `UnboundMethod`, or nil if it's not sig'd + # + # @example T::Utils.signature_for_method(x.method(:foo)) + def self.signature_for_method(method) + T::Private::Methods.signature_for_method(method) + end + + # Returns the signature for the instance method on the supplied module, or nil if it's not found or not typed. + # + # @example T::Utils.signature_for_instance_method(MyClass, :my_method) + def self.signature_for_instance_method(mod, method_name) + T::Private::Methods.signature_for_method(mod.instance_method(method_name)) + end + + def self.wrap_method_with_call_validation_if_needed(mod, method_sig, original_method) + T::Private::Methods::CallValidation.wrap_method_if_needed(mod, method_sig, original_method) + end + + # Unwraps all the sigs. + def self.run_all_sig_blocks + T::Private::Methods.run_all_sig_blocks + end + + # Return the underlying type for a type alias. Otherwise returns type. + def self.resolve_alias(type) + case type + when T::Private::Types::TypeAlias + type.aliased_type + else + type + end + end + + # Give a type which is a subclass of T::Types::Base, determines if the type is a simple nilable type (union of NilClass and something else). + # If so, returns the T::Types::Base of the something else. Otherwise, returns nil. + def self.unwrap_nilable(type) + case type + when T::Types::Union + non_nil_types = type.types.reject {|t| t == Nilable::NIL_TYPE} + return nil if type.types.length == non_nil_types.length + case non_nil_types.length + when 0 then nil + when 1 then non_nil_types.first + else + T::Types::Union::Private::Pool.union_of_types(non_nil_types[0], non_nil_types[1], non_nil_types[2..-1]) + end + else + nil + end + end + + # Returns the arity of a method, unwrapping the sig if needed + def self.arity(method) + arity = method.arity + return arity if arity != -1 || method.is_a?(Proc) + sig = T::Private::Methods.signature_for_method(method) + sig ? sig.method.arity : arity + end + + # Elide the middle of a string as needed and replace it with an ellipsis. + # Keep the given number of characters at the start and end of the string. + # + # This method operates on string length, not byte length. + # + # If the string is shorter than the requested truncation length, return it + # without adding an ellipsis. This method may return a longer string than + # the original if the characters removed are shorter than the ellipsis. + # + # @param [String] str + # + # @param [Fixnum] start_len The length of string before the ellipsis + # @param [Fixnum] end_len The length of string after the ellipsis + # + # @param [String] ellipsis The string to add in place of the elided text + # + # @return [String] + # + def self.string_truncate_middle(str, start_len, end_len, ellipsis='...') + return unless str + + raise ArgumentError.new('must provide start_len') unless start_len + raise ArgumentError.new('must provide end_len') unless end_len + + raise ArgumentError.new('start_len must be >= 0') if start_len < 0 + raise ArgumentError.new('end_len must be >= 0') if end_len < 0 + + str = str.to_s + return str if str.length <= start_len + end_len + + start_part = str[0...start_len - ellipsis.length] + end_part = end_len == 0 ? '' : str[-end_len..-1] + + "#{start_part}#{ellipsis}#{end_part}" + end + + def self.lift_enum(enum) + unless enum.is_a?(T::Types::Enum) + raise ArgumentError.new("#{enum.inspect} is not a T.deprecated_enum") + end + + classes = enum.values.map(&:class).uniq + if classes.empty? + T.untyped + elsif classes.length > 1 + T::Types::Union.new(classes) + else + T::Types::Simple::Private::Pool.type_for_module(classes.first) + end + end + + module Nilable + # :is_union_type, T::Boolean: whether the type is an T::Types::Union type + # :non_nilable_type, Class: if it is an T.nilable type, the corresponding underlying type; otherwise, nil. + TypeInfo = Struct.new(:is_union_type, :non_nilable_type) + + NIL_TYPE = T::Utils.coerce(NilClass) + + def self.get_type_info(prop_type) + if prop_type.is_a?(T::Types::Union) + non_nilable_type = T::Utils.unwrap_nilable(prop_type) + if non_nilable_type&.is_a?(T::Types::Simple) + non_nilable_type = non_nilable_type.raw_type + end + TypeInfo.new(true, non_nilable_type) + else + TypeInfo.new(false, nil) + end + end + + # Get the underlying type inside prop_type: + # - if the type is A, the function returns A + # - if the type is T.nilable(A), the function returns A + def self.get_underlying_type(prop_type) + type_info = get_type_info(prop_type) + if type_info.is_union_type + type_info.non_nilable_type || prop_type + elsif prop_type.is_a?(T::Types::Simple) + prop_type.raw_type + else + prop_type + end + end + + # The difference between this function and the above function is that the Sorbet type, like T::Types::Simple + # is preserved. + def self.get_underlying_type_object(prop_type) + T::Utils.unwrap_nilable(prop_type) || prop_type + end + + def self.is_union_with_nilclass(prop_type) + case prop_type + when T::Types::Union + prop_type.types.include?(NIL_TYPE) + else + false + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/warning-1.3.0/MIT-LICENSE b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/warning-1.3.0/MIT-LICENSE new file mode 100644 index 0000000000..b045251a19 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/warning-1.3.0/MIT-LICENSE @@ -0,0 +1,18 @@ +Copyright (c) 2016-2022 Jeremy Evans + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/warning-1.3.0/lib/warning.rb b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/warning-1.3.0/lib/warning.rb new file mode 100644 index 0000000000..9179aa3773 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.1.0/gems/warning-1.3.0/lib/warning.rb @@ -0,0 +1,296 @@ +require 'monitor' + +module Warning + module Processor + # Map of symbols to regexps for warning messages to ignore. + IGNORE_MAP = { + ambiguous_slash: /: warning: ambiguous first argument; put parentheses or a space even after `\/' operator\n\z|: warning: ambiguity between regexp and two divisions: wrap regexp in parentheses or add a space after `\/' operator\n\z/, + arg_prefix: /: warning: `[&\*]' interpreted as argument prefix\n\z/, + bignum: /: warning: constant ::Bignum is deprecated\n\z/, + fixnum: /: warning: constant ::Fixnum is deprecated\n\z/, + method_redefined: /: warning: method redefined; discarding old .+\n\z|: warning: previous definition of .+ was here\n\z/, + missing_gvar: /: warning: global variable `\$.+' not initialized\n\z/, + missing_ivar: /: warning: instance variable @.+ not initialized\n\z/, + not_reached: /: warning: statement not reached\n\z/, + shadow: /: warning: shadowing outer local variable - \w+\n\z/, + unused_var: /: warning: assigned but unused variable - \w+\n\z/, + useless_operator: /: warning: possibly useless use of [>method /regexp/ + # :bignum :: Ignore warnings when referencing the ::Bignum constant. + # :fixnum :: Ignore warnings when referencing the ::Fixnum constant. + # :keyword_separation :: Ignore warnings related to keyword argument separation. + # :method_redefined :: Ignore warnings when defining a method in a class/module where a + # method of the same name was already defined in that class/module. + # :missing_gvar :: Ignore warnings for accesses to global variables + # that have not yet been initialized + # :missing_ivar :: Ignore warnings for accesses to instance variables + # that have not yet been initialized + # :not_reached :: Ignore statement not reached warnings. + # :safe :: Ignore warnings related to $SAFE and related C-API functions. + # :shadow :: Ignore warnings related to shadowing outer local variables. + # :taint :: Ignore warnings related to taint and related methods and C-API functions. + # :unused_var :: Ignore warnings for unused variables. + # :useless_operator :: Ignore warnings when using operators such as == and > when the + # result is not used. + # :void_context :: Ignore warnings for :: to reference constants when the result is not + # used (often used to trigger autoload). + # + # Examples: + # + # # Ignore all uninitialized instance variable warnings + # Warning.ignore(/instance variable @\w+ not initialized/) + # + # # Ignore all uninitialized instance variable warnings in current file + # Warning.ignore(/instance variable @\w+ not initialized/, __FILE__) + # + # # Ignore all uninitialized instance variable warnings in current file + # Warning.ignore(:missing_ivar, __FILE__) + # + # # Ignore all uninitialized instance variable and method redefined warnings in current file + # Warning.ignore([:missing_ivar, :method_redefined], __FILE__) + def ignore(regexp, path='') + unless regexp = convert_regexp(regexp) + raise TypeError, "first argument to Warning.ignore should be Regexp, Symbol, or Array of Symbols, got #{regexp.inspect}" + end + + synchronize do + @ignore << [path, regexp] + end + nil + end + + # Handle all warnings starting with the given path, instead of + # the default behavior of printing them to $stderr. Examples: + # + # # Write warning to LOGGER at level warning + # Warning.process do |warning| + # LOGGER.warning(warning) + # end + # + # # Write warnings in the current file to LOGGER at level error level + # Warning.process(__FILE__) do |warning| + # LOGGER.error(warning) + # end + # + # The block can return one of the following symbols: + # + # :default :: Take the default action (call super, printing to $stderr). + # :backtrace :: Take the default action (call super, printing to $stderr), + # and also print the backtrace. + # :raise :: Raise a RuntimeError with the warning as the message. + # + # If the block returns anything else, it is assumed the block completely handled + # the warning and takes no other action. + # + # Instead of passing a block, you can pass a hash of actions to take for specific + # warnings, using regexp as keys and a callable objects as values: + # + # Warning.process(__FILE__, + # /instance variable @\w+ not initialized/ => proc do |warning| + # LOGGER.warning(warning) + # end, + # /global variable `\$\w+' not initialized/ => proc do |warning| + # LOGGER.error(warning) + # end + # ) + # + # Instead of passing a regexp as a key, you can pass a symbol that is recognized + # by Warning.ignore. Instead of passing a callable object as a value, you can + # pass a symbol, which will be treated as a callable object that returns that symbol: + # + # Warning.process(__FILE__, :missing_ivar=>:backtrace, :keyword_separation=>:raise) + def process(path='', actions=nil, &block) + unless path.is_a?(String) + raise ArgumentError, "path must be a String (given an instance of #{path.class})" + end + + if block + if actions + raise ArgumentError, "cannot pass both actions and block to Warning.process" + end + elsif actions + block = {} + actions.each do |regexp, value| + unless regexp = convert_regexp(regexp) + raise TypeError, "action provided to Warning.process should be Regexp, Symbol, or Array of Symbols, got #{regexp.inspect}" + end + + block[regexp] = ACTION_PROC_MAP[value] || value + end + else + raise ArgumentError, "must pass either actions or block to Warning.process" + end + + synchronize do + @process << [path, block] + @process.sort_by!(&:first) + @process.reverse! + end + nil + end + + + if RUBY_VERSION >= '3.0' + method_args = ', category: nil' + super_ = "category ? super : super(str)" + # :nocov: + else + super_ = "super" + # :nocov: + end + + class_eval(<<-END, __FILE__, __LINE__+1) + def warn(str#{method_args}) + synchronize{@ignore.dup}.each do |path, regexp| + if str.start_with?(path) && regexp.match?(str) + return + end + end + + if @dedup + if synchronize{@dedup[str]} + return + end + + synchronize{@dedup[str] = true} + end + + action = catch(:action) do + synchronize{@process.dup}.each do |path, block| + if str.start_with?(path) + if block.is_a?(Hash) + block.each do |regexp, blk| + if regexp.match?(str) + throw :action, blk.call(str) + end + end + else + throw :action, block.call(str) + end + end + end + + :default + end + + case action + when :default + #{super_} + when :backtrace + #{super_} + $stderr.puts caller + when :raise + raise str + else + # nothing + end + + nil + end + END + + private + + # Convert the given Regexp, Symbol, or Array of Symbols into a Regexp. + def convert_regexp(regexp) + case regexp + when Regexp + regexp + when Symbol + IGNORE_MAP.fetch(regexp) + when Array + Regexp.union(regexp.map{|re| IGNORE_MAP.fetch(re)}) + else + # nothing + end + end + + def synchronize(&block) + @monitor.synchronize(&block) + end + end + + @ignore = [] + @process = [] + @dedup = false + @monitor = Monitor.new + + extend Processor +end