/******************************************************************************* * * MIT License * * Copyright (C) 2022-2025 Advanced Micro Devices, Inc. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * *******************************************************************************/ #pragma once #include #include #include #include #include #include namespace TensileLite { namespace Serialization { template struct is_Convertible { static const bool value = false; }; template <> struct is_Convertible { static const bool value = true; }; template <> struct is_Convertible { static const bool value = true; }; template <> struct is_Convertible { static const bool value = true; }; template <> struct is_Convertible { static const bool value = true; }; template <> struct is_Convertible { static const bool value = true; }; template <> struct is_Convertible { static const bool value = true; }; template <> struct is_Convertible { static const bool value = true; }; template <> struct is_Convertible { static const bool value = true; }; template <> struct is_Convertible { static const bool value = true; }; TENSILELITEHOST_EXPORT void objectToMap(const msgpack::object& object, std::unordered_map& map); struct MessagePackInput { msgpack::object object; std::vector error; std::unordered_map objectMap; std::unordered_set usedKeys; int enumFound = 0; void* context = nullptr; MessagePackInput(msgpack::object object, void* context = nullptr) : object(object) , context(context) { } MessagePackInput createSubRef(msgpack::object otherObject) { return MessagePackInput(otherObject, context); } void addError(std::string const& msg) { error.push_back(msg); } template void mapRequired(const char* key, T& obj) { if(objectMap.empty()) objectToMap(object, objectMap); auto iterator = objectMap.find(key); if(iterator != objectMap.end()) { auto& value = iterator->second; MessagePackInput subRef = createSubRef(value); subRef.input(obj); error.insert(error.end(), subRef.error.begin(), subRef.error.end()); if(TensileLite::Debug::Instance().printDataInit()) usedKeys.insert(key); } else { std::string msg = "Unknown key "; msg += key; msg += " (keys: "; bool first = true; for(auto const& pair : objectMap) { if(!first) msg += ", "; msg += pair.first; first = false; } msg += ")"; addError(msg); } } template void mapOptional(const char* key, T& obj) { if(objectMap.empty()) objectToMap(object, objectMap); auto iterator = objectMap.find(key); if(iterator != objectMap.end()) { auto& value = iterator->second; createSubRef(value).input(obj); if(TensileLite::Debug::Instance().printDataInit()) usedKeys.insert(key); } } template void input(T& obj) { EmptyContext ctx; input(obj, ctx); } void checkUsedKeys() { std::unordered_set fileKeys; for(auto const& pair : objectMap) fileKeys.insert(pair.first); if(usedKeys != fileKeys) { for(auto const& k : fileKeys) if(usedKeys.find(k) == usedKeys.end()) addError(concatenate("Error: Unused key ", k)); } } template typename std::enable_if::value, void>::type input(T& obj, Context& ctx) { MappingTraits::mapping(*this, obj, ctx); if(TensileLite::Debug::Instance().printDataInit()) checkUsedKeys(); } template typename std::enable_if::value, void>::type input(T& obj, Context& ctx) { MappingTraits::mapping(*this, obj); if(TensileLite::Debug::Instance().printDataInit()) checkUsedKeys(); } template typename std::enable_if::value, void>::type input(T& obj, Context& ctx) { object.convert(obj); } template typename std::enable_if::value, void>::type input(T& obj, Context& ctx) { enumFound = 0; EnumTraits::enumeration(*this, obj); if(enumFound != 1) { std::string s; object.convert(s); addError(concatenate("Enum not found! ", s)); } } template typename std::enable_if::value, void>::type input(T& obj, Context& ctx) { assert(object.type == msgpack::type::object_type::ARRAY); auto result = object.as>(); for(size_t i = 0; i < result.size(); i++) { MessagePackInput subRef = createSubRef(result[i]); auto& value = SequenceTraits::element(*this, obj, i); subRef.input(value); if(!subRef.error.empty()) { error.insert(error.end(), subRef.error.begin(), subRef.error.end()); return; } } } template typename std::enable_if::value, void>::type input(T& obj, Context& ctx) { objectToMap(object, objectMap); for(auto& element : objectMap) { CustomMappingTraits::inputOne(*this, element.first, obj); } } template void enumCase(T& member, const char* key, T value) { bool match = false; if(object.type == msgpack::type::object_type::STR) { std::string result; object.convert(result); if(result == key) match = true; } else if(object.type == msgpack::type::POSITIVE_INTEGER || object.type == msgpack::type::NEGATIVE_INTEGER) { int64_t intValue; object.convert(intValue); if(static_cast(value) == intValue) match = true; } else { addError(concatenate("Unexpected msgpack type for enum: ", (int)object.type, " (expected STRING or INTEGER)")); } if(match) { enumFound++; member = value; } } }; template <> struct IOTraits { template static void mapRequired(MessagePackInput& io, const char* key, T& obj) { io.mapRequired(key, obj); } template static void mapOptional(MessagePackInput& io, const char* key, T& obj) { io.mapOptional(key, obj); } static bool outputting(MessagePackInput& io) { return false; } static void setError(MessagePackInput& io, std::string const& msg) { io.error.push_back(msg); } static void setContext(MessagePackInput& io, void* ctx) { io.context = ctx; } static void* getContext(MessagePackInput& io) { return io.context; } template static void enumCase(MessagePackInput& io, T& member, const char* key, T value) { io.enumCase(member, key, value); } }; template struct SequenceTraits, IO> { static size_t size(MessagePackInput& io, std::vector& v) { return v.size(); } static T& element(MessagePackInput& io, std::vector& v, size_t index) { if(index >= v.size()) { size_t n = index - v.size() + 1; v.insert(v.end(), n, T()); } return v[index]; } }; template struct MappingTraits, IO> { using obj = MasterContractionLibrary; static void mapping(IO& io, std::shared_ptr& o) { PointerMappingTraits::mapping(io, o); } }; } }