• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // inmemory_filesystem_utils.hpp
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 #include "inmemory_filesystem_utils.hpp"
9 
10 #include <iostream>
11 #include <sstream>
12 
13 #include <nlohmann/json.hpp>
14 
15 #include "inmemory_filesystem_metadata.hpp"
16 #include "inmemory_filesystem_metadata_keys.hpp"
17 #include "json_util.hpp"
18 
19 namespace inmemoryfs {
20 
21 using json = nlohmann::json;
22 
to_json(json & j,const Range & range)23 void to_json(json& j, const Range& range) {
24     j = json { { RangeKeys::kOffset, range.offset }, { RangeKeys::kSize, range.size } };
25 }
26 
from_json(const json & j,Range & range)27 void from_json(const json& j, Range& range) {
28     if (j.contains(RangeKeys::kOffset)) {
29         j.at(RangeKeys::kOffset).get_to(range.offset);
30     }
31     if (j.contains(RangeKeys::kSize)) {
32         j.at(RangeKeys::kSize).get_to(range.size);
33     }
34 }
35 
to_json(json & j,const InMemoryNodeMetadata & node)36 void to_json(json& j, const InMemoryNodeMetadata& node) {
37     j = json { { InMemoryNodeMetadataKeys::kName, node.name },
38                { InMemoryNodeMetadataKeys::kDataRegion, node.data_region },
39                { InMemoryNodeMetadataKeys::kChildIndices, node.child_name_to_indices_map },
40                { InMemoryNodeMetadataKeys::kKind, static_cast<int>(node.kind) } };
41 }
42 
from_json(const json & j,InMemoryNodeMetadata & node)43 void from_json(const json& j, InMemoryNodeMetadata& node) {
44     if (j.contains(InMemoryNodeMetadataKeys::kName)) {
45         j.at(InMemoryNodeMetadataKeys::kName).get_to(node.name);
46     }
47     if (j.contains(InMemoryNodeMetadataKeys::kDataRegion)) {
48         j.at(InMemoryNodeMetadataKeys::kDataRegion).get_to(node.data_region);
49     }
50     if (j.contains(InMemoryNodeMetadataKeys::kChildIndices)) {
51         j.at(InMemoryNodeMetadataKeys::kChildIndices).get_to(node.child_name_to_indices_map);
52     }
53     if (j.contains(InMemoryNodeMetadataKeys::kKind)) {
54         j.at(InMemoryNodeMetadataKeys::kKind).get_to(node.kind);
55     }
56 }
57 
to_json(json & j,const InMemoryFileSystemMetadata & fs)58 void to_json(json& j, const InMemoryFileSystemMetadata& fs) {
59     j = json { { InMemoryFileSystemMetadataKeys::kNodes, fs.nodes } };
60 }
61 
from_json(const json & j,InMemoryFileSystemMetadata & fs)62 void from_json(const json& j, InMemoryFileSystemMetadata& fs) {
63     if (j.contains(InMemoryFileSystemMetadataKeys::kNodes)) {
64         j.at(InMemoryFileSystemMetadataKeys::kNodes).get_to(fs.nodes);
65     }
66 }
67 
serialize_metadata(const InMemoryFileSystemMetadata & fs_metadata)68 static std::string serialize_metadata(const InMemoryFileSystemMetadata& fs_metadata) {
69     std::stringstream ss;
70     json value;
71     to_json(value, fs_metadata);
72     ss << value;
73     std::string result = ss.str();
74     // reverse it for writing
75     std::reverse(result.begin(), result.end());
76     return result;
77 }
78 
write_metadata_to_stream(const InMemoryFileSystemMetadata & fs_metadata,std::ostream & stream)79 static bool write_metadata_to_stream(const InMemoryFileSystemMetadata& fs_metadata, std::ostream& stream) {
80     auto content = serialize_metadata(fs_metadata);
81     stream << content;
82     return stream.good();
83 }
84 
write_metadata_to_buffer(const InMemoryFileSystemMetadata & fs_metadata,void * dst)85 static size_t write_metadata_to_buffer(const InMemoryFileSystemMetadata& fs_metadata, void* dst) {
86     auto content = serialize_metadata(fs_metadata);
87     std::memcpy(dst, content.data(), content.length());
88     return content.length();
89 }
90 
serialize(const InMemoryFileSystem & file_system,const std::vector<std::string> & canonical_path,size_t alignment,std::ostream & ostream,std::error_code & ec)91 bool serialize(const InMemoryFileSystem& file_system,
92                const std::vector<std::string>& canonical_path,
93                size_t alignment,
94                std::ostream& ostream,
95                std::error_code& ec) noexcept {
96     InMemoryFileSystem::MetadataWriter metadata_writer = [](const InMemoryFileSystemMetadata& fs_metadata,
97                                                             std::ostream& stream) {
98         write_metadata_to_stream(fs_metadata, stream);
99         return true;
100     };
101 
102     return file_system.serialize(canonical_path, alignment, metadata_writer, ostream, ec);
103 }
104 
serialize(const InMemoryFileSystem & file_system,const std::vector<std::string> & canonical_path,size_t alignment,void * dst,std::error_code & ec)105 bool serialize(const InMemoryFileSystem& file_system,
106                const std::vector<std::string>& canonical_path,
107                size_t alignment,
108                void* dst,
109                std::error_code& ec) noexcept {
110     InMemoryFileSystem::MetadataWriterInMemory metadata_writer = [](const InMemoryFileSystemMetadata& fs_metadata,
111                                                                     void* metadata_dst) {
112         return write_metadata_to_buffer(fs_metadata, metadata_dst);
113     };
114 
115     return file_system.serialize(canonical_path, alignment, metadata_writer, dst, ec);
116 }
117 
get_buffer_size_for_serialization(const InMemoryFileSystem & file_system,const std::vector<std::string> & canonical_path,size_t alignment)118 size_t get_buffer_size_for_serialization(const InMemoryFileSystem& file_system,
119                                          const std::vector<std::string>& canonical_path,
120                                          size_t alignment) noexcept {
121     InMemoryFileSystem::MetadataWriter metadata_writer = [](const InMemoryFileSystemMetadata& fs_metadata,
122                                                             std::ostream& stream) {
123         return write_metadata_to_stream(fs_metadata, stream);
124     };
125 
126     return file_system.get_buffer_size_for_serialization(canonical_path, alignment, metadata_writer);
127 }
128 
make_from_buffer(const std::shared_ptr<MemoryBuffer> & buffer)129 std::unique_ptr<InMemoryFileSystem> make_from_buffer(const std::shared_ptr<MemoryBuffer>& buffer) noexcept {
130     InMemoryFileSystem::MetadataReader metadata_reader = [](std::istream& stream) {
131         auto json_object = executorchcoreml::json::read_object_from_stream(stream);
132         if (!json_object) {
133             return std::optional<InMemoryFileSystemMetadata>();
134         }
135 
136         json metadata_json = json::parse(json_object.value());
137         InMemoryFileSystemMetadata metadata;
138         from_json(metadata_json, metadata);
139         return std::optional<InMemoryFileSystemMetadata>(std::move(metadata));
140     };
141 
142     return InMemoryFileSystem::make_from_buffer(buffer, metadata_reader);
143 }
144 } // namespace inmemoryfs
145