From 991e7dc57f51ea78d4570a7af8e9b1aa29ef885e Mon Sep 17 00:00:00 2001 From: Andrew Pearce Date: Thu, 29 Jan 2026 00:14:46 -0800 Subject: [PATCH] Add pipeline support to byte array conversion functions (#16) --- .../Public/ConvertFrom-Base64ToByteArray.ps1 | 40 ++++++-- .../ConvertFrom-ByteArrayToMemoryStream.ps1 | 39 +++++--- .../ConvertFrom-Base64ToByteArray.Tests.ps1 | 97 ++++++++++++++++--- ...ConvertFrom-Base64ToMemoryStream.Tests.ps1 | 2 +- ...vertFrom-ByteArrayToMemoryStream.Tests.ps1 | 73 +++++++++++--- 5 files changed, 202 insertions(+), 49 deletions(-) diff --git a/src/Convert/Public/ConvertFrom-Base64ToByteArray.ps1 b/src/Convert/Public/ConvertFrom-Base64ToByteArray.ps1 index faea926..d2e5dae 100644 --- a/src/Convert/Public/ConvertFrom-Base64ToByteArray.ps1 +++ b/src/Convert/Public/ConvertFrom-Base64ToByteArray.ps1 @@ -9,26 +9,46 @@ The Base 64 Encoded String to be converted .EXAMPLE - PS C:\> ConvertFrom-Base64ToByteArray -String 'dGVzdA==' - 116 - 101 - 115 - 116 + ConvertFrom-Base64ToByteArray -String 'dGVzdA==' - Converts the base64 string to its byte array representation. + .EXAMPLE + 'SGVsbG8=' | ConvertFrom-Base64ToByteArray + + .EXAMPLE + 'SGVsbG8=', 'V29ybGQ=' | ConvertFrom-Base64ToByteArray + + .OUTPUTS + [Byte[]] .LINK - https://msdn.microsoft.com/en-us/library/system.convert.frombase64string%28v=vs.110%29.aspx + https://austoonz.github.io/Convert/functions/ConvertFrom-Base64ToByteArray/ #> function ConvertFrom-Base64ToByteArray { [CmdletBinding()] [Alias('ConvertFrom-Base64StringToByteArray')] param ( - [Parameter(Mandatory = $true)] + [Parameter( + Mandatory = $true, + ValueFromPipeline = $true, + ValueFromPipelineByPropertyName = $true)] [ValidateNotNullOrEmpty()] [Alias('Base64String')] - [String]$String + [String[]] + $String ) - [System.Convert]::FromBase64String($String) + + begin { + $userErrorActionPreference = $ErrorActionPreference + } + + process { + foreach ($s in $String) { + try { + [System.Convert]::FromBase64String($s) + } catch { + Write-Error -ErrorRecord $_ -ErrorAction $userErrorActionPreference + } + } + } } diff --git a/src/Convert/Public/ConvertFrom-ByteArrayToMemoryStream.ps1 b/src/Convert/Public/ConvertFrom-ByteArrayToMemoryStream.ps1 index 9635592..28799da 100644 --- a/src/Convert/Public/ConvertFrom-ByteArrayToMemoryStream.ps1 +++ b/src/Convert/Public/ConvertFrom-ByteArrayToMemoryStream.ps1 @@ -8,25 +8,42 @@ .PARAMETER ByteArray The Byte Array to be converted - .LINK - https://msdn.microsoft.com/en-us/library/system.io.memorystream(v=vs.110).aspx - - .NOTES - Additional information: - https://msdn.microsoft.com/en-us/library/63z365ty(v=vs.110).aspx - .EXAMPLE ConvertFrom-ByteArrayToMemoryStream -ByteArray ([Byte[]] (,0xFF * 100)) - This command uses the ConvertFrom-ByteArrayToMemoryStream cmdlet to convert a Byte Array into a Memory Stream. + .EXAMPLE + $bytes = [Byte[]]@(72, 101, 108, 108, 111) + ,$bytes | ConvertFrom-ByteArrayToMemoryStream + + .OUTPUTS + [System.IO.MemoryStream[]] + + .LINK + https://austoonz.github.io/Convert/functions/ConvertFrom-ByteArrayToMemoryStream/ #> function ConvertFrom-ByteArrayToMemoryStream { + [CmdletBinding()] param ( - [Parameter(Mandatory = $true)] + [Parameter( + Mandatory = $true, + ValueFromPipeline = $true, + ValueFromPipelineByPropertyName = $true)] [ValidateNotNullOrEmpty()] [Alias('Bytes')] - [System.Byte[]]$ByteArray + [System.Byte[]] + $ByteArray ) - [System.IO.MemoryStream]::new($ByteArray, 0, $ByteArray.Length) + + begin { + $userErrorActionPreference = $ErrorActionPreference + } + + process { + try { + [System.IO.MemoryStream]::new($ByteArray, 0, $ByteArray.Length) + } catch { + Write-Error -ErrorRecord $_ -ErrorAction $userErrorActionPreference + } + } } diff --git a/src/Tests/Unit/ConvertFrom-Base64ToByteArray.Tests.ps1 b/src/Tests/Unit/ConvertFrom-Base64ToByteArray.Tests.ps1 index e5d771a..8e0e221 100644 --- a/src/Tests/Unit/ConvertFrom-Base64ToByteArray.Tests.ps1 +++ b/src/Tests/Unit/ConvertFrom-Base64ToByteArray.Tests.ps1 @@ -1,28 +1,97 @@ $function = $MyInvocation.MyCommand.Name.Split('.')[0] Describe $function { - It 'Returns bytes' { - $text = 'This is a secret and should be hidden' - $bytes = [System.Text.Encoding]::Unicode.GetBytes($text) - $base64String = [Convert]::ToBase64String($bytes) + Context 'Basic Functionality' { + It 'Returns bytes' { + $text = 'This is a secret and should be hidden' + $bytes = [System.Text.Encoding]::Unicode.GetBytes($text) + $base64String = [Convert]::ToBase64String($bytes) - $assertion = ConvertFrom-Base64ToByteArray -String $base64String - $assertion | Should -BeOfType 'byte' + $assertion = ConvertFrom-Base64ToByteArray -String $base64String + $assertion | Should -BeOfType 'byte' + } + + It 'Throws an exception when input is a string of incorrect length' { + { ConvertFrom-Base64ToByteArray -String 'String' } | Should -Throw + } + + It 'Throws an exception when input is of wrong type' { + { ConvertFrom-Base64ToByteArray -String (New-Object -TypeName PSObject) } | Should -Throw + } + + It 'Throws an exception when input is null' { + { ConvertFrom-Base64ToByteArray -String $null } | Should -Throw + } + + It 'Throws an exception when input is empty' { + { ConvertFrom-Base64ToByteArray -String '' } | Should -Throw + } } - It 'Throws an exception when input is a string of incorrect length' { - { ConvertFrom-Base64ToByteArray -String 'String' } | Should -Throw + Context 'Pipeline Support' { + It 'Accepts input from pipeline' { + $result = 'SGVsbG8=' | ConvertFrom-Base64ToByteArray + $result | Should -Not -BeNullOrEmpty + $result | Should -BeOfType 'byte' + } + + It 'Processes multiple strings from pipeline' { + $results = 'SGVsbG8=', 'V29ybGQ=' | ConvertFrom-Base64ToByteArray + $results | Should -Not -BeNullOrEmpty + } + + It 'Processes multiple strings via parameter' { + $results = ConvertFrom-Base64ToByteArray -String 'SGVsbG8=', 'V29ybGQ=' + $results | Should -Not -BeNullOrEmpty + } } - It 'Throws an exception when input is of wrong type' { - { ConvertFrom-Base64ToByteArray -String (New-Object -TypeName PSObject) } | Should -Throw + Context 'Edge Cases' { + It 'Handles minimal valid Base64 (single byte)' { + $result = ConvertFrom-Base64ToByteArray -String 'QQ==' + $result | Should -Be 65 + } + + It 'Handles Base64 with no padding' { + $result = ConvertFrom-Base64ToByteArray -String 'SGVsbG8gV29ybGQ=' + $result | Should -Not -BeNullOrEmpty + } + + It 'Handles Base64 with single padding' { + $result = ConvertFrom-Base64ToByteArray -String 'SGVsbG8=' + $result | Should -Not -BeNullOrEmpty + } + + It 'Handles Base64 with double padding' { + $result = ConvertFrom-Base64ToByteArray -String 'QQ==' + $result | Should -Not -BeNullOrEmpty + } + + It 'Handles binary data encoded as Base64' { + $pngBase64 = 'iVBORw0KGgo=' + $result = ConvertFrom-Base64ToByteArray -String $pngBase64 + $result[0] | Should -Be 0x89 + $result[1] | Should -Be 0x50 + } } - It 'Throws an exception when input is null' { - { ConvertFrom-Base64ToByteArray -String $null } | Should -Throw + Context 'Round-Trip Validation' { + It 'Round-trips correctly with ConvertFrom-ByteArrayToBase64' { + $original = [Byte[]]@(1, 2, 3, 4, 5) + $base64 = ConvertFrom-ByteArrayToBase64 -ByteArray $original + $result = ConvertFrom-Base64ToByteArray -String $base64 + $result | Should -Be $original + } } - It 'Throws an exception when input is empty' { - { ConvertFrom-Base64ToByteArray -String '' } | Should -Throw + Context 'Error Handling' { + It 'Respects ErrorAction parameter' { + { ConvertFrom-Base64ToByteArray -String 'SGVsbG8=' -ErrorAction Stop } | Should -Not -Throw + } + + It 'Writes error for invalid Base64 with ErrorAction Continue' { + $result = ConvertFrom-Base64ToByteArray -String 'Invalid!' -ErrorAction SilentlyContinue + $result | Should -BeNullOrEmpty + } } } diff --git a/src/Tests/Unit/ConvertFrom-Base64ToMemoryStream.Tests.ps1 b/src/Tests/Unit/ConvertFrom-Base64ToMemoryStream.Tests.ps1 index ac9e65c..09f28e4 100644 --- a/src/Tests/Unit/ConvertFrom-Base64ToMemoryStream.Tests.ps1 +++ b/src/Tests/Unit/ConvertFrom-Base64ToMemoryStream.Tests.ps1 @@ -39,7 +39,7 @@ Describe -Name $function -Fixture { # Windows PowerShell 'Invalid length for a Base-64 char array or string.' ) - $assertion.Exception.InnerException.Message | Should -BeIn $exception + $assertion[0].Exception.InnerException.Message | Should -BeIn $exception } } } diff --git a/src/Tests/Unit/ConvertFrom-ByteArrayToMemoryStream.Tests.ps1 b/src/Tests/Unit/ConvertFrom-ByteArrayToMemoryStream.Tests.ps1 index 996c02d..befc439 100644 --- a/src/Tests/Unit/ConvertFrom-ByteArrayToMemoryStream.Tests.ps1 +++ b/src/Tests/Unit/ConvertFrom-ByteArrayToMemoryStream.Tests.ps1 @@ -1,25 +1,72 @@ $function = $MyInvocation.MyCommand.Name.Split('.')[0] Describe $function { - It 'Returns a MemoryStream' { - $byteArray = [Byte[]] (, 0xFF * 100) + Context 'Basic Functionality' { + It 'Returns a MemoryStream' { + $byteArray = [Byte[]] (, 0xFF * 100) - $assertion = ConvertFrom-ByteArrayToMemoryStream -ByteArray $byteArray - $assertion.GetType().Name | Should -BeExactly 'MemoryStream' - } - It 'Does not throw an exception when input is an empty System.Byte' { - { ConvertFrom-ByteArrayToMemoryStream -ByteArray (New-Object -TypeName System.Byte) } | Should -Not -Throw + $assertion = ConvertFrom-ByteArrayToMemoryStream -ByteArray $byteArray + $assertion.GetType().Name | Should -BeExactly 'MemoryStream' + } + + It 'Does not throw an exception when input is an empty System.Byte' { + { ConvertFrom-ByteArrayToMemoryStream -ByteArray (New-Object -TypeName System.Byte) } | Should -Not -Throw + } + + It 'Throws an exception when input is of wrong type' { + { ConvertFrom-ByteArrayToMemoryStream -ByteArray (New-Object -TypeName PSObject) } | Should -Throw + } + + It 'Throws an exception when input is null' { + { ConvertFrom-ByteArrayToMemoryStream -ByteArray $null } | Should -Throw + } } - It 'Does not throw an exception when input is empty' { - { ConvertFrom-ByteArrayToMemoryStream -ByteArray '' } | Should -Not -Throw + Context 'Pipeline Support' { + It 'Accepts input from pipeline' { + $byteArray = [Byte[]]@(65, 66, 67) + $result = ,$byteArray | ConvertFrom-ByteArrayToMemoryStream + $result | Should -Not -BeNullOrEmpty + $result.GetType().Name | Should -BeExactly 'MemoryStream' + } + + It 'Processes multiple byte arrays from pipeline' { + $bytes1 = ,[Byte[]]@(65, 66, 67) + $bytes2 = ,[Byte[]]@(68, 69, 70) + $results = @($bytes1; $bytes2) | ConvertFrom-ByteArrayToMemoryStream + $results.Count | Should -Be 2 + $results[0].GetType().Name | Should -BeExactly 'MemoryStream' + $results[1].GetType().Name | Should -BeExactly 'MemoryStream' + } } - It 'Throws an exception when input is of wrong type' { - { ConvertFrom-ByteArrayToMemoryStream -ByteArray (New-Object -TypeName PSObject) } | Should -Throw + Context 'Edge Cases' { + It 'Handles single byte' { + $singleByte = [Byte[]]@(65) + $result = ConvertFrom-ByteArrayToMemoryStream -ByteArray $singleByte + $result.Length | Should -Be 1 + } + + It 'Handles large byte array' { + $largeBytes = [Byte[]](1..10000 | ForEach-Object { 65 }) + $result = ConvertFrom-ByteArrayToMemoryStream -ByteArray $largeBytes + $result.Length | Should -Be 10000 + } + + It 'Returns readable MemoryStream' { + $bytes = [Byte[]]@(72, 101, 108, 108, 111) # "Hello" + $stream = ConvertFrom-ByteArrayToMemoryStream -ByteArray $bytes + $stream.Position = 0 + $reader = [System.IO.StreamReader]::new($stream) + $reader.ReadToEnd() | Should -BeExactly 'Hello' + $reader.Dispose() + } } - It 'Throws an exception when input is null' { - { ConvertFrom-ByteArrayToMemoryStream -ByteArray $null } | Should -Throw + Context 'Error Handling' { + It 'Respects ErrorAction parameter' { + $bytes = [Byte[]]@(65) + { ConvertFrom-ByteArrayToMemoryStream -ByteArray $bytes -ErrorAction Stop } | Should -Not -Throw + } } }