Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Simple base encoding and decoding in Swift.
import Foundation
enum StringSearchError: Swift.Error {
case didNotFind(Character)
}
extension String {
fileprivate static let DefaultDigits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
fileprivate static let DefaultEmoji = "🤖❤️☠️🤓🦁🍆🧀😎🙄🤢🧠🧶🙈🙉🙊🔥🥕⚽️💊🎶🧶"
func character<T>(at index: T) -> String where T: FixedWidthInteger {
return String(self[self.index(self.startIndex, offsetBy: Int(index))])
}
func position(of char: Character) throws -> Int {
guard let idx = self.firstIndex(of: char) else { throw StringSearchError.didNotFind(char) }
return Int( self.distance(from: self.startIndex, to: idx) )
}
}
enum BaseError: Swift.Error {
case outOfRange
}
extension FixedWidthInteger where Self.Magnitude : UnsignedInteger {
func base36() -> String { return try! self.base(36) }
func base62() -> String { return try! self.base(62) }
func baseEmoji() -> String { return try! self.base(String.DefaultEmoji.count, using: String.DefaultEmoji) }
func base<T>(_ redux: T, using digits: String = .DefaultDigits) throws -> String where T: FixedWidthInteger {
guard 1...digits.count ~= Int(redux) else { throw BaseError.outOfRange }
var result = ""
var value = Int(self)
let rdx = Int(redux)
repeat {
result = digits.character(at: value % rdx) + result
value /= rdx
} while (value > 0)
return result
}
}
extension String {
func decode36() -> Int { return try! self.decode(36) }
func decode62() -> Int { return try! self.decode(62) }
func decode(_ redux: Int, using digits: String = .DefaultDigits) throws -> Int {
let decoded = try self.reduce(0) {
let value = Double( try digits.position(of: $1) )
return Int( Double($0) * Double(redux) + value )
}
return decoded
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.