mirror of
https://github.com/RevenueCat/purchases-ios
synced 2026-11-11 22:55:55 +05:45
81 lines
2.1 KiB
Swift
81 lines
2.1 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
|
|
//
|
|
// UInt8+Extensions.swift
|
|
//
|
|
// Created by Andrés Boedo on 7/24/20.
|
|
//
|
|
|
|
import Foundation
|
|
|
|
// swiftlint:disable identifier_name
|
|
enum BitShiftError: Error {
|
|
|
|
case invalidIndex(_ index: UInt8)
|
|
case rangeFlipped(from: UInt8, to: UInt8)
|
|
case rangeLargerThanByte
|
|
case unhandledRange
|
|
|
|
}
|
|
|
|
extension BitShiftError: CustomStringConvertible {
|
|
|
|
var description: String {
|
|
switch self {
|
|
case .invalidIndex(let index):
|
|
return "invalid index: \(index)"
|
|
case .rangeFlipped(let from, let to):
|
|
return "from: \(from) can't be greater than to: \(to)"
|
|
case .rangeLargerThanByte:
|
|
return "range must be between 1 and 8"
|
|
case .unhandledRange:
|
|
return "unhandled range"
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
extension UInt8 {
|
|
|
|
/// - Throws: `BitShiftError`
|
|
func bitAtIndex(_ index: UInt8) throws -> UInt8 {
|
|
guard index <= 7 else { throw BitShiftError.invalidIndex(index) }
|
|
let shifted = self >> (7 - index)
|
|
return shifted & 0b1
|
|
}
|
|
|
|
/// - Throws: `BitShiftError`
|
|
func valueInRange(from: UInt8, to: UInt8) throws -> UInt8 {
|
|
guard to <= 7 else { throw BitShiftError.invalidIndex(to) }
|
|
guard from <= to else { throw BitShiftError.rangeFlipped(from: from, to: to) }
|
|
|
|
let range: UInt8 = to - from + 1
|
|
let shifted = self >> (7 - to)
|
|
let mask = try self.maskForRange(range)
|
|
return shifted & mask
|
|
}
|
|
|
|
}
|
|
|
|
private extension UInt8 {
|
|
|
|
/// - Returns: 2^range - 1
|
|
/// - Throws: `BitShiftError`
|
|
func maskForRange(_ range: UInt8) throws -> UInt8 {
|
|
guard 0 <= range && range <= 8 else { throw BitShiftError.rangeLargerThanByte }
|
|
|
|
/// Returns 2 ^ range - 1 (a number with range 1s)
|
|
/// Example:
|
|
/// - range 1: 0b1
|
|
/// - range 2: 0b11
|
|
return 0b11111111 >> (8 - range)
|
|
}
|
|
|
|
}
|