make.cpp 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. #include "make.h"
  2. #include "node.h"
  3. #include "yson.h"
  4. #include "json.h"
  5. #include <yql/essentials/public/udf/udf_type_inspection.h>
  6. #include <util/string/builder.h>
  7. namespace NYql::NDom {
  8. using namespace NUdf;
  9. namespace {
  10. TUnboxedValuePod MakeData(const TDataTypeId nodeType, const TUnboxedValuePod value, const IValueBuilder* valueBuilder) {
  11. switch (nodeType) {
  12. case TDataType<char*>::Id: return value;
  13. case TDataType<TUtf8>::Id: return value;
  14. case TDataType<bool>::Id: return SetNodeType<ENodeType::Bool>(value);
  15. case TDataType<i8>::Id: return SetNodeType<ENodeType::Int64>(TUnboxedValuePod(i64(value.Get<i8>())));
  16. case TDataType<i16>::Id: return SetNodeType<ENodeType::Int64>(TUnboxedValuePod(i64(value.Get<i16>())));
  17. case TDataType<i32>::Id: return SetNodeType<ENodeType::Int64>(TUnboxedValuePod(i64(value.Get<i32>())));
  18. case TDataType<i64>::Id: return SetNodeType<ENodeType::Int64>(value);
  19. case TDataType<ui8>::Id: return SetNodeType<ENodeType::Uint64>(TUnboxedValuePod(ui64(value.Get<ui8>())));
  20. case TDataType<ui16>::Id: return SetNodeType<ENodeType::Uint64>(TUnboxedValuePod(ui64(value.Get<ui16>())));
  21. case TDataType<ui32>::Id: return SetNodeType<ENodeType::Uint64>(TUnboxedValuePod(ui64(value.Get<ui32>())));
  22. case TDataType<ui64>::Id: return SetNodeType<ENodeType::Uint64>(value);
  23. case TDataType<float>::Id: return SetNodeType<ENodeType::Double>(TUnboxedValuePod(double(value.Get<float>())));
  24. case TDataType<double>::Id: return SetNodeType<ENodeType::Double>(value);
  25. case TDataType<TYson>::Id: return TryParseYsonDom(value.AsStringRef(), valueBuilder).Release();
  26. case TDataType<TJson>::Id: return TryParseJsonDom(value.AsStringRef(), valueBuilder).Release();
  27. default: break;
  28. }
  29. Y_ABORT("Unsupported data type.");
  30. }
  31. TUnboxedValuePod MakeList(const ITypeInfoHelper* typeHelper, const TType* itemType, const TUnboxedValuePod value, const IValueBuilder* valueBuilder) {
  32. if (const auto elements = value.GetElements()) {
  33. if (const auto size = value.GetListLength()) {
  34. TUnboxedValue* items = nullptr;
  35. auto res = valueBuilder->NewArray(size, items);
  36. for (ui64 i = 0ULL; i < size; ++i) {
  37. *items++ = MakeDom(typeHelper, itemType, elements[i], valueBuilder);
  38. }
  39. return SetNodeType<ENodeType::List>(res.Release());
  40. }
  41. } else {
  42. TSmallVec<TUnboxedValue> items;
  43. if (value.HasFastListLength()) {
  44. items.reserve(value.GetListLength());
  45. }
  46. const auto iterator = value.GetListIterator();
  47. for (TUnboxedValue current; iterator.Next(current);) {
  48. items.emplace_back(MakeDom(typeHelper, itemType, current, valueBuilder));
  49. }
  50. if (!items.empty()) {
  51. auto res = valueBuilder->NewList(items.data(), items.size());
  52. return SetNodeType<ENodeType::List>(res.Release());
  53. }
  54. }
  55. return SetNodeType<ENodeType::List>(TUnboxedValuePod::Void());
  56. }
  57. TUnboxedValuePod MakeDict(const ITypeInfoHelper* typeHelper, const TType* itemType, const TUnboxedValuePod value, const IValueBuilder* valueBuilder) {
  58. TSmallVec<TPair, TStdAllocatorForUdf<TPair>> items;
  59. items.reserve(value.GetDictLength());
  60. const auto it = value.GetDictIterator();
  61. for (TUnboxedValue x, y; it.NextPair(x, y);) {
  62. items.emplace_back(x, MakeDom(typeHelper, itemType, y, valueBuilder));
  63. }
  64. if (items.empty()) {
  65. return SetNodeType<ENodeType::Dict>(TUnboxedValuePod::Void());
  66. }
  67. return SetNodeType<ENodeType::Dict>(TUnboxedValuePod(new TMapNode(items.data(), items.size())));
  68. }
  69. TUnboxedValuePod MakeTuple(const ITypeInfoHelper* typeHelper, const TType* shape, const TUnboxedValuePod value, const IValueBuilder* valueBuilder) {
  70. if (const auto tupleTypeInspector = TTupleTypeInspector(*typeHelper, shape); const auto size = tupleTypeInspector.GetElementsCount()) {
  71. TUnboxedValue* items = nullptr;
  72. auto res = valueBuilder->NewArray(size, items);
  73. for (ui64 i = 0ULL; i < size; ++i) {
  74. *items++ = MakeDom(typeHelper, tupleTypeInspector.GetElementType(i), static_cast<const TUnboxedValuePod&>(value.GetElement(i)), valueBuilder);
  75. }
  76. return SetNodeType<ENodeType::List>(res.Release());
  77. }
  78. return SetNodeType<ENodeType::List>(TUnboxedValuePod::Void());
  79. }
  80. TUnboxedValuePod MakeStruct(const ITypeInfoHelper* typeHelper, const TType* shape, const TUnboxedValuePod value, const IValueBuilder* valueBuilder) {
  81. if (const auto structTypeInspector = TStructTypeInspector(*typeHelper, shape); const auto size = structTypeInspector.GetMembersCount()) {
  82. TSmallVec<TPair, TStdAllocatorForUdf<TPair>> items;
  83. items.reserve(size);
  84. for (ui64 i = 0ULL; i < size; ++i) {
  85. items.emplace_back(
  86. valueBuilder->NewString(structTypeInspector.GetMemberName(i)),
  87. MakeDom(typeHelper, structTypeInspector.GetMemberType(i), static_cast<const TUnboxedValuePod&>(value.GetElement(i)), valueBuilder)
  88. );
  89. }
  90. return SetNodeType<ENodeType::Dict>(TUnboxedValuePod(new TMapNode(items.data(), items.size())));
  91. }
  92. return SetNodeType<ENodeType::Dict>(TUnboxedValuePod::Void());
  93. }
  94. TUnboxedValuePod MakeVariant(const ITypeInfoHelper* typeHelper, const TType* shape, const TUnboxedValuePod value, const IValueBuilder* valueBuilder) {
  95. const auto index = value.GetVariantIndex();
  96. const auto& item = value.GetVariantItem();
  97. const auto underlyingType = TVariantTypeInspector(*typeHelper, shape).GetUnderlyingType();
  98. switch (const auto kind = typeHelper->GetTypeKind(underlyingType)) {
  99. case ETypeKind::Tuple:
  100. if (const auto tupleTypeInspector = TTupleTypeInspector(*typeHelper, underlyingType); index < tupleTypeInspector.GetElementsCount())
  101. return MakeDom(typeHelper, tupleTypeInspector.GetElementType(index), item, valueBuilder);
  102. break;
  103. case ETypeKind::Struct:
  104. if (const auto structTypeInspector = TStructTypeInspector(*typeHelper, underlyingType); index < structTypeInspector.GetMembersCount())
  105. return MakeDom(typeHelper, structTypeInspector.GetMemberType(index), item, valueBuilder);
  106. break;
  107. default:
  108. break;
  109. }
  110. Y_ABORT("Unsupported underlying type.");
  111. }
  112. }
  113. TUnboxedValuePod MakeDom(const ITypeInfoHelper* typeHelper, const TType* shape, const TUnboxedValuePod value, const IValueBuilder* valueBuilder) {
  114. switch (const auto kind = typeHelper->GetTypeKind(shape)) {
  115. case ETypeKind::Null:
  116. case ETypeKind::Void:
  117. return MakeEntity();
  118. case ETypeKind::EmptyList:
  119. return SetNodeType<ENodeType::List>(TUnboxedValuePod::Void());
  120. case ETypeKind::EmptyDict:
  121. return SetNodeType<ENodeType::Dict>(TUnboxedValuePod::Void());
  122. case ETypeKind::Data:
  123. return MakeData(TDataTypeInspector(*typeHelper, shape).GetTypeId(), value, valueBuilder);
  124. case ETypeKind::Optional:
  125. return value ? MakeDom(typeHelper, TOptionalTypeInspector(*typeHelper, shape).GetItemType(), value.GetOptionalValue(), valueBuilder) : MakeEntity();
  126. case ETypeKind::List:
  127. return MakeList(typeHelper, TListTypeInspector(*typeHelper, shape).GetItemType(), value, valueBuilder);
  128. case ETypeKind::Dict: {
  129. const auto dictTypeInspector = TDictTypeInspector(*typeHelper, shape);
  130. const auto keyType = dictTypeInspector.GetKeyType();
  131. Y_ABORT_UNLESS(ETypeKind::Data == typeHelper->GetTypeKind(keyType), "Unsupported dict key type kind.");
  132. const auto keyId = TDataTypeInspector(*typeHelper, keyType).GetTypeId();
  133. Y_ABORT_UNLESS(keyId == TDataType<char*>::Id || keyId == TDataType<TUtf8>::Id, "Unsupported dict key data type.");
  134. return MakeDict(typeHelper, dictTypeInspector.GetValueType(), value, valueBuilder);
  135. }
  136. case ETypeKind::Tuple:
  137. return MakeTuple(typeHelper, shape, value, valueBuilder);
  138. case ETypeKind::Struct:
  139. return MakeStruct(typeHelper, shape, value, valueBuilder);
  140. case ETypeKind::Variant:
  141. return MakeVariant(typeHelper, shape, value, valueBuilder);
  142. case ETypeKind::Resource:
  143. if (const auto inspector = TResourceTypeInspector(*typeHelper, shape); TStringBuf(inspector.GetTag()) == NodeResourceName)
  144. return value;
  145. [[fallthrough]];
  146. default:
  147. Y_ABORT("Unsupported data kind: %s", ToCString(kind));
  148. }
  149. }
  150. }