5#ifndef ANNADB_DRIVER_TYSON_HPP
6#define ANNADB_DRIVER_TYSON_HPP
42 template<std::convertible_to<TySonType> Obj>
43 std::string_view TySonType_repr(Obj &&obj)
noexcept
47 case TySonType::Number:
48 return "TySON-Number";
49 case TySonType::String:
50 return "TySON-String";
55 case TySonType::Timestamp:
56 return "TySON-Timestamp";
59 case TySonType::Vector:
60 return "TySON-Vector";
63 case TySonType::Object:
64 return "TySON-Object";
67 case TySonType::Objects:
68 return "TySON-Objects";
71 case TySonType::Value:
73 case TySonType::ProjectValue:
74 return "TySON-ProjectValue";
87 std::vector<TySonObject> vector_{};
88 std::map<TySonObject, TySonObject> map_{};
89 std::pair<std::string, std::string> link_{};
101 void parse_vector_elements(std::string_view
object)
noexcept
103 const auto to_tyson_object = [](std::string &val) ->
TySonObject
108 auto end_type_sep =
object.find_first_of(
'[') + 1;
109 auto end_value_sep = (
object.size() - 1) - end_type_sep;
111 auto vector_data =
object.substr(end_type_sep, end_value_sep);
113 auto vec_data = utils::split(vector_data,
',');
114 std::transform(vec_data.begin(), vec_data.end(), std::back_inserter(vector_), to_tyson_object);
126 [[ nodiscard ]] std::vector<TySonObject> parse_map_element(std::string_view
object)
noexcept
128 const auto to_tyson_object = [](std::string &val) ->
TySonObject
133 auto vec_data = utils::split(
object,
':');
135 std::vector<TySonObject> result;
136 result.reserve(vec_data.size());
138 std::transform(vec_data.begin(), vec_data.end(), std::back_inserter(result), to_tyson_object);
150 void parse_map_elements(std::string_view
object)
noexcept
152 auto end_type_sep =
object.find_first_of(
'{') + 1;
153 auto end_value_sep = (
object.size() - 1) - end_type_sep;
154 auto map_data =
object.substr(end_type_sep, end_value_sep);
156 auto vec_data = utils::split(map_data,
',');
158 auto to_map_element = [
this](
auto &val) -> std::vector<TySonObject>
160 return parse_map_element(val);
163 std::vector<std::vector<TySonObject>> result;
164 std::transform(vec_data.begin(), vec_data.end(), std::back_inserter(result), to_map_element);
165 std::for_each(result.begin(), result.end(), [
this](
auto key_val)
167 map_.try_emplace(key_val[0], key_val[1]);
175 friend std::ostream& operator<<(std::ostream &out,
TySonObject const &obj)
noexcept
179 case TySonType::Number:
180 return out <<
"n|" << obj.value_ <<
"|";
181 case TySonType::String:
182 return out <<
"s|" << obj.value_ <<
"|";
183 case TySonType::Bool:
184 return out <<
"b|" << obj.value_ <<
"|";
185 case TySonType::Null:
186 return out <<
"null";
187 case TySonType::Timestamp:
188 return out <<
"utc|" << obj.value_ <<
"|";
189 case TySonType::Link:
190 return out << std::get<0>(obj.link_) <<
"|" << std::get<1>(obj.link_) <<
"|";
191 case TySonType::Value:
192 return out <<
"value|" << obj.map_.begin()->first.value_ <<
"|:" << obj.map_.begin()->second;
193 case TySonType::Vector:
195 std::stringstream sstream;
196 std::for_each(obj.vector_.begin(),
198 [&sstream](
const auto &val){ sstream << val <<
","; });
200 return out <<
"v[" << sstream.str() <<
"]";
204 std::stringstream sstream;
205 std::for_each(obj.map_.begin(),
207 [&sstream](
const std::pair<TySonObject, TySonObject> &val)
209 sstream << val.first <<
":" << val.second <<
",";
212 return out <<
"m{" << sstream.str() <<
"}";
214 case TySonType::ProjectValue:
216 return out <<
"value|" << obj.map_.begin()->first.value_ <<
"|";
218 case TySonType::Keep:
220 return out <<
"keep";
235 TySonType cast_type_string(
char &_type)
240 return tyson::TySonType::Number;
242 return tyson::TySonType::String;
244 return tyson::TySonType::Bool;
246 return tyson::TySonType::Timestamp;
248 return tyson::TySonType::Link;
250 return tyson::TySonType::Vector;
252 return tyson::TySonType::Map;
254 return tyson::TySonType::Object;
260 TySonObject() noexcept : type_(tyson::TySonType::Null) {};
271 auto end_type_sep =
object.find_first_of(
'|');
272 auto end_value_sep = (
object.size() - 1) - (end_type_sep + 1);
273 auto type =
object.substr(0, end_type_sep);
275 if (
object ==
"null")
277 type_ = TySonType::Null;
282 if (
object.starts_with(
"uts"))
284 type_ = TySonType::Timestamp;
285 value_ =
object.substr(end_type_sep + 1, end_value_sep);
287 else if (
object.substr(0, 2) ==
"v[")
289 type_ = TySonType::Vector;
291 parse_vector_elements(
object);
293 else if (
object.substr(0, 2) ==
"m{")
295 type_ = TySonType::Map;
296 parse_map_elements(
object);
298 else if (end_type_sep > 1)
300 type_ = TySonType::Link;
301 auto val =
object.substr(end_type_sep + 1, end_value_sep);
302 link_ = std::make_pair(
type, val);
306 type_ = cast_type_string(
const_cast<char &
>(
type.at(0)));
307 value_ =
object.substr(end_type_sep + 1, end_value_sep);
318 return std::tie(this->type_, this->value_, this->vector_, this->map_, this->link_) ==
319 std::tie(rhs.type_, rhs.value_, rhs.vector_, rhs.map_, rhs.link_);
329 return std::tie(this->type_, this->value_, this->vector_) < std::tie(rhs.type_, rhs.value_, rhs.vector_);
340 if (type_ != TySonType::Map)
342 std::stringstream sstream;
343 sstream <<
"Can not be used with";
344 sstream << TySonType_repr(type_);
345 throw std::invalid_argument(sstream.str());
359 requires std::is_integral_v<T>
363 tySonObject.value_ = std::to_string(number);
364 tySonObject.type_ = TySonType::Number;
378 tySonObject.value_ = str;
379 tySonObject.type_ = TySonType::String;
392 tySonObject.value_ = bl ?
"true" :
"false";
393 tySonObject.type_ = TySonType::Bool;
405 tySonObject.value_ =
"null";
406 tySonObject.type_ = TySonType::Null;
418 tySonObject.value_ =
"keep";
419 tySonObject.type_ = TySonType::Keep;
433 tySonObject.value_ = std::to_string(seconds);
434 tySonObject.type_ = TySonType::Timestamp;
445 [[ nodiscard ]]
static TySonObject Link(
const std::string &collection,
const std::string &uuid)
noexcept
448 tySonObject.link_ = {collection, uuid};
449 tySonObject.type_ = TySonType::Link;
459 template<std::convertible_to<tyson::TySonObject> ...Values>
463 tySonObject.vector_.reserve(
sizeof ...(objs));
464 (tySonObject.vector_.emplace_back(objs), ...);
465 tySonObject.type_ = TySonType::Vector;
480 tySonObject.type_ = TySonType::Value;
494 tySonObject.type_ = TySonType::ProjectValue;
504 [[ nodiscard ]]
static TySonObject Map(std::map<std::string, TySonObject> &objs)
noexcept
507 std::for_each(objs.begin(), objs.end(),
508 [&tySonObject](std::pair<const std::string, TySonObject> &val)
510 tySonObject.map_.try_emplace(TySonObject::String(val.first), std::move(val.second));
512 tySonObject.type_ = TySonType::Map;
527 tySonObject.type_ = TySonType::Map;
540 tySonObject.type_ = TySonType::Map;
550 [[ nodiscard ]] std::optional<TySonObject>
operator[](
const std::string_view key)
const noexcept
552 if (type_ == TySonType::Map)
555 std::for_each(map_.begin(),
557 [&result, &key](
const std::pair<TySonObject, TySonObject> &obj)
559 if (obj.first.value_ == key)
576 [[nodiscard]] TySonType
type() const noexcept
587 template<TySonType T>
588 [[nodiscard]] std::string
value() const noexcept
599 template<TySonType T>
600 requires (T == TySonType::Bool)
601 [[nodiscard]]
bool value()
const noexcept
603 return value_ ==
"true";
612 template<TySonType T>
613 requires (T == TySonType::Null)
614 [[nodiscard]] std::string
value()
const noexcept
625 template<TySonType T>
626 requires (T == TySonType::Link)
627 [[nodiscard]] std::pair<std::string, std::string>
value()
const noexcept
638 template<TySonType T>
639 requires (T == TySonType::Vector)
640 [[nodiscard]] std::vector<TySonObject>
value()
const noexcept
651 template<TySonType T>
652 requires (T == TySonType::Map)
653 [[nodiscard]] std::map<TySonObject, TySonObject>
value()
const noexcept
666 requires std::is_arithmetic_v<T>
669 if (type_ == TySonType::Number || type_ == TySonType::Bool || type_ == TySonType::Timestamp)
673 switch (*
typeid(T).name())
678 return std::stoi(value_, &pos);
680 return std::stol(value_, &pos);
682 return static_cast<T
>(std::stof(value_, &pos));
684 return static_cast<T
>(std::stod(value_, &pos));
686 return std::stoll(value_, &pos);
688 return static_cast<T
>(std::stold(value_, &pos));
690 return value_ ==
"true";
692 return value_.c_str()[0];
696 throw std::invalid_argument(
"Invalid Type");
703 std::vector<TySonObject> collection_ids_{};
704 std::vector<std::pair<TySonObject, TySonObject>> collection_objects_{};
712 collection_objects_.reserve(size);
716 collection_ids_.reserve(size);
727 void add(
const std::string &
object)
729 auto tyson_str_data = utils::split(
object,
'|');
730 collection_ids_.emplace_back(TySonObject::Link(tyson_str_data[0], tyson_str_data[1]));
739 void add(
const std::string &link,
const std::string &value)
742 collection_objects_.emplace_back(new_val);
755 template<TySonType T>
756 requires (T == TySonType::Object)
757 [[ nodiscard ]] std::optional<std::pair<TySonObject, TySonObject>>
get(std::string_view obj_id)
noexcept
759 for (
const auto &val: collection_objects_)
761 if (val.first.value<TySonType::Link>().second == obj_id)
776 template<TySonType T>
777 requires (T == TySonType::Objects)
778 [[ nodiscard ]] std::vector<std::pair<TySonObject, TySonObject>>
get(std::string_view collection)
noexcept
780 std::vector<std::pair<TySonObject, TySonObject>> result{};
781 std::for_each(collection_objects_.begin(), collection_objects_.end(),
782 [&collection, &result](
const std::pair<TySonObject, TySonObject> &val)
784 if (val.first.value<TySonType::Link>().first == collection)
786 result.emplace_back(val);
800 template<TySonType T>
801 requires (T == TySonType::Object)
802 [[ nodiscard ]] std::optional<std::pair<TySonObject, TySonObject>>
get(std::string_view collection, std::string_view obj_id)
noexcept
804 for (
const std::pair<TySonObject, TySonObject> &val: collection_objects_)
806 auto tysonLink = val.first.value<TySonType::Link>();
807 if (std::tie(tysonLink.first, tysonLink.second) == std::tie(collection, obj_id))
823 template<TySonType T>
824 requires (T == TySonType::ID)
825 [[ nodiscard ]] std::optional<TySonObject>
get(std::string_view obj_id)
noexcept
829 if (val.value<TySonType::Link>().second == obj_id)
844 template<TySonType T>
845 requires (T == TySonType::IDs)
846 [[ nodiscard ]] std::vector<TySonObject>
get(std::string_view collection)
noexcept
848 std::vector<TySonObject> result{};
849 std::for_each(collection_ids_.begin(), collection_ids_.end(),
852 if (val.value<TySonType::Link>().first == collection)
854 result.emplace_back(val);
868 template<TySonType T>
869 requires (T == TySonType::ID)
870 [[ nodiscard ]] std::optional<TySonObject>
get(std::string_view collection, std::string_view obj_id)
noexcept
874 auto tysonLink = val.value<TySonType::Link>();
875 if (std::tie(tysonLink.first, tysonLink.second) == std::tie(collection, obj_id))
Definition: TySON.hpp:702
std::optional< std::pair< TySonObject, TySonObject > > get(std::string_view collection, std::string_view obj_id) noexcept
Definition: TySON.hpp:802
std::vector< TySonObject > get(std::string_view collection) noexcept
Definition: TySON.hpp:846
void add(const std::string &link, const std::string &value)
Definition: TySON.hpp:739
std::vector< std::pair< TySonObject, TySonObject > > get(std::string_view collection) noexcept
Definition: TySON.hpp:778
std::optional< TySonObject > get(std::string_view obj_id) noexcept
Definition: TySON.hpp:825
std::optional< TySonObject > get(std::string_view collection, std::string_view obj_id) noexcept
Definition: TySON.hpp:870
void add(const std::string &object)
Definition: TySON.hpp:727
std::optional< std::pair< TySonObject, TySonObject > > get(std::string_view obj_id) noexcept
Definition: TySON.hpp:757
T value() const
Definition: TySON.hpp:667
static TySonObject ProjectValue(const std::string &value) noexcept
Definition: TySON.hpp:490
static TySonObject Map(std::map< std::string, TySonObject > &objs) noexcept
Definition: TySON.hpp:504
bool emplace(const std::string &key, tyson::TySonObject &&value)
Definition: TySON.hpp:338
std::pair< std::string, std::string > value() const noexcept
Definition: TySON.hpp:627
TySonObject(std::string_view object) noexcept
Definition: TySON.hpp:269
static TySonObject Null() noexcept
Definition: TySON.hpp:402
bool operator<(const TySonObject &rhs) const noexcept
Definition: TySON.hpp:327
static TySonObject Timestamp(unsigned long long seconds) noexcept
Definition: TySON.hpp:430
std::optional< TySonObject > operator[](const std::string_view key) const noexcept
Definition: TySON.hpp:550
std::map< TySonObject, TySonObject > value() const noexcept
Definition: TySON.hpp:653
std::string value() const noexcept
Definition: TySON.hpp:588
bool operator==(const TySonObject &rhs) const noexcept
Definition: TySON.hpp:316
static TySonObject Map() noexcept
Definition: TySON.hpp:537
static TySonObject Number(T number) noexcept
Definition: TySON.hpp:360
static TySonObject Vector(Values &&...objs) noexcept
Definition: TySON.hpp:460
static TySonObject Link(const std::string &collection, const std::string &uuid) noexcept
Definition: TySON.hpp:445
static TySonObject Keep() noexcept
Definition: TySON.hpp:415
static TySonObject Value(const std::string &field, TySonObject &&val) noexcept
Definition: TySON.hpp:476
TySonType type() const noexcept
Definition: TySON.hpp:576
bool value() const noexcept
Definition: TySON.hpp:601
std::vector< TySonObject > value() const noexcept
Definition: TySON.hpp:640
static TySonObject String(const std::string &str) noexcept
Definition: TySON.hpp:375
std::string value() const noexcept
Definition: TySON.hpp:614
static TySonObject Bool(bool bl) noexcept
Definition: TySON.hpp:389
static TySonObject Map(const std::string &key, TySonObject &&obj) noexcept
Definition: TySON.hpp:523