mkql_validate.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510
  1. #include <library/cpp/containers/stack_vector/stack_vec.h>
  2. #include <yql/essentials/public/udf/udf_value_builder.h>
  3. #include "mkql_validate.h"
  4. #include <yql/essentials/minikql/mkql_node_printer.h>
  5. #include <yql/essentials/minikql/mkql_type_ops.h>
  6. namespace NKikimr {
  7. namespace NMiniKQL {
  8. namespace {
  9. static const TString VERIFY_DELIMITER = "\n - ";
  10. using namespace NUdf;
  11. template<class TValidateErrorPolicy>
  12. struct TLazyVerifyListValue;
  13. template<class TValidateErrorPolicy>
  14. struct TLazyVerifyListIterator: public TBoxedValue {
  15. TLazyVerifyListIterator(const TLazyVerifyListValue<TValidateErrorPolicy>& lazyList, ui64 index = 0)
  16. : LazyList(lazyList)
  17. , OrigIter(TBoxedValueAccessor::GetListIterator(*lazyList.Orig))
  18. , Index(index)
  19. {
  20. if (!OrigIter) {
  21. TValidateErrorPolicy::Generate(TStringBuilder() << "TLazyVerifyListIterator constructor expect non empty result of GetListIterator" << VERIFY_DELIMITER << LazyList.Message);
  22. }
  23. }
  24. private:
  25. const TLazyVerifyListValue<TValidateErrorPolicy>& LazyList;
  26. TUnboxedValue OrigIter;
  27. ui64 Index;
  28. bool Next(NUdf::TUnboxedValue& item) final {
  29. ++Index;
  30. if (!OrigIter.Next(item))
  31. return false;
  32. TType* itemType = LazyList.ListType->GetItemType();
  33. item = TValidate<TValidateErrorPolicy, TValidateModeLazy<TValidateErrorPolicy>>::Value(LazyList.ValueBuilder, itemType, std::move(item),
  34. TStringBuilder() << "LazyList[" << Index << "]" << VERIFY_DELIMITER << LazyList.Message);
  35. return true;
  36. }
  37. bool Skip() final {
  38. ++Index;
  39. return OrigIter.Skip();
  40. }
  41. };
  42. template<class TValidateErrorPolicy>
  43. struct TLazyVerifyDictValue;
  44. template<class TValidateErrorPolicy>
  45. struct TLazyVerifyListValue: public TBoxedValue {
  46. TLazyVerifyListValue(const IValueBuilder* valueBuilder, const TListType* listType, IBoxedValuePtr&& orig, const TString& message)
  47. : ValueBuilder(valueBuilder)
  48. , ListType(listType)
  49. , Orig(std::move(orig))
  50. , Message(message)
  51. {}
  52. const IValueBuilder *const ValueBuilder;
  53. const TListType *const ListType;
  54. const IBoxedValuePtr Orig;
  55. const TString Message;
  56. private:
  57. bool HasFastListLength() const override {
  58. return TBoxedValueAccessor::HasFastListLength(*Orig);
  59. }
  60. ui64 GetListLength() const override {
  61. return TBoxedValueAccessor::GetListLength(*Orig);
  62. }
  63. ui64 GetEstimatedListLength() const override {
  64. return TBoxedValueAccessor::GetEstimatedListLength(*Orig);
  65. }
  66. TUnboxedValue GetListIterator() const override {
  67. return TUnboxedValuePod(new TLazyVerifyListIterator<TValidateErrorPolicy>(*this));
  68. }
  69. const TOpaqueListRepresentation* GetListRepresentation() const override {
  70. return nullptr;
  71. }
  72. IBoxedValuePtr ReverseListImpl(const IValueBuilder& builder) const override {
  73. auto upList = TBoxedValueAccessor::ReverseListImpl(*Orig, builder);
  74. if (upList) {
  75. return new TLazyVerifyListValue<TValidateErrorPolicy>(ValueBuilder, ListType, std::move(upList), Message);
  76. }
  77. return upList;
  78. }
  79. IBoxedValuePtr SkipListImpl(const IValueBuilder& builder, ui64 count) const override {
  80. auto upList = TBoxedValueAccessor::SkipListImpl(*Orig, builder, count);
  81. if (upList) {
  82. return new TLazyVerifyListValue<TValidateErrorPolicy>(ValueBuilder, ListType, std::move(upList), Message);
  83. }
  84. return upList;
  85. }
  86. IBoxedValuePtr TakeListImpl(const IValueBuilder& builder, ui64 count) const override {
  87. auto upList = TBoxedValueAccessor::TakeListImpl(*Orig, builder, count);
  88. if (upList) {
  89. return new TLazyVerifyListValue<TValidateErrorPolicy>(ValueBuilder, ListType, std::move(upList), Message);
  90. }
  91. return upList;
  92. }
  93. IBoxedValuePtr ToIndexDictImpl(const IValueBuilder& builder) const override {
  94. auto dictImpl = TBoxedValueAccessor::ToIndexDictImpl(*Orig, builder);
  95. if (!dictImpl) {
  96. return dictImpl;
  97. }
  98. return IBoxedValuePtr(new TLazyVerifyDictValue<TValidateErrorPolicy>(&builder, ListType->IndexDictKeyType(), ListType->GetItemType(), std::move(dictImpl), TStringBuilder() << "LazyDict over IndexToDict" << VERIFY_DELIMITER << Message));
  99. }
  100. bool HasListItems() const override {
  101. return TBoxedValueAccessor::HasListItems(*Orig);
  102. }
  103. bool HasDictItems() const override {
  104. const bool result = TBoxedValueAccessor::HasDictItems(*Orig);
  105. if (result) {
  106. TValidateErrorPolicy::Generate(TStringBuilder() << "TLazyVerifyListValue::HasDictItems expect false, but got true" << VERIFY_DELIMITER << Message);
  107. }
  108. return result;
  109. }
  110. };
  111. template<class TValidateErrorPolicy, bool Keys>
  112. struct TLazyVerifyDictIterator: public TBoxedValue {
  113. TLazyVerifyDictIterator(const TLazyVerifyDictValue<TValidateErrorPolicy>& lazyDict, ui64 index = 0)
  114. : LazyDict(lazyDict)
  115. , OrigIter((Keys ? &TBoxedValueAccessor::GetKeysIterator : &TBoxedValueAccessor::GetDictIterator)(*LazyDict.Orig))
  116. , Index(index)
  117. {
  118. if (!OrigIter) {
  119. TValidateErrorPolicy::Generate(TStringBuilder() << "TLazyVerifyDictIterator constructor expect non empty result of GetDictIterator" << VERIFY_DELIMITER << LazyDict.Message);
  120. }
  121. }
  122. private:
  123. const TLazyVerifyDictValue<TValidateErrorPolicy>& LazyDict;
  124. TUnboxedValue OrigIter;
  125. ui64 Index;
  126. bool Skip() final {
  127. ++Index;
  128. return OrigIter.Skip();
  129. }
  130. bool Next(NUdf::TUnboxedValue& key) final {
  131. ++Index;
  132. if (!OrigIter.Next(key))
  133. return false;
  134. key = TValidate<TValidateErrorPolicy, TValidateModeLazy<TValidateErrorPolicy>>::Value(LazyDict.ValueBuilder, LazyDict.KeyType, std::move(key),
  135. TStringBuilder() << "LazyDict[" << Index << "], validate key" << VERIFY_DELIMITER << LazyDict.Message);
  136. return true;
  137. }
  138. bool NextPair(NUdf::TUnboxedValue& key, NUdf::TUnboxedValue& payload) final {
  139. ++Index;
  140. if (!OrigIter.NextPair(key, payload))
  141. return false;
  142. key = TValidate<TValidateErrorPolicy, TValidateModeLazy<TValidateErrorPolicy>>::Value(LazyDict.ValueBuilder, LazyDict.KeyType, std::move(key),
  143. TStringBuilder() << "LazyDict[" << Index << "], validate key" << VERIFY_DELIMITER << LazyDict.Message);
  144. payload = TValidate<TValidateErrorPolicy, TValidateModeLazy<TValidateErrorPolicy>>::Value(LazyDict.ValueBuilder, LazyDict.PayloadType, std::move(payload),
  145. TStringBuilder() << "LazyDict[" << Index << "], validate payload" << VERIFY_DELIMITER << LazyDict.Message);
  146. return true;
  147. }
  148. };
  149. template<class TValidateErrorPolicy>
  150. struct TLazyVerifyDictValue: public TBoxedValue {
  151. TLazyVerifyDictValue(const IValueBuilder* valueBuilder, const TDictType* dictType, IBoxedValuePtr&& orig, const TString& message)
  152. : TLazyVerifyDictValue(valueBuilder, dictType->GetKeyType(), dictType->GetPayloadType(), std::move(orig), message)
  153. {}
  154. TLazyVerifyDictValue(const IValueBuilder* valueBuilder, const TType* keyType, const TType* payloadType, IBoxedValuePtr&& orig, const TString& message)
  155. : ValueBuilder(valueBuilder)
  156. , KeyType(keyType)
  157. , PayloadType(payloadType)
  158. , Orig(std::move(orig))
  159. , Message(message)
  160. {}
  161. const IValueBuilder *const ValueBuilder;
  162. const TType *const KeyType;
  163. const TType *const PayloadType;
  164. const IBoxedValuePtr Orig;
  165. const TString Message;
  166. private:
  167. ui64 GetDictLength() const override {
  168. return TBoxedValueAccessor::GetDictLength(*Orig);
  169. }
  170. TUnboxedValue GetKeysIterator() const override {
  171. return TUnboxedValuePod(new TLazyVerifyDictIterator<TValidateErrorPolicy, true>(*this));
  172. }
  173. TUnboxedValue GetDictIterator() const override {
  174. return TUnboxedValuePod(new TLazyVerifyDictIterator<TValidateErrorPolicy, false>(*this));
  175. }
  176. bool Contains(const TUnboxedValuePod& key) const override {
  177. return TBoxedValueAccessor::Contains(*Orig, key);
  178. }
  179. TUnboxedValue Lookup(const TUnboxedValuePod& key) const override {
  180. if (auto lookup = TBoxedValueAccessor::Lookup(*Orig, key)) {
  181. return TValidate<TValidateErrorPolicy, TValidateModeLazy<TValidateErrorPolicy>>::Value(ValueBuilder, PayloadType, lookup.Release().GetOptionalValue(),
  182. TStringBuilder() << "LazyDict, validate Lookup payload" << VERIFY_DELIMITER << Message).Release().MakeOptional();
  183. }
  184. return TUnboxedValuePod();
  185. }
  186. bool HasListItems() const override {
  187. const bool result = TBoxedValueAccessor::HasListItems(*Orig);
  188. if (result) {
  189. TValidateErrorPolicy::Generate(TStringBuilder() << "TLazyVerifyDictValue::HasListItems expect false, but got true" << VERIFY_DELIMITER << Message);
  190. }
  191. return result;
  192. }
  193. bool HasDictItems() const override {
  194. return TBoxedValueAccessor::HasDictItems(*Orig);
  195. }
  196. };
  197. template<class TValidateErrorPolicy, class TValidateMode>
  198. class WrapCallableValue: public TBoxedValue {
  199. public:
  200. WrapCallableValue(const TCallableType* callableType, TUnboxedValue&& callable, const TString& message);
  201. private:
  202. const TCallableType *const CallableType;
  203. const TUnboxedValue Callable;
  204. const TString Message;
  205. TUnboxedValue Run(const IValueBuilder* valueBuilder, const TUnboxedValuePod* args) const final;
  206. };
  207. template<class TValidateErrorPolicy, class TValidateMode>
  208. WrapCallableValue<TValidateErrorPolicy, TValidateMode>::WrapCallableValue(const TCallableType* callableType, TUnboxedValue&& callable, const TString& message)
  209. : CallableType(callableType)
  210. , Callable(std::move(callable))
  211. , Message(message)
  212. {
  213. }
  214. template<class TValidateErrorPolicy, class TValidateMode>
  215. TUnboxedValue WrapCallableValue<TValidateErrorPolicy, TValidateMode>::Run(const IValueBuilder* valueBuilder, const TUnboxedValuePod* args) const {
  216. const ui32 argsCount = CallableType->GetArgumentsCount();
  217. TSmallVec<TUnboxedValue> wrapArgs(argsCount);
  218. bool childWrapped = false;
  219. for (ui32 indexArg = 0; indexArg < argsCount; ++indexArg) {
  220. const auto argType = CallableType->GetArgumentType(indexArg);
  221. wrapArgs[indexArg] = TValidate<TValidateErrorPolicy, TValidateMode>::Value(valueBuilder, argType, TUnboxedValuePod(args[indexArg]), TStringBuilder() << "CallableWrapper<" << CallableType->GetName() << ">.arg[" << indexArg << "]" << VERIFY_DELIMITER << Message, &childWrapped);
  222. }
  223. return TValidate<TValidateErrorPolicy, TValidateMode>::Value(valueBuilder, CallableType->GetReturnType(), Callable.Run(valueBuilder, childWrapped ? wrapArgs.data() : args), TStringBuilder() << "CallableWrapper<" << CallableType->GetName() << ">.result" << VERIFY_DELIMITER << Message);
  224. }
  225. } // anonymous namespace
  226. template<class TValidateErrorPolicy>
  227. struct TValidateModeLazy {
  228. static NUdf::TUnboxedValue ProcessList(const IValueBuilder* valueBuilder, const TListType* listType, IBoxedValuePtr&& boxed, const TString& message, bool* wrapped) {
  229. if (wrapped) {
  230. *wrapped = true;
  231. }
  232. return NUdf::TUnboxedValuePod(new TLazyVerifyListValue<TValidateErrorPolicy>(valueBuilder, listType, std::move(boxed), message));
  233. }
  234. static NUdf::TUnboxedValue ProcessDict(const IValueBuilder* valueBuilder, const TDictType* dictType, IBoxedValuePtr&& boxed, const TString& message, bool* wrapped) {
  235. if (wrapped) {
  236. *wrapped = true;
  237. }
  238. return NUdf::TUnboxedValuePod(new TLazyVerifyDictValue<TValidateErrorPolicy>(valueBuilder, dictType, std::move(boxed), message));
  239. }
  240. };
  241. template<class TValidateErrorPolicy>
  242. struct TValidateModeGreedy {
  243. static NUdf::TUnboxedValue ProcessList(const IValueBuilder* valueBuilder, const TListType* listType, IBoxedValuePtr&& boxed, const TString& message, bool* wrapped) {
  244. if (!TBoxedValueAccessor::HasFastListLength(*boxed)) {
  245. return NUdf::TUnboxedValuePod(new TLazyVerifyListValue<TValidateErrorPolicy>(valueBuilder, listType, std::move(boxed), message));
  246. }
  247. const TType* itemType = listType->GetItemType();
  248. std::vector<NUdf::TUnboxedValue> list;
  249. if (TBoxedValueAccessor::HasFastListLength(*boxed))
  250. list.reserve(TBoxedValueAccessor::GetListLength(*boxed));
  251. bool childWrapped = false;
  252. ui64 curIndex = 0;
  253. const auto iter = TBoxedValueAccessor::GetListIterator(*boxed);
  254. for (NUdf::TUnboxedValue current; iter.Next(current); ++curIndex) {
  255. list.emplace_back(TValidate<TValidateErrorPolicy, TValidateModeGreedy>::Value(valueBuilder, itemType, std::move(current),
  256. TStringBuilder() << "LazyList[" << curIndex << "]" << VERIFY_DELIMITER << message, &childWrapped));
  257. }
  258. const auto elementsCount = TBoxedValueAccessor::GetListLength(*boxed);
  259. if (curIndex != elementsCount) {
  260. TValidateErrorPolicy::Generate(TStringBuilder() << "TValidateModeGreedy::ProcessList, wrong list length returned, expected: " << curIndex << ", but got: " << elementsCount << VERIFY_DELIMITER << message);
  261. }
  262. if (childWrapped) {
  263. if (wrapped) {
  264. *wrapped = true;
  265. }
  266. return valueBuilder->NewList(list.data(), list.size());
  267. }
  268. return NUdf::TUnboxedValuePod(std::move(boxed));
  269. }
  270. static TUnboxedValue ProcessDict(const IValueBuilder* valueBuilder, const TDictType* dictType, IBoxedValuePtr&& boxed, const TString& message, bool* wrapped) {
  271. auto keyType = dictType->GetKeyType();
  272. auto payloadType = dictType->GetPayloadType();
  273. auto dictBuilder = valueBuilder->NewDict(dictType, TDictFlags::Sorted);
  274. bool childWrapped = false;
  275. ui64 curIndex = 0;
  276. const auto iter = TBoxedValueAccessor::GetDictIterator(*boxed);
  277. for (NUdf::TUnboxedValue key, payload; iter.NextPair(key, payload); ++curIndex) {
  278. key = TValidate<TValidateErrorPolicy, TValidateModeLazy<TValidateErrorPolicy>>::Value(valueBuilder, keyType, std::move(key),
  279. TStringBuilder() << "GreedyDict[" << curIndex << "], validate key" << VERIFY_DELIMITER << message);
  280. payload = TValidate<TValidateErrorPolicy, TValidateModeLazy<TValidateErrorPolicy>>::Value(valueBuilder, payloadType, std::move(payload),
  281. TStringBuilder() << "GreedyDict[" << curIndex << "], validate payload" << VERIFY_DELIMITER << message);
  282. dictBuilder->Add(std::move(key), std::move(payload));
  283. }
  284. const auto elementsCount = TBoxedValueAccessor::GetDictLength(*boxed);
  285. if (curIndex != elementsCount) {
  286. TValidateErrorPolicy::Generate(TStringBuilder() << "TValidateModeGreedy::ProcessDict, wrong dict length returned, expected: " << curIndex << ", but got: " << elementsCount << VERIFY_DELIMITER << message);
  287. }
  288. if (childWrapped) {
  289. if (wrapped) {
  290. *wrapped = true;
  291. }
  292. return dictBuilder->Build();
  293. }
  294. return NUdf::TUnboxedValuePod(std::move(boxed));
  295. }
  296. };
  297. template<class TValidateErrorPolicy, class TValidateMode>
  298. NUdf::TUnboxedValue TValidate<TValidateErrorPolicy, TValidateMode>::Value(const IValueBuilder* valueBuilder, const TType* type, NUdf::TUnboxedValue&& value, const TString& message, bool* wrapped) {
  299. if (!value && !(type->IsOptional() || type->IsNull())) {
  300. TValidateErrorPolicy::Generate(TStringBuilder() << "Expected value '" << PrintNode(type, true) << "', but got Empty" << VERIFY_DELIMITER << message);
  301. }
  302. switch (type->GetKind()) {
  303. case TType::EKind::Void:
  304. case TType::EKind::Null:
  305. case TType::EKind::EmptyList:
  306. case TType::EKind::EmptyDict:
  307. break;
  308. case TType::EKind::Data: {
  309. auto dataType = static_cast<const TDataType*>(type);
  310. auto dataTypeId = dataType->GetSchemeType();
  311. auto slot = NUdf::FindDataSlot(dataTypeId);
  312. if (!slot) {
  313. TValidateErrorPolicy::GenerateExc(TUdfValidateException() << "Unregistered TypeId: " << dataTypeId << VERIFY_DELIMITER << message);
  314. }
  315. if (!IsValidValue(*slot, value)) {
  316. TValidateErrorPolicy::Generate(TStringBuilder() << "Expected value '" << PrintNode(type, true) << "' does not conform" << VERIFY_DELIMITER << message);
  317. }
  318. break;
  319. }
  320. case TType::EKind::Optional: {
  321. if (!value) {
  322. break;
  323. }
  324. auto optionalType = static_cast<const TOptionalType*>(type);
  325. bool childWrapped = false;
  326. auto upValue = TValidate<TValidateErrorPolicy, TValidateMode>::Value(valueBuilder, optionalType->GetItemType(), value.GetOptionalValue(), TStringBuilder() << "Optional" << message, &childWrapped);
  327. if (childWrapped) {
  328. if (wrapped) {
  329. *wrapped = true;
  330. }
  331. return upValue.Release().MakeOptional();
  332. }
  333. break;
  334. }
  335. case TType::EKind::List: {
  336. if (!value.IsBoxed()) {
  337. TValidateErrorPolicy::Generate(TStringBuilder() << "expected value '" << PrintNode(type, true) << "' not conform" << VERIFY_DELIMITER << message);
  338. }
  339. auto listType = static_cast<const TListType*>(type);
  340. return TValidateMode::ProcessList(valueBuilder, listType, std::move(value.Release().AsBoxed()), message, wrapped);
  341. }
  342. case TType::EKind::Struct: {
  343. if (!value.IsBoxed()) {
  344. TValidateErrorPolicy::Generate(TStringBuilder() << "expected value '" << PrintNode(type, true) << "' not conform" << VERIFY_DELIMITER << message);
  345. }
  346. auto structType = static_cast<const TStructType*>(type);
  347. bool childWrapped = false;
  348. TSmallVec<TUnboxedValue> stackItems(structType->GetMembersCount());
  349. for (ui32 index = 0; index < structType->GetMembersCount(); ++index) {
  350. TType* memberType = structType->GetMemberType(index);
  351. stackItems[index] = TValidate<TValidateErrorPolicy, TValidateMode>::Value(valueBuilder, memberType, value.GetElement(index), TStringBuilder() << "Struct[" << structType->GetMemberName(index) << "]" << VERIFY_DELIMITER << message, &childWrapped);
  352. }
  353. if (childWrapped) {
  354. TUnboxedValue* items = nullptr;
  355. const auto wrappedStruct = valueBuilder->NewArray(structType->GetMembersCount(), items);
  356. for (ui32 index = 0; index < structType->GetMembersCount(); ++index) {
  357. items[index] = std::move(stackItems[index]);
  358. }
  359. if (wrapped) {
  360. *wrapped = true;
  361. }
  362. return wrappedStruct;
  363. }
  364. break;
  365. }
  366. case TType::EKind::Tuple: {
  367. if (!value.IsBoxed()) {
  368. TValidateErrorPolicy::Generate(TStringBuilder() << "expected value '" << PrintNode(type, true) << "' not conform" << VERIFY_DELIMITER << message);
  369. }
  370. auto tupleType = static_cast<const TTupleType*>(type);
  371. bool childWrapped = false;
  372. TSmallVec<NUdf::TUnboxedValue> stackItems(tupleType->GetElementsCount());
  373. for (ui32 index = 0; index < tupleType->GetElementsCount(); ++index) {
  374. TType* elementType = tupleType->GetElementType(index);
  375. stackItems[index] = TValidate<TValidateErrorPolicy, TValidateMode>::Value(valueBuilder, elementType, value.GetElement(index), TStringBuilder() << "Tuple[" << index << "]" << VERIFY_DELIMITER << message, &childWrapped);
  376. }
  377. if (childWrapped) {
  378. TUnboxedValue* items = nullptr;
  379. const auto wrappedTuple = valueBuilder->NewArray(tupleType->GetElementsCount(), items);
  380. for (ui32 index = 0; index < tupleType->GetElementsCount(); ++index) {
  381. items[index] = std::move(stackItems[index]);
  382. }
  383. if (wrapped) {
  384. *wrapped = true;
  385. }
  386. return wrappedTuple;
  387. }
  388. break;
  389. }
  390. case TType::EKind::Dict: {
  391. if (!value.IsBoxed()) {
  392. TValidateErrorPolicy::Generate(TStringBuilder() << "expected value '" << PrintNode(type, true) << "' not conform" << VERIFY_DELIMITER << message);
  393. }
  394. auto dictType = static_cast<const TDictType*>(type);
  395. return TValidateMode::ProcessDict(valueBuilder, dictType, std::move(value.Release().AsBoxed()), message, wrapped);
  396. }
  397. case TType::EKind::Callable: {
  398. if (!value.IsBoxed()) {
  399. TValidateErrorPolicy::Generate(TStringBuilder() << "expected value '" << PrintNode(type, true) << "' not conform" << VERIFY_DELIMITER << message);
  400. }
  401. auto callableType = static_cast<const TCallableType*>(type);
  402. if (wrapped) {
  403. *wrapped = true;
  404. }
  405. TValidate<TValidateErrorPolicy>::WrapCallable(callableType, value, message);
  406. return value;
  407. }
  408. case TType::EKind::Type:
  409. // metatype allways valid if we meet it
  410. break;
  411. case TType::EKind::Resource:
  412. // resource allways valid if we meet it
  413. break;
  414. case TType::EKind::Stream:
  415. case TType::EKind::Variant:
  416. case TType::EKind::Block:
  417. // TODO validate it
  418. break;
  419. case TType::EKind::Tagged: {
  420. auto taggedType = static_cast<const TTaggedType*>(type);
  421. bool childWrapped = false;
  422. auto upValue = TValidate<TValidateErrorPolicy, TValidateMode>::Value(valueBuilder, taggedType->GetBaseType(), TUnboxedValue(value), TStringBuilder() << "Tagged[" << taggedType->GetTag() << "]" << message, &childWrapped);
  423. if (childWrapped) {
  424. if (wrapped) {
  425. *wrapped = true;
  426. }
  427. return upValue;
  428. }
  429. break;
  430. }
  431. default:
  432. Y_ABORT("Verify value meet unexpected type kind: %s", type->GetKindAsStr().data());
  433. }
  434. return std::move(value);
  435. }
  436. template<class TValidateErrorPolicy, class TValidateMode>
  437. void TValidate<TValidateErrorPolicy, TValidateMode>::WrapCallable(const TCallableType* callableType, NUdf::TUnboxedValue& callable, const TString& message) {
  438. callable = NUdf::TUnboxedValuePod(new WrapCallableValue<TValidateErrorPolicy, TValidateMode>(callableType, std::move(callable), TStringBuilder() << "CallableWrapper<" << callableType->GetName() << ">" << VERIFY_DELIMITER << message));
  439. }
  440. template struct TValidate<TValidateErrorPolicyThrow, TValidateModeLazy<TValidateErrorPolicyThrow>>;
  441. template struct TValidate<TValidateErrorPolicyThrow, TValidateModeGreedy<TValidateErrorPolicyThrow>>;
  442. template struct TValidate<TValidateErrorPolicyFail, TValidateModeLazy<TValidateErrorPolicyFail>>;
  443. template struct TValidate<TValidateErrorPolicyFail, TValidateModeGreedy<TValidateErrorPolicyFail>>;
  444. } // namespace MiniKQL
  445. } // namespace NKikimr