2024-06-19 15:06:39 +00:00
|
|
|
struct JID: Hashable, CustomStringConvertible, Codable, Equatable {
|
|
|
|
let localPart: String
|
|
|
|
let domainPart: String
|
|
|
|
let resourcePart: String?
|
|
|
|
|
|
|
|
init(_ jid: String) throws {
|
|
|
|
let parts = try JID.parse(jid)
|
|
|
|
localPart = parts.0
|
|
|
|
domainPart = parts.1
|
|
|
|
resourcePart = parts.2
|
|
|
|
}
|
|
|
|
|
2024-12-16 12:51:12 +00:00
|
|
|
var full: String {
|
2024-06-19 15:06:39 +00:00
|
|
|
var str = "\(localPart)@\(domainPart)"
|
|
|
|
if let resource = resourcePart {
|
|
|
|
str += "/\(resource)"
|
|
|
|
}
|
|
|
|
return str
|
|
|
|
}
|
|
|
|
|
2024-12-16 12:51:12 +00:00
|
|
|
var description: String {
|
|
|
|
full
|
|
|
|
}
|
|
|
|
|
2024-06-19 15:06:39 +00:00
|
|
|
var hash: Int {
|
|
|
|
if let resourcePart {
|
|
|
|
return "\(localPart)@\(domainPart)/\(resourcePart)".hashValue
|
|
|
|
} else {
|
|
|
|
return "\(localPart)@\(domainPart)".hashValue
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
var bare: String {
|
|
|
|
"\(localPart)@\(domainPart)"
|
|
|
|
}
|
|
|
|
|
|
|
|
var bareHash: Int {
|
|
|
|
"\(localPart)@\(domainPart)".hashValue
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
extension JID {
|
|
|
|
var uStr: String {
|
|
|
|
"\(bareHash)".replacingOccurrences(of: "-", with: "_")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
enum JIDError: String, Error {
|
|
|
|
case wrongJid = "Can't parse or operate with JID"
|
|
|
|
}
|
|
|
|
|
|
|
|
private extension JID {
|
|
|
|
// swiftlint:disable:next large_tuple
|
|
|
|
static func parse(_ str: String) throws -> (String, String, String?) {
|
|
|
|
let parts = str.components(separatedBy: "@")
|
|
|
|
guard parts.count == 2 else {
|
|
|
|
throw JIDError.wrongJid
|
|
|
|
}
|
|
|
|
let secondParts = parts[1].components(separatedBy: "/")
|
|
|
|
guard !secondParts.isEmpty else {
|
|
|
|
throw JIDError.wrongJid
|
|
|
|
}
|
|
|
|
if secondParts.count > 1 {
|
|
|
|
return (parts[0], secondParts[0], secondParts[1])
|
|
|
|
} else {
|
|
|
|
return (parts[0], secondParts[0], nil)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|