Skip to content

Commit cb01c24

Browse files
mikariqyryq
authored andcommitted
Added support for maps with custom key types in yson struct
commit_hash:689f70793e329f380fb3a8c065bce0f3bfff92f5
1 parent 44551d8 commit cb01c24

File tree

5 files changed

+164
-1
lines changed

5 files changed

+164
-1
lines changed
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
#include "complex_key_map.h"
2+
3+
#include <util/string/split.h>
4+
5+
#include <util/string/cast.h>
6+
#include <util/stream/output.h>
7+
8+
namespace NYT::NYTree {
9+
10+
using namespace NYson;
11+
12+
////////////////////////////////////////////////////////////////////////////////
13+
14+
TTestComplexKey TTestComplexKey::FromString(TStringBuf string)
15+
{
16+
TTestComplexKey key;
17+
Split(string, '/', key.First, key.Second);
18+
return key;
19+
}
20+
21+
TString TTestComplexKey::ToString() const
22+
{
23+
return Format("%v/%v", First, Second);
24+
}
25+
26+
bool TTestComplexKey::operator==(const TTestComplexKey& other) const
27+
{
28+
return std::tie(First, Second) == std::tie(other.First, other.Second);
29+
}
30+
31+
bool TTestComplexKey::operator<(const TTestComplexKey& other) const
32+
{
33+
return std::tie(First, Second) < std::tie(other.First, other.Second);
34+
}
35+
36+
void Serialize(const TTestComplexKey& value, IYsonConsumer* consumer)
37+
{
38+
consumer->OnStringScalar(ToString(value));
39+
}
40+
41+
void Deserialize(TTestComplexKey& value, INodePtr node)
42+
{
43+
if (node->GetType() == ENodeType::String) {
44+
value = FromString<TTestComplexKey>(node->AsString()->GetValue());
45+
} else {
46+
THROW_ERROR_EXCEPTION("Cannot parse TTestComplexKey value from %Qlv",
47+
node->GetType());
48+
}
49+
}
50+
51+
////////////////////////////////////////////////////////////////////////////////
52+
53+
} // namespace NYT::NYTree
54+
55+
////////////////////////////////////////////////////////////////////////////////
56+
57+
template <>
58+
NYT::NYTree::TTestComplexKey FromStringImpl<NYT::NYTree::TTestComplexKey, char>(const char* data, size_t size)
59+
{
60+
return NYT::NYTree::TTestComplexKey::FromString(TStringBuf(data, size));
61+
}
62+
63+
template <>
64+
bool TryFromStringImpl<NYT::NYTree::TTestComplexKey, char>(const char* data, size_t size, NYT::NYTree::TTestComplexKey& value)
65+
{
66+
try {
67+
value = NYT::NYTree::TTestComplexKey::FromString(TStringBuf(data, size));
68+
return true;
69+
} catch (const std::exception&) {
70+
return false;
71+
}
72+
}
73+
74+
////////////////////////////////////////////////////////////////////////////////
75+
76+
template <>
77+
void Out<NYT::NYTree::TTestComplexKey>(IOutputStream& out, const NYT::NYTree::TTestComplexKey& value) {
78+
out << value.ToString();
79+
}
80+
81+
////////////////////////////////////////////////////////////////////////////////
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#pragma once
2+
3+
#include <yt/yt/core/ytree/yson_struct.h>
4+
5+
namespace NYT::NYTree {
6+
7+
////////////////////////////////////////////////////////////////////////////////
8+
9+
struct TTestComplexKey
10+
{
11+
TString First;
12+
TString Second;
13+
14+
static TTestComplexKey FromString(TStringBuf string);
15+
TString ToString() const;
16+
17+
bool operator==(const TTestComplexKey& other) const;
18+
bool operator<(const TTestComplexKey& other) const;
19+
};
20+
21+
void Serialize(const TTestComplexKey& value, NYson::IYsonConsumer* consumer);
22+
void Deserialize(TTestComplexKey& value, NYTree::INodePtr node);
23+
24+
////////////////////////////////////////////////////////////////////////////////
25+
26+
} // namespace NYT::NYTree

yt/yt/core/ytree/unittests/ya.make

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ PROTO_NAMESPACE(yt)
77
SRCS(
88
attribute_filter_ut.cpp
99
attributes_ut.cpp
10+
complex_key_map.cpp
1011
lazy_ypath_service_ut.cpp
1112
options_ut.cpp
1213
resolver_ut.cpp

yt/yt/core/ytree/unittests/yson_struct_ut.cpp

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
#include "complex_key_map.h"
2+
13
#include <yt/yt/core/test_framework/framework.h>
24

35
#include <yt/yt/core/yson/writer.h>
@@ -4212,5 +4214,44 @@ TEST(TYsonStructTest, YsonStructLiteMoveAssign)
42124214

42134215
////////////////////////////////////////////////////////////////////////////////
42144216

4217+
struct TTestYsonStructWithMap
4218+
: public TYsonStruct
4219+
{
4220+
std::map<TString, TString> Map;
4221+
std::map<TTestComplexKey, TString> ComplexMap;
4222+
TTestComplexKey ComplexKey;
4223+
4224+
REGISTER_YSON_STRUCT(TTestYsonStructWithMap);
4225+
4226+
static void Register(TRegistrar registrar)
4227+
{
4228+
registrar.Parameter("map", &TThis::Map)
4229+
.Default();
4230+
registrar.Parameter("complex_map", &TThis::ComplexMap)
4231+
.Default();
4232+
registrar.Parameter("complex_key", &TThis::ComplexKey)
4233+
.Default();
4234+
}
4235+
};
4236+
4237+
using TTestYsonStructWithMapPtr = TIntrusivePtr<TTestYsonStructWithMap>;
4238+
4239+
TEST(TYsonStructTest, Map)
4240+
{
4241+
auto ysonStruct = New<TTestYsonStructWithMap>();
4242+
ysonStruct->Map["abc"] = "def";
4243+
ysonStruct->ComplexMap[{"abc", "def"}] = "ghi";
4244+
ysonStruct->ComplexKey = {"abc", "def"};
4245+
4246+
auto node = ConvertToNode(ysonStruct);
4247+
auto fromNode = ConvertTo<TTestYsonStructWithMapPtr>(node);
4248+
EXPECT_EQ(fromNode->Map, ysonStruct->Map);
4249+
EXPECT_EQ(fromNode->ComplexMap, ysonStruct->ComplexMap);
4250+
EXPECT_EQ(fromNode->ComplexKey, ysonStruct->ComplexKey);
4251+
EXPECT_EQ(*fromNode, *ysonStruct);
4252+
}
4253+
4254+
////////////////////////////////////////////////////////////////////////////////
4255+
42154256
} // namespace
42164257
} // namespace NYT::NYTree

yt/yt/core/ytree/yson_struct_detail-inl.h

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,20 @@ T DeserializeMapKey(TStringBuf value)
109109
}
110110
}
111111

112+
template <class T>
113+
TString SerializeMapKey(const T& value)
114+
{
115+
if constexpr (TEnumTraits<T>::IsEnum) {
116+
return FormatEnum(value);
117+
} else if constexpr (std::is_same_v<T, TGuid>) {
118+
return ToString(value);
119+
} else if constexpr (TStrongTypedefTraits<T>::IsStrongTypedef) {
120+
return SerializeMapKey<typename TStrongTypedefTraits<T>::TUnderlying>(value.Underlying());
121+
} else {
122+
return ToString(value);
123+
}
124+
}
125+
112126
////////////////////////////////////////////////////////////////////////////////
113127

114128
template <class T>
@@ -577,7 +591,7 @@ inline void PostprocessRecursive(
577591
PostprocessRecursive(
578592
value,
579593
[&pathGetter, &key = key] {
580-
return pathGetter() + "/" + NYPath::ToYPathLiteral(key);
594+
return pathGetter() + "/" + NYPath::ToYPathLiteral(SerializeMapKey(key));
581595
});
582596
}
583597
}

0 commit comments

Comments
 (0)