binary.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604
  1. #include "binary.h"
  2. #include <yql/essentials/utils/yql_panic.h>
  3. namespace NYql::NJsonPath {
  4. bool TArraySubscriptOffsets::IsRange() const {
  5. return ToOffset > 0;
  6. }
  7. const TStringBuf TJsonPathItem::GetString() const {
  8. return std::get<TStringBuf>(Data);
  9. }
  10. const TVector<TArraySubscriptOffsets>& TJsonPathItem::GetSubscripts() const {
  11. return std::get<TVector<TArraySubscriptOffsets>>(Data);
  12. }
  13. const TBinaryOpArgumentsOffset& TJsonPathItem::GetBinaryOpArguments() const {
  14. return std::get<TBinaryOpArgumentsOffset>(Data);
  15. }
  16. double TJsonPathItem::GetNumber() const {
  17. return std::get<double>(Data);
  18. }
  19. bool TJsonPathItem::GetBoolean() const {
  20. return std::get<bool>(Data);
  21. }
  22. TFilterPredicateOffset TJsonPathItem::GetFilterPredicateOffset() const {
  23. return std::get<TFilterPredicateOffset>(Data);
  24. }
  25. TStartsWithPrefixOffset TJsonPathItem::GetStartsWithPrefixOffset() const {
  26. return std::get<TStartsWithPrefixOffset>(Data);
  27. }
  28. const NReWrapper::IRePtr& TJsonPathItem::GetRegex() const {
  29. return std::get<NReWrapper::IRePtr>(Data);
  30. }
  31. TJsonPathReader::TJsonPathReader(const TJsonPathPtr path)
  32. : Path(path)
  33. , InitialPos(0)
  34. , Mode(ReadMode(InitialPos))
  35. {
  36. }
  37. const TJsonPathItem& TJsonPathReader::ReadFirst() {
  38. return ReadFromPos(InitialPos);
  39. }
  40. const TJsonPathItem& TJsonPathReader::ReadInput(const TJsonPathItem& item) {
  41. YQL_ENSURE(item.InputItemOffset.Defined());
  42. return ReadFromPos(*item.InputItemOffset);
  43. }
  44. const TJsonPathItem& TJsonPathReader::ReadFromSubscript(const TArraySubscriptOffsets& subscript) {
  45. return ReadFromPos(subscript.FromOffset);
  46. }
  47. const TJsonPathItem& TJsonPathReader::ReadToSubscript(const TArraySubscriptOffsets& subscript) {
  48. YQL_ENSURE(subscript.IsRange());
  49. return ReadFromPos(subscript.ToOffset);
  50. }
  51. const TJsonPathItem& TJsonPathReader::ReadLeftOperand(const TJsonPathItem& node) {
  52. return ReadFromPos(node.GetBinaryOpArguments().LeftOffset);
  53. }
  54. const TJsonPathItem& TJsonPathReader::ReadRightOperand(const TJsonPathItem& node) {
  55. return ReadFromPos(node.GetBinaryOpArguments().RightOffset);
  56. }
  57. const TJsonPathItem& TJsonPathReader::ReadFilterPredicate(const TJsonPathItem& node) {
  58. return ReadFromPos(node.GetFilterPredicateOffset().Offset);
  59. }
  60. const TJsonPathItem& TJsonPathReader::ReadPrefix(const TJsonPathItem& node) {
  61. return ReadFromPos(node.GetStartsWithPrefixOffset().Offset);
  62. }
  63. EJsonPathMode TJsonPathReader::GetMode() const {
  64. return Mode;
  65. }
  66. const TJsonPathItem& TJsonPathReader::ReadFromPos(TUint pos) {
  67. YQL_ENSURE(pos < Path->Size());
  68. const auto it = ItemCache.find(pos);
  69. if (it != ItemCache.end()) {
  70. return it->second;
  71. }
  72. TJsonPathItem& result = ItemCache[pos];
  73. result.Type = ReadType(pos);
  74. const auto row = ReadUint(pos);
  75. const auto column = ReadUint(pos);
  76. result.Pos = TPosition(column, row, "jsonpath");
  77. switch (result.Type) {
  78. // Items without input
  79. case EJsonPathItemType::FilterObject:
  80. case EJsonPathItemType::NullLiteral:
  81. case EJsonPathItemType::ContextObject:
  82. case EJsonPathItemType::LastArrayIndex:
  83. break;
  84. case EJsonPathItemType::Variable:
  85. case EJsonPathItemType::StringLiteral:
  86. result.Data = ReadString(pos);
  87. break;
  88. case EJsonPathItemType::NumberLiteral:
  89. result.Data = ReadDouble(pos);
  90. break;
  91. case EJsonPathItemType::BooleanLiteral:
  92. result.Data = ReadBool(pos);
  93. break;
  94. // Items with single input
  95. case EJsonPathItemType::TypeMethod:
  96. case EJsonPathItemType::SizeMethod:
  97. case EJsonPathItemType::KeyValueMethod:
  98. case EJsonPathItemType::AbsMethod:
  99. case EJsonPathItemType::FloorMethod:
  100. case EJsonPathItemType::CeilingMethod:
  101. case EJsonPathItemType::DoubleMethod:
  102. case EJsonPathItemType::WildcardArrayAccess:
  103. case EJsonPathItemType::WildcardMemberAccess:
  104. case EJsonPathItemType::UnaryMinus:
  105. case EJsonPathItemType::UnaryPlus:
  106. case EJsonPathItemType::UnaryNot:
  107. case EJsonPathItemType::IsUnknownPredicate:
  108. case EJsonPathItemType::ExistsPredicate:
  109. result.InputItemOffset = ReadUint(pos);
  110. break;
  111. case EJsonPathItemType::MemberAccess:
  112. result.Data = ReadString(pos);
  113. result.InputItemOffset = ReadUint(pos);
  114. break;
  115. case EJsonPathItemType::ArrayAccess:
  116. result.Data = ReadSubscripts(pos);
  117. result.InputItemOffset = ReadUint(pos);
  118. break;
  119. case EJsonPathItemType::FilterPredicate:
  120. result.Data = TFilterPredicateOffset{ReadUint(pos)};
  121. result.InputItemOffset = ReadUint(pos);
  122. break;
  123. case EJsonPathItemType::StartsWithPredicate:
  124. result.Data = TStartsWithPrefixOffset{ReadUint(pos)};
  125. result.InputItemOffset = ReadUint(pos);
  126. break;
  127. case EJsonPathItemType::LikeRegexPredicate: {
  128. const auto serializedRegex = ReadString(pos);
  129. auto regex = NReWrapper::NDispatcher::Deserialize(serializedRegex);
  130. result.Data = std::move(regex);
  131. result.InputItemOffset = ReadUint(pos);
  132. break;
  133. }
  134. // Items with 2 inputs
  135. case EJsonPathItemType::BinaryAdd:
  136. case EJsonPathItemType::BinarySubstract:
  137. case EJsonPathItemType::BinaryMultiply:
  138. case EJsonPathItemType::BinaryDivide:
  139. case EJsonPathItemType::BinaryModulo:
  140. case EJsonPathItemType::BinaryLess:
  141. case EJsonPathItemType::BinaryLessEqual:
  142. case EJsonPathItemType::BinaryGreater:
  143. case EJsonPathItemType::BinaryGreaterEqual:
  144. case EJsonPathItemType::BinaryEqual:
  145. case EJsonPathItemType::BinaryNotEqual:
  146. case EJsonPathItemType::BinaryAnd:
  147. case EJsonPathItemType::BinaryOr:
  148. TBinaryOpArgumentsOffset data;
  149. data.LeftOffset = ReadUint(pos);
  150. data.RightOffset = ReadUint(pos);
  151. result.Data = data;
  152. break;
  153. }
  154. return result;
  155. }
  156. TUint TJsonPathReader::ReadUint(TUint& pos) {
  157. return ReadPOD<TUint>(pos);
  158. }
  159. double TJsonPathReader::ReadDouble(TUint& pos) {
  160. return ReadPOD<double>(pos);
  161. }
  162. bool TJsonPathReader::ReadBool(TUint& pos) {
  163. return ReadPOD<bool>(pos);
  164. }
  165. EJsonPathItemType TJsonPathReader::ReadType(TUint& pos) {
  166. return static_cast<EJsonPathItemType>(ReadUint(pos));
  167. }
  168. EJsonPathMode TJsonPathReader::ReadMode(TUint& pos) {
  169. return static_cast<EJsonPathMode>(ReadUint(pos));
  170. }
  171. const TStringBuf TJsonPathReader::ReadString(TUint& pos) {
  172. TUint length = ReadUint(pos);
  173. TStringBuf result(Path->Begin() + pos, length);
  174. pos += length;
  175. return result;
  176. }
  177. TVector<TArraySubscriptOffsets> TJsonPathReader::ReadSubscripts(TUint& pos) {
  178. const auto count = ReadUint(pos);
  179. TVector<TArraySubscriptOffsets> result(count);
  180. for (size_t i = 0; i < count; i++) {
  181. result[i].FromOffset = ReadUint(pos);
  182. result[i].ToOffset = ReadUint(pos);
  183. }
  184. return result;
  185. }
  186. void TJsonPathBuilder::VisitRoot(const TRootNode& node) {
  187. // Block structure:
  188. // <(1) TUint>
  189. // Components:
  190. // (1) Must be casted to EJsonPathMode. Jsonpath execution mode
  191. WriteMode(node.GetMode());
  192. node.GetExpr()->Accept(*this);
  193. }
  194. void TJsonPathBuilder::VisitContextObject(const TContextObjectNode& node) {
  195. WriteZeroInputItem(EJsonPathItemType::ContextObject, node);
  196. }
  197. void TJsonPathBuilder::VisitVariable(const TVariableNode& node) {
  198. WriteZeroInputItem(EJsonPathItemType::Variable, node);
  199. WriteString(node.GetName());
  200. }
  201. void TJsonPathBuilder::VisitLastArrayIndex(const TLastArrayIndexNode& node) {
  202. WriteZeroInputItem(EJsonPathItemType::LastArrayIndex, node);
  203. }
  204. void TJsonPathBuilder::VisitNumberLiteral(const TNumberLiteralNode& node) {
  205. WriteZeroInputItem(EJsonPathItemType::NumberLiteral, node);
  206. WriteDouble(node.GetValue());
  207. }
  208. void TJsonPathBuilder::VisitMemberAccess(const TMemberAccessNode& node) {
  209. // Block structure:
  210. // <(1) TUint> <(2) TUint> <(3) TUint> <(4) TUint> <(5) char[]> <(6) TUint>
  211. // Components:
  212. // (1) Must be casted to EJsonPathItemType. Member access item type
  213. // (2) Row of the position in the source jsonpath
  214. // (3) Column of the position in the source jsonpath
  215. // (4) Length of member name string
  216. // (5) Member name string
  217. // (6) Offset of the input item
  218. WriteType(EJsonPathItemType::MemberAccess);
  219. WritePos(node);
  220. WriteString(node.GetMember());
  221. WriteNextPosition();
  222. node.GetInput()->Accept(*this);
  223. }
  224. void TJsonPathBuilder::VisitWildcardMemberAccess(const TWildcardMemberAccessNode& node) {
  225. WriteSingleInputItem(EJsonPathItemType::WildcardMemberAccess, node, node.GetInput());
  226. }
  227. void TJsonPathBuilder::VisitArrayAccess(const TArrayAccessNode& node) {
  228. // Block structure:
  229. // <(1) TUint> <(2) TUint> <(3) TUint> <(4) TUint> <(5) pair<TUint, TUint>[]> <(6) TUint> <(7) items>
  230. // Components:
  231. // (1) Must be casted to EJsonPathItemType. Array access item type
  232. // (2) Row of the position in the source jsonpath
  233. // (3) Column of the position in the source jsonpath
  234. // (4) Count of subscripts stored
  235. // (5) Array of pairs with offsets to subscript items. If subscript is a single index, only first element
  236. // is set to it's offset and second is zero. If subscript is a range, both pair elements are valid offsets
  237. // to the elements of range (lower and upper bound).
  238. // (6) Offset of the input item
  239. // (7) Array of subcsripts. For details about encoding see VisitArraySubscript
  240. WriteType(EJsonPathItemType::ArrayAccess);
  241. WritePos(node);
  242. // (4) Write count of subscripts stored
  243. const auto& subscripts = node.GetSubscripts();
  244. const auto count = subscripts.size();
  245. WriteUint(count);
  246. // (5) We do not know sizes of each subscript. Write array of zeros for offsets
  247. const auto indexStart = CurrentEndPos();
  248. TVector<TUint> offsets(2 * count);
  249. WriteUintSequence(offsets);
  250. // (6) Reserve space for input offset to rewrite it later
  251. const auto inputStart = CurrentEndPos();
  252. WriteFinishPosition();
  253. // (7) Write all subscripts and record offset for each of them
  254. for (size_t i = 0; i < count; i++) {
  255. offsets[2 * i] = CurrentEndPos();
  256. subscripts[i].From->Accept(*this);
  257. if (subscripts[i].To) {
  258. offsets[2 * i + 1] = CurrentEndPos();
  259. subscripts[i].To->Accept(*this);
  260. }
  261. }
  262. // (5) Rewrite offsets with correct values
  263. RewriteUintSequence(offsets, indexStart);
  264. // (6) Rewrite input offset
  265. RewriteUint(CurrentEndPos(), inputStart);
  266. node.GetInput()->Accept(*this);
  267. }
  268. void TJsonPathBuilder::VisitWildcardArrayAccess(const TWildcardArrayAccessNode& node) {
  269. WriteSingleInputItem(EJsonPathItemType::WildcardArrayAccess, node, node.GetInput());
  270. }
  271. void TJsonPathBuilder::VisitUnaryOperation(const TUnaryOperationNode& node) {
  272. EJsonPathItemType type;
  273. switch (node.GetOp()) {
  274. case EUnaryOperation::Plus:
  275. type = EJsonPathItemType::UnaryPlus;
  276. break;
  277. case EUnaryOperation::Minus:
  278. type = EJsonPathItemType::UnaryMinus;
  279. break;
  280. case EUnaryOperation::Not:
  281. type = EJsonPathItemType::UnaryNot;
  282. break;
  283. }
  284. WriteSingleInputItem(type, node, node.GetExpr());
  285. }
  286. void TJsonPathBuilder::VisitBinaryOperation(const TBinaryOperationNode& node) {
  287. EJsonPathItemType type;
  288. switch (node.GetOp()) {
  289. case EBinaryOperation::Add:
  290. type = EJsonPathItemType::BinaryAdd;
  291. break;
  292. case EBinaryOperation::Substract:
  293. type = EJsonPathItemType::BinarySubstract;
  294. break;
  295. case EBinaryOperation::Multiply:
  296. type = EJsonPathItemType::BinaryMultiply;
  297. break;
  298. case EBinaryOperation::Divide:
  299. type = EJsonPathItemType::BinaryDivide;
  300. break;
  301. case EBinaryOperation::Modulo:
  302. type = EJsonPathItemType::BinaryModulo;
  303. break;
  304. case EBinaryOperation::Less:
  305. type = EJsonPathItemType::BinaryLess;
  306. break;
  307. case EBinaryOperation::LessEqual:
  308. type = EJsonPathItemType::BinaryLessEqual;
  309. break;
  310. case EBinaryOperation::Greater:
  311. type = EJsonPathItemType::BinaryGreater;
  312. break;
  313. case EBinaryOperation::GreaterEqual:
  314. type = EJsonPathItemType::BinaryGreaterEqual;
  315. break;
  316. case EBinaryOperation::Equal:
  317. type = EJsonPathItemType::BinaryEqual;
  318. break;
  319. case EBinaryOperation::NotEqual:
  320. type = EJsonPathItemType::BinaryNotEqual;
  321. break;
  322. case EBinaryOperation::And:
  323. type = EJsonPathItemType::BinaryAnd;
  324. break;
  325. case EBinaryOperation::Or:
  326. type = EJsonPathItemType::BinaryOr;
  327. break;
  328. }
  329. WriteTwoInputsItem(type, node, node.GetLeftExpr(), node.GetRightExpr());
  330. }
  331. void TJsonPathBuilder::VisitBooleanLiteral(const TBooleanLiteralNode& node) {
  332. WriteZeroInputItem(EJsonPathItemType::BooleanLiteral, node);
  333. WriteBool(node.GetValue());
  334. }
  335. void TJsonPathBuilder::VisitNullLiteral(const TNullLiteralNode& node) {
  336. WriteZeroInputItem(EJsonPathItemType::NullLiteral, node);
  337. }
  338. void TJsonPathBuilder::VisitStringLiteral(const TStringLiteralNode& node) {
  339. WriteZeroInputItem(EJsonPathItemType::StringLiteral, node);
  340. WriteString(node.GetValue());
  341. }
  342. void TJsonPathBuilder::VisitFilterObject(const TFilterObjectNode& node) {
  343. WriteZeroInputItem(EJsonPathItemType::FilterObject, node);
  344. }
  345. void TJsonPathBuilder::VisitFilterPredicate(const TFilterPredicateNode& node) {
  346. WriteTwoInputsItem(EJsonPathItemType::FilterPredicate, node, node.GetPredicate(), node.GetInput());
  347. }
  348. void TJsonPathBuilder::VisitMethodCall(const TMethodCallNode& node) {
  349. EJsonPathItemType type;
  350. switch (node.GetType()) {
  351. case EMethodType::Abs:
  352. type = EJsonPathItemType::AbsMethod;
  353. break;
  354. case EMethodType::Floor:
  355. type = EJsonPathItemType::FloorMethod;
  356. break;
  357. case EMethodType::Ceiling:
  358. type = EJsonPathItemType::CeilingMethod;
  359. break;
  360. case EMethodType::Double:
  361. type = EJsonPathItemType::DoubleMethod;
  362. break;
  363. case EMethodType::Type:
  364. type = EJsonPathItemType::TypeMethod;
  365. break;
  366. case EMethodType::Size:
  367. type = EJsonPathItemType::SizeMethod;
  368. break;
  369. case EMethodType::KeyValue:
  370. type = EJsonPathItemType::KeyValueMethod;
  371. break;
  372. }
  373. WriteSingleInputItem(type, node, node.GetInput());
  374. }
  375. TJsonPathPtr TJsonPathBuilder::ShrinkAndGetResult() {
  376. Result->ShrinkToFit();
  377. return Result;
  378. }
  379. void TJsonPathBuilder::VisitStartsWithPredicate(const TStartsWithPredicateNode& node) {
  380. WriteTwoInputsItem(EJsonPathItemType::StartsWithPredicate, node, node.GetPrefix(), node.GetInput());
  381. }
  382. void TJsonPathBuilder::VisitExistsPredicate(const TExistsPredicateNode& node) {
  383. WriteSingleInputItem(EJsonPathItemType::ExistsPredicate, node, node.GetInput());
  384. }
  385. void TJsonPathBuilder::VisitIsUnknownPredicate(const TIsUnknownPredicateNode& node) {
  386. WriteSingleInputItem(EJsonPathItemType::IsUnknownPredicate, node, node.GetInput());
  387. }
  388. void TJsonPathBuilder::VisitLikeRegexPredicate(const TLikeRegexPredicateNode& node) {
  389. // Block structure:
  390. // <(1) TUint> <(2) TUint> <(3) TUint> <(4) TUint> <(5) char[]> <(6) TUint>
  391. // Components:
  392. // (1) Must be casted to EJsonPathItemType. Member access item type
  393. // (2) Row of the position in the source jsonpath
  394. // (3) Column of the position in the source jsonpath
  395. // (4) Length of serialized Hyperscan database
  396. // (5) Serialized Hyperscan database
  397. // (6) Offset of the input item
  398. WriteType(EJsonPathItemType::LikeRegexPredicate);
  399. WritePos(node);
  400. const TString serializedRegex = node.GetRegex()->Serialize();
  401. WriteString(serializedRegex);
  402. WriteNextPosition();
  403. node.GetInput()->Accept(*this);
  404. }
  405. void TJsonPathBuilder::WriteZeroInputItem(EJsonPathItemType type, const TAstNode& node) {
  406. // Block structure:
  407. // <(1) TUint> <(2) TUint> <(3) TUint>
  408. // Components:
  409. // (1) Item type
  410. // (2) Row of the position in the source jsonpath
  411. // (3) Column of the position in the source jsonpath
  412. WriteType(type);
  413. WritePos(node);
  414. }
  415. void TJsonPathBuilder::WriteSingleInputItem(EJsonPathItemType type, const TAstNode& node, const TAstNodePtr input) {
  416. // Block structure:
  417. // <(1) TUint> <(2) TUint> <(3) TUint> <(4) TUint> <(5) item>
  418. // Components:
  419. // (1) Item type
  420. // (2) Row of the position in the source jsonpath
  421. // (3) Column of the position in the source jsonpath
  422. // (4) Offset of the input item
  423. // (5) Input item
  424. WriteZeroInputItem(type, node);
  425. WriteNextPosition();
  426. input->Accept(*this);
  427. }
  428. void TJsonPathBuilder::WriteTwoInputsItem(EJsonPathItemType type, const TAstNode& node, const TAstNodePtr firstInput, const TAstNodePtr secondInput) {
  429. // Block structure:
  430. // <(1) TUint> <(2) TUint> <(3) TUint> <(4) TUint> <(5) TUint> <(6) item> <(7) item>
  431. // Components:
  432. // (1) Item type
  433. // (2) Row of the position in the source jsonpath
  434. // (3) Column of the position in the source jsonpath
  435. // (4) Offset of the first input
  436. // (5) Offset of the second input
  437. // (6) JsonPath item representing first input
  438. // (7) JsonPath item representing right input
  439. WriteZeroInputItem(type, node);
  440. // (4) and (5) Fill offsets with zeros
  441. const auto indexStart = CurrentEndPos();
  442. WriteUint(0);
  443. WriteUint(0);
  444. // (6) Write first input and record it's offset
  445. const auto firstInputStart = CurrentEndPos();
  446. firstInput->Accept(*this);
  447. // (7) Write second input and record it's offset
  448. const auto secondInputStart = CurrentEndPos();
  449. secondInput->Accept(*this);
  450. // (4) and (5) Rewrite offsets with correct values
  451. RewriteUintSequence({firstInputStart, secondInputStart}, indexStart);
  452. }
  453. void TJsonPathBuilder::WritePos(const TAstNode& node) {
  454. WriteUint(node.GetPos().Row);
  455. WriteUint(node.GetPos().Column);
  456. }
  457. void TJsonPathBuilder::WriteType(EJsonPathItemType type) {
  458. WriteUint(static_cast<TUint>(type));
  459. }
  460. void TJsonPathBuilder::WriteMode(EJsonPathMode mode) {
  461. WriteUint(static_cast<TUint>(mode));
  462. }
  463. void TJsonPathBuilder::WriteNextPosition() {
  464. WriteUint(CurrentEndPos() + sizeof(TUint));
  465. }
  466. void TJsonPathBuilder::WriteFinishPosition() {
  467. WriteUint(0);
  468. }
  469. void TJsonPathBuilder::WriteString(TStringBuf value) {
  470. WriteUint(value.size());
  471. Result->Append(value.data(), value.size());
  472. }
  473. void TJsonPathBuilder::RewriteUintSequence(const TVector<TUint>& sequence, TUint offset) {
  474. const auto length = sequence.size() * sizeof(TUint);
  475. Y_ASSERT(offset + length < CurrentEndPos());
  476. MemCopy(Result->Data() + offset, reinterpret_cast<const char*>(sequence.data()), length);
  477. }
  478. void TJsonPathBuilder::WriteUintSequence(const TVector<TUint>& sequence) {
  479. const auto length = sequence.size() * sizeof(TUint);
  480. Result->Append(reinterpret_cast<const char*>(sequence.data()), length);
  481. }
  482. void TJsonPathBuilder::RewriteUint(TUint value, TUint offset) {
  483. Y_ASSERT(offset + sizeof(TUint) < CurrentEndPos());
  484. MemCopy(Result->Data() + offset, reinterpret_cast<const char*>(&value), sizeof(TUint));
  485. }
  486. void TJsonPathBuilder::WriteUint(TUint value) {
  487. WritePOD(value);
  488. }
  489. void TJsonPathBuilder::WriteDouble(double value) {
  490. WritePOD(value);
  491. }
  492. void TJsonPathBuilder::WriteBool(bool value) {
  493. WritePOD(value);
  494. }
  495. TUint TJsonPathBuilder::CurrentEndPos() const {
  496. return Result->Size();
  497. }
  498. }