Class: Down::ChunkedIO

Inherits:
Object
  • Object
show all
Defined in:
lib/down/chunked_io.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(chunks:, size: nil, on_close: nil, data: {}, rewindable: true, encoding: nil) ⇒ ChunkedIO

Returns a new instance of ChunkedIO.



10
11
12
13
14
15
16
17
18
19
20
21
# File 'lib/down/chunked_io.rb', line 10

def initialize(chunks:, size: nil, on_close: nil, data: {}, rewindable: true, encoding: nil)
  @chunks     = chunks
  @size       = size
  @on_close   = on_close
  @data       = data
  @encoding   = find_encoding(encoding || Encoding::BINARY)
  @rewindable = rewindable
  @buffer     = nil
  @bytes_read = 0

  retrieve_chunk
end

Instance Attribute Details

#dataObject

Returns the value of attribute data.



8
9
10
# File 'lib/down/chunked_io.rb', line 8

def data
  @data
end

#encodingObject

Returns the value of attribute encoding.



8
9
10
# File 'lib/down/chunked_io.rb', line 8

def encoding
  @encoding
end

#sizeObject

Returns the value of attribute size.



8
9
10
# File 'lib/down/chunked_io.rb', line 8

def size
  @size
end

Instance Method Details

#closeObject



150
151
152
153
154
155
156
157
# File 'lib/down/chunked_io.rb', line 150

def close
  return if @closed

  chunks_fiber.resume(:terminate) if chunks_fiber.alive?
  @buffer = nil
  cache.close! if cache
  @closed = true
end

#closed?Boolean

Returns:

  • (Boolean)


159
160
161
# File 'lib/down/chunked_io.rb', line 159

def closed?
  !!@closed
end

#each_chunkObject

Raises:

  • (IOError)


23
24
25
26
27
28
# File 'lib/down/chunked_io.rb', line 23

def each_chunk
  raise IOError, "closed stream" if closed?

  return enum_for(__method__) if !block_given?
  yield retrieve_chunk until chunks_depleted?
end

#eof?Boolean

Returns:

  • (Boolean)

Raises:

  • (IOError)


135
136
137
138
139
140
# File 'lib/down/chunked_io.rb', line 135

def eof?
  raise IOError, "closed stream" if closed?

  return false if cache && !cache.eof?
  @buffer.nil? && chunks_depleted?
end

#gets(separator_or_limit = $/, limit = nil) ⇒ Object

Raises:

  • (IOError)


50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/down/chunked_io.rb', line 50

def gets(separator_or_limit = $/, limit = nil)
  raise IOError, "closed stream" if closed?

  if separator_or_limit.is_a?(Integer)
    separator = $/
    limit     = separator_or_limit
  else
    separator = separator_or_limit
  end

  return read if separator.nil?

  separator = "\n\n" if separator.empty?

  begin
    data = readpartial(limit)

    until data.include?(separator) || data.bytesize == limit || eof?
      remaining_length = limit - data.bytesize if limit
      data << readpartial(remaining_length, outbuf ||= String.new)
    end

    line, extra = data.split(separator, 2)
    line << separator if data.include?(separator)

    if cache
      cache.pos -= extra.to_s.bytesize
    else
      @buffer = @buffer.to_s.prepend(extra.to_s)
    end
  rescue EOFError
    line = nil
  end

  line
end

#inspectObject



167
168
169
170
171
172
173
174
175
176
177
178
# File 'lib/down/chunked_io.rb', line 167

def inspect
  string  = String.new
  string << "#<Down::ChunkedIO"
  string << " chunks=#{@chunks.inspect}"
  string << " size=#{size.inspect}"
  string << " encoding=#{encoding.inspect}"
  string << " data=#{data.inspect}"
  string << " on_close=#{@on_close.inspect}"
  string << " rewindable=#{@rewindable.inspect}"
  string << " (closed)" if closed?
  string << ">"
end

#posObject



131
132
133
# File 'lib/down/chunked_io.rb', line 131

def pos
  @bytes_read
end

#read(length = nil, outbuf = nil) ⇒ Object

Raises:

  • (IOError)


30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/down/chunked_io.rb', line 30

def read(length = nil, outbuf = nil)
  raise IOError, "closed stream" if closed?

  remaining_length = length

  begin
    data = readpartial(remaining_length, outbuf)
    data = data.dup unless outbuf
    remaining_length = length - data.bytesize if length
  rescue EOFError
  end

  until remaining_length == 0 || eof?
    data << readpartial(remaining_length)
    remaining_length = length - data.bytesize if length
  end

  data.to_s unless length && (data.nil? || data.empty?)
end

#readpartial(length = nil, outbuf = nil) ⇒ Object

Raises:

  • (IOError)


87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/down/chunked_io.rb', line 87

def readpartial(length = nil, outbuf = nil)
  raise IOError, "closed stream" if closed?

  data = outbuf.replace("").force_encoding(@encoding) if outbuf

  if cache && !cache.eof?
    data = cache.read(length, outbuf)
    data.force_encoding(@encoding)
  end

  if @buffer.nil? && (data.nil? || data.empty?)
    raise EOFError, "end of file reached" if chunks_depleted?
    @buffer = retrieve_chunk
  end

  remaining_length = data && length ? length - data.bytesize : length

  unless @buffer.nil? || remaining_length == 0
    buffered_data = if remaining_length && remaining_length < @buffer.bytesize
                      @buffer.byteslice(0, remaining_length)
                    else
                      @buffer
                    end

    if data
      data << buffered_data
    else
      data = buffered_data
    end

    cache.write(buffered_data) if cache

    if buffered_data.bytesize < @buffer.bytesize
      @buffer = @buffer.byteslice(buffered_data.bytesize..-1)
    else
      @buffer = nil
    end
  end

  @bytes_read += data.bytesize

  data
end

#rewindObject

Raises:

  • (IOError)


142
143
144
145
146
147
148
# File 'lib/down/chunked_io.rb', line 142

def rewind
  raise IOError, "closed stream" if closed?
  raise IOError, "this Down::ChunkedIO is not rewindable" if cache.nil?

  cache.rewind
  @bytes_read = 0
end

#rewindable?Boolean

Returns:

  • (Boolean)


163
164
165
# File 'lib/down/chunked_io.rb', line 163

def rewindable?
  @rewindable
end