LCOV - code coverage report
Current view: top level - irohad/model/converters - json_common.hpp (source / functions) Hit Total Coverage
Test: cleared_cor.info Lines: 38 45 84.4 %
Date: 2019-03-07 14:46:43 Functions: 302 302 100.0 %

          Line data    Source code
       1             : /**
       2             :  * Copyright Soramitsu Co., Ltd. All Rights Reserved.
       3             :  * SPDX-License-Identifier: Apache-2.0
       4             :  */
       5             : 
       6             : #ifndef IROHA_JSON_COMMON_HPP
       7             : #define IROHA_JSON_COMMON_HPP
       8             : 
       9             : #include <numeric>
      10             : #include <string>
      11             : #include <unordered_map>
      12             : 
      13             : // Enable std::string support in rapidjson
      14             : #define RAPIDJSON_HAS_STDSTRING 1
      15             : #include <rapidjson/document.h>
      16             : #include <rapidjson/prettywriter.h>
      17             : #include <rapidjson/stringbuffer.h>
      18             : 
      19             : #include "common/bind.hpp"
      20             : #include "common/byteutils.hpp"
      21             : #include "common/obj_utils.hpp"
      22             : #include "model/block.hpp"
      23             : #include "model/common.hpp"
      24             : #include "model/queries/get_transactions.hpp"
      25             : #include "model/signature.hpp"
      26             : 
      27             : namespace iroha {
      28             :   namespace model {
      29             :     namespace converters {
      30             :       /**
      31             :        * Convert functor which specifies output type
      32             :        * @tparam V - output type
      33             :        */
      34             :       template <typename V>
      35             :       struct Convert {
      36             :         /**
      37             :          * Convert input type to defined type
      38             :          * @tparam T - input type
      39             :          * @param x - input value
      40             :          * @return optional of output type from input value
      41             :          */
      42             :         template <typename T>
      43             :         auto operator()(T &&x) const {
      44         123 :           return boost::optional<V>(std::forward<T>(x));
      45             :         }
      46             :       };
      47             : 
      48             :       template <size_t size>
      49             :       struct Convert<blob_t<size>> {
      50             :         template <typename T>
      51             :         auto operator()(T &&x) const {
      52          33 :           return hexstringToArray<size>(std::forward<T>(x));
      53           0 :         }
      54             :       };
      55             : 
      56             :       /**
      57             :        * Deserialize field from given document with given type
      58             :        * @tparam T - getter return type
      59             :        * @tparam D - document type
      60             :        * @param document - document value for deserialization
      61             :        * @param field - field name for deserialization
      62             :        * @return deserialized field on success, nullopt otherwise
      63             :        */
      64             :       template <typename T, typename D>
      65             :       boost::optional<T> deserializeField(const D &document,
      66             :                                           const std::string &field) {
      67         172 :         if (document.HasMember(field.c_str())
      68         172 :             and document[field.c_str()].template Is<T>()) {
      69         172 :           return document[field.c_str()].template Get<T>();
      70             :         }
      71           4 :         return boost::none;
      72         172 :       }
      73             : 
      74             :       /**
      75             :        * Functor for deserialization from given document
      76             :        * @tparam D - document type
      77             :        */
      78             :       template <typename D>
      79             :       struct FieldDeserializer {
      80             :         /**
      81             :          * @param document - document for field deserialization
      82             :          */
      83             :         explicit FieldDeserializer(const D &document) : document(document) {}
      84             : 
      85             :         /**
      86             :          * Create function, which deserializes document field,
      87             :          * transforms the value to required type, and
      88             :          * assigns it to block member
      89             :          * @tparam T - getter return type
      90             :          * @tparam V - block member type
      91             :          * @tparam B - block type
      92             :          * @tparam Convert - transform function type
      93             :          * @param member - pointer to member in block
      94             :          * @param field - field name for deserialization
      95             :          * @param transform - transform function from T to V
      96             :          * @return function, which takes block, returns block with deserialized
      97             :          * member on success, nullopt otherwise
      98             :          */
      99             :         template <typename T,
     100             :                   typename V,
     101             :                   typename B,
     102             :                   typename Convert = Convert<V>>
     103             :         auto deserialize(V B::*member,
     104             :                          const std::string &field,
     105             :                          Convert transform = Convert()) {
     106             :           return [this, member, field, transform](auto block) {
     107          55 :             return deserializeField<T>(document, field) | transform
     108          55 :                 | assignObjectField(block, member);
     109           0 :           };
     110             :         }
     111             : 
     112             :         /**
     113             :          * Deserialize field of Uint type to given member field of block
     114             :          * @tparam V - block member type
     115             :          * @tparam B - block type
     116             :          * @param member - pointer to member in block
     117             :          * @param field - field name for deserialization
     118             :          * @return @see deserialize
     119             :          */
     120             :         template <typename V, typename B>
     121             :         auto Uint(V B::*member, const std::string &field) {
     122           9 :           return deserialize<uint32_t>(member, field);
     123             :         }
     124             : 
     125             :         /**
     126             :          * Deserialize field of Uint64 type to given member field of block
     127             :          * @tparam V - block member type
     128             :          * @tparam B - block type
     129             :          * @param member - pointer to member in block
     130             :          * @param field - field name for deserialization
     131             :          * @return @see deserialize
     132             :          */
     133             :         template <typename V, typename B>
     134             :         auto Uint64(V B::*member, const std::string &field) {
     135          43 :           return deserialize<uint64_t>(member, field);
     136             :         }
     137             : 
     138             :         /**
     139             :          * Deserialize field of Bool type to given member field of block
     140             :          * @tparam V - block member type
     141             :          * @tparam B - block type
     142             :          * @param member - pointer to member in block
     143             :          * @param field - field name for deserialization
     144             :          * @return @see deserialize
     145             :          */
     146             :         template <typename V, typename B>
     147             :         auto Bool(V B::*member, const std::string &field) {
     148             :           return deserialize<bool>(member, field);
     149             :         }
     150             : 
     151             :         /**
     152             :          * Deserialize field of String type to given member field of block
     153             :          * @tparam V - block member type
     154             :          * @tparam B - block type
     155             :          * @param member - pointer to member in block
     156             :          * @param field - field name for deserialization
     157             :          * @return @see deserialize
     158             :          */
     159             :         template <typename V, typename B>
     160             :         auto String(V B::*member, const std::string &field) {
     161          40 :           return deserialize<std::string>(member, field);
     162             :         }
     163             : 
     164             :         /**
     165             :          * Deserialize field of String type
     166             :          * @param field - field name for deserialization
     167             :          * @return deserialized field on success, nullopt otherwise
     168             :          */
     169             :         auto String(const std::string &field) {
     170          49 :           return deserializeField<std::string>(document, field);
     171             :         }
     172             : 
     173             :         /**
     174             :          * Deserialize field of Array type to given member field of block,
     175             :          * using provided transform function
     176             :          * @tparam V - block member type
     177             :          * @tparam B - block type
     178             :          * @tparam Convert - transform function type
     179             :          * @param member - pointer to member in block
     180             :          * @param field - field name for deserialization
     181             :          * @param transform - transform function from Array to V
     182             :          * @return @see deserialize
     183             :          */
     184             :         template <typename V, typename B, typename Convert = Convert<V>>
     185             :         auto Array(V B::*member,
     186             :                    const std::string &field,
     187             :                    Convert transform = Convert()) {
     188           7 :           return deserialize<rapidjson::Value::ConstArray>(
     189           7 :               member, field, transform);
     190             :         }
     191             : 
     192             :         /**
     193             :          * Deserialize field of Object type to given member field of block
     194             :          * @tparam V - block member type
     195             :          * @tparam B - block type
     196             :          * @param member - pointer to member in block
     197             :          * @param field - field name for deserialization
     198             :          * @return @see deserialize
     199             :          */
     200             :         template <typename V, typename B, typename Convert = Convert<V>>
     201             :         auto Object(V B::*member,
     202             :                     const std::string &field,
     203             :                     Convert transform = Convert()) {
     204          21 :           return deserialize<rapidjson::Value::ConstObject>(
     205          21 :               member, field, transform);
     206             :         }
     207             : 
     208             :         // document for deserialization
     209             :         const D &document;
     210             :       };
     211             : 
     212             :       /**
     213             :        * Factory method for FieldDeserializer functor
     214             :        * @tparam D - document type
     215             :        * @param document - document for deserialization
     216             :        * @return FieldDeserializer instance for given arguments
     217             :        */
     218             :       template <typename D>
     219             :       auto makeFieldDeserializer(const D &document) {
     220         100 :         return FieldDeserializer<D>(document);
     221             :       }
     222             : 
     223             :       template <>
     224             :       struct Convert<Signature> {
     225             :         template <typename T>
     226             :         auto operator()(T &&x) const {
     227          19 :           auto des = makeFieldDeserializer(std::forward<T>(x));
     228          19 :           return boost::make_optional(Signature())
     229          19 :               | des.String(&Signature::pubkey, "pubkey")
     230          19 :               | des.String(&Signature::signature, "signature");
     231           0 :         }
     232             :       };
     233             : 
     234             :       template <>
     235             :       struct Convert<Block::SignaturesType> {
     236             :         template <typename T>
     237             :         auto operator()(T &&x) const {
     238             :           auto acc_signatures = [](auto init, auto &x) {
     239             :             return init | [&x](auto signatures) {
     240             :               return Convert<Signature>()(x) | [&signatures](auto signature) {
     241           2 :                 signatures.push_back(signature);
     242           2 :                 return boost::make_optional(std::move(signatures));
     243             :               };
     244           0 :             };
     245             :           };
     246           3 :           return std::accumulate(x.begin(),
     247           3 :                                  x.end(),
     248           3 :                                  boost::make_optional(Block::SignaturesType()),
     249             :                                  acc_signatures);
     250           0 :         }
     251             :       };
     252             : 
     253             :       template <>
     254             :       struct Convert<GetTransactions::TxHashCollectionType> {
     255             :         template <typename T>
     256             :         auto operator()(T &&x) const {
     257             :           auto acc_hashes = [](auto init, auto &x) {
     258             :             return init | [&x](auto tx_hashes)
     259             :                        -> boost::optional<
     260             :                            GetTransactions::TxHashCollectionType> {
     261             :               // If invalid type included, returns nullopt
     262           4 :               if (not x.IsString()) {
     263           0 :                 return boost::none;
     264             :               }
     265             :               auto tx_hash_opt =
     266           4 :                   Convert<GetTransactions::TxHashType>()(x.GetString());
     267           4 :               if (not tx_hash_opt) {
     268             :                 // If the the hash is wrong, just skip.
     269           1 :                 return boost::make_optional(std::move(tx_hashes));
     270             :               }
     271             :               return tx_hash_opt | [&tx_hashes](auto tx_hash) {
     272           3 :                 tx_hashes.push_back(tx_hash);
     273           3 :                 return boost::make_optional(std::move(tx_hashes));
     274             :               };
     275           4 :             };
     276             :           };
     277           3 :           return std::accumulate(
     278           3 :               x.begin(),
     279           3 :               x.end(),
     280           3 :               boost::make_optional(GetTransactions::TxHashCollectionType()),
     281             :               acc_hashes);
     282           0 :         }
     283             :       };
     284             : 
     285             :       /**
     286             :        * Serialize signature to JSON with given allocator
     287             :        * @param signature - signature for serialization
     288             :        * @param allocator - allocator for JSON value
     289             :        * @return JSON value with signature
     290             :        */
     291             :       rapidjson::Value serializeSignature(
     292             :           const Signature &signature,
     293             :           rapidjson::Document::AllocatorType &allocator);
     294             : 
     295             :       /**
     296             :        * Try to parse JSON from string
     297             :        * @param string - string for parsing
     298             :        * @return JSON document on success, nullopt otherwise
     299             :        */
     300             :       boost::optional<rapidjson::Document> stringToJson(
     301             :           const std::string &string);
     302             : 
     303             :       /**
     304             :        * Pretty print JSON document to string
     305             :        * @param document - document for printing
     306             :        * @return pretty printed JSON document
     307             :        */
     308             :       std::string jsonToString(const rapidjson::Document &document);
     309             :     }  // namespace converters
     310             :   }    // namespace model
     311             : }  // namespace iroha
     312             : 
     313             : #endif  // IROHA_JSON_COMMON_HPP

Generated by: LCOV version 1.13