| 1 | /*
 | 
| 2 |  * Souffle - A Datalog Compiler
 | 
| 3 |  * Copyright (c) 2020, The Souffle Developers. All rights reserved.
 | 
| 4 |  * Licensed under the Universal Permissive License v 1.0 as shown at:
 | 
| 5 |  * - https://opensource.org/licenses/UPL
 | 
| 6 |  * - <souffle root>/licenses/SOUFFLE-UPL.txt
 | 
| 7 |  */
 | 
| 8 | 
 | 
| 9 | /************************************************************************
 | 
| 10 |  *
 | 
| 11 |  * @file SerialisationStream.h
 | 
| 12 |  *
 | 
| 13 |  * Defines a common base class for relation serialisation streams.
 | 
| 14 |  *
 | 
| 15 |  ***********************************************************************/
 | 
| 16 | 
 | 
| 17 | #pragma once
 | 
| 18 | 
 | 
| 19 | #include "souffle/RamTypes.h"
 | 
| 20 | #include "souffle/utility/ContainerUtil.h"
 | 
| 21 | #include "souffle/utility/StringUtil.h"
 | 
| 22 | #include "souffle/utility/json11.h"
 | 
| 23 | #include <cassert>
 | 
| 24 | #include <cstddef>
 | 
| 25 | #include <map>
 | 
| 26 | #include <string>
 | 
| 27 | #include <utility>
 | 
| 28 | #include <vector>
 | 
| 29 | 
 | 
| 30 | namespace souffle {
 | 
| 31 | 
 | 
| 32 | class RecordTable;
 | 
| 33 | class SymbolTable;
 | 
| 34 | 
 | 
| 35 | using json11::Json;
 | 
| 36 | 
 | 
| 37 | template <bool readOnlyTables>
 | 
| 38 | class SerialisationStream {
 | 
| 39 | public:
 | 
| 40 |     virtual ~SerialisationStream() = default;
 | 
| 41 | 
 | 
| 42 | protected:
 | 
| 43 |     template <typename A>
 | 
| 44 |     using RO = std::conditional_t<readOnlyTables, const A, A>;
 | 
| 45 | 
 | 
| 46 |     SerialisationStream(RO<SymbolTable>& symTab, RO<RecordTable>& recTab, Json types,
 | 
| 47 |             std::vector<std::string> relTypes, std::size_t auxArity = 0)
 | 
| 48 |             : symbolTable(symTab), recordTable(recTab), types(std::move(types)),
 | 
| 49 |               typeAttributes(std::move(relTypes)), arity(typeAttributes.size() - auxArity),
 | 
| 50 |               auxiliaryArity(auxArity) {}
 | 
| 51 | 
 | 
| 52 |     SerialisationStream(RO<SymbolTable>& symTab, RO<RecordTable>& recTab, Json types)
 | 
| 53 |             : symbolTable(symTab), recordTable(recTab), types(std::move(types)) {
 | 
| 54 |         setupFromJson();
 | 
| 55 |     }
 | 
| 56 | 
 | 
| 57 |     SerialisationStream(RO<SymbolTable>& symTab, RO<RecordTable>& recTab,
 | 
| 58 |             const std::map<std::string, std::string>& rwOperation)
 | 
| 59 |             : symbolTable(symTab), recordTable(recTab) {
 | 
| 60 |         std::string parseErrors;
 | 
| 61 |         types = Json::parse(rwOperation.at("types"), parseErrors);
 | 
| 62 |         assert(parseErrors.size() == 0 && "Internal JSON parsing failed.");
 | 
| 63 |         if (rwOperation.count("params") > 0) {
 | 
| 64 |             params = Json::parse(rwOperation.at("params"), parseErrors);
 | 
| 65 |             assert(parseErrors.size() == 0 && "Internal JSON parsing failed.");
 | 
| 66 |         } else {
 | 
| 67 |             params = Json::object();
 | 
| 68 |         }
 | 
| 69 | 
 | 
| 70 |         auxiliaryArity = RamSignedFromString(getOr(rwOperation, "auxArity", "0"));
 | 
| 71 | 
 | 
| 72 |         setupFromJson();
 | 
| 73 |     }
 | 
| 74 | 
 | 
| 75 |     RO<SymbolTable>& symbolTable;
 | 
| 76 |     RO<RecordTable>& recordTable;
 | 
| 77 |     Json types;
 | 
| 78 |     Json params;
 | 
| 79 |     std::vector<std::string> typeAttributes;
 | 
| 80 | 
 | 
| 81 |     std::size_t arity = 0;
 | 
| 82 |     std::size_t auxiliaryArity = 0;
 | 
| 83 | 
 | 
| 84 | private:
 | 
| 85 |     void setupFromJson() {
 | 
| 86 |         auto&& relInfo = types["relation"];
 | 
| 87 |         arity = static_cast<std::size_t>(relInfo["arity"].long_value());
 | 
| 88 | 
 | 
| 89 |         assert(relInfo["types"].is_array());
 | 
| 90 |         auto&& relTypes = relInfo["types"].array_items();
 | 
| 91 |         assert(relTypes.size() == arity);
 | 
| 92 | 
 | 
| 93 |         for (const auto& jsonType : relTypes) {
 | 
| 94 |             const auto& typeString = jsonType.string_value();
 | 
| 95 |             assert(!typeString.empty() && "malformed types tag");
 | 
| 96 |             typeAttributes.push_back(typeString);
 | 
| 97 |         }
 | 
| 98 | 
 | 
| 99 |         for (std::size_t i = 0; i < auxiliaryArity; i++) {
 | 
| 100 |             typeAttributes.push_back("i:number");
 | 
| 101 |         }
 | 
| 102 |     }
 | 
| 103 | };
 | 
| 104 | 
 | 
| 105 | }  // namespace souffle
 |