Capture UUID values with regex in Swift

When working with UUIDs in Swift, we may need to match and extract them using regular expressions. To achieve this in a type-safe and reusable way, we can define a custom RegexComponent leveraging the Capture component.

# Defining a reusable RegexComponent for UUIDs

The following implementation creates a CaptureUUID struct that conforms to RegexComponent. This struct defines a regular expression pattern for matching UUIDs while ensuring type safety through a transformation function.

import RegexBuilder

struct CaptureUUID: RegexComponent {
    let reference: Reference<UUID>
    
    init(as reference: Reference<UUID>) {
        self.reference = reference
    }
    
    @RegexComponentBuilder
    var regex: Regex<(Substring, UUID)> {
        Capture(as: reference) {
            Repeat(count: 8) { .hexDigit }
            "-"
            Repeat(count: 4) { .hexDigit }
            "-"
            Repeat(count: 4) { .hexDigit }
            "-"
            Repeat(count: 4) { .hexDigit }
            "-"
            Repeat(count: 12) { .hexDigit }
        } transform: { substring in
            try Self.transform(substring)
        }
    }
    
    private static func transform(
        _ substring: Substring
    ) throws -> UUID {
        guard
            let uuid = UUID(uuidString: String(substring))
        else {
            throw RegexTransformError
                .unableToDecode(UUID.self, from: substring)
        }
        return uuid
    }
}

enum RegexTransformError: Error {
    case unableToDecode(Any.Type, from: Substring)
}

# Using CaptureUUID in a regex expression

This component can be integrated into a larger regex pattern to extract UUID values from a given string. For example, the following regex captures a UUID from a URL path:

let accountID = Reference<UUID>()

let regex = Regex {
    "accounts/"
    CaptureUUID(as: accountID)
    "/"
    Optionally {
        "index.json"
    }
    Anchor.endOfSubject
}

let match = url
    .path(percentEncoded: false)
    .firstMatch(of: regex)
    
if let match {
    // Returns the account id as a UUID
    return match[accountID]
}

By using CaptureUUID, we ensure type-safe access to extracted values while improving the clarity and maintainability of our regex-based parsing logic.

Swift Gems by Natalia Panferova book coverSwift Gems by Natalia Panferova book cover

Level up your Swift skills!$35

100+ tips to take your Swift code to the next level

Swift Gemsby Natalia Panferova

  • Advanced Swift techniques for experienced developers bypassing basic tutorials
  • Curated, actionable tips ready for immediate integration into any Swift project
  • Strategies to improve code quality, structure, and performance across all platforms

Level up your Swift skills!

100+ tips to take your Swift code to the next level

Swift Gems by Natalia Panferova book coverSwift Gems by Natalia Panferova book cover

Swift Gems

by Natalia Panferova

$35