Skip to content

Releases

v0.80.0

Choose a tag to compare

@github-actions github-actions released this 03 Nov 11:06
Immutable release. Only release title and notes can be modified.
  • Breaking: typed deserialization now runs the public parameterless constructor, so initializers apply to missing keys.
  • Breaking: typed KVSerializer methods are marked [RequiresUnreferencedCode]/[RequiresDynamicCode]; use KVObject or KVDocument when trimming or with AOT.
  • Faster hex blob parsing, indentation writing and number parsing.

v0.73.0

Choose a tag to compare

@github-actions github-actions released this 22 Oct 08:43
Immutable release. Only release title and notes can be modified.
  • Added packed typed arrays: KVObject.PackedArray(T[] values, KVFlag elementFlag) for bool, short, ushort, int, uint, long, ulong, float and double stores the values directly, without a KVObject per element
  • Added KVObject.IsPackedArray
  • Added KVObject.TryGetArraySpan<T>() to read a packed array's values without copying
  • Added KVObject.ToArray<T>() and KVObject.GetElement<T>(index) to convert array elements, matching the explicit cast operators
  • Added KVObject.Elements to get array elements as an IReadOnlyList<KVObject>
  • Reading a packed array through the indexer, foreach, Values, Children or Elements keeps it packed; AsArraySpan, Add and RemoveAt convert it to elements
  • Reduced allocations when reading and writing: no LINQ, no boxed enumerators, pooled reader and builder states, and number formatting without allocating strings

v0.72.0

Choose a tag to compare

@github-actions github-actions released this 17 Oct 09:38
Immutable release. Only release title and notes can be modified.
  • Breaking: KV3 text quoted values are always strings, so "42" and "true" no longer become numbers or bools
  • Breaking: KV3 text parsing is stricter and throws on: a missing = after a key, missing commas between array elements (a trailing comma is still allowed), unquoted values that are not booleans, null, numbers, nan or inf, unquoted keys that are not identifiers, unquoted non-ASCII tokens, blob bytes that are not separate hex pairs, and header names that are quoted or an encoding other than text
  • Breaking: KV3 multi-line strings only end at """ at the start of a line that does not follow a backslash
  • Breaking: KV1 text =, { and } end unquoted keys and values, so a=b reads as key a with value b
  • Breaking: KV1 text #include and #base are directives only outside the root object (before or after it); inside an object they are ordinary keys, and other # values are plain strings instead of throwing
  • Breaking: KV1 text throws on two consecutive conditionals, and when a pair has several conditionals the last one decides
  • Added KV1 text = assignments (key = value), with conditions allowed on either side of =
  • Added KV1 binary wide strings and binary blobs, which used to throw NotSupportedException
  • Added KVFlag.Localize for the KV3 localize: flag
  • KV1 binary accepts both end markers regardless of header
  • KV3 text parses true, false and null in any case, floats with a leading decimal point, and a lone + as zero
  • KV3 text allows whitespace and comments around flags, # blobs, blob bytes and header tokens, and // comments continue onto the next line after a trailing backslash
  • KV3 multi-line strings unescape \""" and normalize CRLF to LF
  • KV3 text writer matches Valve's formatting: apostrophes in quoted keys are not escaped, and a flagged root object's { goes on its own line
  • Source maps report KV1 text = as Assignment, and unquoted KV3 tokens as Identifier
  • Fixed KV3 text writer copying the input document's encoding into the header instead of text
  • Fixed KV3 text parser looping forever on a stray ;, : or |
  • Fixed KV3 text writer producing unreadable multi-line strings for values ending in a backslash or carriage return

v0.71.0

Choose a tag to compare

@github-actions github-actions released this 23 Sep 10:47
Immutable release. Only release title and notes can be modified.
  • Breaking: Throw on documents with multiple root objects (KV1 text, KV1 binary, KV3) instead of misparsing
  • Breaking: Malformed input now consistently throws KeyValueException instead of InvalidDataException/InvalidOperationException
  • Breaking: Parse KV1 hex numbers like Valve does (only lowercase 0x prefix)
  • Breaking: Condition variables are now case-insensitive
  • Breaking: Throw when deserializing into unsupported enumerable types
  • Breaking: Invalid enum values throw NotSupportedException
  • Added SerializeWithSourceMap<T>
  • Added public KVFlag.SerializeFlagName() extension
  • Added enum deserialization from names (including flags) in collections, dictionaries and lookups
  • Improved exception messages to include line and column
  • Suggest enabling escape sequences if parsing fails on \"
  • Rewrote KVConditionEvaluator to match Valve's implementation
  • Serialize char and decimal properties as scalars
  • Skip get-only properties when deserializing
  • Skip record EqualityContract and indexer properties
  • Fixed KVObject.ToString() and ToType() to default to invariant culture
  • Fixed circular reference detection to use reference equality
  • Fixed stray trailing bracket not throwing
  • Fixed KVObject and KVDocument values being reflected over when serializing typed objects

v0.70.0

Choose a tag to compare

@github-actions github-actions released this 09 Apr 19:04
Immutable release. Only release title and notes can be modified.
  • Do not sort object members by name (.NET 7 makes this declaration order)
  • Add (de)serialize mode that produces sourcemaps for syntax highlighting

v0.65.0

Choose a tag to compare

@github-actions github-actions released this 05 Apr 09:09
Immutable release. Only release title and notes can be modified.
  • Breaking: Make KVDocument standalone
    • Added Root property
    • Added string indexer and implicit cast to KVObject for backwards compatibility, but you should use Root.
  • Breaking: Remove AsSpan (returned blobs), add AsArraySpan for getting KV3 arrays
  • Make root name and header nullable

v0.60.0

Choose a tag to compare

@github-actions github-actions released this 03 Apr 17:46
Immutable release. Only release title and notes can be modified.
  • Breaking: Made string indexer throw on unknown key, removed GetChild
  • Breaking: Made casting null to string throw
  • Breaking: Made casting null byte[] throw
  • Breaking: Made (string null) constructor throw
  • Breaking: Made this[int] throw on dictionaries
  • Breaking: Made Remove/Clear on non-collections throw
  • Breaking: Made setting null create a null object instead of removing
  • Breaking: Enabled nullable annotations
  • Added SkipHeader option for KV3
  • Added support for (de)serializing into nullables
  • Added support for read-only collection and dictionary interface types
  • Added missing (u)short constructors
  • Added byte[] explicit operator
  • Added To* methods without formatter
  • Added TryAdd
  • Added IsCollection
  • Fixed Nullable deserialization/serialization
  • Fixed Add to throw on existing keys in dictionaries
  • Fixed Add methods to not store raw nulls
  • Fixed ToString() on null type return a "null" string

v0.51.0

Choose a tag to compare

@github-actions github-actions released this 31 Mar 13:51
Immutable release. Only release title and notes can be modified.
  • KVObject fields are now readonly (immutable after construction)
  • Scalar type conversions now use checked casts (throws OverflowException instead of silent truncation)
  • ToBoolean() explicitly supports integer/float/string types, throws for Collection/Array/Blob
  • KVObject implements IReadOnlyDictionary<string, KVObject> instead of IEnumerable<KeyValuePair<string, KVObject>>
  • Add Collection(capacity), ListCollection(capacity), Array(capacity) overloads
  • Fix UInt64 conversions for ToDecimal, ToDouble, ToSingle
  • Fix peeked value unboxing in KV3 token reader
  • Throw on unclosed comments and invalid hex in KV3
  • Optimize text/binary string writing
  • Reuse StringBuilder and use SearchValues for faster scanning

v0.50.0

Choose a tag to compare

@github-actions github-actions released this 30 Mar 18:53
Immutable release. Only release title and notes can be modified.

BREAKING CHANGES: This release is a second pass at improving the overall API. If you run into issues or unergonomic API, open a new issue.

  • Merged KVValue into KVObject, this is now a single type.
  • Name removed from KVObject, keys are stored in the parent container. Use KVDocument.Name for the root key name.
  • Iteration yields KeyValuePair<string,KVObject> instead of KVObject.
  • KVDocument is now the return type of Deserialize(), holding the root Name and Header.
  • Added Keys and Values properties on KVObject
  • Added KVObject.ListCollection(IEnumerable) factory for creating list-backed collections from existing data
  • Added Implicit operators for byte and sbyte

v0.40.0

Choose a tag to compare

@github-actions github-actions released this 29 Mar 19:51
Immutable release. Only release title and notes can be modified.

BREAKING CHANGES: This release changes how the API works to make it easier to iterate and modify values. If you run into issues or unergonomic API, open a new issue.

  • Replaced KVArrayValue, KVCollectionValue, KVBinaryBlob, KVNullValue classes with a single KVValue readonly record struct (scalars stored inline, no boxing)
  • KVObject string/int indexers now return KVObject instead of KVValue
  • KVObject string indexer setter now takes KVObject instead of KVValue (implicit conversions from primitives)
  • Added dictionary-backed collections for KV3 (KVObject.Collection()) with O(1) lookup
  • Added KVObject.ListCollection() for explicit list-backed collections (KV1 duplicate key support)
  • Added KVObject.Array() and KVObject.Blob() static factory methods
  • Added TryGetChild(string, out KVObject)
  • KVObject now implements IConvertible, Convert.ChangeType() works on indexer results
  • KVValue.Flag is now init-only (use with expression to modify)
  • Removed ChildrenValues property
  • Renamed AddProperty to Add(string, KVValue)
  • Typed deserialization now supports KV3 native arrays (List, T[], etc.)
  • Typed deserialization now supports byte[] properties from binary blobs
  • Typed deserialization now supports enum properties
  • SetChild on list-backed collections now replaces in-place instead of remove + append