Files
purchases-ios/RevenueCatUI/Checkpoints/CheckpointIdentifierValidator.swift
Rick 0ff3e97d0d feat(Checkpoints): validate checkpoint identifiers (#7441)
* Validate checkpoint identifiers

* Address checkpoint identifier review feedback

* Fix checkpoint validation review feedback
2026-08-19 16:19:50 +02:00

52 lines
1.7 KiB
Swift

//
// Copyright RevenueCat Inc. All Rights Reserved.
//
// Licensed under the MIT License (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://opensource.org/licenses/MIT
//
// CheckpointIdentifierValidator.swift
//
// Created by Rick van der Linden.
//
enum CheckpointIdentifierValidator {
static let maxLength = 255
static func isValid(_ identifier: String) -> Bool {
let characters = identifier.utf8
guard
(1...Self.maxLength).contains(characters.count),
let firstCharacter = characters.first,
Self.isASCIILetter(firstCharacter)
else {
return false
}
return characters.dropFirst().allSatisfy(Self.isAllowedCharacter)
}
static func invalidIdentifierLogMessage(_ identifier: String) -> String {
return "Dropping invalid checkpoint identifier '\(identifier)'. Identifiers must start with a letter, " +
"contain only ASCII letters, numbers, underscores, and hyphens, and be no more than " +
"\(Self.maxLength) characters."
}
private static func isAllowedCharacter(_ character: UInt8) -> Bool {
return Self.isASCIILetter(character)
|| (UInt8(ascii: "0")...UInt8(ascii: "9")).contains(character)
|| character == UInt8(ascii: "_")
|| character == UInt8(ascii: "-")
}
private static func isASCIILetter(_ character: UInt8) -> Bool {
return (UInt8(ascii: "a")...UInt8(ascii: "z")).contains(character)
|| (UInt8(ascii: "A")...UInt8(ascii: "Z")).contains(character)
}
}