Apple questions

Socket Message Reader

ApplePhone screenMedium

A connection delivers bytes in pieces of any size. recv() returns the next piece as a list of integers from 0 to 255, and returns an empty list once the sender has closed the connection. It is provided. Pieces do not line up with messages: a piece can end in the middle of a message or contain several.

Each test builds a reader from a list of pieces and an optional max_size, then calls the methods in order. An operation that raises is recorded as the exception name, and no call is made after one that raised.

Part 1: Length-prefixed and newline-delimited reads

Implement read_message() and read_line() on top of recv(). Both keep bytes received but not yet returned in one shared buffer, so calls to the two methods may be mixed.

read_message() reads a length-prefixed message: a 4-byte big-endian unsigned length N, then N payload bytes. It returns the payload as a list of integers.

read_line() reads one newline-delimited line: a line ends at byte 10, which may be preceded by byte 13. It returns the line without its ending; a 13 directly before the 10 is removed too.

Both methods return None when the sender has closed and nothing is pending. If the sender closes in the middle of a header, a payload, or a line, the method raises EOFError.

The constructor takes max_size. read_message() raises ValueError as soon as the header announces more than max_size payload bytes. read_line() raises ValueError as soon as the bytes received show the line will be longer than max_size, not counting its ending.

  1. Example 1
    init
    [[[0,0,0,3,7],[8,9,0,0,0,1,5]]]
    operations
    [["read_message",[]],["read_message",[]],["read_message",[]]]
    Output
    [[7,8,9],[5],null]

    Why: The first piece holds the header (length 3) and one payload byte; the second piece supplies the other two bytes and the start of the next message, whose length is 1. The reader keeps the leftover bytes between calls. After the second message the sender has closed with nothing pending, so the third call returns None.

  2. Example 2
    init
    [[[104,105,13],[10,111,10]]]
    operations
    [["read_line",[]],["read_line",[]],["read_line",[]]]
    Output
    [[104,105],[111],null]

    Why: The first line is the bytes hi; its CR arrives at the end of one piece and the LF at the start of the next, and both are dropped. The second line is o. Then the sender has closed with nothing pending, so None.

Constraints

  • 1 <= len(chunks) <= 10^6 total bytes across all pieces
  • 0 <= max_size <= 10^6
  • Every piece chunk[i] is non-empty
  • Each chunk[i] holds integers with 0 <= chunk[i][j] <= 255
  • No read_message or read_line call is made after a call that raised
Import your own questions
Paste a question you were asked and get a full problem: statement, tests and a checked solution.
Import a question