Skip to content

Clarify no-op usage #15

@nebkat

Description

@nebkat

The no-op value type is somewhat ambiguous.


My current interpretation is:

A. In an array - the element is skipped

[[]
    [#][i][2]
    [i][1]
    [N]
    [N]
    [i][2]
[1, 2]

Note that the container count doesn't include the no-op elements.

B. In an object - the key is discarded

[{]
    [#][i][2]
    [i][3][foo][i][1]
    [N]
    [i][3][bar][i][2]
{"foo": 1, "bar": 2}

Should the following also be allowed? The merits of it are somewhat questionable, as there is no point in including the key if the value is going to cause it to be removed.

[{]
    [#][i][2]
    [i][3][foo][i][1]
    [i][3][bar][N]
{"foo": 1}

C. Top level N - Error or symbol/sentinel value

In languages where it is available: Symbol('noop') (JavaScript, Dart).

Otherwise throw a dedicated error: 'N' can only occur in arrays/objects (distinct from an unexpected byte error!), and ignore if processing a stream.

Importantly, do not skip N before/after a value is found: bjdata.decode("NTN") != bjdata.decode("T").

D. In an un-delimited sequence of BJData objects / an implicit stream of values - the entry is ignored:

Sequence of BJData values in a file or streamed over network - implicitly wrapped in [ and ] so effectively the same as A.

[T]
[i][4]
[N]
[F]
true
4
false

Another way to interpret it is at the tokenizer level, where it could appear anywhere a token is expected i.e. only excluding strongly-typed contexts where it is impossible to differentiate between the value 0x4E and N:

Surrounding a value:

[N][S][i][3][foo][N][EOF]
"foo" // Not a stream, but doesn't complain because [N] are ignored

When waiting for a length:

[S][N][i][3][foo]
"foo"

When waiting for a count:

[[]
    [$][U]
    [N]
    [#][N][i][1]
    [5]
[5]

Within an array:

[[]
    [#][i][2]
    [i][1]
    [N]
    [N]
    [i][2]
[1, 2]

nlohmann/json exhibits some of these behaviors.


Don't think the latter interpretation is ever what was intended, but we would certainly benefit from being more explicit.

To summarize:

  1. Can N appear in arrays? ✅ This is the main purpose
  2. Can N appear in objects before keys? ✅ Also potentially useful
  3. Can N appear in objects after keys? ❌ Seems redundant
  4. Can N appear at top-level? ❌ It is not meaningful in that context. Throw error/special value, and handle in streams.
  5. Can N appear in special contexts (between [/$/#, S/i, etc)? ❌ Seems redundant
  6. Does N contribute towards container count? ❌ We might know we have to produce 10 values, but have to send keep-alives in between them because processing is slow. Could also ban N in counted containers.
  7. Are leading/trailing N ignored when looking for a value? ❌

If we can agree on the expected behavior I can make a PR with the appropriate spec changes.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions