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