rippled
STParsedJSON.cpp
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2012, 2013 Ripple Labs Inc.
5 
6  Permission to use, copy, modify, and/or distribute this software for any
7  purpose with or without fee is hereby granted, provided that the above
8  copyright notice and this permission notice appear in all copies.
9 
10  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18 //==============================================================================
19 
20 #include <ripple/basics/StringUtilities.h>
21 #include <ripple/basics/contract.h>
22 #include <ripple/basics/safe_cast.h>
23 #include <ripple/beast/core/LexicalCast.h>
24 #include <ripple/protocol/ErrorCodes.h>
25 #include <ripple/protocol/LedgerFormats.h>
26 #include <ripple/protocol/SField.h>
27 #include <ripple/protocol/STAccount.h>
28 #include <ripple/protocol/STAmount.h>
29 #include <ripple/protocol/STArray.h>
30 #include <ripple/protocol/STBitString.h>
31 #include <ripple/protocol/STBlob.h>
32 #include <ripple/protocol/STInteger.h>
33 #include <ripple/protocol/STIssue.h>
34 #include <ripple/protocol/STParsedJSON.h>
35 #include <ripple/protocol/STPathSet.h>
36 #include <ripple/protocol/STVector256.h>
37 #include <ripple/protocol/STXChainBridge.h>
38 #include <ripple/protocol/TER.h>
39 #include <ripple/protocol/TxFormats.h>
40 #include <ripple/protocol/UintTypes.h>
41 #include <ripple/protocol/XChainAttestations.h>
42 #include <ripple/protocol/impl/STVar.h>
43 
44 #include <cassert>
45 #include <charconv>
46 #include <memory>
47 
48 namespace ripple {
49 
50 namespace STParsedJSONDetail {
51 template <typename U, typename S>
52 constexpr std::
53  enable_if_t<std::is_unsigned<U>::value && std::is_signed<S>::value, U>
54  to_unsigned(S value)
55 {
56  if (value < 0 || std::numeric_limits<U>::max() < value)
57  Throw<std::runtime_error>("Value out of range");
58  return static_cast<U>(value);
59 }
60 
61 template <typename U1, typename U2>
62 constexpr std::
63  enable_if_t<std::is_unsigned<U1>::value && std::is_unsigned<U2>::value, U1>
64  to_unsigned(U2 value)
65 {
66  if (std::numeric_limits<U1>::max() < value)
67  Throw<std::runtime_error>("Value out of range");
68  return static_cast<U1>(value);
69 }
70 
71 static std::string
72 make_name(std::string const& object, std::string const& field)
73 {
74  if (field.empty())
75  return object;
76 
77  return object + "." + field;
78 }
79 
80 static Json::Value
81 not_an_object(std::string const& object, std::string const& field)
82 {
83  return RPC::make_error(
85  "Field '" + make_name(object, field) + "' is not a JSON object.");
86 }
87 
88 static Json::Value
89 not_an_object(std::string const& object)
90 {
91  return not_an_object(object, "");
92 }
93 
94 static Json::Value
95 not_an_array(std::string const& object)
96 {
97  return RPC::make_error(
98  rpcINVALID_PARAMS, "Field '" + object + "' is not a JSON array.");
99 }
100 
101 static Json::Value
102 unknown_field(std::string const& object, std::string const& field)
103 {
104  return RPC::make_error(
106  "Field '" + make_name(object, field) + "' is unknown.");
107 }
108 
109 static Json::Value
110 out_of_range(std::string const& object, std::string const& field)
111 {
112  return RPC::make_error(
114  "Field '" + make_name(object, field) + "' is out of range.");
115 }
116 
117 static Json::Value
118 bad_type(std::string const& object, std::string const& field)
119 {
120  return RPC::make_error(
122  "Field '" + make_name(object, field) + "' has bad type.");
123 }
124 
125 static Json::Value
126 invalid_data(std::string const& object, std::string const& field)
127 {
128  return RPC::make_error(
130  "Field '" + make_name(object, field) + "' has invalid data.");
131 }
132 
133 static Json::Value
134 invalid_data(std::string const& object)
135 {
136  return invalid_data(object, "");
137 }
138 
139 static Json::Value
140 array_expected(std::string const& object, std::string const& field)
141 {
142  return RPC::make_error(
144  "Field '" + make_name(object, field) + "' must be a JSON array.");
145 }
146 
147 static Json::Value
148 string_expected(std::string const& object, std::string const& field)
149 {
150  return RPC::make_error(
152  "Field '" + make_name(object, field) + "' must be a string.");
153 }
154 
155 static Json::Value
156 too_deep(std::string const& object)
157 {
158  return RPC::make_error(
160  "Field '" + object + "' exceeds nesting depth limit.");
161 }
162 
163 static Json::Value
164 singleton_expected(std::string const& object, unsigned int index)
165 {
166  return RPC::make_error(
168  "Field '" + object + "[" + std::to_string(index) +
169  "]' must be an object with a single key/object value.");
170 }
171 
172 static Json::Value
173 template_mismatch(SField const& sField)
174 {
175  return RPC::make_error(
177  "Object '" + sField.getName() +
178  "' contents did not meet requirements for that type.");
179 }
180 
181 static Json::Value
183 {
184  return RPC::make_error(
186  "Item '" + item + "' at index " + std::to_string(index) +
187  " is not an object. Arrays may only contain objects.");
188 }
189 
190 // This function is used by parseObject to parse any JSON type that doesn't
191 // recurse. Everything represented here is a leaf-type.
194  std::string const& json_name,
195  std::string const& fieldName,
196  SField const* name,
197  Json::Value const& value,
198  Json::Value& error)
199 {
201 
202  auto const& field = SField::getField(fieldName);
203 
204  if (field == sfInvalid)
205  {
206  error = unknown_field(json_name, fieldName);
207  return ret;
208  }
209 
210  switch (field.fieldType)
211  {
212  case STI_UINT8:
213  try
214  {
215  constexpr auto minValue =
217  constexpr auto maxValue =
219  if (value.isString())
220  {
221  std::string const strValue = value.asString();
222 
223  if (!strValue.empty() &&
224  ((strValue[0] < '0') || (strValue[0] > '9')))
225  {
226  if (field == sfTransactionResult)
227  {
228  auto ter = transCode(strValue);
229 
230  if (!ter || TERtoInt(*ter) < minValue ||
231  TERtoInt(*ter) > maxValue)
232  {
233  error = out_of_range(json_name, fieldName);
234  return ret;
235  }
236 
237  ret = detail::make_stvar<STUInt8>(
238  field,
239  static_cast<std::uint8_t>(TERtoInt(*ter)));
240  }
241  else
242  {
243  error = bad_type(json_name, fieldName);
244  return ret;
245  }
246  }
247  else
248  {
249  ret = detail::make_stvar<STUInt8>(
250  field,
251  beast::lexicalCastThrow<std::uint8_t>(strValue));
252  }
253  }
254  else if (value.isInt())
255  {
256  if (value.asInt() < minValue || value.asInt() > maxValue)
257  {
258  error = out_of_range(json_name, fieldName);
259  return ret;
260  }
261 
262  ret = detail::make_stvar<STUInt8>(
263  field, static_cast<std::uint8_t>(value.asInt()));
264  }
265  else if (value.isUInt())
266  {
267  if (value.asUInt() > maxValue)
268  {
269  error = out_of_range(json_name, fieldName);
270  return ret;
271  }
272 
273  ret = detail::make_stvar<STUInt8>(
274  field, static_cast<std::uint8_t>(value.asUInt()));
275  }
276  else
277  {
278  error = bad_type(json_name, fieldName);
279  return ret;
280  }
281  }
282  catch (std::exception const&)
283  {
284  error = invalid_data(json_name, fieldName);
285  return ret;
286  }
287  break;
288 
289  case STI_UINT16:
290  try
291  {
292  if (value.isString())
293  {
294  std::string const strValue = value.asString();
295 
296  if (!strValue.empty() &&
297  ((strValue[0] < '0') || (strValue[0] > '9')))
298  {
299  if (field == sfTransactionType)
300  {
301  ret = detail::make_stvar<STUInt16>(
302  field,
303  static_cast<std::uint16_t>(
304  TxFormats::getInstance().findTypeByName(
305  strValue)));
306 
307  if (*name == sfGeneric)
308  name = &sfTransaction;
309  }
310  else if (field == sfLedgerEntryType)
311  {
312  ret = detail::make_stvar<STUInt16>(
313  field,
314  static_cast<std::uint16_t>(
315  LedgerFormats::getInstance().findTypeByName(
316  strValue)));
317 
318  if (*name == sfGeneric)
319  name = &sfLedgerEntry;
320  }
321  else
322  {
323  error = invalid_data(json_name, fieldName);
324  return ret;
325  }
326  }
327  else
328  {
329  ret = detail::make_stvar<STUInt16>(
330  field,
331  beast::lexicalCastThrow<std::uint16_t>(strValue));
332  }
333  }
334  else if (value.isInt())
335  {
336  ret = detail::make_stvar<STUInt16>(
337  field, to_unsigned<std::uint16_t>(value.asInt()));
338  }
339  else if (value.isUInt())
340  {
341  ret = detail::make_stvar<STUInt16>(
342  field, to_unsigned<std::uint16_t>(value.asUInt()));
343  }
344  else
345  {
346  error = bad_type(json_name, fieldName);
347  return ret;
348  }
349  }
350  catch (std::exception const&)
351  {
352  error = invalid_data(json_name, fieldName);
353  return ret;
354  }
355 
356  break;
357 
358  case STI_UINT32:
359  try
360  {
361  if (value.isString())
362  {
363  ret = detail::make_stvar<STUInt32>(
364  field,
365  beast::lexicalCastThrow<std::uint32_t>(
366  value.asString()));
367  }
368  else if (value.isInt())
369  {
370  ret = detail::make_stvar<STUInt32>(
371  field, to_unsigned<std::uint32_t>(value.asInt()));
372  }
373  else if (value.isUInt())
374  {
375  ret = detail::make_stvar<STUInt32>(
376  field, safe_cast<std::uint32_t>(value.asUInt()));
377  }
378  else
379  {
380  error = bad_type(json_name, fieldName);
381  return ret;
382  }
383  }
384  catch (std::exception const&)
385  {
386  error = invalid_data(json_name, fieldName);
387  return ret;
388  }
389 
390  break;
391 
392  case STI_UINT64:
393  try
394  {
395  if (value.isString())
396  {
397  auto const str = value.asString();
398 
399  std::uint64_t val;
400 
401  auto [p, ec] = std::from_chars(
402  str.data(), str.data() + str.size(), val, 16);
403 
404  if (ec != std::errc() || (p != str.data() + str.size()))
405  Throw<std::invalid_argument>("invalid data");
406 
407  ret = detail::make_stvar<STUInt64>(field, val);
408  }
409  else if (value.isInt())
410  {
411  ret = detail::make_stvar<STUInt64>(
412  field, to_unsigned<std::uint64_t>(value.asInt()));
413  }
414  else if (value.isUInt())
415  {
416  ret = detail::make_stvar<STUInt64>(
417  field, safe_cast<std::uint64_t>(value.asUInt()));
418  }
419  else
420  {
421  error = bad_type(json_name, fieldName);
422  return ret;
423  }
424  }
425  catch (std::exception const&)
426  {
427  error = invalid_data(json_name, fieldName);
428  return ret;
429  }
430 
431  break;
432 
433  case STI_UINT128: {
434  if (!value.isString())
435  {
436  error = bad_type(json_name, fieldName);
437  return ret;
438  }
439 
440  uint128 num;
441 
442  if (auto const s = value.asString(); !num.parseHex(s))
443  {
444  if (!s.empty())
445  {
446  error = invalid_data(json_name, fieldName);
447  return ret;
448  }
449 
450  num.zero();
451  }
452 
453  ret = detail::make_stvar<STUInt128>(field, num);
454  break;
455  }
456 
457  case STI_UINT160: {
458  if (!value.isString())
459  {
460  error = bad_type(json_name, fieldName);
461  return ret;
462  }
463 
464  uint160 num;
465 
466  if (auto const s = value.asString(); !num.parseHex(s))
467  {
468  if (!s.empty())
469  {
470  error = invalid_data(json_name, fieldName);
471  return ret;
472  }
473 
474  num.zero();
475  }
476 
477  ret = detail::make_stvar<STUInt160>(field, num);
478  break;
479  }
480 
481  case STI_UINT256: {
482  if (!value.isString())
483  {
484  error = bad_type(json_name, fieldName);
485  return ret;
486  }
487 
488  uint256 num;
489 
490  if (auto const s = value.asString(); !num.parseHex(s))
491  {
492  if (!s.empty())
493  {
494  error = invalid_data(json_name, fieldName);
495  return ret;
496  }
497 
498  num.zero();
499  }
500 
501  ret = detail::make_stvar<STUInt256>(field, num);
502  break;
503  }
504 
505  case STI_VL:
506  if (!value.isString())
507  {
508  error = bad_type(json_name, fieldName);
509  return ret;
510  }
511 
512  try
513  {
514  if (auto vBlob = strUnHex(value.asString()))
515  {
516  ret = detail::make_stvar<STBlob>(
517  field, vBlob->data(), vBlob->size());
518  }
519  else
520  {
521  Throw<std::invalid_argument>("invalid data");
522  }
523  }
524  catch (std::exception const&)
525  {
526  error = invalid_data(json_name, fieldName);
527  return ret;
528  }
529 
530  break;
531 
532  case STI_AMOUNT:
533  try
534  {
535  ret =
536  detail::make_stvar<STAmount>(amountFromJson(field, value));
537  }
538  catch (std::exception const&)
539  {
540  error = invalid_data(json_name, fieldName);
541  return ret;
542  }
543 
544  break;
545 
546  case STI_VECTOR256:
547  if (!value.isArrayOrNull())
548  {
549  error = array_expected(json_name, fieldName);
550  return ret;
551  }
552 
553  try
554  {
555  STVector256 tail(field);
556  for (Json::UInt i = 0; value.isValidIndex(i); ++i)
557  {
558  uint256 s;
559  if (!s.parseHex(value[i].asString()))
560  Throw<std::invalid_argument>("invalid data");
561  tail.push_back(s);
562  }
563  ret = detail::make_stvar<STVector256>(std::move(tail));
564  }
565  catch (std::exception const&)
566  {
567  error = invalid_data(json_name, fieldName);
568  return ret;
569  }
570 
571  break;
572 
573  case STI_PATHSET:
574  if (!value.isArrayOrNull())
575  {
576  error = array_expected(json_name, fieldName);
577  return ret;
578  }
579 
580  try
581  {
582  STPathSet tail(field);
583 
584  for (Json::UInt i = 0; value.isValidIndex(i); ++i)
585  {
586  STPath p;
587 
588  if (!value[i].isArrayOrNull())
589  {
591  ss << fieldName << "[" << i << "]";
592  error = array_expected(json_name, ss.str());
593  return ret;
594  }
595 
596  for (Json::UInt j = 0; value[i].isValidIndex(j); ++j)
597  {
599  ss << fieldName << "[" << i << "][" << j << "]";
600  std::string const element_name(
601  json_name + "." + ss.str());
602 
603  // each element in this path has some combination of
604  // account, currency, or issuer
605 
606  Json::Value pathEl = value[i][j];
607 
608  if (!pathEl.isObject())
609  {
610  error = not_an_object(element_name);
611  return ret;
612  }
613 
614  Json::Value const& account = pathEl["account"];
615  Json::Value const& currency = pathEl["currency"];
616  Json::Value const& issuer = pathEl["issuer"];
617  bool hasCurrency = false;
618  AccountID uAccount, uIssuer;
619  Currency uCurrency;
620 
621  if (account)
622  {
623  // human account id
624  if (!account.isString())
625  {
626  error =
627  string_expected(element_name, "account");
628  return ret;
629  }
630 
631  // If we have what looks like a 160-bit hex value,
632  // we set it, otherwise, we assume it's an AccountID
633  if (!uAccount.parseHex(account.asString()))
634  {
635  auto const a =
636  parseBase58<AccountID>(account.asString());
637  if (!a)
638  {
639  error =
640  invalid_data(element_name, "account");
641  return ret;
642  }
643  uAccount = *a;
644  }
645  }
646 
647  if (currency)
648  {
649  // human currency
650  if (!currency.isString())
651  {
652  error =
653  string_expected(element_name, "currency");
654  return ret;
655  }
656 
657  hasCurrency = true;
658 
659  if (!uCurrency.parseHex(currency.asString()))
660  {
661  if (!to_currency(
662  uCurrency, currency.asString()))
663  {
664  error =
665  invalid_data(element_name, "currency");
666  return ret;
667  }
668  }
669  }
670 
671  if (issuer)
672  {
673  // human account id
674  if (!issuer.isString())
675  {
676  error = string_expected(element_name, "issuer");
677  return ret;
678  }
679 
680  if (!uIssuer.parseHex(issuer.asString()))
681  {
682  auto const a =
683  parseBase58<AccountID>(issuer.asString());
684  if (!a)
685  {
686  error =
687  invalid_data(element_name, "issuer");
688  return ret;
689  }
690  uIssuer = *a;
691  }
692  }
693 
694  p.emplace_back(
695  uAccount, uCurrency, uIssuer, hasCurrency);
696  }
697 
698  tail.push_back(p);
699  }
700  ret = detail::make_stvar<STPathSet>(std::move(tail));
701  }
702  catch (std::exception const&)
703  {
704  error = invalid_data(json_name, fieldName);
705  return ret;
706  }
707 
708  break;
709 
710  case STI_ACCOUNT: {
711  if (!value.isString())
712  {
713  error = bad_type(json_name, fieldName);
714  return ret;
715  }
716 
717  std::string const strValue = value.asString();
718 
719  try
720  {
721  if (AccountID account; account.parseHex(strValue))
722  return detail::make_stvar<STAccount>(field, account);
723 
724  if (auto result = parseBase58<AccountID>(strValue))
725  return detail::make_stvar<STAccount>(field, *result);
726 
727  error = invalid_data(json_name, fieldName);
728  return ret;
729  }
730  catch (std::exception const&)
731  {
732  error = invalid_data(json_name, fieldName);
733  return ret;
734  }
735  }
736  break;
737 
738  case STI_ISSUE:
739  try
740  {
741  ret = detail::make_stvar<STIssue>(issueFromJson(field, value));
742  }
743  catch (std::exception const&)
744  {
745  error = invalid_data(json_name, fieldName);
746  return ret;
747  }
748  break;
749 
750  case STI_XCHAIN_BRIDGE:
751  try
752  {
753  ret = detail::make_stvar<STXChainBridge>(
754  STXChainBridge(field, value));
755  }
756  catch (std::exception const&)
757  {
758  error = invalid_data(json_name, fieldName);
759  return ret;
760  }
761  break;
762 
763  default:
764  error = bad_type(json_name, fieldName);
765  return ret;
766  }
767 
768  return ret;
769 }
770 
771 static const int maxDepth = 64;
772 
773 // Forward declaration since parseObject() and parseArray() call each other.
775 parseArray(
776  std::string const& json_name,
777  Json::Value const& json,
778  SField const& inName,
779  int depth,
780  Json::Value& error);
781 
784  std::string const& json_name,
785  Json::Value const& json,
786  SField const& inName,
787  int depth,
788  Json::Value& error)
789 {
790  if (!json.isObjectOrNull())
791  {
792  error = not_an_object(json_name);
793  return std::nullopt;
794  }
795 
796  if (depth > maxDepth)
797  {
798  error = too_deep(json_name);
799  return std::nullopt;
800  }
801 
802  try
803  {
804  STObject data(inName);
805 
806  for (auto const& fieldName : json.getMemberNames())
807  {
808  Json::Value const& value = json[fieldName];
809 
810  auto const& field = SField::getField(fieldName);
811 
812  if (field == sfInvalid)
813  {
814  error = unknown_field(json_name, fieldName);
815  return std::nullopt;
816  }
817 
818  switch (field.fieldType)
819  {
820  // Object-style containers (which recurse).
821  case STI_OBJECT:
822  case STI_TRANSACTION:
823  case STI_LEDGERENTRY:
824  case STI_VALIDATION:
825  if (!value.isObject())
826  {
827  error = not_an_object(json_name, fieldName);
828  return std::nullopt;
829  }
830 
831  try
832  {
833  auto ret = parseObject(
834  json_name + "." + fieldName,
835  value,
836  field,
837  depth + 1,
838  error);
839  if (!ret)
840  return std::nullopt;
841  data.emplace_back(std::move(*ret));
842  }
843  catch (std::exception const&)
844  {
845  error = invalid_data(json_name, fieldName);
846  return std::nullopt;
847  }
848 
849  break;
850 
851  // Array-style containers (which recurse).
852  case STI_ARRAY:
853  try
854  {
855  auto array = parseArray(
856  json_name + "." + fieldName,
857  value,
858  field,
859  depth + 1,
860  error);
861  if (!array.has_value())
862  return std::nullopt;
863  data.emplace_back(std::move(*array));
864  }
865  catch (std::exception const&)
866  {
867  error = invalid_data(json_name, fieldName);
868  return std::nullopt;
869  }
870 
871  break;
872 
873  // Everything else (types that don't recurse).
874  default: {
875  auto leaf =
876  parseLeaf(json_name, fieldName, &inName, value, error);
877 
878  if (!leaf)
879  return std::nullopt;
880 
881  data.emplace_back(std::move(*leaf));
882  }
883 
884  break;
885  }
886  }
887 
888  // Some inner object types have templates. Attempt to apply that.
889  data.applyTemplateFromSField(inName); // May throw
890 
891  return data;
892  }
893  catch (STObject::FieldErr const& e)
894  {
895  std::cerr << "template_mismatch: " << e.what() << "\n";
896  error = template_mismatch(inName);
897  }
898  catch (std::exception const&)
899  {
900  error = invalid_data(json_name);
901  }
902  return std::nullopt;
903 }
904 
907  std::string const& json_name,
908  Json::Value const& json,
909  SField const& inName,
910  int depth,
911  Json::Value& error)
912 {
913  if (!json.isArrayOrNull())
914  {
915  error = not_an_array(json_name);
916  return std::nullopt;
917  }
918 
919  if (depth > maxDepth)
920  {
921  error = too_deep(json_name);
922  return std::nullopt;
923  }
924 
925  try
926  {
927  STArray tail(inName);
928 
929  for (Json::UInt i = 0; json.isValidIndex(i); ++i)
930  {
931  bool const isObjectOrNull(json[i].isObjectOrNull());
932  bool const singleKey(isObjectOrNull ? json[i].size() == 1 : true);
933 
934  if (!isObjectOrNull || !singleKey)
935  {
936  // null values are !singleKey
937  error = singleton_expected(json_name, i);
938  return std::nullopt;
939  }
940 
941  // TODO: There doesn't seem to be a nice way to get just the
942  // first/only key in an object without copying all keys into
943  // a vector
944  std::string const objectName(json[i].getMemberNames()[0]);
945  ;
946  auto const& nameField(SField::getField(objectName));
947 
948  if (nameField == sfInvalid)
949  {
950  error = unknown_field(json_name, objectName);
951  return std::nullopt;
952  }
953 
954  Json::Value const objectFields(json[i][objectName]);
955 
957  ss << json_name << "."
958  << "[" << i << "]." << objectName;
959 
960  auto ret = parseObject(
961  ss.str(), objectFields, nameField, depth + 1, error);
962  if (!ret)
963  {
964  std::string errMsg = error["error_message"].asString();
965  error["error_message"] =
966  "Error at '" + ss.str() + "'. " + errMsg;
967  return std::nullopt;
968  }
969 
970  if (ret->getFName().fieldType != STI_OBJECT)
971  {
972  ss << "Field type: " << ret->getFName().fieldType << " ";
973  error = non_object_in_array(ss.str(), i);
974  return std::nullopt;
975  }
976 
977  tail.push_back(std::move(*ret));
978  }
979 
980  return detail::make_stvar<STArray>(std::move(tail));
981  }
982  catch (std::exception const&)
983  {
984  error = invalid_data(json_name);
985  return std::nullopt;
986  }
987 }
988 
989 } // namespace STParsedJSONDetail
990 
991 //------------------------------------------------------------------------------
992 
994  std::string const& name,
995  Json::Value const& json)
996 {
997  using namespace STParsedJSONDetail;
998  object = parseObject(name, json, sfGeneric, 0, error);
999 }
1000 
1001 //------------------------------------------------------------------------------
1002 
1004  std::string const& name,
1005  Json::Value const& json)
1006 {
1007  using namespace STParsedJSONDetail;
1008  auto arr = parseArray(name, json, sfGeneric, 0, error);
1009  if (!arr)
1010  array.reset();
1011  else
1012  {
1013  auto p = dynamic_cast<STArray*>(&arr->get());
1014  if (p == nullptr)
1015  array.reset();
1016  else
1017  array = std::move(*p);
1018  }
1019 }
1020 
1021 } // namespace ripple
Json::Value::isInt
bool isInt() const
Definition: json_value.cpp:979
ripple::to_currency
bool to_currency(Currency &currency, std::string const &code)
Tries to convert a string to a Currency, returns true on success.
Definition: UintTypes.cpp:80
std::is_signed
ripple::STParsedJSONDetail::maxDepth
static const int maxDepth
Definition: STParsedJSON.cpp:771
ripple::STParsedJSONDetail::singleton_expected
static Json::Value singleton_expected(std::string const &object, unsigned int index)
Definition: STParsedJSON.cpp:164
std::is_unsigned
Json::Value::isObject
bool isObject() const
Definition: json_value.cpp:1027
std::string
STL class.
ripple::rpcINVALID_PARAMS
@ rpcINVALID_PARAMS
Definition: ErrorCodes.h:84
Json::Value::isString
bool isString() const
Definition: json_value.cpp:1009
Json::Value::isValidIndex
bool isValidIndex(UInt index) const
Return true if index < size().
Definition: json_value.cpp:841
std::exception
STL class.
ripple::sfGeneric
const SField sfGeneric(access, 0)
Definition: SField.h:356
ripple::STParsedJSONDetail::template_mismatch
static Json::Value template_mismatch(SField const &sField)
Definition: STParsedJSON.cpp:173
ripple::STParsedJSONDetail::bad_type
static Json::Value bad_type(std::string const &object, std::string const &field)
Definition: STParsedJSON.cpp:118
charconv
Json::UInt
unsigned int UInt
Definition: json_forwards.h:27
ripple::STParsedJSONDetail::parseArray
static std::optional< detail::STVar > parseArray(std::string const &json_name, Json::Value const &json, SField const &inName, int depth, Json::Value &error)
Definition: STParsedJSON.cpp:906
ripple::STVector256::push_back
void push_back(uint256 const &v)
Definition: STVector256.h:216
ripple::STParsedJSONDetail::non_object_in_array
static Json::Value non_object_in_array(std::string const &item, Json::UInt index)
Definition: STParsedJSON.cpp:182
std::stringstream
STL class.
ripple::STArray::push_back
void push_back(STObject const &object)
Definition: STArray.h:212
ripple::STParsedJSONDetail::too_deep
static Json::Value too_deep(std::string const &object)
Definition: STParsedJSON.cpp:156
std::cerr
ripple::SField::getField
static const SField & getField(int fieldCode)
Definition: SField.cpp:452
ripple::TERtoInt
constexpr TERUnderlyingType TERtoInt(TELcodes v)
Definition: TER.h:340
ripple::sfInvalid
const SField sfInvalid(access, -1)
Definition: SField.h:355
ripple::STPathSet
Definition: STPathSet.h:176
ripple::STParsedJSONDetail::parseLeaf
static std::optional< detail::STVar > parseLeaf(std::string const &json_name, std::string const &fieldName, SField const *name, Json::Value const &value, Json::Value &error)
Definition: STParsedJSON.cpp:193
ripple::transCode
std::optional< TER > transCode(std::string const &token)
Definition: TER.cpp:258
ripple::STParsedJSONObject::error
Json::Value error
On failure, an appropriate set of error values.
Definition: STParsedJSON.h:53
ripple::sfLedgerEntry
const SField sfLedgerEntry
ripple::base_uint
Integers of any length that is a multiple of 32-bits.
Definition: base_uint.h:82
ripple::sfTransactionType
const SF_UINT16 sfTransactionType
ripple::STObject::FieldErr
Definition: STObject.h:647
ripple::STParsedJSONDetail::out_of_range
static Json::Value out_of_range(std::string const &object, std::string const &field)
Definition: STParsedJSON.cpp:110
ripple::TxFormats::getInstance
static TxFormats const & getInstance()
Definition: TxFormats.cpp:489
Json::Value::isArrayOrNull
bool isArrayOrNull() const
Definition: json_value.cpp:1021
ripple::STArray
Definition: STArray.h:28
std::to_string
T to_string(T... args)
ripple::STPath::emplace_back
void emplace_back(Args &&... args)
Definition: STPathSet.h:412
std::errc
ripple::amountFromJson
STAmount amountFromJson(SField const &name, Json::Value const &v)
Definition: STAmount.cpp:927
std::uint8_t
ripple::issueFromJson
Issue issueFromJson(Json::Value const &v)
Definition: Issue.cpp:78
std::from_chars
T from_chars(T... args)
ripple::STParsedJSONDetail::to_unsigned
constexpr std::enable_if_t< std::is_unsigned< U >::value &&std::is_signed< S >::value, U > to_unsigned(S value)
Definition: STParsedJSON.cpp:54
memory
ripple::LedgerFormats::getInstance
static LedgerFormats const & getInstance()
Definition: LedgerFormats.cpp:346
ripple::STXChainBridge
Definition: STXChainBridge.h:32
std::numeric_limits::min
T min(T... args)
ripple::STObject
Definition: STObject.h:53
ripple::STParsedJSONArray::STParsedJSONArray
STParsedJSONArray()=delete
Json::Value::getMemberNames
Members getMemberNames() const
Return a list of the member names.
Definition: json_value.cpp:948
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::sfTransactionResult
const SF_UINT8 sfTransactionResult
ripple::sfLedgerEntryType
const SF_UINT16 sfLedgerEntryType
ripple::STParsedJSONDetail::parseObject
static std::optional< STObject > parseObject(std::string const &json_name, Json::Value const &json, SField const &inName, int depth, Json::Value &error)
Definition: STParsedJSON.cpp:783
ripple::SField
Identifies fields.
Definition: SField.h:139
ripple::base_uint::zero
void zero()
Definition: base_uint.h:542
ripple::SField::getName
std::string const & getName() const
Definition: SField.h:202
ripple::STParsedJSONDetail::not_an_object
static Json::Value not_an_object(std::string const &object, std::string const &field)
Definition: STParsedJSON.cpp:81
cassert
Json::Value::asUInt
UInt asUInt() const
Definition: json_value.cpp:545
Json::Value::isUInt
bool isUInt() const
Definition: json_value.cpp:985
ripple::STParsedJSONDetail::make_name
static std::string make_name(std::string const &object, std::string const &field)
Definition: STParsedJSON.cpp:72
ripple::STVector256
Definition: STVector256.h:29
ripple::STParsedJSONDetail::invalid_data
static Json::Value invalid_data(std::string const &object, std::string const &field)
Definition: STParsedJSON.cpp:126
std::string::empty
T empty(T... args)
std::optional
std::stringstream::str
T str(T... args)
Json::Value::asInt
Int asInt() const
Definition: json_value.cpp:503
ripple::STParsedJSONObject::STParsedJSONObject
STParsedJSONObject()=delete
ripple::STParsedJSONDetail::string_expected
static Json::Value string_expected(std::string const &object, std::string const &field)
Definition: STParsedJSON.cpp:148
std::numeric_limits::max
T max(T... args)
ripple::base_uint::parseHex
constexpr bool parseHex(std::string_view sv)
Parse a hex string into a base_uint.
Definition: base_uint.h:496
ripple::STPath
Definition: STPathSet.h:118
ripple::strUnHex
std::optional< Blob > strUnHex(std::size_t strSize, Iterator begin, Iterator end)
Definition: StringUtilities.h:52
std::numeric_limits
Json::Value::isObjectOrNull
bool isObjectOrNull() const
Definition: json_value.cpp:1033
ripple::sfTransaction
const SField sfTransaction
ripple::STParsedJSONDetail::array_expected
static Json::Value array_expected(std::string const &object, std::string const &field)
Definition: STParsedJSON.cpp:140
ripple::RPC::make_error
Json::Value make_error(error_code_i code)
Returns a new json object that reflects the error code.
Definition: ErrorCodes.cpp:180
std::runtime_error::what
T what(T... args)
Json::Value
Represents a JSON value.
Definition: json_value.h:145
ripple::STParsedJSONDetail::not_an_array
static Json::Value not_an_array(std::string const &object)
Definition: STParsedJSON.cpp:95
ripple::STParsedJSONDetail::unknown_field
static Json::Value unknown_field(std::string const &object, std::string const &field)
Definition: STParsedJSON.cpp:102
Json::Value::asString
std::string asString() const
Returns the unquoted string value.
Definition: json_value.cpp:469
ripple::STPathSet::push_back
void push_back(STPath const &e)
Definition: STPathSet.h:509