Skip to content

MAC Address Generator — Swift source

Generate random EUI-48 MAC addresses with a chosen separator, optional OUI prefix, uppercase formatting, and a locally-administered flag. Runs entirely in your browser with crypto-grade randomness.

This is the Swift implementation — the same logic the interactive tool runs, in a shareable, citable form.

// mac-address-generator — random EUI-48 MAC address generator. Swift port
// (canonical TS: src/lib/mac-generator.ts; Go twin: cli/mac-address-generator).
// The default rng draws from Double.random (SystemRandomNumberGenerator —
// arc4random under the hood); the showcase keeps the rng injectable (a
// closure returning [0, 1)) so the demo asserts exact MAC strings.
import Foundation

struct MacOptions {
    var separator: String? = nil          // nil -> ":"; "" concatenates
    var uppercase = false
    var oui: String? = nil                // 6 hex digits (separators tolerated)
    var locallyAdministered = false       // force U/L bit (0x02) of the first octet
    var rng: (() -> Double)? = nil        // nil -> Double.random(in: 0..<1)
}

enum MacError: Error { case badOui(String) }

// Strip non-hex chars, require exactly 6 digits, parse the 3 OUI octets.
func parseOui(_ oui: String) throws -> [Int] {
    let clean = oui.filter(\.isHexDigit)
    guard clean.count == 6 else { throw MacError.badOui(oui) }
    return [0, 2, 4].map { Int(clean.dropFirst($0).prefix(2), radix: 16)! }
}

// Build a random EUI-48 MAC: 3 OUI octets (given or random) + 3 random,
// U/L bit forced when asked, joined as %02x with the separator.
func generateMac(_ o: MacOptions = MacOptions()) throws -> String {
    let rng = o.rng ?? { Double.random(in: 0..<1) }
    var oct: [Int]
    // TS `if (opts.oui)` truthiness: nil and "" both take the random path.
    if let oui = o.oui, !oui.isEmpty {
        oct = try parseOui(oui)
    } else {
        oct = (0..<3).map { _ in Int(rng() * 256) }
    }
    oct += (0..<3).map { _ in Int(rng() * 256) }
    if o.locallyAdministered { oct[0] = (oct[0] & 0xFD) | 0x02 }
    let mac = oct.map { String(format: "%02x", $0) }.joined(separator: o.separator ?? ":")
    return o.uppercase ? mac.uppercased() : mac
}

print(try! generateMac(MacOptions(rng: { 0 })))                                   // 00:00:00:00:00:00
print(try! generateMac(MacOptions(separator: "-")))                               // 6 random pairs, dash-joined
print(try! generateMac(MacOptions(uppercase: true, rng: { 0.7 })))                // B3:B3:B3:B3:B3:B3
print(try! generateMac(MacOptions(oui: "aa-bb-cc", rng: { 0 })))                  // aa:bb:cc:00:00:00
print(try! generateMac(MacOptions(locallyAdministered: true, rng: { 0.5 })))      // 82:80:80:80:80:80

Also available in 13 other languages

Every CosmoDev tool ships its pure logic in TypeScript (web) and Go (CLI), with authored implementations in a dozen-plus languages — the same contract, ported. Compare all languages side by side →