1*af2ec015STomasz Sapeta // Copyright 2022-present 650 Industries. All rights reserved.
2*af2ec015STomasz Sapeta 
3*af2ec015STomasz Sapeta import Security
4*af2ec015STomasz Sapeta import ABI49_0_0ExpoModulesCore
5*af2ec015STomasz Sapeta 
6*af2ec015STomasz Sapeta public class RandomModule: Module {
definitionnull7*af2ec015STomasz Sapeta   public func definition() -> ModuleDefinition {
8*af2ec015STomasz Sapeta     Name("ExpoRandom")
9*af2ec015STomasz Sapeta 
10*af2ec015STomasz Sapeta     AsyncFunction("getRandomBase64StringAsync", getRandomBase64String)
11*af2ec015STomasz Sapeta 
12*af2ec015STomasz Sapeta     Function("getRandomBase64String", getRandomBase64String)
13*af2ec015STomasz Sapeta   }
14*af2ec015STomasz Sapeta }
15*af2ec015STomasz Sapeta 
getRandomBase64Stringnull16*af2ec015STomasz Sapeta private func getRandomBase64String(length: Int) throws -> String {
17*af2ec015STomasz Sapeta   var bytes = [UInt8](repeating: 0, count: length)
18*af2ec015STomasz Sapeta   let status = SecRandomCopyBytes(kSecRandomDefault, length, &bytes)
19*af2ec015STomasz Sapeta 
20*af2ec015STomasz Sapeta   guard status == errSecSuccess else {
21*af2ec015STomasz Sapeta     throw FailedGeneratingRandomBytesException(status)
22*af2ec015STomasz Sapeta   }
23*af2ec015STomasz Sapeta   return Data(bytes).base64EncodedString()
24*af2ec015STomasz Sapeta }
25*af2ec015STomasz Sapeta 
26*af2ec015STomasz Sapeta private class FailedGeneratingRandomBytesException: GenericException<OSStatus> {
27*af2ec015STomasz Sapeta   override var reason: String {
28*af2ec015STomasz Sapeta     "Generating random bytes has failed with OSStatus code: \(param)"
29*af2ec015STomasz Sapeta   }
30*af2ec015STomasz Sapeta }
31