-
Notifications
You must be signed in to change notification settings - Fork 47
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[IMA-10467] Add convert command to export a JSON representation of Ap…
…p Thinning Size Reports (#73) * Add converter * add converter * update parser * added documentation, update code * [IMA-10467] Add method documentation. * [IMA-10467] Update convert overview text. * [IMA-10467] Fix error with setting the output name based on the report path. Also modified usage text. Co-authored-by: Vido Shaweddy <vido.shaweddy@chargepoint.com>
- Loading branch information
1 parent
40f3848
commit 3622c47
Showing
24 changed files
with
1,464 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
// | ||
// FileController.swift | ||
// AppThinningConverter | ||
// | ||
// Created by Vido Shaweddy on 3/25/21. | ||
// | ||
|
||
import Foundation | ||
|
||
public class FileController { | ||
// load file with given url | ||
public static func loadFileContents(url: String) -> String? { | ||
var res: String? | ||
let url = URL(fileURLWithPath: url) | ||
if let fileContents = try? String(contentsOf: url) { | ||
res = fileContents | ||
} | ||
|
||
return res | ||
} | ||
|
||
// write file to the url directory for the given data | ||
public static func writeFile(data: String, url: String, outputName: String = "report", format: String = "json") { | ||
let url = URL(fileURLWithPath: url) | ||
let location = url.appendingPathComponent("\(outputName).\(format)") | ||
do { | ||
try data.write(to: location, atomically: true, encoding: String.Encoding.utf8) | ||
} catch { | ||
print(error.localizedDescription) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,172 @@ | ||
// | ||
// Units.swift | ||
// AppThinningConverter | ||
// | ||
// Created by Vido Shaweddy on 3/30/21. | ||
// | ||
|
||
import Foundation | ||
|
||
public struct MemorySize { | ||
enum Unit: String, Codable { | ||
case bytes = "B" | ||
case kilobytes = "KB" | ||
case megabytes = "MB" | ||
case gigabytes = "GB" | ||
} | ||
|
||
public var bytes: Double { | ||
get { | ||
return Double(kilobytes) * 1_024 | ||
} | ||
} | ||
|
||
public var kilobytes: Double | ||
|
||
public var megabytes: Double { | ||
return kilobytes / 1_024 | ||
} | ||
|
||
public var gigabytes: Double { | ||
return megabytes / 1_024 | ||
} | ||
|
||
public init(bytes: Int64) { | ||
self.kilobytes = Double(bytes) / 1_024 | ||
} | ||
|
||
public init(bytes: Double) { | ||
self.kilobytes = bytes / 1_024 | ||
} | ||
|
||
public init(kilobytes: Double) { | ||
self.kilobytes = kilobytes | ||
} | ||
|
||
public init(megabytes: Double) { | ||
self.kilobytes = megabytes * 1_024 | ||
} | ||
|
||
public init(gigabytes: Double) { | ||
self.kilobytes = gigabytes * 1_024 * 1_024 | ||
} | ||
|
||
public init?(text: String) { | ||
self.kilobytes = 0 | ||
if let value = parseFrom(text: text) { | ||
self.kilobytes = value.kilobytes | ||
} else { | ||
return nil | ||
} | ||
} | ||
} | ||
|
||
extension MemorySize { | ||
var displayString: String { | ||
switch bytes { | ||
case 0..<pow(1_024, 1): | ||
return "\(bytes) bytes" | ||
case pow(1_024, 1)..<pow(1_024, 2): | ||
return "\(String(format: "%.2f", kilobytes)) KB" | ||
case pow(1_024, 2)..<pow(1_024, 3): | ||
return "\(String(format: "%.2f", megabytes)) MB" | ||
case pow(1_024, 3)...: | ||
return "\(String(format: "%.2f", gigabytes)) GB" | ||
default: | ||
return "\(bytes) bytes" | ||
} | ||
} | ||
|
||
// parse memory size from text | ||
func parseFrom(text: String) -> MemorySize? { | ||
let textToMemoryUnit: [String: MemorySize.Unit] = | ||
[ | ||
"b": .bytes, | ||
"byte": .bytes, | ||
"bytes": .bytes, | ||
"kb": .kilobytes, | ||
"kilobyte": .kilobytes, | ||
"kilobytes": .kilobytes, | ||
"mb": .megabytes, | ||
"megabyte": .megabytes, | ||
"megabytes": .megabytes, | ||
"gb": .gigabytes, | ||
"gigabyte": .gigabytes, | ||
"gigabytes": .gigabytes, | ||
] | ||
|
||
let unit = textToMemoryUnit[parseUnits(text: text)] ?? .megabytes | ||
guard let size = parseSize(text: text) else { | ||
return nil | ||
} | ||
|
||
switch unit { | ||
case .bytes: | ||
return MemorySize(bytes: size) | ||
case .kilobytes: | ||
return MemorySize(kilobytes: size) | ||
case .megabytes: | ||
return MemorySize(megabytes: size) | ||
case .gigabytes: | ||
return MemorySize(gigabytes: size) | ||
} | ||
} | ||
|
||
// parse the unit from text | ||
func parseUnits(text: String) -> String { | ||
// when it's 0 kb the report text is going to be "zero kb" so we need to handle it manually | ||
if text.lowercased() == Self.zeroSize { return "kb" } | ||
return parseUnits(text: Array(text)) | ||
} | ||
|
||
// parse the unit from text (array of character) | ||
func parseUnits(text: [Character]) -> String { | ||
var unitString = "" | ||
|
||
for character in text where character.isLetter { | ||
if character != "." && character != "," { | ||
unitString.append(character.lowercased()) | ||
} | ||
} | ||
|
||
return unitString | ||
} | ||
|
||
// parse the memory size from text | ||
func parseSize(text: String) -> Double? { | ||
// when it's 0 kb the report text is going to be "zero kb" so we need to handle it manually | ||
if text.lowercased() == Self.zeroSize { return 0 } | ||
return parseSize(text: Array(text)) | ||
} | ||
|
||
// parse the memory size from text (array of character) | ||
func parseSize(text: [Character]) -> Double? { | ||
var sizeString = "" | ||
|
||
for character in text { | ||
if character.isNumber || character == "." || character == "," { | ||
sizeString.append(character) | ||
} | ||
} | ||
|
||
return Double(sizeString) | ||
} | ||
} | ||
|
||
extension MemorySize: Comparable { | ||
public static func < (lhs: MemorySize, rhs: MemorySize) -> Bool { | ||
return lhs.kilobytes < rhs.kilobytes | ||
} | ||
|
||
public static func > (lhs: MemorySize, rhs: MemorySize) -> Bool { | ||
return lhs.kilobytes > rhs.kilobytes | ||
} | ||
|
||
public static func == (lhs: MemorySize, rhs: MemorySize) -> Bool { | ||
return lhs.kilobytes == rhs.kilobytes | ||
} | ||
} | ||
|
||
public extension MemorySize { | ||
static let zeroSize = "zero kb" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
// | ||
// ResultFactory.swift | ||
// AppThinningConverter | ||
// | ||
// Created by Vido Shaweddy on 3/29/21. | ||
// | ||
|
||
import Foundation | ||
|
||
final class ResultFactory { | ||
/// A factory class for parsing text | ||
/// | ||
/// Use this method to get the result for each parser. | ||
/// - Warning: Returns optional any type. if the parser is unable to find the data it will returns nil. | ||
/// - Parameter: | ||
/// - text: the text you want to parse | ||
/// - modelType: the | ||
/// - Returns: The result for each parser in any data type. | ||
func parse(from text: String, using parser: VariantModel.ParsingKeys) -> Any? { | ||
let result: Any? | ||
switch parser { | ||
case .variant: | ||
result = VariantParser(text: text).result | ||
case .supportedVariantDescriptors: | ||
result = VariantDescriptorParser(text: text).result | ||
case .appOnDemandResourcesSize: | ||
result = AppSizeParser(text: text).result | ||
case .appSize: | ||
result = AppSizeParser(text: text).result | ||
case .onDemandResourcesSize: | ||
result = AppSizeParser(text: text).result | ||
} | ||
return result | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
// | ||
// AppOnDemandModel.swift | ||
// AppThinningConverter | ||
// | ||
// Created by Vido Shaweddy on 3/25/21. | ||
// | ||
|
||
import Foundation | ||
|
||
protocol ModelSize: Codable, Equatable { | ||
var compressed: SizeModel { get set } | ||
var uncompressed: SizeModel { get set } | ||
} | ||
|
||
class AppSizeModel: ModelSize { | ||
var compressed: SizeModel | ||
var uncompressed: SizeModel | ||
|
||
enum CodingKeys: String, CodingKey, CaseIterable { | ||
case compressed, uncompressed | ||
} | ||
|
||
// MARK: - Constructor | ||
|
||
init(compressed: SizeModel = SizeModel.placeholder(), uncompressed: SizeModel = SizeModel.placeholder()) { | ||
self.compressed = compressed | ||
self.uncompressed = uncompressed | ||
} | ||
|
||
static func == (lhs: AppSizeModel, rhs: AppSizeModel) -> Bool { | ||
return lhs.compressed == rhs.compressed && lhs.uncompressed == rhs.uncompressed | ||
} | ||
} | ||
|
||
struct SizeModel: Codable, Equatable { | ||
let rawValue: String | ||
let value: Double | ||
let unit: MemorySize.Unit | ||
} | ||
|
||
private extension SizeModel { | ||
static func placeholder() -> SizeModel { | ||
return SizeModel(rawValue: "Unknown", value: 0, unit: .bytes) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
// | ||
// DeviceModel.swift | ||
// AppThinningConverter | ||
// | ||
// Created by Vido Shaweddy on 3/25/21. | ||
// | ||
|
||
import Foundation | ||
|
||
struct DeviceModel: Codable, Equatable { | ||
let device: String | ||
let osVersion: String | ||
|
||
enum ParsingKeys: String, CaseIterable { | ||
case device | ||
case osVersion = "os-version" | ||
} | ||
|
||
enum CodingKeys: String, CodingKey { | ||
case device, osVersion | ||
} | ||
} |
Oops, something went wrong.