# encoding: utf-8 module HTTPkit class Body include Adamantium::Mutable def self.build(source = nil, length = nil) if source.is_a?(self) source else new(source, length) end end attr_reader :closed # @param [String,#each,nil] source def initialize(source = nil, length = nil, closed = Promise.new) @source, @length = source, length @closed = closed @chunks = [] apply_source @closed.fulfill if source end def length @length || 0 end def length_known? !@length.nil? end def write(chunk) if @closed.pending? && !chunk.empty? @chunks << chunk @closed.progress(chunk) end end def each(&block) return to_enum(__method__) unless block if @source.respond_to?(:each) @source.each(&block) else each_chunk(&block) end end def to_s each.to_a.join end def inspect len = length_known? ? length : 'unknown' sprintf('#<%s:0x%d @length=%s>', self.class.name, object_id, len) end private def apply_source if @source.respond_to?(:to_str) && (chunk = @source.to_str) @length = chunk.bytesize write(chunk) elsif @source.respond_to?(:bytesize) @length = @source.bytesize end end def each_chunk(&block) @closed.on_progress(&block) @chunks.dup.each(&block) @closed.sync end end end