Skip to content

The extra fast, low memory footprint YAML library for C#, focued on .NET.

License

Notifications You must be signed in to change notification settings

EPD-Libraries/LiteYaml

 
 

Repository files navigation

LiteYaml

License NuGet

Lightweight yaml parser and emitter stripped from VYaml

Parser

YamlParser struct provides access to the complete meta-information of yaml.

  • YamlParser.Read() reads through to the next syntax on yaml. (If end of stream then return false.)
  • YamlParser.ParseEventType indicates the state of the currently read yaml parsing result.
  • How to access scalar value:
    • YamlParser.GetScalarAs* families take the result of converting a scalar at the current position to a specified type.
    • YamlParser.TryGetScalarAs* families return true and take a result if the current position is a scalar and of the specified type.
    • YamlParser.ReadScalarAs* families is similar to GetScalarAs*, but advances the present position to after the scalar read.
  • How to access meta information:
    • YamlParser.TryGetTag(out Tag tag)
    • YamlParser.TryGetCurrentAnchor(out Anchor anchor)

Basic example:

var parser = YamlParser.FromBytes(utf8Bytes);

// YAML contains more than one `Document`. 
// Here we skip to before first document content.
parser.SkipAfter(ParseEventType.DocumentStart);

// Scanning...
while (parser.Read())
{
    // If the current syntax is Scalar, 
    if (parser.CurrentEventType == ParseEventType.Scalar)
    {
        var intValue = parser.GetScalarAsInt32();
        var stringValue = parser.GetScalarAsString();
        // ...
        
        if (parser.TryGetCurrentTag(out var tag))
        {
            // Check for the tag...
        }
        
        if (parser.TryGetCurrentAnchor(out var anchor))
        {
            // Check for the anchor...
        }        
    }
    
    // If the current syntax is Sequence (Like a list in yaml)
    else if (parser.CurrentEventType == ParseEventType.SequenceStart)
    {
        // We can check for the tag...
        // We can check for the anchor...
        
        parser.Read(); // Skip SequenceStart

        // Read to end of sequence
        while (!parser.End && parser.CurrentEventType != ParseEventType.SequenceEnd)
        {
             // A sequence element may be a scalar or other...
             if (parser.CurrentEventType = ParseEventType.Scalar)
             {
                 // ...
             }
             // ...
             // ...
             else
             {
                 // We can skip current element. (It could be a scalar, or alias, sequence, mapping...)
                 parser.SkipCurrentNode();
             }
        }
        parser.Read(); // Skip SequenceEnd.
    }
    
    // If the current syntax is Mapping (like a Dictionary in yaml)
    else if (parser.CurrentEventType == ParseEventType.MappingStart)
    {
        // We can check for the tag...
        // We can check for the anchor...
        
        parser.Read(); // Skip MappingStart

        // Read to end of mapping
        while (parser.CurrentEventType != ParseEventType.MappingEnd)
        {
             // After Mapping start, key and value appear alternately.
             
             var key = parser.ReadScalarAsString();  // if key is scalar
             var value = parser.ReadScalarAsString(); // if value is scalar
             
             // Or we can skip current key/value. (It could be a scalar, or alias, sequence, mapping...)
             // parser.SkipCurrentNode(); // skip key
             // parser.SkipCurrentNode(); // skip value
        }
        parser.Read(); // Skip MappingEnd.
    }
    
    // Alias
    else if (parser.CurrentEventType == ParseEventType.Alias)
    {
        // If Alias is used, the previous anchors must be holded somewhere.
        // In the High level Deserialize API, `YamlDeserializationContext` does exactly this. 
    }
}

See test code for more information. The above test covers various patterns for the order of ParsingEvent.

Emitter

Utf8YamlEmitter struct provides to write YAML formatted string.

Basic usage:

var buffer = new ArrayBufferWriter();
var emitter = new Utf8YamlEmitter(buffer); // It needs buffer implemented `IBufferWriter<byte>`

emitter.BeginMapping(); // Mapping is a collection like Dictionary in YAML
{
    emitter.WriteString("key1");
    emitter.WriteString("value-1");
    
    emitter.WriteString("key2");
    emitter.WriteInt32(222);
    
    emitter.WriteString("key3");
    emitter.WriteFloat(3.333f);
}
emitter.EndMapping();
// If you want to expand a string in memory, you can do this.
System.Text.Encoding.UTF8.GetString(buffer.WrittenSpan); 
key1: value-1
key2: 222
key3: 3.333

Emit string in various formats

By default, WriteString() automatically determines the format of a scalar.

Multi-line strings are automatically format as a literal scalar:

emitter.WriteString("Hello,\nWorld!\n");
|
  Hello,
  World!

Special characters contained strings are automatically quoted.

emitter.WriteString("&aaaaa ");
"&aaaaa "

Or you can specify the style explicitly:

emitter.WriteString("aaaaaaa", ScalarStyle.Literal);
|-
  aaaaaaaa

Emit sequences and other structures

e.g:

emitter.BeginSequence();
{
    emitter.BeginSequence(SequenceStyle.Flow);
    {
        emitter.WriteInt32(100);
        emitter.WriteString("&hoge");
        emitter.WriteString("bra");
    }
    emitter.EndSequence();
    
    emitter.BeginMapping();
    {
        emitter.WriteString("key1");
        emitter.WriteString("item1");
        
        emitter.WriteString("key2");
        emitter.BeginSequence();
        {
            emitter.WriteString("nested-item1")
            emitter.WriteString("nested-item2")
            emitter.BeginMapping();
            {
                emitter.WriteString("nested-key1")
                emitter.WriteInt32(100)
            }
            emitter.EndMapping();
        }
        emitter.EndSequence();
    }
    emitter.EndMapping();
}
emitter.EndMapping();
- [100, "&hoge", bra]
- key1: item1
  key2:
  - nested-item1
  - nested-item2
  - nested-key1: 100

YAML 1.2 spec support status

Implicit primitive type conversion of scalar

The following is the default implicit type interpretation.

Basically, it follows YAML Core Schema. https://yaml.org/spec/1.2.2/#103-core-schema

Support Regular expression Resolved to type
null | Null | NULL | ~ null
/* Empty */ null
true | True | TRUE | false | False | FALSE boolean
[-+]? [0-9]+ int (Base 10)
0o [0-7]+ int (Base 8)
0x [0-9a-fA-F]+ int (Base 16)
[-+]? ( \. [0-9]+ | [0-9]+ ( \. [0-9]* )? ) ( [eE] [-+]? [0-9]+ )? float
[-+]? ( \.inf | \.Inf | \.INF ) float (Infinity)
\.nan | \.NaN | \.NAN float (Not a number)

Following is the results of the test for the examples from the yaml spec page.

  • 2.1. Collections
    • ✅ Example 2.1 Sequence of Scalars (ball players)
    • ✅ Example 2.2 Mapping Scalars to Scalars (player statistics)
    • ✅ Example 2.3 Mapping Scalars to Sequences (ball clubs in each league)
    • ✅ Example 2.4 Sequence of Mappings (players statistics)
    • ✅ Example 2.5 Sequence of Sequences
    • ✅ Example 2.6 Mapping of Mappings
  • 2.2. Structures
    • ✅ Example 2.7 Two Documents in a Stream (each with a leading comment)
    • ✅ Example 2.8 Play by Play Feed from a Game
    • ✅ Example 2.9 Single Document with Two Comments
    • ✅ Example 2.10 Node for Sammy Sosa appears twice in this document
    • ✅ Example 2.11 Mapping between Sequences
    • ✅ Example 2.12 Compact Nested Mapping
  • 2.3. Scalars
    • ✅ Example 2.13 In literals, newlines are preserved
    • ✅ Example 2.14 In the folded scalars, newlines become spaces
    • ✅ Example 2.15 Folded newlines are preserved for more indented and blank lines
    • ✅ Example 2.16 Indentation determines scope
    • ✅ Example 2.17 Quoted Scalars
    • ✅ Example 2.18 Multi-line Flow Scalars
  • 2.4. Tags
    • ✅ Example 2.19 Integers
    • ✅ Example 2.20 Floating Point
    • ✅ Example 2.21 Miscellaneous
    • ✅ Example 2.22 Timestamps
    • ✅ Example 2.23 Various Explicit Tags
    • ✅ Example 2.24 Global Tags
    • ✅ Example 2.25 Unordered Sets
    • ✅ Example 2.26 Ordered Mappings
  • 2.5. Full Length Example
    • ✅ Example 2.27 Invoice
    • ✅ Example 2.28 Log File
  • 5.2. Character Encodings
    • ✅ Example 5.1 Byte Order Mark
    • ✅ Example 5.2 Invalid Byte Order Mark
  • 5.3. Indicator Characters
    • ✅ Example 5.3 Block Structure Indicators
    • ✅ Example 5.4 Flow Collection Indicators
    • ✅ Example 5.5 Comment Indicator
    • ✅ Example 5.6 Node Property Indicators
    • ✅ Example 5.7 Block Scalar Indicators
    • ✅ Example 5.8 Quoted Scalar Indicators
    • ✅ Example 5.9 Directive Indicator
    • ✅ Example 5.10 Invalid use of Reserved Indicators
  • 5.4. Line Break Characters
    • ✅ Example 5.11 Line Break Characters
    • ✅ Example 5.12 Tabs and Spaces
    • ✅ Example 5.13 Escaped Characters
    • ✅ Example 5.14 Invalid Escaped Characters
  • 6.1. Indentation Spaces
    • ✅ Example 6.1 Indentation Spaces
    • ✅ Example 6.2 Indentation Indicators
  • 6.2. Separation Spaces
    • ✅ Example 6.3 Separation Spaces
  • 6.3. Line Prefixes
    • ✅ Example 6.4 Line Prefixes
  • 6.4. Empty Lines
    • ✅ Example 6.5 Empty Lines
  • 6.5. Line Folding
    • ✅ Example 6.6 Line Folding
    • ✅ Example 6.7 Block Folding
    • ✅ Example 6.8 Flow Folding
  • 6.6. Comments
    • ✅ Example 6.9 Separated Comment
    • ✅ Example 6.10 Comment Lines
    • ✅ Example 6.11 Multi-Line Comments
  • 6.7. Separation Lines
    • ✅ Example 6.12 Separation Spaces
  • 6.8. Directives
    • ✅ Example 6.13 Reserved Directives
    • ✅ Example 6.14 YAML directive
    • ✅ Example 6.15 Invalid Repeated YAML directive
    • ✅ Example 6.16 TAG directive
    • ✅ Example 6.17 Invalid Repeated TAG directive
    • ✅ Example 6.18 Primary Tag Handle
    • ✅ Example 6.19 Secondary Tag Handle
    • ✅ Example 6.20 Tag Handles
    • ✅ Example 6.21 Local Tag Prefix
    • ✅ Example 6.22 Global Tag Prefix
  • 6.9. Node Properties
    • ✅ Example 6.23 Node Properties
    • ✅ Example 6.24 Verbatim Tags
    • ✅ Example 6.25 Invalid Verbatim Tags
    • ✅ Example 6.26 Tag Shorthands
    • ✅ Example 6.27 Invalid Tag Shorthands
    • ✅ Example 6.28 Non-Specific Tags
    • ✅ Example 6.29 Node Anchors
  • 7.1. Alias Nodes
    • ✅ Example 7.1 Alias Nodes
  • 7.2. Empty Nodes
    • ✅ Example 7.2 Empty Content
    • ✅ Example 7.3 Completely Empty Flow Nodes
  • 7.3. Flow Scalar Styles
    • ✅ Example 7.4 Double Quoted Implicit Keys
    • ✅ Example 7.5 Double Quoted Line Breaks
    • ✅ Example 7.6 Double Quoted Lines
    • ✅ Example 7.7 Single Quoted Characters
    • ✅ Example 7.8 Single Quoted Implicit Keys
    • ✅ Example 7.9 Single Quoted Lines
    • ✅ Example 7.10 Plain Characters
    • ✅ Example 7.11 Plain Implicit Keys
    • ✅ Example 7.12 Plain Lines
  • 7.4. Flow Collection Styles
    • ✅ Example 7.13 Flow Sequence
    • ✅ Example 7.14 Flow Sequence Entries
    • ✅ Example 7.15 Flow Mappings
    • ✅ Example 7.16 Flow Mapping Entries
    • ✅ Example 7.17 Flow Mapping Separate Values
    • ✅ Example 7.18 Flow Mapping Adjacent Values
    • ✅ Example 7.20 Single Pair Explicit Entry
    • ❌ Example 7.21 Single Pair Implicit Entries
    • ✅ Example 7.22 Invalid Implicit Keys
    • ✅ Example 7.23 Flow Content
    • ✅ Example 7.24 Flow Nodes
  • 8.1. Block Scalar Styles
    • ✅ Example 8.1 Block Scalar Header
    • ❌ Example 8.2 Block Indentation Indicator
    • ✅ Example 8.3 Invalid Block Scalar Indentation Indicators
    • ✅ Example 8.4 Chomping Final Line Break
    • ✅ Example 8.5 Chomping Trailing Lines
    • ✅ Example 8.6 Empty Scalar Chomping
    • ✅ Example 8.7 Literal Scalar
    • ✅ Example 8.8 Literal Content
    • ✅ Example 8.9 Folded Scalar
    • ✅ Example 8.10 Folded Lines
    • ✅ Example 8.11 More Indented Lines
    • ✅ Example 8.12 Empty Separation Lines
    • ✅ Example 8.13 Final Empty Lines
    • ✅ Example 8.14 Block Sequence
    • ✅ Example 8.15 Block Sequence Entry Types
    • ✅ Example 8.16 Block Mappings
    • ✅ Example 8.17 Explicit Block Mapping Entries
    • ✅ Example 8.18 Implicit Block Mapping Entries
    • ✅ Example 8.19 Compact Block Mappings
    • ✅ Example 8.20 Block Node Types
    • ✅ Example 8.21 Block Scalar Nodes
    • ✅ Example 8.22 Block Collection Nodes

Credits

LiteYaml is a stripped back version of VYaml with minor updates.

Author

@hadashiA

License

MIT

About

The extra fast, low memory footprint YAML library for C#, focued on .NET.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • C# 100.0%