xref: /aosp_15_r20/external/executorch/backends/apple/coreml/runtime/sdk/model_package_info.mm (revision 523fa7a60841cd1ecfb9cc4201f1ca8b03ed023a)
1//
2// model_package_info.mm
3//
4// Copyright © 2024 Apple Inc. All rights reserved.
5//
6// Please refer to the license found in the LICENSE file in the root directory of the source tree.
7
8#import "model_package_info.h"
9
10#import "ETCoreMLLogging.h"
11#import "objc_json_serde.h"
12#import "serde_json.h"
13
14namespace  {
15struct ModelPackageInfoKeys {
16    struct Item {
17        constexpr static std::string_view kAuthorKey = "author";
18        constexpr static std::string_view kDescriptionKey = "description";
19        constexpr static std::string_view kNameKey = "name";
20        constexpr static std::string_view kPathKey = "path";
21    };
22
23    constexpr static std::string_view kItemInfoEntriesKey = "itemInfoEntries";
24    constexpr static std::string_view kRootModelIdentifierKey = "rootModelIdentifier";
25};
26}
27
28namespace executorchcoreml {
29namespace serde {
30namespace json {
31template <>
32struct Converter<ModelPackageInfo::Item> {
33    static void from_json(id json, ModelPackageInfo::Item& item) {
34        NSDictionary<NSString *, id> *json_dict = SAFE_CAST(json, NSDictionary);
35        if (!json_dict) {
36            return;
37        }
38
39        from_json_value(json_dict[to_string(ModelPackageInfoKeys::Item::kAuthorKey)], item.author);
40        from_json_value(json_dict[to_string(ModelPackageInfoKeys::Item::kDescriptionKey)], item.description);
41        from_json_value(json_dict[to_string(ModelPackageInfoKeys::Item::kNameKey)], item.name);
42        from_json_value(json_dict[to_string(ModelPackageInfoKeys::Item::kPathKey)], item.path);
43    }
44};
45
46template <>
47struct Converter<ModelPackageInfo> {
48    static void from_json(id json, ModelPackageInfo& package_info) {
49        NSDictionary<NSString *, id> *json_dict = SAFE_CAST(json, NSDictionary);
50        if (!json_dict) {
51            return;
52        }
53
54        from_json_value(json_dict[to_string(ModelPackageInfoKeys::kRootModelIdentifierKey)], package_info.root_model_identifier);
55        from_json_value(json_dict[to_string(ModelPackageInfoKeys::kItemInfoEntriesKey)], package_info.items);
56    }
57};
58}
59}
60}
61
62namespace executorchcoreml {
63std::optional<ModelPackageInfo> ModelPackageInfo::make(NSURL* model_package_url,
64                                                       NSFileManager* fm,
65                                                       NSError * __autoreleasing *error) noexcept {
66    NSURL *manifest_url = [model_package_url URLByAppendingPathComponent:@"manifest.json"].URLByStandardizingPath;
67    BOOL is_directory = NO;
68    if (![fm fileExistsAtPath:manifest_url.path isDirectory:&is_directory] || is_directory) {
69        ETCoreMLLogErrorAndSetNSError(error, 0, "%@ is broken, manifest doesn't exist.", model_package_url.lastPathComponent);
70        return std::nullopt;
71    }
72
73    NSData *data = [NSData dataWithContentsOfURL:manifest_url options:NSDataReadingMappedIfSafe error:error];
74    if (!data) {
75        return std::nullopt;
76    }
77
78    id json_dictionary = [NSJSONSerialization JSONObjectWithData:data options:(NSJSONReadingOptions)0 error:error];
79    if (!json_dictionary) {
80        return std::nullopt;
81    }
82
83    ModelPackageInfo info;
84    serde::json::from_json_value(json_dictionary, info);
85    return info;
86}
87}
88