summaryrefslogtreecommitdiffstats
path: root/yql/essentials/providers/common/structured_token/yql_structured_token.cpp
blob: 88482f68312476842ee25cee055e9dbf0aa633b8 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
#include "yql_structured_token.h"

#include <yql/essentials/utils/utf8.h>

#include <library/cpp/json/json_reader.h>
#include <library/cpp/json/json_writer.h>
#include <library/cpp/string_utils/base64/base64.h>


namespace NYql {

TStructuredToken::TStructuredToken(TMap<TString, TString>&& data)
    : Data_(std::move(data)) {

}

TString TStructuredToken::GetField(const TString& name) const {
    return Data_.at(name);
}

TString TStructuredToken::GetFieldOrDefault(const TString& name, const TString& defaultValue) const {
    return FindField(name).GetOrElse(defaultValue);
}

TMaybe<TString> TStructuredToken::FindField(const TString& name) const {
    auto* r = Data_.FindPtr(name);
    return r ? MakeMaybe(*r) : Nothing();
}

bool TStructuredToken::HasField(const TString& name) const {
    return Data_.contains(name);
}

TStructuredToken& TStructuredToken::SetField(const TString& name, const TString& value) {
    Data_[name] = value;
    return *this;
}

TStructuredToken& TStructuredToken::ClearField(const TString& name) {
    Data_.erase(name);
    return *this;
}

TString TStructuredToken::ToJson() const {
    TStringStream output;
    // set "format output" to false, no need for extra indents
    // "sort keys" value is not used actually
    // turn on UTF8 validation (need for keys checks)
    NJson::TJsonWriter writer(&output, false, true, true);
    writer.OpenMap();

    for (auto&[k, v] : Data_) {
        if (!IsUtf8(v)) {
            writer.Write(k + "(base64)", Base64Encode(TStringBuf(v)));
        } else {
            writer.Write(k, v);
        }
    }
    writer.CloseMap();
    writer.Flush();

    return output.Str();
}

TStructuredToken ParseStructuredToken(const TString& content) {
    Y_ABORT_UNLESS(IsStructuredTokenJson(content));

    NJson::TJsonValue v;
    // will throw on error
    NJson::ReadJsonTree(content, &v, true);
    TMap<TString, TString> data;
    const auto& m = v.GetMapSafe();
    for (auto&[k, v] : m) {
        TStringBuf key(k);
        if (key.ChopSuffix("(base64)")) {
            const auto& s = v.GetStringSafe();
            data[TString(key)] = Base64Decode(TStringBuf(s));
        } else {
            data[k] = v.GetStringSafe();
        }
    }
    return TStructuredToken(std::move(data));
}

bool IsStructuredTokenJson(const TString& content) {
    return content.StartsWith("{") && content.EndsWith("}");
}

} // namespace NYql