Types/OpenPackage/GetContent.ps1

<#
.SYNOPSIS
    Gets part content
.DESCRIPTION
    Gets the content of one or more parts.

    Will attempt to get the content in the best type available, using any available reader.
    
    Otherwise, will attempt to convert xml, and, if that fails, will return content bytes.
.NOTES
    Yaml support requires the installation of an appropriate ConvertFrom-Yaml command
    
    [YaYaml](https://github.com/jborean93/PowerShell-Yayaml/) is recommended.

    Toml support requires the installation of an appropriate ConvertFrom-Toml command

    [PSToml](https://github.com/jborean93/PSToml) is recommended.
#>

param()

$unrolledArgs = @(foreach ($arg in $args) {
    $arg
})

filter addPackageAndPart {
    $_ |
        Add-Member NoteProperty Package $this -Force -PassThru |
        Add-Member NoteProperty PartUri $thisPart.Uri -Force -PassThru 
}

$myParts = @($this.GetParts())

$matchingParts = 
    foreach ($arg in $unrolledArgs) {
        if ($arg -is [string]) {
            $SlashPart = '/' + ($arg -replace '^/')
            if ($this.PartExists($SlashPart)) {
                $this.GetPart($SlashPart)
            } elseif ($arg -match '\*') {
                @($myParts.Uri) -like $arg
            }
        }
    }

:nextPart foreach ($part in $matchingParts) {
    $thisPart = $part

    # If we have a reader, just read the content.
    if ($part.Reader) {
        $part.Read()
        continue nextPart
    }
    
    $partStream = $thisPart.GetStream()
    
    $memoryStream = [IO.MemoryStream]::new()
    $partStream.CopyTo($memoryStream)                
    $partStream.Close()
    $partStream.Dispose()

    [byte[]]$partBytes = $memoryStream.ToArray()

    $memoryStream.Close()
    $memoryStream.Dispose()

    $byteStream = [IO.MemoryStream]::new($partBytes)
    $partStreamReader = [IO.StreamReader]::new($byteStream)
    $partString = $partStreamReader.ReadToEnd()
    $partStreamReader.Close()
    $partStreamReader.Dispose()
    $byteStream.Close()
    $byteStream.Dispose()

    $partAsXml = $partString -as [xml]
    if ($null -ne $partAsXml) {
        if ($partASXml.Objs) {
            try {
                [Management.Automation.PSSerializer]::Deserialize($partString) |
                    addPackageAndPart        
                continue nextPart
            } catch {
                Write-Warning "$($thisPart.Uri) was not clixml"
            }
        } else {
            $partAsXml | addPackageAndPart
        }

        continue nextPart
    }

    if ($thisPart.Uri -match './astro$') {
        $partString |
            addPackageAndPart
        continue nextPart
    }

    if ($thisPart.ContentType -match '^text/') {
        $partString |
            addPackageAndPart
    } else {
        $partBytes
    }            
}