Skip to content

Commit

Permalink
Better support for array serialization (#8)
Browse files Browse the repository at this point in the history
Ensure that any IList type like ArrayList or a Generic list is treated
as a TOML array to align with how ConvertTo-Json works. Also properly
deserializes a TOML array of array/table values into actual dotnet
objects to provide a better deserialized value.
  • Loading branch information
jborean93 authored Jan 15, 2024
1 parent 001d059 commit 79124b5
Show file tree
Hide file tree
Showing 6 changed files with 148 additions and 8 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Changelog for PSToml

## v0.3.1 - TBD

+ Serialize any IList type as a Toml array value and not just an array
+ Deserialize Toml array values that contain table/array/ values into the proper dotnet object
+ Support serializing `IntPtr` and `UIntPtr` instances

## v0.3.0 - 2023-11-28

+ Migrated to new ALC structure that simplifies the code and ensures deps are loaded in the ALC
Expand Down
2 changes: 1 addition & 1 deletion module/PSToml.psd1
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
RootModule = 'PSToml.psm1'

# Version number of this module.
ModuleVersion = '0.3.0'
ModuleVersion = '0.3.1'

# Supported PSEditions
# CompatiblePSEditions = @()
Expand Down
13 changes: 12 additions & 1 deletion src/PSToml/ConvertFromToml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,18 @@ private OrderedDictionary ConvertToOrderedDictionary(TomlTable table)
private object?[] ConvertToArray(TomlArray array)
{
List<object?> result = new();
result.AddRange(array);
foreach (object? value in array)
{
object? newValue = value switch
{
TomlArray a => ConvertToArray(a),
TomlTable t => ConvertToOrderedDictionary(t),
TomlTableArray ta => ConvertToListOfOrderedDictionary(ta),
TomlDateTime dt => dt.DateTime,
_ => value,
};
result.Add(newValue);
}

return result.ToArray();
}
Expand Down
49 changes: 43 additions & 6 deletions src/PSToml/ConvertToToml.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Management.Automation;
using Tomlyn;
using Tomlyn.Model;
Expand Down Expand Up @@ -93,26 +94,54 @@ private object ConvertToTomlObject(object? inputObject, int depth)
return inputObject switch
{
IDictionary dict => ConvertToTomlTable(dict, depth),
Array array => ConvertToTomlArray(array, depth),
IList array => ConvertToTomlArray(array, depth),
_ => ConvertToTomlFriendlyObject(inputObject, depth),
};
}

private TomlArray ConvertToTomlArray(Array array, int depth)
private TomlObject ConvertToTomlArray(IList array, int depth)
{
TomlArray result = new();
List<object> results = new();
bool isTableArray = true;

foreach (object value in array)
{
result.Add(ConvertToTomlObject(value, depth - 1));
object toSerialize = ConvertToTomlObject(value, depth - 1);

if (!(toSerialize is TomlTable tt))
{
isTableArray = false;
}

results.Add(toSerialize);
}

return result;
if (isTableArray)
{
TomlTableArray ta = new();
foreach (object v in results)
{
ta.Add((TomlTable)v);
}

return ta;
}
else
{
TomlArray a = new();
foreach (object v in results)
{
a.Add(v);
}

return a;

}
}

private TomlTable ConvertToTomlTable(IDictionary dict, int depth)
{
TomlTable model = new();
TomlTable model = new(inline: false);
foreach (DictionaryEntry entry in dict)
{
object value = ConvertToTomlObject(entry.Value ?? "", depth - 1);
Expand Down Expand Up @@ -141,6 +170,14 @@ private object ConvertToTomlFriendlyObject(object obj, int depth)
{
return Convert.ChangeType(enumObj, enumObj.GetTypeCode());
}
else if (obj is IntPtr ptr)
{
return (long)ptr;
}
else if (obj is UIntPtr uptr)
{
return (ulong)uptr;
}

if (
obj is bool ||
Expand Down
66 changes: 66 additions & 0 deletions tests/ConvertFrom-Toml.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -149,4 +149,70 @@ color = "gray"
$actual.products[2].sku | Should -Be 284758393
$actual.products[2].color | Should -Be gray
}

It "Converts inline array of normal values" {
$actual = ConvertFrom-Toml -InputObject @'
foo = [1, "2", 3.4]
'@

,$actual.foo | Should -BeOfType ([object[]])
$actual.foo.Count | Should -Be 3

$actual.foo[0] | Should -Be 1
$actual.foo[0] | Should -BeOfType ([long])

$actual.foo[1] | Should -Be 2
$actual.foo[1] | Should -BeOfType ([string])

$actual.foo[2] | Should -Be 3.4
$actual.foo[2] | Should -BeOfType ([double])
}

It "Converts inline array of array values" {
$actual = ConvertFrom-Toml -InputObject @'
foo = [[1, 2], ["3", "4"], [5.6]]
'@

,$actual.foo | Should -BeOfType ([object[]])
$actual.foo.Count | Should -Be 3


,$actual.foo[0] | Should -BeOfType ([object[]])
$actual.foo[0].Count | Should -Be 2
$actual.foo[0][0] | Should -Be 1
$actual.foo[0][0] | Should -BeOfType ([long])
$actual.foo[0][1] | Should -Be 2
$actual.foo[0][1] | Should -BeOfType ([long])

,$actual.foo[1] | Should -BeOfType ([object[]])
$actual.foo[1].Count | Should -Be 2
$actual.foo[1][0] | Should -Be 3
$actual.foo[1][0] | Should -BeOfType ([string])
$actual.foo[1][1] | Should -Be 4
$actual.foo[1][1] | Should -BeOfType ([string])

,$actual.foo[2] | Should -BeOfType ([object[]])
$actual.foo[2].Count | Should -Be 1
$actual.foo[2][0] | Should -Be 5.6
$actual.foo[2][0] | Should -BeOfType ([double])
}

It "Converts inline array of table values" {
$actual = ConvertFrom-Toml -InputObject @'
foo = [{foo = 1, bar = 2}, {foo = 3, bar = 4}]
'@

,$actual.foo | Should -BeOfType ([object[]])
$actual.foo.Count | Should -Be 2

$actual.foo[0] | Should -BeOfType ([System.Collections.Specialized.OrderedDictionary])
$actual.foo[0].Keys.Count | Should -Be 2
$actual.foo[0].foo | Should -Be 1
$actual.foo[0].bar | Should -Be 2

$actual.foo[1] | Should -BeOfType ([System.Collections.Specialized.OrderedDictionary])
$actual.foo[1].Keys.Count | Should -Be 2
$actual.foo[1].foo | Should -Be 3
$actual.foo[1].bar | Should -Be 4
}
}
20 changes: 20 additions & 0 deletions tests/ConvertTo-Toml.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -78,12 +78,32 @@ name = "plantain"
char = [char]'c'
null = $null
enum = [System.IO.FileShare]::ReadWrite
intptr = [IntPtr]::new(-1)
uintptr = [UIntPtr]::new(1)
})
$actual | Should -Be @'
guid = "00000000-0000-0000-0000-000000000000"
char = "c"
null = ""
enum = 3
intptr = -1
uintptr = 1
'@
}

It "Serializes array and list types" {
$actual = ConvertTo-Toml -InputObject ([Ordered]@{
array = @(1, 2, 3)
typed_array = [string[]]@(1, 2, "3")
array_list = [System.Collections.ArrayList]@(1, 2, 3)
generic_list = [System.Collections.Generic.List[string]]@(1, "2", 3)
})
$actual | Should -Be @'
array = [1, 2, 3]
typed_array = ["1", "2", "3"]
array_list = [1, 2, 3]
generic_list = ["1", "2", "3"]
'@
}
Expand Down

0 comments on commit 79124b5

Please sign in to comment.