More fun with Swift 5 String Interpolation: Radix formatting

I’m still kicking the tires and enjoying the new string interpolation features in Swift 5. Today’s extension enables (optionally padded) radix-based interpolation. You interpolate a number and specify a radix, the numerical base used to present it.

For example:

"\(42, radix: .hex)" // 2a
"\(42, radix: .binary)" // 101010
"\(42, radix: .octal)" // 52
"\(0x2a, radix: .decimal)" // 42
"\(15, radix: .hex, prefix: true, toWidth: 2)" // 0x0F

With padding you can ensure, for example, that a non-wide color is presented using two digits per color, with or without a prefix. Start with 15 and end up with F, 0F, or 0x0F , as desired.

It’s a simple extension for a task I use pretty regularly. I decided to use lowercase prefixes (0x and 0b) and uppercase hex (7F vs 7f). If you’d rather swap that out, change the prefix property and/or the first line in the interpolation:

public extension String.StringInterpolation {
    /// Represents a single numeric radix
    enum Radix: Int {
        case binary = 2, octal = 8, decimal = 10, hex = 16
        
        /// Returns a radix's optional prefix
        var prefix: String {
             return [.binary: "0b", .octal: "0o", .hex: "0x"][self, default: ""]
        }
    }
    
    /// Return padded version of the value using a specified radix
    mutating func appendInterpolation<I: Binary Integer>(_ value: I, radix: Radix, prefix: Bool = false, toWidth width: Int = 0) {
        
        // Values are uppercased, producing `FF` instead of `ff`
        var string = String(value, radix: radix.rawValue).uppercased()
        
        // Strings are pre-padded with 0 to match target widths
        if string.count < width {
            string = String(repeating: "0", count: max(0, width - string.count)) + string
        }
        
        // Prefixes use lower case, sourced from `String.StringInterpolation.Radix`
        if prefix {
            string = radix.prefix + string
        }
        
        appendInterpolation(string)
    }
}

I haven’t had a chance to test this much so if you see any issues, please let me know.

I have more to follow with more general NumberFormatter approaches that extend the interpolator (thanks, Dave DeLong!) and some fun suggestions and examples that will cover the new custom string delimiters.

Comments are closed.