// // Copyright 2020 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only // import Foundation public extension UInt32 { /// Convert the given millisecond time to seconds. /// /// - Returns /// The millisecond time in seconds, or `nil` if the resulting value would /// overflow `UInt32`. static func msToSecs(_ millis: UInt64) -> UInt32? { return UInt32(exactly: millis / UInt64.secondInMs) } } // MARK: - Safe Casts // Casts that can't fail and will complain if they become unsafe or redundant. extension UInt64 { public init(safeCast source: UInt) { self = UInt64(source) } public init(safeCast source: UInt8) { self = UInt64(source) } public init(safeCast source: UInt16) { self = UInt64(source) } public init(safeCast source: UInt32) { self = UInt64(source) } // It's safe to cast a UInt64 from a UInt64, but we shouldn't. } extension Int64 { public init(safeCast source: UInt8) { self = Int64(source) } public init(safeCast source: UInt16) { self = Int64(source) } public init(safeCast source: UInt32) { self = Int64(source) } } // MARK: - public extension Int { var abbreviatedString: String { let value: Double let suffix: String switch abs(self) { case 1_000..<1_000_000: value = Double(self) / 1_000 suffix = "K" case 1_000_000..<1_000_000_000: value = Double(self) / 1_000_000 suffix = "M" case 1_000_000_000...Int.max: value = Double(self) / 1_000_000_000 suffix = "B" default: value = Double(self) suffix = "" } let numberFormatter = NumberFormatter() numberFormatter.maximumFractionDigits = 1 numberFormatter.minimumFractionDigits = 0 numberFormatter.negativeSuffix = suffix numberFormatter.positiveSuffix = suffix guard let result = numberFormatter.string(for: value) else { owsFailDebug("unexpectedly failed to format number") return "\(self)" } return result } }