hadashiA/VYaml

Utf8YamlEmitter.BeginScalar | Scalar tags are not written when the CurrentState is BlockMappingValue

Closed this issue · 5 comments

The Issue

When emitting a simple YAML struct, I noticed my tags were written (prefixed) before the wrong values. When writing any value scalar the tag is not written, but the tag is written the next time a Sequence is written.

Looking into it further, I found out that the CurrentState when writing the scalar values was EmitState.BlockMappingValue, which skips writing the tag. See Utf8YamlEmitter.BeginScalar >

Is there a reason EmitState.BlockMappingValue does not write the current tag when EmitState.FlowMappingValue and EmitState.None do?

I am new to the codebase so I might be doing something wrong, but it seems odd.

Proposed Solution

Include EmitState.BlockMappingValue in the case with EmitState.FlowMappingValue and EmitState.None so the tag is written.

If this should not be done, I would appreciate some pointers on how this should be correctly handled.

Note

If it's easier, I'd be happy to make a PR.

I found another instance of this issue in the EmitState.FlowSequenceEntry case.

Tags are not written before scalar values in flow sequences.

Proposed Solution

ArchLeaders@57585f3

Tag emitter support is very limited and, as you point out, incomplete.

First, I only supported tagging to BlockMapping to support Union.
All cases should be supported, but it was put on the back burner.

If possible, could you please share some sample code that shows unintended behaviour?
This would make it easier to work with.

Here's a sample with each of the issues above.

There is also one additional issue where block sequence elements are written out of the sequence if a tag is set before the element.

Utf8YamlEmitter emitter = new(writer);

emitter.BeginMapping();
{
    emitter.WriteString("A1");
    emitter.Tag("!a1");
    emitter.WriteFloat(float.Pi); // !a1 is skipped and written later

    emitter.WriteString("NoTag1");
    emitter.BeginSequence(SequenceStyle.Flow); // !a1 is written here instead of after A1:
    {
        emitter.Tag("!a2"); // This tag is ignored unless the sequence style is Block
        emitter.WriteString("A2");
    }
    emitter.EndSequence();

    emitter.WriteString("NoTag2");
    emitter.BeginSequence(SequenceStyle.Block); // !a2 is not written here like it was for !a1 (because of the SequenceStyle)
    {
        emitter.Tag("!a3"); // This tag is written, but it breaks the sequence
        emitter.WriteString("A3"); // This is written outside of the sequence
    }
    emitter.EndSequence();
}
emitter.EndMapping();

Here is the real output:

A1: 3.1415927
NoTag1: !a1 [A2]
NoTag2: 
- !a3
A3

This is the desired output:

A1: !a1 3.1415927
NoTag1: [!a2 A2]
NoTag2: 
- !a3 A3

Please let me know if you need anything else.

Thanks for your amazing work on this library.

Thanks! I'm working on #98.

Merged #98 . Thanks a lot.