module Lithic::Internal::Util
def self.monotonic_secs = Process.clock_gettime(Process::CLOCK_MONOTONIC)
-
(Float)
-
Other tags:
- Api: - private
def self.monotonic_secs = Process.clock_gettime(Process::CLOCK_MONOTONIC)
def arch
-
(String)
-
Other tags:
- Api: - private
def arch case (arch = RbConfig::CONFIG["arch"])&.downcase in nil "unknown" in /aarch64|arm64/ "arm64" in /x86_64/ "x64" in /arm/ "arm" else "other:#{arch}" end end
def chain_fused(enum, &blk)
-
(Enumerable
-
Other tags:
- Yieldparam: -
Parameters:
-
blk
(Proc
) -- -
enum
(Enumerable
) --
Other tags:
- Api: - private
def chain_fused(enum, &blk) iter = Enumerator.new { blk.call(_1) } fused_enum(iter) { close_fused!(enum) } end
def close_fused!(enum)
-
enum
(Enumerable
) --
Other tags:
- Api: - private
def close_fused!(enum) return unless enum.is_a?(Enumerator) # rubocop:disable Lint/UnreachableLoop enum.rewind.each { break } # rubocop:enable Lint/UnreachableLoop end
def coerce_boolean(input)
-
(Boolean, Object)
-
Parameters:
-
input
(String, Boolean
) --
Other tags:
- Api: - private
def coerce_boolean(input) case input.is_a?(String) ? input.downcase : input in "true" true in "false" false else input end end
def coerce_boolean!(input)
-
(Boolean, nil)
-
Raises:
-
(ArgumentError)
-
Parameters:
-
input
(String, Boolean
) --
Other tags:
- Api: - private
def coerce_boolean!(input) case coerce_boolean(input) in true | false | nil => coerced coerced else raise ArgumentError.new("Unable to coerce #{input.inspect} into boolean value") end end
def coerce_float(input)
-
(Float, Object)
-
Parameters:
-
input
(String, Integer, Float
) --
Other tags:
- Api: - private
def coerce_float(input) Float(input, exception: false) || input end
def coerce_hash(input)
-
(Hash{Object=>Object}, Object)
-
Parameters:
-
input
(Object
) --
Other tags:
- Api: - private
def coerce_hash(input) case input in NilClass | Array | Set | Enumerator | StringIO | IO input else input.respond_to?(:to_h) ? input.to_h : input end end
def coerce_hash!(input)
-
(Hash{Object=>Object}, nil)
-
Raises:
-
(ArgumentError)
-
Parameters:
-
input
(Object
) --
Other tags:
- Api: - private
def coerce_hash!(input) case coerce_hash(input) in Hash | nil => coerced coerced else message = "Expected a #{Hash} or #{Lithic::Internal::Type::BaseModel}, got #{data.inspect}" raise ArgumentError.new(message) end end
def coerce_integer(input)
-
(Integer, Object)
-
Parameters:
-
input
(String, Integer
) --
Other tags:
- Api: - private
def coerce_integer(input) Integer(input, exception: false) || input end
def decode_content(headers, stream:, suppress_error: false)
-
(Object)
-
Raises:
-
(JSON::ParserError)
-
Parameters:
-
suppress_error
(Boolean
) -- -
stream
(Enumerable
) -- -
headers
(Hash{String=>String}, Net::HTTPHeader
) --
Other tags:
- Api: - private
def decode_content(headers, stream:, suppress_error: false) case (content_type = headers["content-type"]) in Lithic::Internal::Util::JSON_CONTENT json = stream.to_a.join begin JSON.parse(json, symbolize_names: true) rescue JSON::ParserError => e raise e unless suppress_error json end in Lithic::Internal::Util::JSONL_CONTENT lines = decode_lines(stream) chain_fused(lines) do |y| lines.each { y << JSON.parse(_1, symbolize_names: true) } end in %r{^text/event-stream} lines = decode_lines(stream) decode_sse(lines) else text = stream.to_a.join force_charset!(content_type, text: text) StringIO.new(text) end end
def decode_lines(enum)
-
(Enumerable
-)
Parameters:
-
enum
(Enumerable
) --
Other tags:
- Api: - private
def decode_lines(enum) re = /(\r\n|\r|\n)/ buffer = String.new cr_seen = nil chain_fused(enum) do |y| enum.each do |row| offset = buffer.bytesize buffer << row while (match = re.match(buffer, cr_seen&.to_i || offset)) case [match.captures.first, cr_seen] in ["\r", nil] cr_seen = match.end(1) next in ["\r" | "\r\n", Integer] y << buffer.slice!(..(cr_seen.pred)) else y << buffer.slice!(..(match.end(1).pred)) end offset = 0 cr_seen = nil end end y << buffer.slice!(..(cr_seen.pred)) unless cr_seen.nil? y << buffer unless buffer.empty? end end
def decode_query(query)
-
(Hash{String=>Array
-})
Parameters:
-
query
(String, nil
) --
Other tags:
- Api: - private
def decode_query(query) CGI.parse(query.to_s) end
def decode_sse(lines)
-
(Enumerable
-Object}>)
Parameters:
-
lines
(Enumerable
) --
Other tags:
- Api: - private
def decode_sse(lines) # rubocop:disable Metrics/BlockLength chain_fused(lines) do |y| blank = {event: nil, data: nil, id: nil, retry: nil} current = {} lines.each do |line| case line.sub(/\R$/, "") in "" next if current.empty? y << {**blank, **current} current = {} in /^:/ next in /^([^:]+):\s?(.*)$/ field, value = Regexp.last_match.captures case field in "event" current.merge!(event: value) in "data" (current[:data] ||= String.new) << (value << "\n") in "id" unless value.include?("\0") current.merge!(id: value) in "retry" if /^\d+$/ =~ value current.merge!(retry: Integer(value)) else end else end end # rubocop:enable Metrics/BlockLength y << {**blank, **current} unless current.empty? end end
def deep_merge(*values, sentinel: nil, concat: false)
-
(Object)
-
Parameters:
-
concat
(Boolean
) -- whether to merge sequences by concatenation. -
sentinel
(Object, nil
) -- the value to return if no values are provided. -
values
(Array
) --
Other tags:
- Api: - private
def deep_merge(*values, sentinel: nil, concat: false) case values in [value, *values] values.reduce(value) do |acc, val| deep_merge_lr(acc, val, concat: concat) end else sentinel end end
def deep_merge_lr(lhs, rhs, concat: false)
-
(Object)
-
Parameters:
-
concat
(Boolean
) -- -
rhs
(Object
) -- -
lhs
(Object
) --
Other tags:
- Api: - private
def deep_merge_lr(lhs, rhs, concat: false) lhs, rhs, concat] sh, Hash, _] merge(rhs) { deep_merge_lr(_2, _3, concat: concat) } ray, Array, true] concat(rhs)
def dig(data, pick, &blk)
-
(Object, nil)
-
Parameters:
-
blk
(Proc, nil
) -- -
pick
(Symbol, Integer, Array
) --, Proc, nil -
data
(Hash{Symbol=>Object}, Array
) --
Other tags:
- Api: - private
def dig(data, pick, &blk) case [data, pick] in [_, nil] data in [Hash, Symbol] | [Array, Integer] data.fetch(pick) { blk&.call } in [Hash | Array, Array] pick.reduce(data) do |acc, key| case acc in Hash if acc.key?(key) acc.fetch(key) in Array if key.is_a?(Integer) && key < acc.length acc[key] else return blk&.call end end in [_, Proc] pick.call(data) else blk&.call end end
def encode_content(headers, body)
-
(Object)
-
Parameters:
-
body
(Object
) -- -
headers
(Hash{String=>String}
) --
Other tags:
- Api: - private
def encode_content(headers, body) content_type = headers["content-type"] case [content_type, body] in [Lithic::Internal::Util::JSON_CONTENT, Hash | Array | -> { primitive?(_1) }] [headers, JSON.generate(body)] in [Lithic::Internal::Util::JSONL_CONTENT, Enumerable] unless body.is_a?(Lithic::Internal::Type::FileInput) [headers, body.lazy.map { JSON.generate(_1) }] in [%r{^multipart/form-data}, Hash | Lithic::Internal::Type::FileInput] boundary, strio = encode_multipart_streaming(body) headers = {**headers, "content-type" => "#{content_type}; boundary=#{boundary}"} [headers, strio] in [_, Symbol | Numeric] [headers, body.to_s] in [_, StringIO] [headers, body.string] in [_, Lithic::FilePart] [headers, body.content] else [headers, body] end end
def encode_multipart_streaming(body)
-
(Array(String, Enumerable
-))
Parameters:
-
body
(Object
) --
Other tags:
- Api: - private
def encode_multipart_streaming(body) ry = SecureRandom.urlsafe_base64(60) g = [] = writable_enum do |y| body ash dy.each do |key, val| case val in Array if val.all? { primitive?(_1) } val.each do |v| write_multipart_chunk(y, boundary: boundary, key: key, val: v, closing: closing) end else write_multipart_chunk(y, boundary: boundary, key: key, val: val, closing: closing) end d ite_multipart_chunk(y, boundary: boundary, key: nil, val: body, closing: closing) "--#{boundary}--\r\n" io = fused_enum(strio) { closing.each(&:call) } ary, fused_io]
def encode_query(query)
-
(String, nil)
-
Parameters:
-
query
(Hash{String=>Array
) --, String, nil}, nil
Other tags:
- Api: - private
def encode_query(query) query.to_h.empty? ? nil : URI.encode_www_form(query) end
def force_charset!(content_type, text:)
-
text
(String
) -- -
content_type
(String
) --
Other tags:
- Api: - private
def force_charset!(content_type, text:) charset = /charset=([^;\s]+)/.match(content_type)&.captures&.first return unless charset begin encoding = Encoding.find(charset) text.force_encoding(encoding) rescue ArgumentError nil end end
def fused_enum(enum, external: false, &close)
-
(Enumerable
-
Parameters:
-
close
(Proc
) -- -
external
(Boolean
) -- -
enum
(Enumerable
) --
Other tags:
- Api: - private
def fused_enum(enum, external: false, &close) fused = false iter = Enumerator.new do |y| next if fused fused = true if external loop { y << enum.next } else enum.each(&y) end ensure close&.call close = nil end iter.define_singleton_method(:rewind) do fused = true self end iter end
def interpolate_path(path)
-
(String)
-
Parameters:
-
path
(String, Array
) --
Other tags:
- Api: - private
def interpolate_path(path) case path in String path in [] "" in [String => p, *interpolations] encoded = interpolations.map { ERB::Util.url_encode(_1) } format(p, *encoded) end end
def join_parsed_uri(lhs, rhs)
-
(URI::Generic)
-
Options Hash:
(**rhs)
-
:query
(Hash{String=>Array
) --} -
:path
(String, nil
) -- -
:port
(Integer, nil
) -- -
:host
(String, nil
) -- -
:scheme
(String, nil
) -- -
:query
(Hash{String=>Array
) --} -
:path
(String, nil
) -- -
:port
(Integer, nil
) -- -
:host
(String, nil
) -- -
:scheme
(String, nil
) --
Parameters:
-
rhs
(Hash{Symbol=>String, Integer, nil}
) -- . -
lhs
(Hash{Symbol=>String, Integer, nil}
) -- .
Other tags:
- Api: - private
def join_parsed_uri(lhs, rhs) base_path, base_query = lhs.fetch_values(:path, :query) slashed = base_path.end_with?("/") ? base_path : "#{base_path}/" parsed_path, parsed_query = parse_uri(rhs.fetch(:path)).fetch_values(:path, :query) override = URI::Generic.build(**rhs.slice(:scheme, :host, :port), path: parsed_path) joined = URI.join(URI::Generic.build(lhs.except(:path, :query)), slashed, override) query = deep_merge( joined.path == base_path ? base_query : {}, parsed_query, rhs[:query].to_h, concat: true ) joined.query = encode_query(query) joined end
def normalized_headers(*headers)
-
(Hash{String=>String})
-
Parameters:
-
headers
(Hash{String=>String, Integer, Array
) --, nil}
Other tags:
- Api: - private
def normalized_headers(*headers) {}.merge(*headers.compact).to_h do |key, val| value = case val in Array val.filter_map { _1&.to_s&.strip }.join(", ") else val&.to_s&.strip end [key.downcase, value] end end
def os
-
(String)
-
Other tags:
- Api: - private
def os case (host = RbConfig::CONFIG["host_os"])&.downcase in nil "Unknown" in /linux/ "Linux" in /darwin/ "MacOS" in /freebsd/ "FreeBSD" in /openbsd/ "OpenBSD" in /mswin|mingw|cygwin|ucrt/ "Windows" else "Other:#{host}" end end
def parse_uri(url)
-
(Hash{Symbol=>String, Integer, nil})
-
Parameters:
-
url
(URI::Generic, String
) --
Other tags:
- Api: - private
def parse_uri(url) parsed = URI::Generic.component.zip(URI.split(url)).to_h {**parsed, query: decode_query(parsed.fetch(:query))} end
def primitive?(input)
-
(Boolean)
-
Parameters:
-
input
(Object
) --
Other tags:
- Api: - private
def primitive?(input) case input in true | false | Numeric | Symbol | String true else false end end
def unparse_uri(parsed)
-
(URI::Generic)
-
Options Hash:
(**parsed)
-
:query
(Hash{String=>Array
) --} -
:path
(String, nil
) -- -
:port
(Integer, nil
) -- -
:host
(String, nil
) -- -
:scheme
(String, nil
) --
Parameters:
-
parsed
(Hash{Symbol=>String, Integer, nil}
) -- .
Other tags:
- Api: - private
def unparse_uri(parsed) URI::Generic.build(**parsed, query: encode_query(parsed.fetch(:query))) end
def uri_origin(uri)
-
(String)
-
Parameters:
-
uri
(URI::Generic
) --
Other tags:
- Api: - private
def uri_origin(uri) "#{uri.scheme}://#{uri.host}#{uri.port == uri.default_port ? '' : ":#{uri.port}"}" end
def writable_enum(&blk)
-
(Enumerable
-)
Other tags:
- Yieldparam: -
Parameters:
-
blk
(Proc
) --
def writable_enum(&blk) Enumerator.new do |y| buf = String.new y.define_singleton_method(:write) do self << buf.replace(_1) buf.bytesize end blk.call(y) end end
def write_multipart_chunk(y, boundary:, key:, val:, closing:)
-
closing
(Array
) -- -
val
(Object
) -- -
key
(Symbol, String
) -- -
boundary
(String
) -- -
y
(Enumerator::Yielder
) --
Other tags:
- Api: - private
def write_multipart_chunk(y, boundary:, key:, val:, closing:) --#{boundary}\r\n" Content-Disposition: form-data" key.nil? = ERB::Util.url_encode(key.to_s) "; name=\"#{name}\"" al hic::FilePart unless val.filename.nil? name = ERB::Util.url_encode(val.filename) "; filename=\"#{filename}\"" hname | IO name = ERB::Util.url_encode(::File.basename(val.to_path)) "; filename=\"#{filename}\"" \r\n" multipart_content(y, val: val, closing: closing)
def write_multipart_content(y, val:, closing:, content_type: nil)
-
content_type
(String, nil
) -- -
closing
(Array
) -- -
val
(Object
) -- -
y
(Enumerator::Yielder
) --
Other tags:
- Api: - private
def write_multipart_content(y, val:, closing:, content_type: nil) t_type ||= "application/octet-stream" al hic::FilePart rn write_multipart_content( l: val.content, osing: closing, ntent_type: val.content_type hname "Content-Type: #{content_type}\r\n\r\n" val.open(binmode: true) ing << io.method(:close) opy_stream(io, y) "Content-Type: #{content_type}\r\n\r\n" opy_stream(val, y) ingIO "Content-Type: #{content_type}\r\n\r\n" val.string ing "Content-Type: #{content_type}\r\n\r\n" val.to_s { primitive?(_1) } "Content-Type: text/plain\r\n\r\n" val.to_s "Content-Type: application/json\r\n\r\n" JSON.generate(val) \r\n"