Skip to content

Commit

Permalink
Add support for (de)serializing CLR boolean values. (#83)
Browse files Browse the repository at this point in the history
This should match the Valve implementation precisely.

Fixes #81.
  • Loading branch information
yaakov-h authored Nov 6, 2023
1 parent b546c9c commit e756e31
Show file tree
Hide file tree
Showing 7 changed files with 106 additions and 2 deletions.
6 changes: 6 additions & 0 deletions ValveKeyValue/ValveKeyValue.Test/Test Data/Text/boolean.vdf
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
"object"
{
"test1_false" "0"
"test2_true" "1"
"test3_oob" "2"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
"object"
{
"test1_false" "0"
"test2_true" "1"
}
1 change: 1 addition & 0 deletions ValveKeyValue/ValveKeyValue.Test/Test Data/apisurface.txt
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ public class ValveKeyValue.KVValue
public static IntPtr op_Explicit(ValveKeyValue.KVValue value);
public static ValveKeyValue.KVValue op_Implicit(string value);
public static ValveKeyValue.KVValue op_Implicit(int value);
public static ValveKeyValue.KVValue op_Implicit(bool value);
public static ValveKeyValue.KVValue op_Implicit(IntPtr value);
public static ValveKeyValue.KVValue op_Implicit(ulong value);
public static ValveKeyValue.KVValue op_Implicit(float value);
Expand Down
83 changes: 83 additions & 0 deletions ValveKeyValue/ValveKeyValue.Test/Text/BooleanTestCase.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using NUnit.Framework;

namespace ValveKeyValue.Test
{
class BooleanTestCase
{
[Test]
public void DynamicDeserialization()
{
using var stream = TestDataHelper.OpenResource("Text.boolean.vdf");
var data = KVSerializer.Create(KVSerializationFormat.KeyValues1Text).Deserialize(stream);

Assert.Multiple(() =>
{
Assert.That((bool)data["test1_false"], Is.False, "test1_false");
Assert.That((bool)data["test2_true"], Is.True, "test2_true");
Assert.That((bool)data["test3_oob"], Is.True, "test3_oob");
});
}

[Test]
public void StronglyTypedDeserialization()
{
using var stream = TestDataHelper.OpenResource("Text.boolean.vdf");
var data = KVSerializer.Create(KVSerializationFormat.KeyValues1Text).Deserialize<SerializedType>(stream);

Assert.Multiple(() =>
{
Assert.That(data.test1_false, Is.False, nameof(data.test1_false));
Assert.That(data.test2_true, Is.True, nameof(data.test2_true));
Assert.That(data.test3_oob, Is.True, nameof(data.test3_oob));
});
}

[Test]
public void DynamicSerialization()
{
var data = new KVObject("object", new[]
{
new KVObject("test1_false", false),
new KVObject("test2_true", true),
});

var expected = TestDataHelper.ReadTextResource("Text.boolean_serialization.vdf");

using var ms = new MemoryStream();
KVSerializer.Create(KVSerializationFormat.KeyValues1Text).Serialize(ms, data);
var text = Encoding.UTF8.GetString(ms.ToArray());

Assert.That(text, Is.EqualTo(expected));
}

[Test]
public void StronglyTypedSerialization()
{
var data = new
{
test1_false = false,
test2_true = true,
};

var expected = TestDataHelper.ReadTextResource("Text.boolean_serialization.vdf");

using var ms = new MemoryStream();
KVSerializer.Create(KVSerializationFormat.KeyValues1Text).Serialize(ms, data, "object");
var text = Encoding.UTF8.GetString(ms.ToArray());

Assert.That(text, Is.EqualTo(expected));
}

class SerializedType
{
public bool test1_false { get; set; }
public bool test2_true { get; set; }
public bool test3_oob { get; set; }
}
}
}
2 changes: 1 addition & 1 deletion ValveKeyValue/ValveKeyValue/KVObjectValue.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public override TypeCode GetTypeCode()
};
}

public override bool ToBoolean(IFormatProvider provider) => ToInt32(provider) == 1;
public override bool ToBoolean(IFormatProvider provider) => ToInt32(provider) != 0;

public override byte ToByte(IFormatProvider provider) => (byte)Convert.ChangeType(value, typeof(byte), provider);

Expand Down
9 changes: 9 additions & 0 deletions ValveKeyValue/ValveKeyValue/KVValue_operators.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,15 @@ public static implicit operator KVValue(int value)
return new KVObjectValue<int>(value, KVValueType.Int32);
}

/// <summary>
/// Implicit cast operator for <see cref="bool"/> to KVValue.
/// </summary>
/// <param name="value">The <see cref="bool"/> to cast.</param>
public static implicit operator KVValue(bool value)
{
return new KVObjectValue<int>(value ? 1 : 0, KVValueType.Int32);
}

/// <summary>
/// Implicit cast operator for <see cref="IntPtr"/> to KVValue.
/// </summary>
Expand Down
2 changes: 1 addition & 1 deletion ValveKeyValue/ValveKeyValue/ObjectCopier.cs
Original file line number Diff line number Diff line change
Expand Up @@ -437,7 +437,7 @@ static KVValue ConvertToKVValue(object value, Type type)

return Type.GetTypeCode(type) switch
{
//TypeCode.Boolean => throw new NotImplementedException("Converting to boolean is not yet supported"),
TypeCode.Boolean => (KVValue)(bool)value,
//TypeCode.Byte => throw new NotImplementedException("Converting to byte is not yet supported"),
//TypeCode.Char => throw new NotImplementedException("Converting to char is not yet supported"),
//TypeCode.DateTime => throw new NotImplementedException(), // Datetime are not supported
Expand Down

0 comments on commit e756e31

Please sign in to comment.