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