yql_restricted_yson.cpp 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  1. #include "yql_restricted_yson.h"
  2. #include <yql/essentials/utils/parse_double.h>
  3. #include <yql/essentials/utils/yql_panic.h>
  4. #include <library/cpp/yson/detail.h>
  5. #include <library/cpp/yson/parser.h>
  6. #include <library/cpp/yson/node/node_io.h>
  7. #include <library/cpp/yson/node/node_visitor.h>
  8. #include <util/generic/algorithm.h>
  9. #include <util/generic/stack.h>
  10. namespace NYql {
  11. namespace NResult {
  12. namespace {
  13. class TRestrictedYsonFormatter : public NYson::TYsonConsumerBase {
  14. public:
  15. TRestrictedYsonFormatter(TYsonResultWriter& writer)
  16. : Writer(writer) {
  17. }
  18. void OnStringScalar(TStringBuf value) override {
  19. Open();
  20. Type(TStringBuf("string"));
  21. Buffer.clear();
  22. bool isAscii = true;
  23. for (size_t i = 0; i < value.size(); ++i) {
  24. if (ui8(value[i]) < 128) {
  25. if (!isAscii) {
  26. Buffer.push_back(value[i]);
  27. }
  28. } else {
  29. if (isAscii) {
  30. Buffer.resize(i);
  31. Copy(value.data(), value.data() + i, Buffer.data());
  32. isAscii = false;
  33. }
  34. Buffer.push_back('\xC0' | (ui8(value[i]) >> 6));
  35. Buffer.push_back('\x80' | (ui8(value[i]) & ~'\xC0'));
  36. }
  37. }
  38. if (isAscii) {
  39. Value(value);
  40. } else {
  41. Value(TStringBuf(Buffer.data(), Buffer.size()));
  42. }
  43. Close();
  44. }
  45. void OnInt64Scalar(i64 value) override {
  46. Open();
  47. Type(TStringBuf("int64"));
  48. Value(ToString(value));
  49. Close();
  50. }
  51. void OnUint64Scalar(ui64 value) override {
  52. Open();
  53. Type(TStringBuf("uint64"));
  54. Value(ToString(value));
  55. Close();
  56. }
  57. void OnDoubleScalar(double value) override {
  58. Open();
  59. Type(TStringBuf("double"));
  60. Value(::FloatToString(value));
  61. Close();
  62. }
  63. void OnBooleanScalar(bool value) override {
  64. Open();
  65. Type(TStringBuf("boolean"));
  66. Value(value ? TStringBuf("true") : TStringBuf("false"));
  67. Close();
  68. }
  69. void OnEntity() override {
  70. if (AfterAttributes) {
  71. Writer.OnKeyedItem(TStringBuf("$value"));
  72. Writer.OnEntity();
  73. Writer.OnEndMap();
  74. AfterAttributes = false;
  75. } else {
  76. Writer.OnEntity();
  77. }
  78. }
  79. void OnBeginList() override {
  80. if (AfterAttributes) {
  81. Writer.OnKeyedItem(TStringBuf("$value"));
  82. }
  83. Writer.OnBeginList();
  84. HasAttributes.push(AfterAttributes);
  85. AfterAttributes = false;
  86. }
  87. void OnListItem() override {
  88. Writer.OnListItem();
  89. }
  90. void OnEndList() override {
  91. Writer.OnEndList();
  92. if (HasAttributes.top()) {
  93. Writer.OnEndMap();
  94. }
  95. HasAttributes.pop();
  96. }
  97. void OnBeginMap() override {
  98. if (AfterAttributes) {
  99. Writer.OnKeyedItem(TStringBuf("$value"));
  100. }
  101. Writer.OnBeginMap();
  102. HasAttributes.push(AfterAttributes);
  103. AfterAttributes = false;
  104. }
  105. void OnKeyedItem(TStringBuf key) override {
  106. if (key.StartsWith('$')) {
  107. Writer.OnKeyedItem(TString("$") + key);
  108. } else {
  109. Writer.OnKeyedItem(key);
  110. }
  111. }
  112. void OnEndMap() override {
  113. Writer.OnEndMap();
  114. if (HasAttributes.top()) {
  115. Writer.OnEndMap();
  116. }
  117. HasAttributes.pop();
  118. }
  119. void OnBeginAttributes() override {
  120. Writer.OnBeginMap();
  121. Writer.OnKeyedItem(TStringBuf("$attributes"));
  122. Writer.OnBeginMap();
  123. }
  124. void OnEndAttributes() override {
  125. Writer.OnEndMap();
  126. AfterAttributes = true;
  127. }
  128. void Open() {
  129. if (!AfterAttributes) {
  130. Writer.OnBeginMap();
  131. }
  132. }
  133. void Close() {
  134. Writer.OnEndMap();
  135. AfterAttributes = false;
  136. }
  137. void Type(const TStringBuf& type) {
  138. Writer.OnKeyedItem(TStringBuf("$type"));
  139. Writer.OnUtf8StringScalar(type);
  140. }
  141. void Value(const TStringBuf& value) {
  142. Writer.OnKeyedItem(TStringBuf("$value"));
  143. Writer.OnUtf8StringScalar(value);
  144. }
  145. private:
  146. TYsonResultWriter& Writer;
  147. TStack<bool> HasAttributes;
  148. bool AfterAttributes = false;
  149. TVector<char> Buffer;
  150. };
  151. TString DecodeRestrictedBinaryString(const TString& data) {
  152. TString res;
  153. for (size_t i = 0; i < data.size(); ++i) {
  154. char c = data[i];
  155. if (((unsigned char)c) >= 128) {
  156. YQL_ENSURE(i + 1 < data.size());
  157. res.push_back(((c & 0x03) << 6) | (data[i + 1] & 0x3f));
  158. ++i;
  159. } else {
  160. res.push_back(c);
  161. }
  162. }
  163. return res;
  164. }
  165. void DecodeRestrictedYson(const NYT::TNode& node, NYson::TYsonConsumerBase& writer) {
  166. switch (node.GetType()) {
  167. case NYT::TNode::String:
  168. writer.OnStringScalar(node.AsString());
  169. return;
  170. case NYT::TNode::Int64:
  171. writer.OnInt64Scalar(node.AsInt64());
  172. return;
  173. case NYT::TNode::Uint64:
  174. writer.OnUint64Scalar(node.AsUint64());
  175. return;
  176. case NYT::TNode::Bool:
  177. writer.OnBooleanScalar(node.AsBool());
  178. return;
  179. case NYT::TNode::Double:
  180. writer.OnDoubleScalar(node.AsDouble());
  181. return;
  182. case NYT::TNode::Null:
  183. writer.OnEntity();
  184. return;
  185. case NYT::TNode::List:
  186. // just a list without attributes
  187. writer.OnBeginList();
  188. for (const auto& item : node.AsList()) {
  189. writer.OnListItem();
  190. DecodeRestrictedYson(item, writer);
  191. }
  192. writer.OnEndList();
  193. return;
  194. case NYT::TNode::Map:
  195. // process below
  196. break;
  197. default:
  198. YQL_ENSURE(false, "Unsupported node type: " << static_cast<int>(node.GetType()));
  199. }
  200. YQL_ENSURE(node.IsMap());
  201. if (!node.HasKey("$value")) {
  202. // just a map without attributes
  203. writer.OnBeginMap();
  204. for (const auto& x : node.AsMap()) {
  205. if (x.first.StartsWith("$$")) {
  206. writer.OnKeyedItem(x.first.substr(1));
  207. } else {
  208. writer.OnKeyedItem(x.first);
  209. }
  210. DecodeRestrictedYson(x.second, writer);
  211. }
  212. writer.OnEndMap();
  213. return;
  214. }
  215. if (node.HasKey("$attributes")) {
  216. writer.OnBeginAttributes();
  217. for (const auto& x : node["$attributes"].AsMap()) {
  218. if (x.first.StartsWith("$$")) {
  219. writer.OnKeyedItem(x.first.substr(1));
  220. } else {
  221. writer.OnKeyedItem(x.first);
  222. }
  223. DecodeRestrictedYson(x.second, writer);
  224. }
  225. writer.OnEndAttributes();
  226. }
  227. if (!node.HasKey("$type")) {
  228. // non-scalars with attributes
  229. DecodeRestrictedYson(node["$value"], writer);
  230. return;
  231. }
  232. auto type = node["$type"].AsString();
  233. if (type == "int64") {
  234. writer.OnInt64Scalar(FromString<i64>(node["$value"].AsString()));
  235. } else if (type == "uint64") {
  236. writer.OnUint64Scalar(FromString<ui64>(node["$value"].AsString()));
  237. } else if (type == "double") {
  238. writer.OnDoubleScalar(DoubleFromString(TStringBuf(node["$value"].AsString())));
  239. } else if (type == "boolean") {
  240. writer.OnBooleanScalar(FromString<bool>(node["$value"].AsString()));
  241. } else if (type == "string") {
  242. writer.OnStringScalar(DecodeRestrictedBinaryString(node["$value"].AsString()));
  243. } else {
  244. YQL_ENSURE(false, "Unsupported type: " << type);
  245. }
  246. }
  247. } // anonymous namespace
  248. void EncodeRestrictedYson(TYsonResultWriter& writer, const TStringBuf& yson) {
  249. TRestrictedYsonFormatter formatter(writer);
  250. NYson::ParseYsonStringBuffer(yson, &formatter);
  251. }
  252. TString EncodeRestrictedYson(const NYT::TNode& node, NYson::EYsonFormat format) {
  253. TStringStream stream;
  254. NYson::TYsonWriter writer(&stream, format);
  255. TYsonResultWriter resultWriter(writer);
  256. TRestrictedYsonFormatter formatter(resultWriter);
  257. NYT::TNodeVisitor visitor(&formatter);
  258. visitor.Visit(node);
  259. return stream.Str();
  260. }
  261. TString DecodeRestrictedYson(const NYT::TNode& node, NYson::EYsonFormat format) {
  262. TStringStream stream;
  263. NYson::TYsonWriter writer(&stream, format);
  264. DecodeRestrictedYson(node, writer);
  265. return stream.Str();
  266. }
  267. TString DecodeRestrictedYson(const TStringBuf& yson, NYson::EYsonFormat format) {
  268. return DecodeRestrictedYson(NYT::NodeFromYsonString(yson), format);
  269. }
  270. }
  271. }