Last active
December 5, 2024 19:25
-
-
Save prachigauriar/c9d22353aa2476d74c2ce77fe871bc39 to your computer and use it in GitHub Desktop.
ByteFormatStyle
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
struct ByteFormatStyle<Bytes> : FormatStyle, Hashable, Sendable where Bytes : Collection, Bytes.Element == UInt8 { | |
typealias FormatInput = Bytes | |
typealias FormatOutput = String | |
var radix: Int = 16 | |
var uppercase: Bool = false | |
var groupingSeparator: String = " " | |
var groupingSize: Int = Int.bitWidth / 8 | |
var secondaryGroupingSeparator: String = " " | |
var secondaryGroupingSize: Int = 2 | |
var tertiaryGroupingSeparator: String = "\n" | |
var tertiaryGroupingSize: Int = 2 | |
func radix(_ radix: Int, uppercase: Bool = false) -> Self { | |
var copy = self | |
copy.radix = radix | |
copy.uppercase = uppercase | |
return copy | |
} | |
func grouping(size: Int, separator: String = " ") -> Self { | |
var copy = self | |
copy.groupingSize = size | |
copy.groupingSeparator = separator | |
return copy | |
} | |
func secondaryGrouping(size: Int, separator: String = " ") -> Self { | |
var copy = self | |
copy.secondaryGroupingSize = size | |
copy.secondaryGroupingSeparator = separator | |
return copy | |
} | |
func tertiaryGrouping(size: Int, separator: String = "\n") -> Self { | |
var copy = self | |
copy.tertiaryGroupingSize = size | |
copy.tertiaryGroupingSeparator = separator | |
return copy | |
} | |
func format(_ value: Bytes) -> String { | |
let byteCharacterCount = String(UInt8.max, radix: radix).count | |
var formattedString = "" | |
var byteCount = 0 | |
var primaryGroupCount = 0 | |
var secondaryGroupCount = 0 | |
for byte in value { | |
var byteString = String(byte, radix: radix, uppercase: uppercase) | |
let paddingCharacterCount = byteCharacterCount - byteString.count | |
if paddingCharacterCount > 0 { | |
byteString.insert( | |
contentsOf: String(repeating: "0", count: paddingCharacterCount), | |
at: byteString.startIndex | |
) | |
} | |
formattedString.append(byteString) | |
byteCount += 1 | |
var appendPrimaryGroup = groupingSize > 0 && byteCount == groupingSize | |
if appendPrimaryGroup { | |
byteCount = 0 | |
primaryGroupCount += 1 | |
} | |
var appendSecondaryGroup = secondaryGroupingSize > 0 && primaryGroupCount == secondaryGroupingSize | |
if appendSecondaryGroup { | |
appendPrimaryGroup = false | |
primaryGroupCount = 0 | |
secondaryGroupCount += 1 | |
} | |
let appendTertiaryGroup = tertiaryGroupingSize > 0 && secondaryGroupCount == tertiaryGroupingSize | |
if appendTertiaryGroup { | |
appendSecondaryGroup = false | |
secondaryGroupCount = 0 | |
} | |
if appendTertiaryGroup { | |
formattedString.append(tertiaryGroupingSeparator) | |
} else if appendSecondaryGroup { | |
formattedString.append(secondaryGroupingSeparator) | |
} else if appendPrimaryGroup { | |
formattedString.append(groupingSeparator) | |
} | |
} | |
return formattedString | |
} | |
} | |
let randomData = Data((0 ..< 128).map { _ in UInt8.random(in: .min ... .max) }) | |
let formatStyle = ByteFormatStyle<Data>() | |
.radix(16, uppercase: true) | |
.grouping(size: 4, separator: " ") | |
.secondaryGrouping(size: 4, separator: " ") | |
.tertiaryGrouping(size: 2, separator: "\n") | |
print(formatStyle.format(randomData)) | |
// 1616EC47 3BB6D892 85C86BBD 2841EBC8 6DD27D77 E1043EF9 EAD76A98 12720DC8 | |
// 4F0D0F68 08578EDA B53D3517 39E93BAB 42D323BB 29A4FA9E 1DEDAC5F 29F3C92A | |
// 3BB5E5A3 3DCAF028 27A6D6D4 CCB492BA 53ED4C1F F1CF886A 9D9B0BAD A0C04AC8 | |
// 10334DFB 74502BEF 836BC0FD 00E02605 83FFC261 0A4BB137 0D25068C 7B92421D |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment