-
Notifications
You must be signed in to change notification settings - Fork 7
/
NanoID.swift
125 lines (103 loc) · 3.66 KB
/
NanoID.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
//
// NanoID.swift
//
// Created by Anton Lovchikov on 05/07/2018.
// Copyright © 2018 Anton Lovchikov. All rights reserved.
//
import Foundation
/// USAGE
///
/// Nano ID with default alphabet (0-9a-zA-Z_~) and length (21 chars)
/// let id = NanoID.new()
///
/// Nano ID with default alphabet and given length
/// let id = NanoID.new(12)
///
/// Nano ID with given alphabet and length
/// let id = NanoID.new(alphabet: .uppercasedLatinLetters, size: 15)
///
/// Nano ID with preset custom parameters
/// let nanoID = NanoID(alphabet: .lowercasedLatinLetters,.numbers, size:10)
/// let idFirst = nanoID.new()
/// let idSecond = nanoID.new()
class NanoID {
// Shared Parameters
private var size: Int
private var alphabet: String
/// Inits an instance with Shared Parameters
init(alphabet: NanoIDAlphabet..., size: Int) {
self.size = size
self.alphabet = NanoIDHelper.parse(alphabet)
}
/// Generates a Nano ID using Shared Parameters
func new() -> String {
return NanoIDHelper.generate(from: alphabet, of: size)
}
// Default Parameters
private static let defaultSize = 21
private static let defaultAphabet = NanoIDAlphabet.urlSafe.toString()
/// Generates a Nano ID using Default Parameters
static func new() -> String {
return NanoIDHelper.generate(from: defaultAphabet, of: defaultSize)
}
/// Generates a Nano ID using given occasional parameters
static func new(alphabet: NanoIDAlphabet..., size: Int) -> String {
let charactersString = NanoIDHelper.parse(alphabet)
return NanoIDHelper.generate(from: charactersString, of: size)
}
/// Generates a Nano ID using Default Alphabet and given size
static func new(_ size: Int) -> String {
return NanoIDHelper.generate(from: NanoID.defaultAphabet, of: size)
}
}
fileprivate class NanoIDHelper {
/// Parses input alphabets into a string
static func parse(_ alphabets: [NanoIDAlphabet]) -> String {
var stringCharacters = ""
for alphabet in alphabets {
stringCharacters.append(alphabet.toString())
}
return stringCharacters
}
/// Generates a Nano ID using given parameters
static func generate(from alphabet: String, of length: Int) -> String {
var nanoID = ""
for _ in 0..<length {
let randomCharacter = NanoIDHelper.randomCharacter(from: alphabet)
nanoID.append(randomCharacter)
}
return nanoID
}
/// Returns a random character from a given string
static func randomCharacter(from string: String) -> Character {
let randomNum = Int(arc4random_uniform(UInt32(string.count)))
let randomIndex = string.index(string.startIndex, offsetBy: randomNum)
return string[randomIndex]
}
}
enum NanoIDAlphabet {
case urlSafe
case uppercasedLatinLetters
case lowercasedLatinLetters
case numbers
func toString() -> String {
switch self {
case .uppercasedLatinLetters, .lowercasedLatinLetters, .numbers:
return self.chars()
case .urlSafe:
return ("\(NanoIDAlphabet.uppercasedLatinLetters.chars())\(NanoIDAlphabet.lowercasedLatinLetters.chars())\(NanoIDAlphabet.numbers.chars())~_")
}
}
private func chars() -> String {
switch self {
case .uppercasedLatinLetters:
return "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
case .lowercasedLatinLetters:
return "abcdefghijklmnopqrstuvwxyz"
case .numbers:
return "1234567890"
default:
return ""
}
}
}