Private/State.ps1
|
function ConvertTo-PodeStateData { param( [Parameter()] [object] $InputObject ) # return null if no object if ($null -eq $InputObject) { return $null } # for date/times, return in ISO 8601 format if ($InputObject -is [datetime]) { return @{ Type = 'DateTime' Value = $InputObject.ToString('o') } } # for time spans, return as ticks if ($InputObject -is [timespan]) { return @{ Type = 'TimeSpan' Value = $InputObject.Ticks } } # for a guid, return as string if ($InputObject -is [guid]) { return @{ Type = 'Guid' Value = $InputObject.ToString() } } # return raw object if it's a value type or string if (($InputObject -is [valuetype]) -or ($InputObject -is [string])) { return @{ Type = $InputObject.GetType().Name Value = $InputObject } } # handle each key for hashtables, and dictionaries if ( ($InputObject -is [hashtable]) -or ($InputObject -is [System.Collections.Specialized.OrderedDictionary]) -or ($InputObject -is [System.Collections.Generic.Dictionary[string, object]]) -or ($InputObject -is [System.Collections.Concurrent.ConcurrentDictionary[string, object]]) -or ($InputObject -is [Pode.Utilities.Structures.PodeConcurrentOrderedDictionary[string, object]]) ) { $result = @{ Type = ($InputObject.GetType().Name -split '`')[0] Items = @() } foreach ($key in $InputObject.Keys) { $result.Items += @{ Key = $key Value = ConvertTo-PodeStateData -InputObject $InputObject[$key] } } return $result } # handle each item in lists, set, and bags if ( ($InputObject -is [System.Collections.Generic.List[object]]) -or ($InputObject -is [System.Collections.Generic.HashSet[object]]) -or ($InputObject -is [System.Collections.Generic.SortedSet[object]]) -or ($InputObject -is [System.Collections.Concurrent.ConcurrentBag[object]]) -or ($InputObject -is [Pode.Utilities.Structures.PodeConcurrentList[object]]) -or ($InputObject -is [Pode.Utilities.Structures.PodeConcurrentSet[object]]) ) { $result = @{ Type = ($InputObject.GetType().Name -split '`')[0] Items = @() } foreach ($item in $InputObject) { $result.Items += ConvertTo-PodeStateData -InputObject $item } return $result } # handle generic arrays / IEnumerable if (($InputObject -is [array]) -or ($InputObject -is [System.Collections.IEnumerable])) { if ($InputObject.Length -eq 0) { return , @() } $items = @() foreach ($item in $InputObject) { $items += ConvertTo-PodeStateData -InputObject $item } return , $items } # handle PSCustomObject if ($InputObject -is [PSCustomObject]) { $result = @{ Type = 'PSCustomObject' Items = @() } foreach ($key in $InputObject.PSObject.Properties.Name) { $result.Items += @{ Key = $key Value = ConvertTo-PodeStateData -InputObject $InputObject.$key } } return $result } # return object as is return $InputObject } function ConvertFrom-PodeStateJson { param( [Parameter()] [pscustomobject] $InputObject ) # legacy version, convert to concurrent dictionary and return if ($null -eq $InputObject.__pode_state_metadata__) { $state = New-PodeStateDictionary if ($InputObject -is [hashtable]) { foreach ($key in $InputObject.Keys) { $state[$key] = $InputObject[$key] } } else { foreach ($key in $InputObject.psobject.properties.name) { $state[$key] = $InputObject.$key } } return $state } # convert based on the version of the state file switch ($InputObject.__pode_state_metadata__.Version) { 2 { return ConvertFrom-PodeStateData -InputObject $InputObject.__pode_state_data__ } } } function ConvertFrom-PodeStateData { param( [Parameter()] [object] $InputObject ) # return null if no object if ($null -eq $InputObject) { return $null } # if it's not a pscustomobject, or doesn't contain a Type, handle raw types if ([string]::IsNullOrEmpty($InputObject.Type) -or ($InputObject.Type.Count -gt 1)) { # handle value types and strings if (($InputObject -is [valuetype]) -or ($InputObject -is [string])) { return $InputObject } # handle arrays if (($InputObject -is [array]) -or ($InputObject -is [System.Collections.IEnumerable])) { $items = @() foreach ($item in $InputObject) { $items += ConvertFrom-PodeStateData -InputObject $item } return , $items } # else return the object as is return $InputObject } # convert based on the type of object switch ($InputObject.Type) { 'DateTime' { if ($InputObject.Value -is [datetime]) { return $InputObject.Value } return [datetime]::Parse($InputObject.Value) } 'TimeSpan' { return [timespan]::FromTicks($InputObject.Value) } 'Guid' { return [guid]::Parse($InputObject.Value) } 'Int32' { return [int]$InputObject.Value } 'Int64' { return [long]$InputObject.Value } 'Double' { return [double]$InputObject.Value } 'Decimal' { return [decimal]$InputObject.Value } 'Float' { return [float]$InputObject.Value } 'Boolean' { return [bool]$InputObject.Value } 'String' { return [string]$InputObject.Value } 'Char' { return [char]$InputObject.Value } 'Byte' { return [byte]$InputObject.Value } 'SByte' { return [sbyte]$InputObject.Value } 'UInt16' { return [uint16]$InputObject.Value } 'UInt32' { return [uint32]$InputObject.Value } 'UInt64' { return [uint64]$InputObject.Value } 'Single' { return [single]$InputObject.Value } 'Int16' { return [int16]$InputObject.Value } 'SyncHashtable' { $result = [hashtable]::Synchronized(@{}) foreach ($item in $InputObject.Items) { $result[$item.Key] = ConvertFrom-PodeStateData -InputObject $item.Value } return $result } 'Hashtable' { $result = @{} foreach ($item in $InputObject.Items) { $result[$item.Key] = ConvertFrom-PodeStateData -InputObject $item.Value } return $result } { $_ -iin @('OrderedDictionary', 'OrderedHashtable') } { $result = [ordered]@{} foreach ($item in $InputObject.Items) { $result[$item.Key] = ConvertFrom-PodeStateData -InputObject $item.Value } return $result } 'Dictionary' { $result = [System.Collections.Generic.Dictionary[string, object]]::new() foreach ($item in $InputObject.Items) { $result[$item.Key] = ConvertFrom-PodeStateData -InputObject $item.Value } return $result } 'ConcurrentDictionary' { $result = [System.Collections.Concurrent.ConcurrentDictionary[string, object]]::new() foreach ($item in $InputObject.Items) { $result[$item.Key] = ConvertFrom-PodeStateData -InputObject $item.Value } return $result } 'PodeConcurrentOrderedDictionary' { $result = New-PodeStateDictionary foreach ($item in $InputObject.Items) { $result[$item.Key] = ConvertFrom-PodeStateData -InputObject $item.Value } return , $result } 'List' { $result = [System.Collections.Generic.List[object]]::new() foreach ($item in $InputObject.Items) { $null = $result.Add((ConvertFrom-PodeStateData -InputObject $item)) } return , $result } 'HashSet' { $result = [System.Collections.Generic.HashSet[object]]::new() foreach ($item in $InputObject.Items) { $null = $result.Add((ConvertFrom-PodeStateData -InputObject $item)) } return , $result } 'SortedSet' { $result = [System.Collections.Generic.SortedSet[object]]::new() foreach ($item in $InputObject.Items) { $null = $result.Add((ConvertFrom-PodeStateData -InputObject $item)) } return , $result } 'ConcurrentBag' { $result = [System.Collections.Concurrent.ConcurrentBag[object]]::new() foreach ($item in $InputObject.Items) { $null = $result.TryAdd((ConvertFrom-PodeStateData -InputObject $item)) } return , $result } 'PodeConcurrentList' { $result = New-PodeStateList foreach ($item in $InputObject.Items) { $null = $result.TryAdd((ConvertFrom-PodeStateData -InputObject $item)) } return , $result } 'PodeConcurrentSet' { $result = New-PodeStateSet foreach ($item in $InputObject.Items) { $null = $result.TryAdd((ConvertFrom-PodeStateData -InputObject $item)) } return , $result } 'PSCustomObject' { $result = [PSCustomObject]@{} foreach ($item in $InputObject.Items) { $null = $result | Add-Member -MemberType NoteProperty -Name $item.Key -Value (ConvertFrom-PodeStateData -InputObject $item.Value) -Force } return $result } } # if we get here, return the object as is if ($InputObject.Value) { return $InputObject.Value } return $InputObject.Items } |