xref: /aosp_15_r20/external/executorch/backends/apple/coreml/runtime/inmemoryfs/inmemory_filesystem_utils.mm (revision 523fa7a60841cd1ecfb9cc4201f1ca8b03ed023a)
1//
2// inmemory_filesystem_utils.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 "inmemory_filesystem_utils.hpp"
9
10#import <iostream>
11#import <sstream>
12#import <unordered_map>
13
14#import <Foundation/Foundation.h>
15
16#import "inmemory_filesystem_metadata.hpp"
17#import "inmemory_filesystem_metadata_keys.hpp"
18#import "json_util.hpp"
19#import "objc_json_serde.h"
20
21namespace executorchcoreml {
22namespace serde {
23namespace json {
24
25using namespace inmemoryfs;
26
27template <>
28struct Converter<Range> {
29    static id to_json(const Range& range) {
30        return @{
31            to_string(RangeKeys::kOffset) : to_json_value(range.offset),
32            to_string(RangeKeys::kSize) : to_json_value(range.size)
33        };
34    }
35
36    static void from_json(id json, Range& range) {
37        NSDictionary<NSString *, id> *json_dict = SAFE_CAST(json, NSDictionary);
38        if (!json_dict) {
39            return;
40        }
41
42        from_json_value(json_dict[to_string(RangeKeys::kOffset)], range.offset);
43        from_json_value(json_dict[to_string(RangeKeys::kSize)], range.size);
44    }
45};
46
47template <>
48struct Converter<InMemoryNodeMetadata> {
49    static id to_json(const InMemoryNodeMetadata& node) {
50        return @{
51            to_string(InMemoryNodeMetadataKeys::kName) : to_json_value(node.name),
52            to_string(InMemoryNodeMetadataKeys::kDataRegion) : to_json_value(node.data_region),
53            to_string(InMemoryNodeMetadataKeys::kChildIndices) : to_json_value(node.child_name_to_indices_map),
54            to_string(InMemoryNodeMetadataKeys::kKind) : to_json_value(node.kind)
55        };
56    }
57
58    static void from_json(id json, InMemoryNodeMetadata& node) {
59        NSDictionary<NSString *, id> *json_dict = SAFE_CAST(json, NSDictionary);
60        if (!json_dict) {
61            return;
62        }
63
64        from_json_value(json_dict[to_string(InMemoryNodeMetadataKeys::kName)], node.name);
65        from_json_value(json_dict[to_string(InMemoryNodeMetadataKeys::kDataRegion)], node.data_region);
66        from_json_value(json_dict[to_string(InMemoryNodeMetadataKeys::kChildIndices)], node.child_name_to_indices_map);
67        from_json_value(json_dict[to_string(InMemoryNodeMetadataKeys::kKind)], node.kind);
68    }
69};
70
71template <>
72struct Converter<InMemoryFileSystemMetadata> {
73    static id to_json(const InMemoryFileSystemMetadata& fs) {
74        return @{
75            to_string(InMemoryFileSystemMetadataKeys::kNodes) : to_json_value(fs.nodes)
76        };
77    }
78
79    static void from_json(id json, InMemoryFileSystemMetadata& fs) {
80        NSDictionary<NSString *, id> *json_dict = SAFE_CAST(json, NSDictionary);
81        if (!json_dict) {
82            return;
83        }
84
85        from_json_value(json_dict[to_string(InMemoryFileSystemMetadataKeys::kNodes)], fs.nodes);
86    }
87};
88
89} // namespace json
90} // namespace serde
91} // namespace executorchcoreml
92
93namespace {
94using namespace inmemoryfs;
95
96std::string serialize_metadata(const InMemoryFileSystemMetadata& metadata) {
97    using namespace executorchcoreml::serde::json;
98    std::string result = to_json_string(Converter<InMemoryFileSystemMetadata>::to_json(metadata));
99    std::reverse(result.begin(), result.end());
100    return result;
101}
102
103bool write_metadata_to_stream(const InMemoryFileSystemMetadata& metadata, std::ostream& stream) {
104    auto content = serialize_metadata(metadata);
105    return stream.write(content.data(), content.length()).good();
106}
107
108size_t write_metadata_to_buffer(const InMemoryFileSystemMetadata& metadata, void *dst) {
109    auto content = serialize_metadata(metadata);
110    std::memcpy(dst, content.data(), content.length());
111    return content.length();
112}
113
114std::optional<InMemoryFileSystemMetadata> read_metadata_from_stream(std::istream& stream) {
115    using namespace executorchcoreml::serde::json;
116    auto json_object = executorchcoreml::json::read_object_from_stream(stream);
117    if (!json_object) {
118        return std::optional<InMemoryFileSystemMetadata>();
119    }
120
121    InMemoryFileSystemMetadata metadata;
122    Converter<InMemoryFileSystemMetadata>::from_json(to_json_object(json_object.value()), metadata);
123    return metadata;
124}
125} // namespace
126
127namespace inmemoryfs {
128bool serialize(const InMemoryFileSystem& file_system,
129               const std::vector<std::string>& canonical_path,
130               size_t alignment,
131               std::ostream& ostream,
132               std::error_code& ec) noexcept {
133    InMemoryFileSystem::MetadataWriter metadata_writer = [](const InMemoryFileSystemMetadata& fs_metadata,
134                                                            std::ostream& stream) {
135        write_metadata_to_stream(fs_metadata, stream);
136        return true;
137    };
138
139    return file_system.serialize(canonical_path, alignment, metadata_writer, ostream, ec);
140}
141
142bool serialize(const InMemoryFileSystem& file_system,
143               const std::vector<std::string>& canonical_path,
144               size_t alignment,
145               void *dst,
146               std::error_code& ec) noexcept {
147    InMemoryFileSystem::MetadataWriterInMemory metadata_writer = [](const InMemoryFileSystemMetadata& fs_metadata,
148                                                                    void *metadata_dst) {
149        return ::write_metadata_to_buffer(fs_metadata, metadata_dst);
150    };
151
152    return file_system.serialize(canonical_path, alignment, metadata_writer, dst, ec);
153}
154
155size_t get_buffer_size_for_serialization(const InMemoryFileSystem& file_system,
156                                         const std::vector<std::string>& canonical_path,
157                                         size_t alignment) noexcept {
158    InMemoryFileSystem::MetadataWriter metadata_writer = [](const InMemoryFileSystemMetadata& fs_metadata,
159                                                            std::ostream& stream) {
160        return ::write_metadata_to_stream(fs_metadata, stream);
161    };
162
163    return file_system.get_buffer_size_for_serialization(canonical_path, alignment, metadata_writer);
164}
165
166std::unique_ptr<InMemoryFileSystem> make_from_buffer(const std::shared_ptr<MemoryBuffer>& buffer) noexcept {
167    InMemoryFileSystem::MetadataReader metadata_reader = [](std::istream& stream) {
168        return ::read_metadata_from_stream(stream);
169    };
170
171    return InMemoryFileSystem::make_from_buffer(buffer, metadata_reader);
172}
173} // namespace inmemoryfs
174