C++ YT Wrapper
C++ library for working with YT clusters
Loading...
Searching...
No Matches
fluent.h
Go to the documentation of this file.
1#pragma once
2
108
109
110#include "common.h"
111#include "serialize.h"
112
113#include <library/cpp/yson/node/serialize.h>
114#include <library/cpp/yson/node/node_builder.h>
115
116#include <library/cpp/yson/consumer.h>
117#include <library/cpp/yson/writer.h>
118
119#include <util/generic/noncopyable.h>
120#include <util/generic/ptr.h>
121#include <util/stream/str.h>
122
123namespace NYT {
124
126
127template <class T>
129{
130 using TUnwrapped = T;
131
132 static TUnwrapped Unwrap(T t)
133 {
134 return std::move(t);
135 }
136};
137
139
141{ };
142
143template <>
145{
146 using TUnwrapped = void;
147
148 static TUnwrapped Unwrap(TFluentYsonVoid)
149 { }
150};
151
153
156 : private TNonCopyable
157{
158private:
159 template <class T>
160 static void WriteValue(NYT::NYson::IYsonConsumer* consumer, const T& value)
161 {
162 Serialize(value, consumer);
163 }
164
165public:
166 class TFluentAny;
167 template <class TParent> class TAny;
168 template <class TParent> class TToAttributes;
169 template <class TParent> class TAttributes;
170 template <class TParent> class TListType;
171 template <class TParent> class TMapType;
172
174 template <class TParent>
176 {
177 public:
179 operator NYT::NYson::IYsonConsumer* () const
180 {
181 return Consumer;
182 }
183
184 protected:
186 NYT::NYson::IYsonConsumer* Consumer;
187 TParent Parent;
188
189 TFluentBase(NYT::NYson::IYsonConsumer* consumer, TParent parent)
190 : Consumer(consumer)
191 , Parent(std::move(parent))
192 { }
193
194 using TUnwrappedParent = typename TFluentYsonUnwrapper<TParent>::TUnwrapped;
195
196 TUnwrappedParent GetUnwrappedParent()
197 {
198 return TFluentYsonUnwrapper<TParent>::Unwrap(std::move(Parent));
199 }
201 };
202
204 template <template <class TParent> class TThis, class TParent>
205 class TFluentFragmentBase
206 : public TFluentBase<TParent>
207 {
208 public:
209 using TDeepThis = TThis<TParent>;
210 using TShallowThis = TThis<TFluentYsonVoid>;
211 using TUnwrappedParent = typename TFluentYsonUnwrapper<TParent>::TUnwrapped;
212
213 explicit TFluentFragmentBase(NYT::NYson::IYsonConsumer* consumer, TParent parent = TParent())
214 : TFluentBase<TParent>(consumer, std::move(parent))
215 { }
216
218 template <class TFunc>
219 TDeepThis& Do(const TFunc& func)
220 {
221 func(TShallowThis(this->Consumer));
222 return *static_cast<TDeepThis*>(this);
223 }
224
226 template <class TFunc>
227 TDeepThis& DoIf(bool condition, const TFunc& func)
228 {
229 if (condition) {
230 func(TShallowThis(this->Consumer));
231 }
232 return *static_cast<TDeepThis*>(this);
233 }
234
236 template <class TFunc, class TIterator>
237 TDeepThis& DoFor(const TIterator& begin, const TIterator& end, const TFunc& func)
238 {
239 for (auto current = begin; current != end; ++current) {
240 func(TShallowThis(this->Consumer), current);
241 }
242 return *static_cast<TDeepThis*>(this);
243 }
244
246 template <class TFunc, class TCollection>
247 TDeepThis& DoFor(const TCollection& collection, const TFunc& func)
248 {
249 for (const auto& item : collection) {
250 func(TShallowThis(this->Consumer), item);
251 }
252 return *static_cast<TDeepThis*>(this);
253 }
254
255 };
256
258 template <class TParent>
259 class TAnyWithoutAttributes
260 : public TFluentBase<TParent>
261 {
262 public:
263 using TUnwrappedParent = typename TFluentYsonUnwrapper<TParent>::TUnwrapped;
264
265 TAnyWithoutAttributes(NYT::NYson::IYsonConsumer* consumer, TParent parent)
266 : TFluentBase<TParent>(consumer, std::move(parent))
267 { }
268
270 template <class T>
271 TUnwrappedParent Value(const T& value)
272 {
273 WriteValue(this->Consumer, value);
274 return this->GetUnwrappedParent();
275 }
276
278 TUnwrappedParent Entity()
279 {
280 this->Consumer->OnEntity();
281 return this->GetUnwrappedParent();
282 }
283
285 template <class TCollection>
286 TUnwrappedParent List(const TCollection& collection)
287 {
288 this->Consumer->OnBeginList();
289 for (const auto& item : collection) {
290 this->Consumer->OnListItem();
291 WriteValue(this->Consumer, item);
292 }
293 this->Consumer->OnEndList();
294 return this->GetUnwrappedParent();
295 }
296
298 template <class TCollection>
299 TUnwrappedParent ListLimited(const TCollection& collection, size_t maxSize)
300 {
301 this->Consumer->OnBeginAttributes();
302 this->Consumer->OnKeyedItem("count");
303 this->Consumer->OnInt64Scalar(collection.size());
304 this->Consumer->OnEndAttributes();
305 this->Consumer->OnBeginList();
306 size_t printedSize = 0;
307 for (const auto& item : collection) {
308 if (printedSize >= maxSize)
309 break;
310 this->Consumer->OnListItem();
311 WriteValue(this->Consumer, item);
312 ++printedSize;
313 }
314 this->Consumer->OnEndList();
315 return this->GetUnwrappedParent();
316 }
317
320 {
321 this->Consumer->OnBeginList();
322 return TListType<TParent>(this->Consumer, this->Parent);
323 }
324
326 template <class TFunc>
327 TUnwrappedParent DoList(const TFunc& func)
328 {
329 this->Consumer->OnBeginList();
330 func(TListType<TFluentYsonVoid>(this->Consumer));
331 this->Consumer->OnEndList();
332 return this->GetUnwrappedParent();
333 }
334
336 template <class TFunc, class TIterator>
337 TUnwrappedParent DoListFor(const TIterator& begin, const TIterator& end, const TFunc& func)
338 {
339 this->Consumer->OnBeginList();
340 for (auto current = begin; current != end; ++current) {
341 func(TListType<TFluentYsonVoid>(this->Consumer), current);
342 }
343 this->Consumer->OnEndList();
344 return this->GetUnwrappedParent();
345 }
346
348 template <class TFunc, class TCollection>
349 TUnwrappedParent DoListFor(const TCollection& collection, const TFunc& func)
350 {
351 this->Consumer->OnBeginList();
352 for (const auto& item : collection) {
353 func(TListType<TFluentYsonVoid>(this->Consumer), item);
354 }
355 this->Consumer->OnEndList();
356 return this->GetUnwrappedParent();
357 }
358
361 {
362 this->Consumer->OnBeginMap();
363 return TMapType<TParent>(this->Consumer, this->Parent);
364 }
365
367 template <class TFunc>
368 TUnwrappedParent DoMap(const TFunc& func)
369 {
370 this->Consumer->OnBeginMap();
371 func(TMapType<TFluentYsonVoid>(this->Consumer));
372 this->Consumer->OnEndMap();
373 return this->GetUnwrappedParent();
374 }
375
377 template <class TFunc, class TIterator>
378 TUnwrappedParent DoMapFor(const TIterator& begin, const TIterator& end, const TFunc& func)
379 {
380 this->Consumer->OnBeginMap();
381 for (auto current = begin; current != end; ++current) {
382 func(TMapType<TFluentYsonVoid>(this->Consumer), current);
383 }
384 this->Consumer->OnEndMap();
385 return this->GetUnwrappedParent();
386 }
387
389 template <class TFunc, class TCollection>
390 TUnwrappedParent DoMapFor(const TCollection& collection, const TFunc& func)
391 {
392 this->Consumer->OnBeginMap();
393 for (const auto& item : collection) {
394 func(TMapType<TFluentYsonVoid>(this->Consumer), item);
395 }
396 this->Consumer->OnEndMap();
397 return this->GetUnwrappedParent();
398 }
399 };
400
402 template <class TParent>
403 class TAny
404 : public TAnyWithoutAttributes<TParent>
405 {
406 public:
407 using TBase = TAnyWithoutAttributes<TParent>;
408
409 explicit TAny(NYT::NYson::IYsonConsumer* consumer, TParent parent)
410 : TBase(consumer, std::move(parent))
411 { }
412
415 {
416 this->Consumer->OnBeginAttributes();
417 return TAttributes<TBase>(
418 this->Consumer,
419 TBase(this->Consumer, this->Parent));
420 }
421 };
422
424 template <class TParent = TFluentYsonVoid>
425 class TAttributes
426 : public TFluentFragmentBase<TAttributes, TParent>
427 {
428 public:
429 using TThis = TAttributes<TParent>;
430 using TUnwrappedParent = typename TFluentYsonUnwrapper<TParent>::TUnwrapped;
431
432 explicit TAttributes(NYT::NYson::IYsonConsumer* consumer, TParent parent = TParent())
433 : TFluentFragmentBase<TFluentYsonBuilder::TAttributes, TParent>(consumer, std::move(parent))
434 { }
435
437 TAny<TThis> Item(const TStringBuf& key)
438 {
439 this->Consumer->OnKeyedItem(key);
440 return TAny<TThis>(this->Consumer, *this);
441 }
442
444 template <size_t Size>
445 TAny<TThis> Item(const char (&key)[Size])
446 {
447 return Item(TStringBuf(key, Size - 1));
448 }
449
450 //TODO: from TNode
451
453 TUnwrappedParent EndAttributes()
454 {
455 this->Consumer->OnEndAttributes();
456 return this->GetUnwrappedParent();
457 }
458 };
459
461 template <class TParent = TFluentYsonVoid>
462 class TListType
463 : public TFluentFragmentBase<TListType, TParent>
464 {
465 public:
466 using TThis = TListType<TParent>;
467 using TUnwrappedParent = typename TFluentYsonUnwrapper<TParent>::TUnwrapped;
468
469 explicit TListType(NYT::NYson::IYsonConsumer* consumer, TParent parent = TParent())
470 : TFluentFragmentBase<TFluentYsonBuilder::TListType, TParent>(consumer, std::move(parent))
471 { }
472
475 {
476 this->Consumer->OnListItem();
477 return TAny<TThis>(this->Consumer, *this);
478 }
479
480 // TODO: from TNode
481
483 TUnwrappedParent EndList()
484 {
485 this->Consumer->OnEndList();
486 return this->GetUnwrappedParent();
487 }
488 };
489
491 template <class TParent = TFluentYsonVoid>
492 class TMapType
493 : public TFluentFragmentBase<TMapType, TParent>
494 {
495 public:
496 using TThis = TMapType<TParent>;
497 using TUnwrappedParent = typename TFluentYsonUnwrapper<TParent>::TUnwrapped;
498
499 explicit TMapType(NYT::NYson::IYsonConsumer* consumer, TParent parent = TParent())
500 : TFluentFragmentBase<TFluentYsonBuilder::TMapType, TParent>(consumer, std::move(parent))
501 { }
502
504 template <size_t Size>
505 TAny<TThis> Item(const char (&key)[Size])
506 {
507 return Item(TStringBuf(key, Size - 1));
508 }
509
511 TAny<TThis> Item(const TStringBuf& key)
512 {
513 this->Consumer->OnKeyedItem(key);
514 return TAny<TThis>(this->Consumer, *this);
515 }
516
517 // TODO: from TNode
518
520 TUnwrappedParent EndMap()
521 {
522 this->Consumer->OnEndMap();
523 return this->GetUnwrappedParent();
524 }
525 };
526
527};
528
530
533
536
539
542
544
546static inline TFluentAny BuildYsonFluently(NYT::NYson::IYsonConsumer* consumer)
547{
548 return TFluentAny(consumer, TFluentYsonVoid());
549}
550
552static inline TFluentList BuildYsonListFluently(NYT::NYson::IYsonConsumer* consumer)
553{
554 return TFluentList(consumer);
555}
556
558static inline TFluentMap BuildYsonMapFluently(NYT::NYson::IYsonConsumer* consumer)
559{
560 return TFluentMap(consumer);
561}
562
564
565class TFluentYsonWriterState
566 : public TThrRefBase
567{
568public:
569 using TValue = TString;
570
571 explicit TFluentYsonWriterState(::NYson::EYsonFormat format)
572 : Writer(&Output, format)
573 { }
574
575 TString GetValue()
576 {
577 return Output.Str();
578 }
579
580 NYT::NYson::IYsonConsumer* GetConsumer()
581 {
582 return &Writer;
583 }
584
585private:
586 TStringStream Output;
587 ::NYson::TYsonWriter Writer;
588};
589
591
592class TFluentYsonBuilderState
593 : public TThrRefBase
594{
595public:
596 using TValue = TNode;
597
598 explicit TFluentYsonBuilderState()
599 : Builder(&Node)
600 { }
601
602 TNode GetValue()
603 {
604 return std::move(Node);
605 }
606
607 NYT::NYson::IYsonConsumer* GetConsumer()
608 {
609 return &Builder;
610 }
611
612private:
613 TNode Node;
614 TNodeBuilder Builder;
615};
616
618
619template <class TState>
620class TFluentYsonHolder
621{
622public:
623 explicit TFluentYsonHolder(::TIntrusivePtr<TState> state)
624 : State(state)
625 { }
626
627 ::TIntrusivePtr<TState> GetState() const
628 {
629 return State;
630 }
631
632private:
633 ::TIntrusivePtr<TState> State;
634};
635
637
638template <class TState>
640{
641 using TUnwrapped = typename TState::TValue;
642
643 static TUnwrapped Unwrap(const TFluentYsonHolder<TState>& holder)
644 {
645 return std::move(holder.GetState()->GetValue());
646 }
647};
648
650
651template <class TState>
653BuildYsonFluentlyWithState(::TIntrusivePtr<TState> state)
654{
656 state->GetConsumer(),
658}
659
661inline TFluentYsonBuilder::TAny<TFluentYsonHolder<TFluentYsonWriterState>>
662BuildYsonStringFluently(::NYson::EYsonFormat format = ::NYson::EYsonFormat::Text)
663{
664 ::TIntrusivePtr<TFluentYsonWriterState> state(new TFluentYsonWriterState(format));
665 return BuildYsonFluentlyWithState(state);
666}
667
669inline TFluentYsonBuilder::TAny<TFluentYsonHolder<TFluentYsonBuilderState>>
671{
672 ::TIntrusivePtr<TFluentYsonBuilderState> state(new TFluentYsonBuilderState);
673 return BuildYsonFluentlyWithState(state);
674}
675
677
678} // namespace NYT
Definition fluent.h:594
TUnwrappedParent DoList(const TFunc &func)
Open a list, delegate invocation to func, then close the list.
Definition fluent.h:327
TListType< TParent > BeginList()
Open a list.
Definition fluent.h:319
TUnwrappedParent DoMapFor(const TIterator &begin, const TIterator &end, const TFunc &func)
Open a map, call func(*this, element) for each element of range, then close the map.
Definition fluent.h:378
TUnwrappedParent DoListFor(const TCollection &collection, const TFunc &func)
Open a list, call func(*this, element) for each element of collection, then close the list.
Definition fluent.h:349
TMapType< TParent > BeginMap()
Open a map.
Definition fluent.h:360
TUnwrappedParent Value(const T &value)
Pass value to underlying consumer.
Definition fluent.h:271
TUnwrappedParent DoMapFor(const TCollection &collection, const TFunc &func)
Open a map, call func(*this, element) for each element of collection, then close the map.
Definition fluent.h:390
TUnwrappedParent Entity()
Call OnEntity() of underlying consumer.
Definition fluent.h:278
TUnwrappedParent ListLimited(const TCollection &collection, size_t maxSize)
Serialize maximum maxSize elements of collection to underlying consumer as a list.
Definition fluent.h:299
TUnwrappedParent List(const TCollection &collection)
Serialize collection to underlying consumer as a list.
Definition fluent.h:286
TUnwrappedParent DoListFor(const TIterator &begin, const TIterator &end, const TFunc &func)
Open a list, call func(*this, element) for each element of range, then close the list.
Definition fluent.h:337
TUnwrappedParent DoMap(const TFunc &func)
Open a map, delegate invocation to func, then close the map.
Definition fluent.h:368
Fluent adapter of any value.
Definition fluent.h:405
TAttributes< TBase > BeginAttributes()
Open attributes.
Definition fluent.h:414
Fluent adapter of attributes fragment (the inside part of attributes).
Definition fluent.h:427
TUnwrappedParent EndAttributes()
Close the attributes.
Definition fluent.h:453
TAny< TThis > Item(const TStringBuf &key)
Pass attribute key to underlying consumer.
Definition fluent.h:437
TAny< TThis > Item(const char(&key)[Size])
Pass attribute key to underlying consumer.
Definition fluent.h:445
Base class for all fluent adapters.
Definition fluent.h:176
TDeepThis & DoIf(bool condition, const TFunc &func)
Conditionally delegate invocation to a separate procedure.
Definition fluent.h:227
TDeepThis & DoFor(const TIterator &begin, const TIterator &end, const TFunc &func)
Calls func(*this, element) for each element in range [begin, end).
Definition fluent.h:237
TDeepThis & Do(const TFunc &func)
Delegate invocation to a separate procedure.
Definition fluent.h:219
TDeepThis & DoFor(const TCollection &collection, const TFunc &func)
Calls func(*this, element) for each element in collection.
Definition fluent.h:247
Fluent adapter of list fragment (the inside part of a list).
Definition fluent.h:464
TAny< TThis > Item()
Call OnListItem() of underlying consumer.
Definition fluent.h:474
TUnwrappedParent EndList()
Close the list.
Definition fluent.h:483
Fluent adapter of map fragment (the inside part of a map).
Definition fluent.h:494
TAny< TThis > Item(const char(&key)[Size])
Pass map key to underlying consumer.
Definition fluent.h:505
TUnwrappedParent EndMap()
Close the map.
Definition fluent.h:520
TAny< TThis > Item(const TStringBuf &key)
Pass map key to underlying consumer.
Definition fluent.h:511
This class is actually a namespace for specific fluent adapter classes.
Definition fluent.h:157
Definition fluent.h:621
Definition fluent.h:567
Main namespace of YT client.
Definition abortable_stream.h:7
TFluentYsonBuilder::TAny< TFluentYsonHolder< TFluentYsonBuilderState > > BuildYsonNodeFluently()
Create a fluent adapter returning a NYT::TNode when construction is finished.
Definition fluent.h:670
TFluentYsonBuilder::TListType< TFluentYsonVoid > TFluentList
Builder representing the inside of a list (list fragment).
Definition fluent.h:535
TFluentYsonBuilder::TAny< TFluentYsonVoid > TFluentAny
Builder representing any value.
Definition fluent.h:532
TFluentYsonBuilder::TAttributes< TFluentYsonVoid > TFluentAttributes
Builder representing the inside of attributes.
Definition fluent.h:541
TTableReaderIterator< T > end(TTableReader< T > &)
Function to facilitate range-based-for for NYT::TTableReader.
Definition io.h:359
TFluentYsonBuilder::TMapType< TFluentYsonVoid > TFluentMap
Builder representing the inside of a map (map fragment).
Definition fluent.h:538
TFluentYsonBuilder::TAny< TFluentYsonHolder< TFluentYsonWriterState > > BuildYsonStringFluently(::NYson::EYsonFormat format=::NYson::EYsonFormat::Text)
Create a fluent adapter returning a TString with corresponding YSON when construction is finished.
Definition fluent.h:662
TTableReaderIterator< T > begin(TTableReader< T > &reader)
Function to facilitate range-based-for for NYT::TTableReader.
Definition io.h:350
Definition fluent.h:129
Definition fluent.h:141