Class: Kobako::Sandbox::OutputBuffer

Inherits:
Object
  • Object
show all
Defined in:
lib/kobako/sandbox/output_buffer.rb

Overview

In-memory bounded byte buffer for one of the guest’s output channels. Tracks accumulated bytes (binary-encoded) and enforces the per-channel cap by truncating-with-marker (SPEC.md B-04).

When the accumulated byte count would exceed the limit, the buffer keeps as many leading bytes as fit and seals itself. Subsequent appends are discarded. On the next read, OUTPUT_TRUNCATION_MARKER is appended to signal the overflow to the caller.

Constant Summary collapse

OUTPUT_TRUNCATION_MARKER =

Marker appended to a buffer that hit its capture limit (SPEC.md B-04).

"[truncated]"

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(limit) ⇒ OutputBuffer

Returns a new instance of OutputBuffer.

Raises:

  • (ArgumentError)


20
21
22
23
24
25
26
# File 'lib/kobako/sandbox/output_buffer.rb', line 20

def initialize(limit)
  raise ArgumentError, "limit must be a positive Integer" unless limit.is_a?(Integer) && limit.positive?

  @limit = limit
  @bytes = String.new(encoding: Encoding::ASCII_8BIT)
  @truncated = false
end

Instance Attribute Details

#limitObject (readonly)

Returns the value of attribute limit.



18
19
20
# File 'lib/kobako/sandbox/output_buffer.rb', line 18

def limit
  @limit
end

Instance Method Details

#<<(bytes) ⇒ Object

Append bytes to the buffer. If the append would push the cumulative byte count past the limit, the buffer keeps as many leading bytes as fit and seals itself; subsequent appends are discarded. SPEC.md B-04 — truncation is a non-error outcome.



33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/kobako/sandbox/output_buffer.rb', line 33

def <<(bytes)
  return self if @truncated

  appended = bytes.to_s.b
  room = @limit - @bytes.bytesize
  if appended.bytesize <= room
    @bytes << appended
  else
    @bytes << appended.byteslice(0, room) if room.positive?
    @truncated = true
  end
  self
end

#bytesizeObject

Returns the number of bytes currently stored.



53
54
55
# File 'lib/kobako/sandbox/output_buffer.rb', line 53

def bytesize
  @bytes.bytesize
end

#clearObject

Reset the buffer to empty. Used at the per-#run boundary.



72
73
74
75
76
# File 'lib/kobako/sandbox/output_buffer.rb', line 72

def clear
  @bytes.clear
  @truncated = false
  self
end

#empty?Boolean

Returns true when the buffer is empty.

Returns:

  • (Boolean)


58
59
60
# File 'lib/kobako/sandbox/output_buffer.rb', line 58

def empty?
  @bytes.empty?
end

#to_sObject

Returns the accumulated bytes as a UTF-8 String, with the [truncated] marker appended when the buffer overflowed.



64
65
66
67
68
69
# File 'lib/kobako/sandbox/output_buffer.rb', line 64

def to_s
  copy = @bytes.dup
  copy << OUTPUT_TRUNCATION_MARKER.b if @truncated
  copy.force_encoding(Encoding::UTF_8)
  copy.valid_encoding? ? copy : copy.dup.force_encoding(Encoding::ASCII_8BIT)
end

#truncated?Boolean

Returns true when the buffer was sealed by an overflow.

Returns:

  • (Boolean)


48
49
50
# File 'lib/kobako/sandbox/output_buffer.rb', line 48

def truncated?
  @truncated
end