openlayer 0.3.0 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.ignore +2 -0
- data/CHANGELOG.md +36 -0
- data/README.md +280 -39
- data/SECURITY.md +27 -0
- data/lib/openlayer/client.rb +64 -59
- data/lib/openlayer/errors.rb +228 -0
- data/lib/openlayer/file_part.rb +58 -0
- data/lib/openlayer/internal/transport/base_client.rb +567 -0
- data/lib/openlayer/internal/transport/pooled_net_requester.rb +198 -0
- data/lib/openlayer/internal/type/array_of.rb +168 -0
- data/lib/openlayer/internal/type/base_model.rb +531 -0
- data/lib/openlayer/internal/type/base_page.rb +55 -0
- data/lib/openlayer/internal/type/boolean.rb +77 -0
- data/lib/openlayer/internal/type/converter.rb +327 -0
- data/lib/openlayer/internal/type/enum.rb +131 -0
- data/lib/openlayer/internal/type/file_input.rb +111 -0
- data/lib/openlayer/internal/type/hash_of.rb +188 -0
- data/lib/openlayer/internal/type/request_parameters.rb +42 -0
- data/lib/openlayer/internal/type/union.rb +237 -0
- data/lib/openlayer/internal/type/unknown.rb +81 -0
- data/lib/openlayer/internal/util.rb +914 -0
- data/lib/openlayer/internal.rb +20 -0
- data/lib/openlayer/models/commit_retrieve_params.rb +14 -0
- data/lib/openlayer/models/commit_retrieve_response.rb +275 -0
- data/lib/openlayer/models/commits/test_result_list_params.rb +91 -0
- data/lib/openlayer/models/commits/test_result_list_response.rb +566 -0
- data/lib/openlayer/models/inference_pipeline_delete_params.rb +14 -0
- data/lib/openlayer/models/inference_pipeline_retrieve_params.rb +33 -0
- data/lib/openlayer/models/inference_pipeline_retrieve_response.rb +605 -0
- data/lib/openlayer/models/inference_pipeline_update_params.rb +42 -0
- data/lib/openlayer/models/inference_pipeline_update_response.rb +605 -0
- data/lib/openlayer/models/inference_pipelines/data_stream_params.rb +463 -0
- data/lib/openlayer/models/inference_pipelines/data_stream_response.rb +28 -0
- data/lib/openlayer/models/inference_pipelines/row_update_params.rb +90 -0
- data/lib/openlayer/models/inference_pipelines/row_update_response.rb +28 -0
- data/lib/openlayer/models/inference_pipelines/test_result_list_params.rb +83 -0
- data/lib/openlayer/models/inference_pipelines/test_result_list_response.rb +568 -0
- data/lib/openlayer/models/project_create_params.rb +51 -0
- data/lib/openlayer/models/project_create_response.rb +262 -0
- data/lib/openlayer/models/project_list_params.rb +59 -0
- data/lib/openlayer/models/project_list_response.rb +274 -0
- data/lib/openlayer/models/projects/commit_create_params.rb +61 -0
- data/lib/openlayer/models/projects/commit_create_response.rb +277 -0
- data/lib/openlayer/models/projects/commit_list_params.rb +32 -0
- data/lib/openlayer/models/projects/commit_list_response.rb +288 -0
- data/lib/openlayer/models/projects/inference_pipeline_create_params.rb +229 -0
- data/lib/openlayer/models/projects/inference_pipeline_create_response.rb +612 -0
- data/lib/openlayer/models/projects/inference_pipeline_list_params.rb +40 -0
- data/lib/openlayer/models/projects/inference_pipeline_list_response.rb +623 -0
- data/lib/openlayer/models/projects/test_create_params.rb +367 -0
- data/lib/openlayer/models/projects/test_create_response.rb +438 -0
- data/lib/openlayer/models/projects/test_list_params.rb +91 -0
- data/lib/openlayer/models/projects/test_list_response.rb +452 -0
- data/lib/openlayer/models/projects/test_update_params.rb +262 -0
- data/lib/openlayer/models/projects/test_update_response.rb +24 -0
- data/lib/openlayer/models/storage/presigned_url_create_params.rb +24 -0
- data/lib/openlayer/models/storage/presigned_url_create_response.rb +35 -0
- data/lib/openlayer/models.rb +61 -0
- data/lib/openlayer/request_options.rb +77 -0
- data/lib/openlayer/resources/commits/test_results.rb +51 -0
- data/lib/openlayer/resources/commits.rb +38 -0
- data/lib/openlayer/resources/inference_pipelines/data.rb +46 -0
- data/lib/openlayer/resources/inference_pipelines/rows.rb +46 -0
- data/lib/openlayer/resources/inference_pipelines/test_results.rb +49 -0
- data/lib/openlayer/resources/inference_pipelines.rb +101 -0
- data/lib/openlayer/resources/projects/commits.rb +72 -0
- data/lib/openlayer/resources/projects/inference_pipelines.rb +74 -0
- data/lib/openlayer/resources/projects/tests.rb +135 -0
- data/lib/openlayer/resources/projects.rb +80 -0
- data/lib/openlayer/resources/storage/presigned_url.rb +38 -0
- data/lib/openlayer/resources/storage.rb +18 -0
- data/lib/openlayer/version.rb +1 -1
- data/lib/openlayer.rb +96 -12
- data/manifest.yaml +15 -0
- data/rbi/openlayer/client.rbi +58 -0
- data/rbi/openlayer/errors.rbi +205 -0
- data/rbi/openlayer/file_part.rbi +37 -0
- data/rbi/openlayer/internal/transport/base_client.rbi +293 -0
- data/rbi/openlayer/internal/transport/pooled_net_requester.rbi +79 -0
- data/rbi/openlayer/internal/type/array_of.rbi +104 -0
- data/rbi/openlayer/internal/type/base_model.rbi +304 -0
- data/rbi/openlayer/internal/type/base_page.rbi +42 -0
- data/rbi/openlayer/internal/type/boolean.rbi +58 -0
- data/rbi/openlayer/internal/type/converter.rbi +216 -0
- data/rbi/openlayer/internal/type/enum.rbi +82 -0
- data/rbi/openlayer/internal/type/file_input.rbi +59 -0
- data/rbi/openlayer/internal/type/hash_of.rbi +104 -0
- data/rbi/openlayer/internal/type/request_parameters.rbi +29 -0
- data/rbi/openlayer/internal/type/union.rbi +128 -0
- data/rbi/openlayer/internal/type/unknown.rbi +58 -0
- data/rbi/openlayer/internal/util.rbi +487 -0
- data/rbi/openlayer/internal.rbi +18 -0
- data/rbi/openlayer/models/commit_retrieve_params.rbi +27 -0
- data/rbi/openlayer/models/commit_retrieve_response.rbi +393 -0
- data/rbi/openlayer/models/commits/test_result_list_params.rbi +214 -0
- data/rbi/openlayer/models/commits/test_result_list_response.rbi +1256 -0
- data/rbi/openlayer/models/inference_pipeline_delete_params.rbi +30 -0
- data/rbi/openlayer/models/inference_pipeline_retrieve_params.rbi +101 -0
- data/rbi/openlayer/models/inference_pipeline_retrieve_response.rbi +1022 -0
- data/rbi/openlayer/models/inference_pipeline_update_params.rbi +67 -0
- data/rbi/openlayer/models/inference_pipeline_update_response.rbi +1018 -0
- data/rbi/openlayer/models/inference_pipelines/data_stream_params.rbi +750 -0
- data/rbi/openlayer/models/inference_pipelines/data_stream_response.rbi +73 -0
- data/rbi/openlayer/models/inference_pipelines/row_update_params.rbi +153 -0
- data/rbi/openlayer/models/inference_pipelines/row_update_response.rbi +73 -0
- data/rbi/openlayer/models/inference_pipelines/test_result_list_params.rbi +216 -0
- data/rbi/openlayer/models/inference_pipelines/test_result_list_response.rbi +1258 -0
- data/rbi/openlayer/models/project_create_params.rbi +99 -0
- data/rbi/openlayer/models/project_create_response.rbi +401 -0
- data/rbi/openlayer/models/project_list_params.rbi +121 -0
- data/rbi/openlayer/models/project_list_response.rbi +442 -0
- data/rbi/openlayer/models/projects/commit_create_params.rbi +125 -0
- data/rbi/openlayer/models/projects/commit_create_response.rbi +409 -0
- data/rbi/openlayer/models/projects/commit_list_params.rbi +62 -0
- data/rbi/openlayer/models/projects/commit_list_response.rbi +454 -0
- data/rbi/openlayer/models/projects/inference_pipeline_create_params.rbi +560 -0
- data/rbi/openlayer/models/projects/inference_pipeline_create_response.rbi +1027 -0
- data/rbi/openlayer/models/projects/inference_pipeline_list_params.rbi +73 -0
- data/rbi/openlayer/models/projects/inference_pipeline_list_response.rbi +1070 -0
- data/rbi/openlayer/models/projects/test_create_params.rbi +940 -0
- data/rbi/openlayer/models/projects/test_create_response.rbi +1026 -0
- data/rbi/openlayer/models/projects/test_list_params.rbi +165 -0
- data/rbi/openlayer/models/projects/test_list_response.rbi +1067 -0
- data/rbi/openlayer/models/projects/test_update_params.rbi +699 -0
- data/rbi/openlayer/models/projects/test_update_response.rbi +43 -0
- data/rbi/openlayer/models/storage/presigned_url_create_params.rbi +45 -0
- data/rbi/openlayer/models/storage/presigned_url_create_response.rbi +55 -0
- data/rbi/openlayer/models.rbi +26 -0
- data/rbi/openlayer/request_options.rbi +59 -0
- data/rbi/openlayer/resources/commits/test_results.rbi +45 -0
- data/rbi/openlayer/resources/commits.rbi +29 -0
- data/rbi/openlayer/resources/inference_pipelines/data.rbi +41 -0
- data/rbi/openlayer/resources/inference_pipelines/rows.rbi +40 -0
- data/rbi/openlayer/resources/inference_pipelines/test_results.rbi +46 -0
- data/rbi/openlayer/resources/inference_pipelines.rbi +79 -0
- data/rbi/openlayer/resources/projects/commits.rbi +60 -0
- data/rbi/openlayer/resources/projects/inference_pipelines.rbi +69 -0
- data/rbi/openlayer/resources/projects/tests.rbi +123 -0
- data/rbi/openlayer/resources/projects.rbi +64 -0
- data/rbi/openlayer/resources/storage/presigned_url.rbi +28 -0
- data/rbi/openlayer/resources/storage.rbi +15 -0
- data/rbi/openlayer/version.rbi +5 -0
- data/sig/openlayer/client.rbs +32 -0
- data/sig/openlayer/errors.rbs +117 -0
- data/sig/openlayer/file_part.rbs +21 -0
- data/sig/openlayer/internal/transport/base_client.rbs +131 -0
- data/sig/openlayer/internal/transport/pooled_net_requester.rbs +45 -0
- data/sig/openlayer/internal/type/array_of.rbs +48 -0
- data/sig/openlayer/internal/type/base_model.rbs +102 -0
- data/sig/openlayer/internal/type/base_page.rbs +24 -0
- data/sig/openlayer/internal/type/boolean.rbs +26 -0
- data/sig/openlayer/internal/type/converter.rbs +79 -0
- data/sig/openlayer/internal/type/enum.rbs +32 -0
- data/sig/openlayer/internal/type/file_input.rbs +25 -0
- data/sig/openlayer/internal/type/hash_of.rbs +48 -0
- data/sig/openlayer/internal/type/request_parameters.rbs +19 -0
- data/sig/openlayer/internal/type/union.rbs +52 -0
- data/sig/openlayer/internal/type/unknown.rbs +26 -0
- data/sig/openlayer/internal/util.rbs +185 -0
- data/sig/openlayer/internal.rbs +9 -0
- data/sig/openlayer/models/commit_retrieve_params.rbs +15 -0
- data/sig/openlayer/models/commit_retrieve_response.rbs +209 -0
- data/sig/openlayer/models/commits/test_result_list_params.rbs +91 -0
- data/sig/openlayer/models/commits/test_result_list_response.rbs +529 -0
- data/sig/openlayer/models/inference_pipeline_delete_params.rbs +15 -0
- data/sig/openlayer/models/inference_pipeline_retrieve_params.rbs +41 -0
- data/sig/openlayer/models/inference_pipeline_retrieve_response.rbs +493 -0
- data/sig/openlayer/models/inference_pipeline_update_params.rbs +34 -0
- data/sig/openlayer/models/inference_pipeline_update_response.rbs +493 -0
- data/sig/openlayer/models/inference_pipelines/data_stream_params.rbs +386 -0
- data/sig/openlayer/models/inference_pipelines/data_stream_response.rbs +32 -0
- data/sig/openlayer/models/inference_pipelines/row_update_params.rbs +75 -0
- data/sig/openlayer/models/inference_pipelines/row_update_response.rbs +32 -0
- data/sig/openlayer/models/inference_pipelines/test_result_list_params.rbs +84 -0
- data/sig/openlayer/models/inference_pipelines/test_result_list_response.rbs +529 -0
- data/sig/openlayer/models/project_create_params.rbs +53 -0
- data/sig/openlayer/models/project_create_response.rbs +210 -0
- data/sig/openlayer/models/project_list_params.rbs +68 -0
- data/sig/openlayer/models/project_list_response.rbs +225 -0
- data/sig/openlayer/models/projects/commit_create_params.rbs +82 -0
- data/sig/openlayer/models/projects/commit_create_response.rbs +211 -0
- data/sig/openlayer/models/projects/commit_list_params.rbs +34 -0
- data/sig/openlayer/models/projects/commit_list_response.rbs +228 -0
- data/sig/openlayer/models/projects/inference_pipeline_create_params.rbs +308 -0
- data/sig/openlayer/models/projects/inference_pipeline_create_response.rbs +495 -0
- data/sig/openlayer/models/projects/inference_pipeline_list_params.rbs +40 -0
- data/sig/openlayer/models/projects/inference_pipeline_list_response.rbs +512 -0
- data/sig/openlayer/models/projects/test_create_params.rbs +388 -0
- data/sig/openlayer/models/projects/test_create_response.rbs +427 -0
- data/sig/openlayer/models/projects/test_list_params.rbs +85 -0
- data/sig/openlayer/models/projects/test_list_response.rbs +442 -0
- data/sig/openlayer/models/projects/test_update_params.rbs +275 -0
- data/sig/openlayer/models/projects/test_update_response.rbs +25 -0
- data/sig/openlayer/models/storage/presigned_url_create_params.rbs +25 -0
- data/sig/openlayer/models/storage/presigned_url_create_response.rbs +22 -0
- data/sig/openlayer/models.rbs +21 -0
- data/sig/openlayer/request_options.rbs +34 -0
- data/sig/openlayer/resources/commits/test_results.rbs +19 -0
- data/sig/openlayer/resources/commits.rbs +14 -0
- data/sig/openlayer/resources/inference_pipelines/data.rbs +16 -0
- data/sig/openlayer/resources/inference_pipelines/rows.rbs +17 -0
- data/sig/openlayer/resources/inference_pipelines/test_results.rbs +18 -0
- data/sig/openlayer/resources/inference_pipelines.rbs +32 -0
- data/sig/openlayer/resources/projects/commits.rbs +25 -0
- data/sig/openlayer/resources/projects/inference_pipelines.rbs +26 -0
- data/sig/openlayer/resources/projects/tests.rbs +45 -0
- data/sig/openlayer/resources/projects.rbs +28 -0
- data/sig/openlayer/resources/storage/presigned_url.rbs +14 -0
- data/sig/openlayer/resources/storage.rbs +9 -0
- data/sig/openlayer/version.rbs +3 -0
- metadata +223 -91
- data/.env +0 -0
- data/.rspec +0 -3
- data/.rubocop.yml +0 -13
- data/LICENSE +0 -21
- data/Rakefile +0 -12
- data/examples/staging/.DS_Store +0 -0
- data/examples/staging/commit.yaml +0 -2
- data/examples/staging/model/model_config.yaml +0 -12
- data/examples/staging/validation/dataset_config.yaml +0 -12
- data/lib/openlayer/error.rb +0 -5
- data/lib/openlayer/inference_pipeline.rb +0 -36
- data/lib/openlayer/object.rb +0 -28
- data/lib/openlayer/objects/project.rb +0 -185
- data/lib/openlayer/objects/project_version.rb +0 -89
- data/lib/openlayer/services/s3_presigned_client.rb +0 -47
- data/lib/openlayer/services/tar_file_helper.rb +0 -55
- data/openlayer.gemspec +0 -45
- data/sig/openlayer.rbs +0 -4
| @@ -0,0 +1,914 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Openlayer
         | 
| 4 | 
            +
              module Internal
         | 
| 5 | 
            +
                # @api private
         | 
| 6 | 
            +
                module Util
         | 
| 7 | 
            +
                  # @api private
         | 
| 8 | 
            +
                  #
         | 
| 9 | 
            +
                  # @return [Float]
         | 
| 10 | 
            +
                  def self.monotonic_secs = Process.clock_gettime(Process::CLOCK_MONOTONIC)
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                  # @api private
         | 
| 13 | 
            +
                  #
         | 
| 14 | 
            +
                  # @param ns [Module, Class]
         | 
| 15 | 
            +
                  #
         | 
| 16 | 
            +
                  # @return [Enumerable<Module, Class>]
         | 
| 17 | 
            +
                  def self.walk_namespaces(ns)
         | 
| 18 | 
            +
                    ns.constants(false).lazy.flat_map do
         | 
| 19 | 
            +
                      case (c = ns.const_get(_1, false))
         | 
| 20 | 
            +
                      in Module | Class
         | 
| 21 | 
            +
                        walk_namespaces(c)
         | 
| 22 | 
            +
                      else
         | 
| 23 | 
            +
                        []
         | 
| 24 | 
            +
                      end
         | 
| 25 | 
            +
                    end
         | 
| 26 | 
            +
                      .chain([ns])
         | 
| 27 | 
            +
                  end
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                  class << self
         | 
| 30 | 
            +
                    # @api private
         | 
| 31 | 
            +
                    #
         | 
| 32 | 
            +
                    # @return [String]
         | 
| 33 | 
            +
                    def arch
         | 
| 34 | 
            +
                      case (arch = RbConfig::CONFIG["arch"])&.downcase
         | 
| 35 | 
            +
                      in nil
         | 
| 36 | 
            +
                        "unknown"
         | 
| 37 | 
            +
                      in /aarch64|arm64/
         | 
| 38 | 
            +
                        "arm64"
         | 
| 39 | 
            +
                      in /x86_64/
         | 
| 40 | 
            +
                        "x64"
         | 
| 41 | 
            +
                      in /arm/
         | 
| 42 | 
            +
                        "arm"
         | 
| 43 | 
            +
                      else
         | 
| 44 | 
            +
                        "other:#{arch}"
         | 
| 45 | 
            +
                      end
         | 
| 46 | 
            +
                    end
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                    # @api private
         | 
| 49 | 
            +
                    #
         | 
| 50 | 
            +
                    # @return [String]
         | 
| 51 | 
            +
                    def os
         | 
| 52 | 
            +
                      case (host = RbConfig::CONFIG["host_os"])&.downcase
         | 
| 53 | 
            +
                      in nil
         | 
| 54 | 
            +
                        "Unknown"
         | 
| 55 | 
            +
                      in /linux/
         | 
| 56 | 
            +
                        "Linux"
         | 
| 57 | 
            +
                      in /darwin/
         | 
| 58 | 
            +
                        "MacOS"
         | 
| 59 | 
            +
                      in /freebsd/
         | 
| 60 | 
            +
                        "FreeBSD"
         | 
| 61 | 
            +
                      in /openbsd/
         | 
| 62 | 
            +
                        "OpenBSD"
         | 
| 63 | 
            +
                      in /mswin|mingw|cygwin|ucrt/
         | 
| 64 | 
            +
                        "Windows"
         | 
| 65 | 
            +
                      else
         | 
| 66 | 
            +
                        "Other:#{host}"
         | 
| 67 | 
            +
                      end
         | 
| 68 | 
            +
                    end
         | 
| 69 | 
            +
                  end
         | 
| 70 | 
            +
             | 
| 71 | 
            +
                  class << self
         | 
| 72 | 
            +
                    # @api private
         | 
| 73 | 
            +
                    #
         | 
| 74 | 
            +
                    # @param input [Object]
         | 
| 75 | 
            +
                    #
         | 
| 76 | 
            +
                    # @return [Boolean]
         | 
| 77 | 
            +
                    def primitive?(input)
         | 
| 78 | 
            +
                      case input
         | 
| 79 | 
            +
                      in true | false | Numeric | Symbol | String
         | 
| 80 | 
            +
                        true
         | 
| 81 | 
            +
                      else
         | 
| 82 | 
            +
                        false
         | 
| 83 | 
            +
                      end
         | 
| 84 | 
            +
                    end
         | 
| 85 | 
            +
             | 
| 86 | 
            +
                    # @api private
         | 
| 87 | 
            +
                    #
         | 
| 88 | 
            +
                    # @param input [String, Boolean]
         | 
| 89 | 
            +
                    #
         | 
| 90 | 
            +
                    # @return [Boolean, Object]
         | 
| 91 | 
            +
                    def coerce_boolean(input)
         | 
| 92 | 
            +
                      case input.is_a?(String) ? input.downcase : input
         | 
| 93 | 
            +
                      in "true"
         | 
| 94 | 
            +
                        true
         | 
| 95 | 
            +
                      in "false"
         | 
| 96 | 
            +
                        false
         | 
| 97 | 
            +
                      else
         | 
| 98 | 
            +
                        input
         | 
| 99 | 
            +
                      end
         | 
| 100 | 
            +
                    end
         | 
| 101 | 
            +
             | 
| 102 | 
            +
                    # @api private
         | 
| 103 | 
            +
                    #
         | 
| 104 | 
            +
                    # @param input [String, Boolean]
         | 
| 105 | 
            +
                    #
         | 
| 106 | 
            +
                    # @raise [ArgumentError]
         | 
| 107 | 
            +
                    # @return [Boolean, nil]
         | 
| 108 | 
            +
                    def coerce_boolean!(input)
         | 
| 109 | 
            +
                      case coerce_boolean(input)
         | 
| 110 | 
            +
                      in true | false | nil => coerced
         | 
| 111 | 
            +
                        coerced
         | 
| 112 | 
            +
                      else
         | 
| 113 | 
            +
                        raise ArgumentError.new("Unable to coerce #{input.inspect} into boolean value")
         | 
| 114 | 
            +
                      end
         | 
| 115 | 
            +
                    end
         | 
| 116 | 
            +
             | 
| 117 | 
            +
                    # @api private
         | 
| 118 | 
            +
                    #
         | 
| 119 | 
            +
                    # @param input [String, Integer]
         | 
| 120 | 
            +
                    #
         | 
| 121 | 
            +
                    # @return [Integer, Object]
         | 
| 122 | 
            +
                    def coerce_integer(input)
         | 
| 123 | 
            +
                      Integer(input, exception: false) || input
         | 
| 124 | 
            +
                    end
         | 
| 125 | 
            +
             | 
| 126 | 
            +
                    # @api private
         | 
| 127 | 
            +
                    #
         | 
| 128 | 
            +
                    # @param input [String, Integer, Float]
         | 
| 129 | 
            +
                    #
         | 
| 130 | 
            +
                    # @return [Float, Object]
         | 
| 131 | 
            +
                    def coerce_float(input)
         | 
| 132 | 
            +
                      Float(input, exception: false) || input
         | 
| 133 | 
            +
                    end
         | 
| 134 | 
            +
             | 
| 135 | 
            +
                    # @api private
         | 
| 136 | 
            +
                    #
         | 
| 137 | 
            +
                    # @param input [Object]
         | 
| 138 | 
            +
                    #
         | 
| 139 | 
            +
                    # @return [Hash{Object=>Object}, Object]
         | 
| 140 | 
            +
                    def coerce_hash(input)
         | 
| 141 | 
            +
                      case input
         | 
| 142 | 
            +
                      in NilClass | Array | Set | Enumerator | StringIO | IO
         | 
| 143 | 
            +
                        input
         | 
| 144 | 
            +
                      else
         | 
| 145 | 
            +
                        input.respond_to?(:to_h) ? input.to_h : input
         | 
| 146 | 
            +
                      end
         | 
| 147 | 
            +
                    end
         | 
| 148 | 
            +
             | 
| 149 | 
            +
                    # @api private
         | 
| 150 | 
            +
                    #
         | 
| 151 | 
            +
                    # @param input [Object]
         | 
| 152 | 
            +
                    #
         | 
| 153 | 
            +
                    # @raise [ArgumentError]
         | 
| 154 | 
            +
                    # @return [Hash{Object=>Object}, nil]
         | 
| 155 | 
            +
                    def coerce_hash!(input)
         | 
| 156 | 
            +
                      case coerce_hash(input)
         | 
| 157 | 
            +
                      in Hash | nil => coerced
         | 
| 158 | 
            +
                        coerced
         | 
| 159 | 
            +
                      else
         | 
| 160 | 
            +
                        message = "Expected a #{Hash} or #{Openlayer::Internal::Type::BaseModel}, got #{data.inspect}"
         | 
| 161 | 
            +
                        raise ArgumentError.new(message)
         | 
| 162 | 
            +
                      end
         | 
| 163 | 
            +
                    end
         | 
| 164 | 
            +
                  end
         | 
| 165 | 
            +
             | 
| 166 | 
            +
                  class << self
         | 
| 167 | 
            +
                    # @api private
         | 
| 168 | 
            +
                    #
         | 
| 169 | 
            +
                    # @param lhs [Object]
         | 
| 170 | 
            +
                    # @param rhs [Object]
         | 
| 171 | 
            +
                    # @param concat [Boolean]
         | 
| 172 | 
            +
                    #
         | 
| 173 | 
            +
                    # @return [Object]
         | 
| 174 | 
            +
                    private def deep_merge_lr(lhs, rhs, concat: false)
         | 
| 175 | 
            +
                      case [lhs, rhs, concat]
         | 
| 176 | 
            +
                      in [Hash, Hash, _]
         | 
| 177 | 
            +
                        lhs.merge(rhs) { deep_merge_lr(_2, _3, concat: concat) }
         | 
| 178 | 
            +
                      in [Array, Array, true]
         | 
| 179 | 
            +
                        lhs.concat(rhs)
         | 
| 180 | 
            +
                      else
         | 
| 181 | 
            +
                        rhs
         | 
| 182 | 
            +
                      end
         | 
| 183 | 
            +
                    end
         | 
| 184 | 
            +
             | 
| 185 | 
            +
                    # @api private
         | 
| 186 | 
            +
                    #
         | 
| 187 | 
            +
                    # Recursively merge one hash with another. If the values at a given key are not
         | 
| 188 | 
            +
                    # both hashes, just take the new value.
         | 
| 189 | 
            +
                    #
         | 
| 190 | 
            +
                    # @param values [Array<Object>]
         | 
| 191 | 
            +
                    #
         | 
| 192 | 
            +
                    # @param sentinel [Object, nil] the value to return if no values are provided.
         | 
| 193 | 
            +
                    #
         | 
| 194 | 
            +
                    # @param concat [Boolean] whether to merge sequences by concatenation.
         | 
| 195 | 
            +
                    #
         | 
| 196 | 
            +
                    # @return [Object]
         | 
| 197 | 
            +
                    def deep_merge(*values, sentinel: nil, concat: false)
         | 
| 198 | 
            +
                      case values
         | 
| 199 | 
            +
                      in [value, *values]
         | 
| 200 | 
            +
                        values.reduce(value) do |acc, val|
         | 
| 201 | 
            +
                          deep_merge_lr(acc, val, concat: concat)
         | 
| 202 | 
            +
                        end
         | 
| 203 | 
            +
                      else
         | 
| 204 | 
            +
                        sentinel
         | 
| 205 | 
            +
                      end
         | 
| 206 | 
            +
                    end
         | 
| 207 | 
            +
             | 
| 208 | 
            +
                    # @api private
         | 
| 209 | 
            +
                    #
         | 
| 210 | 
            +
                    # @param data [Hash{Symbol=>Object}, Array<Object>, Object]
         | 
| 211 | 
            +
                    # @param pick [Symbol, Integer, Array<Symbol, Integer>, Proc, nil]
         | 
| 212 | 
            +
                    # @param blk [Proc, nil]
         | 
| 213 | 
            +
                    #
         | 
| 214 | 
            +
                    # @return [Object, nil]
         | 
| 215 | 
            +
                    def dig(data, pick, &blk)
         | 
| 216 | 
            +
                      case [data, pick]
         | 
| 217 | 
            +
                      in [_, nil]
         | 
| 218 | 
            +
                        data
         | 
| 219 | 
            +
                      in [Hash, Symbol] | [Array, Integer]
         | 
| 220 | 
            +
                        data.fetch(pick) { blk&.call }
         | 
| 221 | 
            +
                      in [Hash | Array, Array]
         | 
| 222 | 
            +
                        pick.reduce(data) do |acc, key|
         | 
| 223 | 
            +
                          case acc
         | 
| 224 | 
            +
                          in Hash if acc.key?(key)
         | 
| 225 | 
            +
                            acc.fetch(key)
         | 
| 226 | 
            +
                          in Array if key.is_a?(Integer) && key < acc.length
         | 
| 227 | 
            +
                            acc[key]
         | 
| 228 | 
            +
                          else
         | 
| 229 | 
            +
                            return blk&.call
         | 
| 230 | 
            +
                          end
         | 
| 231 | 
            +
                        end
         | 
| 232 | 
            +
                      in [_, Proc]
         | 
| 233 | 
            +
                        pick.call(data)
         | 
| 234 | 
            +
                      else
         | 
| 235 | 
            +
                        blk&.call
         | 
| 236 | 
            +
                      end
         | 
| 237 | 
            +
                    end
         | 
| 238 | 
            +
                  end
         | 
| 239 | 
            +
             | 
| 240 | 
            +
                  class << self
         | 
| 241 | 
            +
                    # @api private
         | 
| 242 | 
            +
                    #
         | 
| 243 | 
            +
                    # @param uri [URI::Generic]
         | 
| 244 | 
            +
                    #
         | 
| 245 | 
            +
                    # @return [String]
         | 
| 246 | 
            +
                    def uri_origin(uri)
         | 
| 247 | 
            +
                      "#{uri.scheme}://#{uri.host}#{":#{uri.port}" unless uri.port == uri.default_port}"
         | 
| 248 | 
            +
                    end
         | 
| 249 | 
            +
             | 
| 250 | 
            +
                    # @api private
         | 
| 251 | 
            +
                    #
         | 
| 252 | 
            +
                    # @param path [String, Array<String>]
         | 
| 253 | 
            +
                    #
         | 
| 254 | 
            +
                    # @return [String]
         | 
| 255 | 
            +
                    def interpolate_path(path)
         | 
| 256 | 
            +
                      case path
         | 
| 257 | 
            +
                      in String
         | 
| 258 | 
            +
                        path
         | 
| 259 | 
            +
                      in []
         | 
| 260 | 
            +
                        ""
         | 
| 261 | 
            +
                      in [String => p, *interpolations]
         | 
| 262 | 
            +
                        encoded = interpolations.map { ERB::Util.url_encode(_1) }
         | 
| 263 | 
            +
                        format(p, *encoded)
         | 
| 264 | 
            +
                      end
         | 
| 265 | 
            +
                    end
         | 
| 266 | 
            +
                  end
         | 
| 267 | 
            +
             | 
| 268 | 
            +
                  class << self
         | 
| 269 | 
            +
                    # @api private
         | 
| 270 | 
            +
                    #
         | 
| 271 | 
            +
                    # @param query [String, nil]
         | 
| 272 | 
            +
                    #
         | 
| 273 | 
            +
                    # @return [Hash{String=>Array<String>}]
         | 
| 274 | 
            +
                    def decode_query(query)
         | 
| 275 | 
            +
                      CGI.parse(query.to_s)
         | 
| 276 | 
            +
                    end
         | 
| 277 | 
            +
             | 
| 278 | 
            +
                    # @api private
         | 
| 279 | 
            +
                    #
         | 
| 280 | 
            +
                    # @param query [Hash{String=>Array<String>, String, nil}, nil]
         | 
| 281 | 
            +
                    #
         | 
| 282 | 
            +
                    # @return [String, nil]
         | 
| 283 | 
            +
                    def encode_query(query)
         | 
| 284 | 
            +
                      query.to_h.empty? ? nil : URI.encode_www_form(query)
         | 
| 285 | 
            +
                    end
         | 
| 286 | 
            +
                  end
         | 
| 287 | 
            +
             | 
| 288 | 
            +
                  class << self
         | 
| 289 | 
            +
                    # @api private
         | 
| 290 | 
            +
                    #
         | 
| 291 | 
            +
                    # @param url [URI::Generic, String]
         | 
| 292 | 
            +
                    #
         | 
| 293 | 
            +
                    # @return [Hash{Symbol=>String, Integer, nil}]
         | 
| 294 | 
            +
                    def parse_uri(url)
         | 
| 295 | 
            +
                      parsed = URI::Generic.component.zip(URI.split(url)).to_h
         | 
| 296 | 
            +
                      {**parsed, query: decode_query(parsed.fetch(:query))}
         | 
| 297 | 
            +
                    end
         | 
| 298 | 
            +
             | 
| 299 | 
            +
                    # @api private
         | 
| 300 | 
            +
                    #
         | 
| 301 | 
            +
                    # @param parsed [Hash{Symbol=>String, Integer, nil}] .
         | 
| 302 | 
            +
                    #
         | 
| 303 | 
            +
                    #   @option parsed [String, nil] :scheme
         | 
| 304 | 
            +
                    #
         | 
| 305 | 
            +
                    #   @option parsed [String, nil] :host
         | 
| 306 | 
            +
                    #
         | 
| 307 | 
            +
                    #   @option parsed [Integer, nil] :port
         | 
| 308 | 
            +
                    #
         | 
| 309 | 
            +
                    #   @option parsed [String, nil] :path
         | 
| 310 | 
            +
                    #
         | 
| 311 | 
            +
                    #   @option parsed [Hash{String=>Array<String>}] :query
         | 
| 312 | 
            +
                    #
         | 
| 313 | 
            +
                    # @return [URI::Generic]
         | 
| 314 | 
            +
                    def unparse_uri(parsed)
         | 
| 315 | 
            +
                      URI::Generic.build(**parsed, query: encode_query(parsed.fetch(:query)))
         | 
| 316 | 
            +
                    end
         | 
| 317 | 
            +
             | 
| 318 | 
            +
                    # @api private
         | 
| 319 | 
            +
                    #
         | 
| 320 | 
            +
                    # @param lhs [Hash{Symbol=>String, Integer, nil}] .
         | 
| 321 | 
            +
                    #
         | 
| 322 | 
            +
                    #   @option lhs [String, nil] :scheme
         | 
| 323 | 
            +
                    #
         | 
| 324 | 
            +
                    #   @option lhs [String, nil] :host
         | 
| 325 | 
            +
                    #
         | 
| 326 | 
            +
                    #   @option lhs [Integer, nil] :port
         | 
| 327 | 
            +
                    #
         | 
| 328 | 
            +
                    #   @option lhs [String, nil] :path
         | 
| 329 | 
            +
                    #
         | 
| 330 | 
            +
                    #   @option lhs [Hash{String=>Array<String>}] :query
         | 
| 331 | 
            +
                    #
         | 
| 332 | 
            +
                    # @param rhs [Hash{Symbol=>String, Integer, nil}] .
         | 
| 333 | 
            +
                    #
         | 
| 334 | 
            +
                    #   @option rhs [String, nil] :scheme
         | 
| 335 | 
            +
                    #
         | 
| 336 | 
            +
                    #   @option rhs [String, nil] :host
         | 
| 337 | 
            +
                    #
         | 
| 338 | 
            +
                    #   @option rhs [Integer, nil] :port
         | 
| 339 | 
            +
                    #
         | 
| 340 | 
            +
                    #   @option rhs [String, nil] :path
         | 
| 341 | 
            +
                    #
         | 
| 342 | 
            +
                    #   @option rhs [Hash{String=>Array<String>}] :query
         | 
| 343 | 
            +
                    #
         | 
| 344 | 
            +
                    # @return [URI::Generic]
         | 
| 345 | 
            +
                    def join_parsed_uri(lhs, rhs)
         | 
| 346 | 
            +
                      base_path, base_query = lhs.fetch_values(:path, :query)
         | 
| 347 | 
            +
                      slashed = base_path.end_with?("/") ? base_path : "#{base_path}/"
         | 
| 348 | 
            +
             | 
| 349 | 
            +
                      parsed_path, parsed_query = parse_uri(rhs.fetch(:path)).fetch_values(:path, :query)
         | 
| 350 | 
            +
                      override = URI::Generic.build(**rhs.slice(:scheme, :host, :port), path: parsed_path)
         | 
| 351 | 
            +
             | 
| 352 | 
            +
                      joined = URI.join(URI::Generic.build(lhs.except(:path, :query)), slashed, override)
         | 
| 353 | 
            +
                      query = deep_merge(
         | 
| 354 | 
            +
                        joined.path == base_path ? base_query : {},
         | 
| 355 | 
            +
                        parsed_query,
         | 
| 356 | 
            +
                        rhs[:query].to_h,
         | 
| 357 | 
            +
                        concat: true
         | 
| 358 | 
            +
                      )
         | 
| 359 | 
            +
             | 
| 360 | 
            +
                      joined.query = encode_query(query)
         | 
| 361 | 
            +
                      joined
         | 
| 362 | 
            +
                    end
         | 
| 363 | 
            +
                  end
         | 
| 364 | 
            +
             | 
| 365 | 
            +
                  class << self
         | 
| 366 | 
            +
                    # @api private
         | 
| 367 | 
            +
                    #
         | 
| 368 | 
            +
                    # @param headers [Hash{String=>String, Integer, Array<String, Integer, nil>, nil}]
         | 
| 369 | 
            +
                    #
         | 
| 370 | 
            +
                    # @return [Hash{String=>String}]
         | 
| 371 | 
            +
                    def normalized_headers(*headers)
         | 
| 372 | 
            +
                      {}.merge(*headers.compact).to_h do |key, val|
         | 
| 373 | 
            +
                        value =
         | 
| 374 | 
            +
                          case val
         | 
| 375 | 
            +
                          in Array
         | 
| 376 | 
            +
                            val.filter_map { _1&.to_s&.strip }.join(", ")
         | 
| 377 | 
            +
                          else
         | 
| 378 | 
            +
                            val&.to_s&.strip
         | 
| 379 | 
            +
                          end
         | 
| 380 | 
            +
                        [key.downcase, value]
         | 
| 381 | 
            +
                      end
         | 
| 382 | 
            +
                    end
         | 
| 383 | 
            +
                  end
         | 
| 384 | 
            +
             | 
| 385 | 
            +
                  # @api private
         | 
| 386 | 
            +
                  #
         | 
| 387 | 
            +
                  # An adapter that satisfies the IO interface required by `::IO.copy_stream`
         | 
| 388 | 
            +
                  class ReadIOAdapter
         | 
| 389 | 
            +
                    # @api private
         | 
| 390 | 
            +
                    #
         | 
| 391 | 
            +
                    # @return [Boolean, nil]
         | 
| 392 | 
            +
                    def close? = @closing
         | 
| 393 | 
            +
             | 
| 394 | 
            +
                    # @api private
         | 
| 395 | 
            +
                    def close
         | 
| 396 | 
            +
                      case @stream
         | 
| 397 | 
            +
                      in Enumerator
         | 
| 398 | 
            +
                        Openlayer::Internal::Util.close_fused!(@stream)
         | 
| 399 | 
            +
                      in IO if close?
         | 
| 400 | 
            +
                        @stream.close
         | 
| 401 | 
            +
                      else
         | 
| 402 | 
            +
                      end
         | 
| 403 | 
            +
                    end
         | 
| 404 | 
            +
             | 
| 405 | 
            +
                    # @api private
         | 
| 406 | 
            +
                    #
         | 
| 407 | 
            +
                    # @param max_len [Integer, nil]
         | 
| 408 | 
            +
                    #
         | 
| 409 | 
            +
                    # @return [String]
         | 
| 410 | 
            +
                    private def read_enum(max_len)
         | 
| 411 | 
            +
                      case max_len
         | 
| 412 | 
            +
                      in nil
         | 
| 413 | 
            +
                        @stream.to_a.join
         | 
| 414 | 
            +
                      in Integer
         | 
| 415 | 
            +
                        @buf << @stream.next while @buf.length < max_len
         | 
| 416 | 
            +
                        @buf.slice!(..max_len)
         | 
| 417 | 
            +
                      end
         | 
| 418 | 
            +
                    rescue StopIteration
         | 
| 419 | 
            +
                      @stream = nil
         | 
| 420 | 
            +
                      @buf.slice!(0..)
         | 
| 421 | 
            +
                    end
         | 
| 422 | 
            +
             | 
| 423 | 
            +
                    # @api private
         | 
| 424 | 
            +
                    #
         | 
| 425 | 
            +
                    # @param max_len [Integer, nil]
         | 
| 426 | 
            +
                    # @param out_string [String, nil]
         | 
| 427 | 
            +
                    #
         | 
| 428 | 
            +
                    # @return [String, nil]
         | 
| 429 | 
            +
                    def read(max_len = nil, out_string = nil)
         | 
| 430 | 
            +
                      case @stream
         | 
| 431 | 
            +
                      in nil
         | 
| 432 | 
            +
                        nil
         | 
| 433 | 
            +
                      in IO | StringIO
         | 
| 434 | 
            +
                        @stream.read(max_len, out_string)
         | 
| 435 | 
            +
                      in Enumerator
         | 
| 436 | 
            +
                        read = read_enum(max_len)
         | 
| 437 | 
            +
                        case out_string
         | 
| 438 | 
            +
                        in String
         | 
| 439 | 
            +
                          out_string.replace(read)
         | 
| 440 | 
            +
                        in nil
         | 
| 441 | 
            +
                          read
         | 
| 442 | 
            +
                        end
         | 
| 443 | 
            +
                      end
         | 
| 444 | 
            +
                        .tap(&@blk)
         | 
| 445 | 
            +
                    end
         | 
| 446 | 
            +
             | 
| 447 | 
            +
                    # @api private
         | 
| 448 | 
            +
                    #
         | 
| 449 | 
            +
                    # @param src [String, Pathname, StringIO, Enumerable<String>]
         | 
| 450 | 
            +
                    # @param blk [Proc]
         | 
| 451 | 
            +
                    #
         | 
| 452 | 
            +
                    # @yieldparam [String]
         | 
| 453 | 
            +
                    def initialize(src, &blk)
         | 
| 454 | 
            +
                      @stream =
         | 
| 455 | 
            +
                        case src
         | 
| 456 | 
            +
                        in String
         | 
| 457 | 
            +
                          StringIO.new(src)
         | 
| 458 | 
            +
                        in Pathname
         | 
| 459 | 
            +
                          @closing = true
         | 
| 460 | 
            +
                          src.open(binmode: true)
         | 
| 461 | 
            +
                        else
         | 
| 462 | 
            +
                          src
         | 
| 463 | 
            +
                        end
         | 
| 464 | 
            +
                      @buf = String.new
         | 
| 465 | 
            +
                      @blk = blk
         | 
| 466 | 
            +
                    end
         | 
| 467 | 
            +
                  end
         | 
| 468 | 
            +
             | 
| 469 | 
            +
                  class << self
         | 
| 470 | 
            +
                    # @param blk [Proc]
         | 
| 471 | 
            +
                    #
         | 
| 472 | 
            +
                    # @yieldparam [Enumerator::Yielder]
         | 
| 473 | 
            +
                    # @return [Enumerable<String>]
         | 
| 474 | 
            +
                    def writable_enum(&blk)
         | 
| 475 | 
            +
                      Enumerator.new do |y|
         | 
| 476 | 
            +
                        y.define_singleton_method(:write) do
         | 
| 477 | 
            +
                          self << _1.dup
         | 
| 478 | 
            +
                          _1.bytesize
         | 
| 479 | 
            +
                        end
         | 
| 480 | 
            +
             | 
| 481 | 
            +
                        blk.call(y)
         | 
| 482 | 
            +
                      end
         | 
| 483 | 
            +
                    end
         | 
| 484 | 
            +
                  end
         | 
| 485 | 
            +
             | 
| 486 | 
            +
                  # @type [Regexp]
         | 
| 487 | 
            +
                  JSON_CONTENT = %r{^application/(?:vnd(?:\.[^.]+)*\+)?json(?!l)}
         | 
| 488 | 
            +
                  # @type [Regexp]
         | 
| 489 | 
            +
                  JSONL_CONTENT = %r{^application/(:?x-(?:n|l)djson)|(:?(?:x-)?jsonl)}
         | 
| 490 | 
            +
             | 
| 491 | 
            +
                  class << self
         | 
| 492 | 
            +
                    # @api private
         | 
| 493 | 
            +
                    #
         | 
| 494 | 
            +
                    # @param y [Enumerator::Yielder]
         | 
| 495 | 
            +
                    # @param val [Object]
         | 
| 496 | 
            +
                    # @param closing [Array<Proc>]
         | 
| 497 | 
            +
                    # @param content_type [String, nil]
         | 
| 498 | 
            +
                    private def write_multipart_content(y, val:, closing:, content_type: nil)
         | 
| 499 | 
            +
                      content_line = "Content-Type: %s\r\n\r\n"
         | 
| 500 | 
            +
             | 
| 501 | 
            +
                      case val
         | 
| 502 | 
            +
                      in Openlayer::FilePart
         | 
| 503 | 
            +
                        return write_multipart_content(
         | 
| 504 | 
            +
                          y,
         | 
| 505 | 
            +
                          val: val.content,
         | 
| 506 | 
            +
                          closing: closing,
         | 
| 507 | 
            +
                          content_type: val.content_type
         | 
| 508 | 
            +
                        )
         | 
| 509 | 
            +
                      in Pathname
         | 
| 510 | 
            +
                        y << format(content_line, content_type || "application/octet-stream")
         | 
| 511 | 
            +
                        io = val.open(binmode: true)
         | 
| 512 | 
            +
                        closing << io.method(:close)
         | 
| 513 | 
            +
                        IO.copy_stream(io, y)
         | 
| 514 | 
            +
                      in IO
         | 
| 515 | 
            +
                        y << format(content_line, content_type || "application/octet-stream")
         | 
| 516 | 
            +
                        IO.copy_stream(val, y)
         | 
| 517 | 
            +
                      in StringIO
         | 
| 518 | 
            +
                        y << format(content_line, content_type || "application/octet-stream")
         | 
| 519 | 
            +
                        y << val.string
         | 
| 520 | 
            +
                      in -> { primitive?(_1) }
         | 
| 521 | 
            +
                        y << format(content_line, content_type || "text/plain")
         | 
| 522 | 
            +
                        y << val.to_s
         | 
| 523 | 
            +
                      else
         | 
| 524 | 
            +
                        y << format(content_line, content_type || "application/json")
         | 
| 525 | 
            +
                        y << JSON.generate(val)
         | 
| 526 | 
            +
                      end
         | 
| 527 | 
            +
                      y << "\r\n"
         | 
| 528 | 
            +
                    end
         | 
| 529 | 
            +
             | 
| 530 | 
            +
                    # @api private
         | 
| 531 | 
            +
                    #
         | 
| 532 | 
            +
                    # @param y [Enumerator::Yielder]
         | 
| 533 | 
            +
                    # @param boundary [String]
         | 
| 534 | 
            +
                    # @param key [Symbol, String]
         | 
| 535 | 
            +
                    # @param val [Object]
         | 
| 536 | 
            +
                    # @param closing [Array<Proc>]
         | 
| 537 | 
            +
                    private def write_multipart_chunk(y, boundary:, key:, val:, closing:)
         | 
| 538 | 
            +
                      y << "--#{boundary}\r\n"
         | 
| 539 | 
            +
                      y << "Content-Disposition: form-data"
         | 
| 540 | 
            +
             | 
| 541 | 
            +
                      unless key.nil?
         | 
| 542 | 
            +
                        name = ERB::Util.url_encode(key.to_s)
         | 
| 543 | 
            +
                        y << "; name=\"#{name}\""
         | 
| 544 | 
            +
                      end
         | 
| 545 | 
            +
             | 
| 546 | 
            +
                      case val
         | 
| 547 | 
            +
                      in Openlayer::FilePart unless val.filename.nil?
         | 
| 548 | 
            +
                        filename = ERB::Util.url_encode(val.filename)
         | 
| 549 | 
            +
                        y << "; filename=\"#{filename}\""
         | 
| 550 | 
            +
                      in Pathname | IO
         | 
| 551 | 
            +
                        filename = ERB::Util.url_encode(::File.basename(val.to_path))
         | 
| 552 | 
            +
                        y << "; filename=\"#{filename}\""
         | 
| 553 | 
            +
                      else
         | 
| 554 | 
            +
                      end
         | 
| 555 | 
            +
                      y << "\r\n"
         | 
| 556 | 
            +
             | 
| 557 | 
            +
                      write_multipart_content(y, val: val, closing: closing)
         | 
| 558 | 
            +
                    end
         | 
| 559 | 
            +
             | 
| 560 | 
            +
                    # @api private
         | 
| 561 | 
            +
                    #
         | 
| 562 | 
            +
                    # https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.1.md#special-considerations-for-multipart-content
         | 
| 563 | 
            +
                    #
         | 
| 564 | 
            +
                    # @param body [Object]
         | 
| 565 | 
            +
                    #
         | 
| 566 | 
            +
                    # @return [Array(String, Enumerable<String>)]
         | 
| 567 | 
            +
                    private def encode_multipart_streaming(body)
         | 
| 568 | 
            +
                      # RFC 1521 Section 7.2.1 says we should have 70 char maximum for boundary length
         | 
| 569 | 
            +
                      boundary = SecureRandom.urlsafe_base64(46)
         | 
| 570 | 
            +
             | 
| 571 | 
            +
                      closing = []
         | 
| 572 | 
            +
                      strio = writable_enum do |y|
         | 
| 573 | 
            +
                        case body
         | 
| 574 | 
            +
                        in Hash
         | 
| 575 | 
            +
                          body.each do |key, val|
         | 
| 576 | 
            +
                            case val
         | 
| 577 | 
            +
                            in Array if val.all? { primitive?(_1) }
         | 
| 578 | 
            +
                              val.each do |v|
         | 
| 579 | 
            +
                                write_multipart_chunk(y, boundary: boundary, key: key, val: v, closing: closing)
         | 
| 580 | 
            +
                              end
         | 
| 581 | 
            +
                            else
         | 
| 582 | 
            +
                              write_multipart_chunk(y, boundary: boundary, key: key, val: val, closing: closing)
         | 
| 583 | 
            +
                            end
         | 
| 584 | 
            +
                          end
         | 
| 585 | 
            +
                        else
         | 
| 586 | 
            +
                          write_multipart_chunk(y, boundary: boundary, key: nil, val: body, closing: closing)
         | 
| 587 | 
            +
                        end
         | 
| 588 | 
            +
                        y << "--#{boundary}--\r\n"
         | 
| 589 | 
            +
                      end
         | 
| 590 | 
            +
             | 
| 591 | 
            +
                      fused_io = fused_enum(strio) { closing.each(&:call) }
         | 
| 592 | 
            +
                      [boundary, fused_io]
         | 
| 593 | 
            +
                    end
         | 
| 594 | 
            +
             | 
| 595 | 
            +
                    # @api private
         | 
| 596 | 
            +
                    #
         | 
| 597 | 
            +
                    # @param headers [Hash{String=>String}]
         | 
| 598 | 
            +
                    # @param body [Object]
         | 
| 599 | 
            +
                    #
         | 
| 600 | 
            +
                    # @return [Object]
         | 
| 601 | 
            +
                    def encode_content(headers, body)
         | 
| 602 | 
            +
                      # rubocop:disable Style/CaseEquality
         | 
| 603 | 
            +
                      # rubocop:disable Layout/LineLength
         | 
| 604 | 
            +
                      content_type = headers["content-type"]
         | 
| 605 | 
            +
                      case [content_type, body]
         | 
| 606 | 
            +
                      in [Openlayer::Internal::Util::JSON_CONTENT, Hash | Array | -> { primitive?(_1) }]
         | 
| 607 | 
            +
                        [headers, JSON.generate(body)]
         | 
| 608 | 
            +
                      in [Openlayer::Internal::Util::JSONL_CONTENT, Enumerable] unless Openlayer::Internal::Type::FileInput === body
         | 
| 609 | 
            +
                        [headers, body.lazy.map { JSON.generate(_1) }]
         | 
| 610 | 
            +
                      in [%r{^multipart/form-data}, Hash | Openlayer::Internal::Type::FileInput]
         | 
| 611 | 
            +
                        boundary, strio = encode_multipart_streaming(body)
         | 
| 612 | 
            +
                        headers = {**headers, "content-type" => "#{content_type}; boundary=#{boundary}"}
         | 
| 613 | 
            +
                        [headers, strio]
         | 
| 614 | 
            +
                      in [_, Symbol | Numeric]
         | 
| 615 | 
            +
                        [headers, body.to_s]
         | 
| 616 | 
            +
                      in [_, StringIO]
         | 
| 617 | 
            +
                        [headers, body.string]
         | 
| 618 | 
            +
                      in [_, Openlayer::FilePart]
         | 
| 619 | 
            +
                        [headers, body.content]
         | 
| 620 | 
            +
                      else
         | 
| 621 | 
            +
                        [headers, body]
         | 
| 622 | 
            +
                      end
         | 
| 623 | 
            +
                      # rubocop:enable Layout/LineLength
         | 
| 624 | 
            +
                      # rubocop:enable Style/CaseEquality
         | 
| 625 | 
            +
                    end
         | 
| 626 | 
            +
             | 
| 627 | 
            +
                    # @api private
         | 
| 628 | 
            +
                    #
         | 
| 629 | 
            +
                    # https://www.iana.org/assignments/character-sets/character-sets.xhtml
         | 
| 630 | 
            +
                    #
         | 
| 631 | 
            +
                    # @param content_type [String]
         | 
| 632 | 
            +
                    # @param text [String]
         | 
| 633 | 
            +
                    def force_charset!(content_type, text:)
         | 
| 634 | 
            +
                      charset = /charset=([^;\s]+)/.match(content_type)&.captures&.first
         | 
| 635 | 
            +
             | 
| 636 | 
            +
                      return unless charset
         | 
| 637 | 
            +
             | 
| 638 | 
            +
                      begin
         | 
| 639 | 
            +
                        encoding = Encoding.find(charset)
         | 
| 640 | 
            +
                        text.force_encoding(encoding)
         | 
| 641 | 
            +
                      rescue ArgumentError
         | 
| 642 | 
            +
                        nil
         | 
| 643 | 
            +
                      end
         | 
| 644 | 
            +
                    end
         | 
| 645 | 
            +
             | 
| 646 | 
            +
                    # @api private
         | 
| 647 | 
            +
                    #
         | 
| 648 | 
            +
                    # Assumes each chunk in stream has `Encoding::BINARY`.
         | 
| 649 | 
            +
                    #
         | 
| 650 | 
            +
                    # @param headers [Hash{String=>String}]
         | 
| 651 | 
            +
                    # @param stream [Enumerable<String>]
         | 
| 652 | 
            +
                    # @param suppress_error [Boolean]
         | 
| 653 | 
            +
                    #
         | 
| 654 | 
            +
                    # @raise [JSON::ParserError]
         | 
| 655 | 
            +
                    # @return [Object]
         | 
| 656 | 
            +
                    def decode_content(headers, stream:, suppress_error: false)
         | 
| 657 | 
            +
                      case (content_type = headers["content-type"])
         | 
| 658 | 
            +
                      in Openlayer::Internal::Util::JSON_CONTENT
         | 
| 659 | 
            +
                        json = stream.to_a.join
         | 
| 660 | 
            +
                        begin
         | 
| 661 | 
            +
                          JSON.parse(json, symbolize_names: true)
         | 
| 662 | 
            +
                        rescue JSON::ParserError => e
         | 
| 663 | 
            +
                          raise e unless suppress_error
         | 
| 664 | 
            +
                          json
         | 
| 665 | 
            +
                        end
         | 
| 666 | 
            +
                      in Openlayer::Internal::Util::JSONL_CONTENT
         | 
| 667 | 
            +
                        lines = decode_lines(stream)
         | 
| 668 | 
            +
                        chain_fused(lines) do |y|
         | 
| 669 | 
            +
                          lines.each { y << JSON.parse(_1, symbolize_names: true) }
         | 
| 670 | 
            +
                        end
         | 
| 671 | 
            +
                      in %r{^text/event-stream}
         | 
| 672 | 
            +
                        lines = decode_lines(stream)
         | 
| 673 | 
            +
                        decode_sse(lines)
         | 
| 674 | 
            +
                      else
         | 
| 675 | 
            +
                        text = stream.to_a.join
         | 
| 676 | 
            +
                        force_charset!(content_type, text: text)
         | 
| 677 | 
            +
                        StringIO.new(text)
         | 
| 678 | 
            +
                      end
         | 
| 679 | 
            +
                    end
         | 
| 680 | 
            +
                  end
         | 
| 681 | 
            +
             | 
| 682 | 
            +
                  class << self
         | 
| 683 | 
            +
                    # @api private
         | 
| 684 | 
            +
                    #
         | 
| 685 | 
            +
                    # https://doc.rust-lang.org/std/iter/trait.FusedIterator.html
         | 
| 686 | 
            +
                    #
         | 
| 687 | 
            +
                    # @param enum [Enumerable<Object>]
         | 
| 688 | 
            +
                    # @param external [Boolean]
         | 
| 689 | 
            +
                    # @param close [Proc]
         | 
| 690 | 
            +
                    #
         | 
| 691 | 
            +
                    # @return [Enumerable<Object>]
         | 
| 692 | 
            +
                    def fused_enum(enum, external: false, &close)
         | 
| 693 | 
            +
                      fused = false
         | 
| 694 | 
            +
                      iter = Enumerator.new do |y|
         | 
| 695 | 
            +
                        next if fused
         | 
| 696 | 
            +
             | 
| 697 | 
            +
                        fused = true
         | 
| 698 | 
            +
                        if external
         | 
| 699 | 
            +
                          loop { y << enum.next }
         | 
| 700 | 
            +
                        else
         | 
| 701 | 
            +
                          enum.each(&y)
         | 
| 702 | 
            +
                        end
         | 
| 703 | 
            +
                      ensure
         | 
| 704 | 
            +
                        close&.call
         | 
| 705 | 
            +
                        close = nil
         | 
| 706 | 
            +
                      end
         | 
| 707 | 
            +
             | 
| 708 | 
            +
                      iter.define_singleton_method(:rewind) do
         | 
| 709 | 
            +
                        fused = true
         | 
| 710 | 
            +
                        self
         | 
| 711 | 
            +
                      end
         | 
| 712 | 
            +
                      iter
         | 
| 713 | 
            +
                    end
         | 
| 714 | 
            +
             | 
| 715 | 
            +
                    # @api private
         | 
| 716 | 
            +
                    #
         | 
| 717 | 
            +
                    # @param enum [Enumerable<Object>, nil]
         | 
| 718 | 
            +
                    def close_fused!(enum)
         | 
| 719 | 
            +
                      return unless enum.is_a?(Enumerator)
         | 
| 720 | 
            +
             | 
| 721 | 
            +
                      # rubocop:disable Lint/UnreachableLoop
         | 
| 722 | 
            +
                      enum.rewind.each { break }
         | 
| 723 | 
            +
                      # rubocop:enable Lint/UnreachableLoop
         | 
| 724 | 
            +
                    end
         | 
| 725 | 
            +
             | 
| 726 | 
            +
                    # @api private
         | 
| 727 | 
            +
                    #
         | 
| 728 | 
            +
                    # @param enum [Enumerable<Object>, nil]
         | 
| 729 | 
            +
                    # @param blk [Proc]
         | 
| 730 | 
            +
                    #
         | 
| 731 | 
            +
                    # @yieldparam [Enumerator::Yielder]
         | 
| 732 | 
            +
                    # @return [Enumerable<Object>]
         | 
| 733 | 
            +
                    def chain_fused(enum, &blk)
         | 
| 734 | 
            +
                      iter = Enumerator.new { blk.call(_1) }
         | 
| 735 | 
            +
                      fused_enum(iter) { close_fused!(enum) }
         | 
| 736 | 
            +
                    end
         | 
| 737 | 
            +
                  end
         | 
| 738 | 
            +
             | 
| 739 | 
            +
                  class << self
         | 
| 740 | 
            +
                    # @api private
         | 
| 741 | 
            +
                    #
         | 
| 742 | 
            +
                    # Assumes Strings have been forced into having `Encoding::BINARY`.
         | 
| 743 | 
            +
                    #
         | 
| 744 | 
            +
                    # This decoder is responsible for reassembling lines split across multiple
         | 
| 745 | 
            +
                    # fragments.
         | 
| 746 | 
            +
                    #
         | 
| 747 | 
            +
                    # @param enum [Enumerable<String>]
         | 
| 748 | 
            +
                    #
         | 
| 749 | 
            +
                    # @return [Enumerable<String>]
         | 
| 750 | 
            +
                    def decode_lines(enum)
         | 
| 751 | 
            +
                      re = /(\r\n|\r|\n)/
         | 
| 752 | 
            +
                      buffer = String.new
         | 
| 753 | 
            +
                      cr_seen = nil
         | 
| 754 | 
            +
             | 
| 755 | 
            +
                      chain_fused(enum) do |y|
         | 
| 756 | 
            +
                        enum.each do |row|
         | 
| 757 | 
            +
                          offset = buffer.bytesize
         | 
| 758 | 
            +
                          buffer << row
         | 
| 759 | 
            +
                          while (match = re.match(buffer, cr_seen&.to_i || offset))
         | 
| 760 | 
            +
                            case [match.captures.first, cr_seen]
         | 
| 761 | 
            +
                            in ["\r", nil]
         | 
| 762 | 
            +
                              cr_seen = match.end(1)
         | 
| 763 | 
            +
                              next
         | 
| 764 | 
            +
                            in ["\r" | "\r\n", Integer]
         | 
| 765 | 
            +
                              y << buffer.slice!(..(cr_seen.pred))
         | 
| 766 | 
            +
                            else
         | 
| 767 | 
            +
                              y << buffer.slice!(..(match.end(1).pred))
         | 
| 768 | 
            +
                            end
         | 
| 769 | 
            +
                            offset = 0
         | 
| 770 | 
            +
                            cr_seen = nil
         | 
| 771 | 
            +
                          end
         | 
| 772 | 
            +
                        end
         | 
| 773 | 
            +
             | 
| 774 | 
            +
                        y << buffer.slice!(..(cr_seen.pred)) unless cr_seen.nil?
         | 
| 775 | 
            +
                        y << buffer unless buffer.empty?
         | 
| 776 | 
            +
                      end
         | 
| 777 | 
            +
                    end
         | 
| 778 | 
            +
             | 
| 779 | 
            +
                    # @api private
         | 
| 780 | 
            +
                    #
         | 
| 781 | 
            +
                    # https://html.spec.whatwg.org/multipage/server-sent-events.html#parsing-an-event-stream
         | 
| 782 | 
            +
                    #
         | 
| 783 | 
            +
                    # Assumes that `lines` has been decoded with `#decode_lines`.
         | 
| 784 | 
            +
                    #
         | 
| 785 | 
            +
                    # @param lines [Enumerable<String>]
         | 
| 786 | 
            +
                    #
         | 
| 787 | 
            +
                    # @return [Enumerable<Hash{Symbol=>Object}>]
         | 
| 788 | 
            +
                    def decode_sse(lines)
         | 
| 789 | 
            +
                      # rubocop:disable Metrics/BlockLength
         | 
| 790 | 
            +
                      chain_fused(lines) do |y|
         | 
| 791 | 
            +
                        blank = {event: nil, data: nil, id: nil, retry: nil}
         | 
| 792 | 
            +
                        current = {}
         | 
| 793 | 
            +
             | 
| 794 | 
            +
                        lines.each do |line|
         | 
| 795 | 
            +
                          case line.sub(/\R$/, "")
         | 
| 796 | 
            +
                          in ""
         | 
| 797 | 
            +
                            next if current.empty?
         | 
| 798 | 
            +
                            y << {**blank, **current}
         | 
| 799 | 
            +
                            current = {}
         | 
| 800 | 
            +
                          in /^:/
         | 
| 801 | 
            +
                            next
         | 
| 802 | 
            +
                          in /^([^:]+):\s?(.*)$/
         | 
| 803 | 
            +
                            field, value = Regexp.last_match.captures
         | 
| 804 | 
            +
                            case field
         | 
| 805 | 
            +
                            in "event"
         | 
| 806 | 
            +
                              current.merge!(event: value)
         | 
| 807 | 
            +
                            in "data"
         | 
| 808 | 
            +
                              (current[:data] ||= String.new) << (value << "\n")
         | 
| 809 | 
            +
                            in "id" unless value.include?("\0")
         | 
| 810 | 
            +
                              current.merge!(id: value)
         | 
| 811 | 
            +
                            in "retry" if /^\d+$/ =~ value
         | 
| 812 | 
            +
                              current.merge!(retry: Integer(value))
         | 
| 813 | 
            +
                            else
         | 
| 814 | 
            +
                            end
         | 
| 815 | 
            +
                          else
         | 
| 816 | 
            +
                          end
         | 
| 817 | 
            +
                        end
         | 
| 818 | 
            +
                        # rubocop:enable Metrics/BlockLength
         | 
| 819 | 
            +
             | 
| 820 | 
            +
                        y << {**blank, **current} unless current.empty?
         | 
| 821 | 
            +
                      end
         | 
| 822 | 
            +
                    end
         | 
| 823 | 
            +
                  end
         | 
| 824 | 
            +
             | 
| 825 | 
            +
                  # @api private
         | 
| 826 | 
            +
                  module SorbetRuntimeSupport
         | 
| 827 | 
            +
                    class MissingSorbetRuntimeError < ::RuntimeError
         | 
| 828 | 
            +
                    end
         | 
| 829 | 
            +
             | 
| 830 | 
            +
                    # @api private
         | 
| 831 | 
            +
                    #
         | 
| 832 | 
            +
                    # @return [Hash{Symbol=>Object}]
         | 
| 833 | 
            +
                    private def sorbet_runtime_constants = @sorbet_runtime_constants ||= {}
         | 
| 834 | 
            +
             | 
| 835 | 
            +
                    # @api private
         | 
| 836 | 
            +
                    #
         | 
| 837 | 
            +
                    # @param name [Symbol]
         | 
| 838 | 
            +
                    def const_missing(name)
         | 
| 839 | 
            +
                      super unless sorbet_runtime_constants.key?(name)
         | 
| 840 | 
            +
             | 
| 841 | 
            +
                      unless Object.const_defined?(:T)
         | 
| 842 | 
            +
                        message = "Trying to access a Sorbet constant #{name.inspect} without `sorbet-runtime`."
         | 
| 843 | 
            +
                        raise MissingSorbetRuntimeError.new(message)
         | 
| 844 | 
            +
                      end
         | 
| 845 | 
            +
             | 
| 846 | 
            +
                      sorbet_runtime_constants.fetch(name).call
         | 
| 847 | 
            +
                    end
         | 
| 848 | 
            +
             | 
| 849 | 
            +
                    # @api private
         | 
| 850 | 
            +
                    #
         | 
| 851 | 
            +
                    # @param name [Symbol]
         | 
| 852 | 
            +
                    #
         | 
| 853 | 
            +
                    # @return [Boolean]
         | 
| 854 | 
            +
                    def sorbet_constant_defined?(name) = sorbet_runtime_constants.key?(name)
         | 
| 855 | 
            +
             | 
| 856 | 
            +
                    # @api private
         | 
| 857 | 
            +
                    #
         | 
| 858 | 
            +
                    # @param name [Symbol]
         | 
| 859 | 
            +
                    # @param blk [Proc]
         | 
| 860 | 
            +
                    def define_sorbet_constant!(name, &blk) = sorbet_runtime_constants.store(name, blk)
         | 
| 861 | 
            +
             | 
| 862 | 
            +
                    # @api private
         | 
| 863 | 
            +
                    #
         | 
| 864 | 
            +
                    # @return [Object]
         | 
| 865 | 
            +
                    def to_sorbet_type = raise NotImplementedError
         | 
| 866 | 
            +
             | 
| 867 | 
            +
                    class << self
         | 
| 868 | 
            +
                      # @api private
         | 
| 869 | 
            +
                      #
         | 
| 870 | 
            +
                      # @param type [Openlayer::Internal::Util::SorbetRuntimeSupport, Object]
         | 
| 871 | 
            +
                      #
         | 
| 872 | 
            +
                      # @return [Object]
         | 
| 873 | 
            +
                      def to_sorbet_type(type)
         | 
| 874 | 
            +
                        case type
         | 
| 875 | 
            +
                        in Openlayer::Internal::Util::SorbetRuntimeSupport
         | 
| 876 | 
            +
                          type.to_sorbet_type
         | 
| 877 | 
            +
                        in Class | Module
         | 
| 878 | 
            +
                          type
         | 
| 879 | 
            +
                        in true | false
         | 
| 880 | 
            +
                          T::Boolean
         | 
| 881 | 
            +
                        else
         | 
| 882 | 
            +
                          type.class
         | 
| 883 | 
            +
                        end
         | 
| 884 | 
            +
                      end
         | 
| 885 | 
            +
                    end
         | 
| 886 | 
            +
                  end
         | 
| 887 | 
            +
             | 
| 888 | 
            +
                  extend Openlayer::Internal::Util::SorbetRuntimeSupport
         | 
| 889 | 
            +
             | 
| 890 | 
            +
                  define_sorbet_constant!(:ParsedUri) do
         | 
| 891 | 
            +
                    T.type_alias do
         | 
| 892 | 
            +
                      {
         | 
| 893 | 
            +
                        scheme: T.nilable(String),
         | 
| 894 | 
            +
                        host: T.nilable(String),
         | 
| 895 | 
            +
                        port: T.nilable(Integer),
         | 
| 896 | 
            +
                        path: T.nilable(String),
         | 
| 897 | 
            +
                        query: T::Hash[String, T::Array[String]]
         | 
| 898 | 
            +
                      }
         | 
| 899 | 
            +
                    end
         | 
| 900 | 
            +
                  end
         | 
| 901 | 
            +
             | 
| 902 | 
            +
                  define_sorbet_constant!(:ServerSentEvent) do
         | 
| 903 | 
            +
                    T.type_alias do
         | 
| 904 | 
            +
                      {
         | 
| 905 | 
            +
                        event: T.nilable(String),
         | 
| 906 | 
            +
                        data: T.nilable(String),
         | 
| 907 | 
            +
                        id: T.nilable(String),
         | 
| 908 | 
            +
                        retry: T.nilable(Integer)
         | 
| 909 | 
            +
                      }
         | 
| 910 | 
            +
                    end
         | 
| 911 | 
            +
                  end
         | 
| 912 | 
            +
                end
         | 
| 913 | 
            +
              end
         | 
| 914 | 
            +
            end
         |