Private/Switch-ByteNibble.ps1

function Switch-ByteNibble {
    <#
        .SYNOPSIS
        Swaps the nibbles (4-bit halves) of each byte in a byte array or GUID.
 
        .DESCRIPTION
        Takes a byte array or GUID and swaps the high and low nibbles of each byte.
        This is useful for certain encoding/decoding operations.
 
        .EXAMPLE
        Switch-ByteNibble -Bytes @(0x12, 0x34, 0x56)
        Returns byte array with nibbles swapped: @(0x21, 0x43, 0x65)
 
        .EXAMPLE
        [Guid]'12345678-1234-1234-1234-123456789012' | Switch-ByteNibble
        Returns a new GUID with nibbles swapped in each byte.
    #>

    [OutputType([byte[]], ParameterSetName = 'Bytes')]
    [OutputType([guid], ParameterSetName = 'Guid')]
    [CmdletBinding(DefaultParameterSetName = 'Bytes')]
    param (
        [Parameter(
            Mandatory,
            Position = 0,
            ValueFromPipeline,
            ParameterSetName = 'Bytes'
        )]
        [byte[]]$Bytes,

        [Parameter(
            Mandatory,
            Position = 0,
            ValueFromPipeline,
            ParameterSetName = 'Guid'
        )]
        [Guid]$Guid
    )

    begin {
        $FunctionName = $MyInvocation.MyCommand.Name
        $ParamSet = $PSCmdlet.ParameterSetName
        $VERBOSE = $PSBoundParameters.ContainsKey('Verbose')
        function Show-Step {
            param (
                [string]$Step,
                [byte]$Byte1,
                [byte]$Byte2
            )

            $Byte1Fmt = [System.Convert]::ToString($Byte1, 2).PadLeft(8, '0')
            $Byte2Fmt = [System.Convert]::ToString($Byte2, 2).PadLeft(8, '0')

            '{0}: {1} - 0x{2:X2} => 0x{3:X2}; 0b{4} => 0b{5}' -f $FunctionName, $Step, $Byte1, $Byte2, $Byte1Fmt, $Byte2Fmt
        }
    }

    process {
        if ($ParamSet -eq 'Guid') {
            $Bytes = $Guid.ToByteArray()
            Write-Verbose "${FunctionName}: Input GUID converted to $($Bytes.Count) bytes"
            <# if($LITTLE_ENDIAN) {
                $Bytes = [byte[]]$Bytes[3..0] + [byte[]]$Bytes[5..4] + [byte[]]$Bytes[7..6] + [byte[]]$Bytes[8..15]
            } #>

        }

        $bytecount = 0
        $reversedBytes = [byte[]]::new($Bytes.Length)

        foreach ($byte in $Bytes) {
            # $reversedByte = [byte]0
            <# for ($i = 0; $i -lt 8; $i++) {
                $reversedByte = $reversedByte -bor (($byte -shr $i -band 1) -shl (7 - $i))
            } #>

            # Left nibble <-> Right nibble
            $leftBits = $byte -shl 4 -band 0xF0
            $rightBits = $byte -shr 4 -band 0x0F
            $reversedByte = $leftBits -bor $rightBits

            Show-Step -Step $bytecount -Byte1 $byte -Byte2 $reversedByte | Write-Debug
            $reversedBytes[$bytecount] = $reversedByte
            $bytecount++
        }

        if ($ParamSet -eq 'Guid') {
            Write-Verbose " ${FunctionName}: Outputting $($reversedBytes.Count) bytes as GUID"
            return [Guid]::new($reversedBytes)
        }
        elseif ($ParamSet -eq 'Bytes') {
            Write-Verbose " ${FunctionName}: Outputting $($reversedBytes.Count) bytes as $($reversedBytes.GetType().Name)"
            return ,$reversedBytes
            # Write-Output (,$reversedBytes)
        }
    }
}