Make Stdout provide data in chunks

This commit is contained in:
Marcin Kulik 2013-08-13 19:27:02 +02:00
parent fa4c5e4664
commit 6c8dbf4173
6 changed files with 40 additions and 59 deletions

View File

@ -56,17 +56,7 @@ class Asciicast < ActiveRecord::Base
end
def stdout
@stdout ||= Stdout.new(read_stdout_data, read_stdout_timing)
end
private
def read_stdout_data
stdout_data.decompressed
end
def read_stdout_timing
TimingParser.parse(stdout_timing.decompressed)
@stdout ||= Stdout.new(stdout_data, stdout_timing)
end
end

View File

@ -1,40 +1,30 @@
class Stdout
include Enumerable
attr_reader :data, :timing
attr_reader :data_file, :timing_file
def initialize(data, timing)
@data = data
@timing = timing
def initialize(data_file, timing_file)
@data_file = data_file
@timing_file = timing_file
end
def each
offset = 0
timing.each do |line|
delay, size = line
yield(delay, bytes[offset...offset+size])
offset += size
File.open(data_file.decompressed_path, 'rb') do |file|
File.foreach(timing_file.decompressed_path) do |line|
delay, size = TimingParser.parse_line(line)
yield(delay, file.read(size).force_encoding('utf-8'))
end
end
end
def bytes_until(seconds)
bytes = []
def each_until(seconds)
time = 0
each do |delay, frame_bytes|
each do |delay, frame_data|
time += delay
break if time > seconds
bytes.concat(frame_bytes)
yield(delay, frame_data)
end
bytes
end
private
def bytes
@bytes ||= data.bytes
end
end

1
spec/fixtures/stdout.decompressed vendored Normal file
View File

@ -0,0 +1 @@
foobarbazquxżółć

View File

@ -0,0 +1,3 @@
0.5 6
1.0 7
2.0 7

View File

@ -84,17 +84,21 @@ describe Asciicast do
end
describe '#stdout' do
let(:asciicast) { stub_model(Asciicast) }
let(:data_file) { double('data_file') }
let(:timing_file) { double('timing_file') }
let(:stdout) { double('stdout') }
before do
allow(asciicast.stdout_data).to receive(:decompressed) { 'foo' }
allow(asciicast.stdout_timing).to receive(:decompressed) { '123.0 45' }
allow(asciicast).to receive(:stdout_data) { data_file }
allow(asciicast).to receive(:stdout_timing) { timing_file }
allow(Stdout).to receive(:new) { stdout }
end
it 'creates a new Stdout instance' do
asciicast.stdout
expect(Stdout).to have_received(:new).with('foo', [[123.0, 45]])
expect(Stdout).to have_received(:new).with(data_file, timing_file)
end
it 'returns created Stdout instance' do

View File

@ -3,31 +3,24 @@
require 'spec_helper'
describe Stdout do
let(:stdout) { Stdout.new(data, timing) }
let(:data) { 'foobarbazquxżółć' }
let(:timing) { [[0.5, 6], [1.0, 7], [2.0, 7]] }
describe '#bytes_until' do
subject { stdout.bytes_until(1.7) }
it { should eq([102, 111, 111, 98, 97, 114, 98, 97, 122, 113, 117, 120, 197]) }
end
let(:stdout) { Stdout.new(data_file, timing_file) }
let(:data_file) { double('data_file', :decompressed_path => 'spec/fixtures/stdout.decompressed') }
let(:timing_file) { double('timing_file', :decompressed_path => 'spec/fixtures/stdout.time.decompressed') }
describe '#each' do
it 'yields for each frame with delay and frame bytes' do
frames = []
stdout.each do |delay, bytes|
frames << [delay, bytes]
end
expect(frames[0][0]).to eq(0.5)
expect(frames[0][1]).to eq([102, 111, 111, 98, 97, 114])
expect(frames[1][0]).to eq(1.0)
expect(frames[1][1]).to eq([98, 97, 122, 113, 117, 120, 197])
expect(frames[2][0]).to eq(2.0)
expect(frames[2][1]).to eq([188, 195, 179, 197, 130, 196, 135])
it 'yields for each frame with delay and data' do
expect { |b| stdout.each(&b) }.
to yield_successive_args([0.5, 'foobar'],
[1.0, "bazqux\xC5"],
[2.0, "\xBCółć"])
end
end
describe '#each_until' do
it 'yields for each frame with delay and data until given time (in seconds)' do
expect { |b| stdout.each_until(1.7, &b) }.
to yield_successive_args([0.5, 'foobar'], [1.0, "bazqux\xC5"])
end
end
end