/* * Copyright (C) 2019-present ScyllaDB */ /* * SPDX-License-Identifier: AGPL-3.0-or-later */ #pragma once #include #include "types/types.hh" #include "types/list.hh" #include "types/map.hh" #include "types/set.hh" #include "types/tuple.hh" #include "types/user.hh" #include "utils/big_decimal.hh" struct empty_type_impl final : public abstract_type { using native_type = empty_type_representation; empty_type_impl(); }; struct counter_type_impl final : public abstract_type { counter_type_impl(); }; template struct simple_type_impl : public concrete_type { simple_type_impl(abstract_type::kind k, sstring name, std::optional value_length_if_fixed); }; template struct integer_type_impl : public simple_type_impl { integer_type_impl(abstract_type::kind k, sstring name, std::optional value_length_if_fixed); }; struct byte_type_impl final : public integer_type_impl { byte_type_impl(); }; struct short_type_impl final : public integer_type_impl { short_type_impl(); }; struct int32_type_impl final : public integer_type_impl { int32_type_impl(); }; struct long_type_impl final : public integer_type_impl { long_type_impl(); }; struct boolean_type_impl final : public simple_type_impl { boolean_type_impl(); }; template struct floating_type_impl : public simple_type_impl { floating_type_impl(abstract_type::kind k, sstring name, std::optional value_length_if_fixed); }; struct double_type_impl final : public floating_type_impl { double_type_impl(); }; struct float_type_impl final : public floating_type_impl { float_type_impl(); }; struct decimal_type_impl final : public concrete_type { decimal_type_impl(); }; struct duration_type_impl final : public concrete_type { duration_type_impl(); }; struct timestamp_type_impl final : public simple_type_impl { timestamp_type_impl(); static db_clock::time_point from_sstring(sstring_view s); }; struct simple_date_type_impl final : public simple_type_impl { simple_date_type_impl(); static uint32_t from_sstring(sstring_view s); }; struct time_type_impl final : public simple_type_impl { time_type_impl(); static int64_t from_sstring(sstring_view s); }; struct string_type_impl : public concrete_type { string_type_impl(kind k, sstring name); }; struct ascii_type_impl final : public string_type_impl { ascii_type_impl(); }; struct utf8_type_impl final : public string_type_impl { utf8_type_impl(); }; struct bytes_type_impl final : public concrete_type { bytes_type_impl(); }; // This is the old version of timestamp_type_impl, but has been replaced as it // wasn't comparing pre-epoch timestamps correctly. This is kept for backward // compatibility but shouldn't be used in new code. struct date_type_impl final : public concrete_type { date_type_impl(); }; using timestamp_date_base_class = concrete_type; sstring timestamp_to_json_string(const timestamp_date_base_class& t, const bytes_view& bv); struct timeuuid_type_impl final : public concrete_type { timeuuid_type_impl(); static utils::UUID from_sstring(sstring_view s); }; struct varint_type_impl final : public concrete_type { varint_type_impl(); }; struct inet_addr_type_impl final : public concrete_type { inet_addr_type_impl(); static seastar::net::inet_address from_sstring(sstring_view s); }; struct uuid_type_impl final : public concrete_type { uuid_type_impl(); static utils::UUID from_sstring(sstring_view s); }; template using visit_ret_type = std::invoke_result_t; template concept CanHandleAllTypes = requires(Func f) { { f(*static_cast(nullptr)) } -> std::same_as>; { f(*static_cast(nullptr)) } -> std::same_as>; { f(*static_cast(nullptr)) } -> std::same_as>; { f(*static_cast(nullptr)) } -> std::same_as>; { f(*static_cast(nullptr)) } -> std::same_as>; { f(*static_cast(nullptr)) } -> std::same_as>; { f(*static_cast(nullptr)) } -> std::same_as>; { f(*static_cast(nullptr)) } -> std::same_as>; { f(*static_cast(nullptr)) } -> std::same_as>; { f(*static_cast(nullptr)) } -> std::same_as>; { f(*static_cast(nullptr)) } -> std::same_as>; { f(*static_cast(nullptr)) } -> std::same_as>; { f(*static_cast(nullptr)) } -> std::same_as>; { f(*static_cast(nullptr)) } -> std::same_as>; { f(*static_cast(nullptr)) } -> std::same_as>; { f(*static_cast(nullptr)) } -> std::same_as>; { f(*static_cast(nullptr)) } -> std::same_as>; { f(*static_cast(nullptr)) } -> std::same_as>; { f(*static_cast(nullptr)) } -> std::same_as>; { f(*static_cast(nullptr)) } -> std::same_as>; { f(*static_cast(nullptr)) } -> std::same_as>; { f(*static_cast(nullptr)) } -> std::same_as>; { f(*static_cast(nullptr)) } -> std::same_as>; { f(*static_cast(nullptr)) } -> std::same_as>; { f(*static_cast(nullptr)) } -> std::same_as>; { f(*static_cast(nullptr)) } -> std::same_as>; { f(*static_cast(nullptr)) } -> std::same_as>; { f(*static_cast(nullptr)) } -> std::same_as>; }; template requires CanHandleAllTypes static inline visit_ret_type visit(const abstract_type& t, Func&& f) { switch (t.get_kind()) { case abstract_type::kind::ascii: return f(*static_cast(&t)); case abstract_type::kind::boolean: return f(*static_cast(&t)); case abstract_type::kind::byte: return f(*static_cast(&t)); case abstract_type::kind::bytes: return f(*static_cast(&t)); case abstract_type::kind::counter: return f(*static_cast(&t)); case abstract_type::kind::date: return f(*static_cast(&t)); case abstract_type::kind::decimal: return f(*static_cast(&t)); case abstract_type::kind::double_kind: return f(*static_cast(&t)); case abstract_type::kind::duration: return f(*static_cast(&t)); case abstract_type::kind::empty: return f(*static_cast(&t)); case abstract_type::kind::float_kind: return f(*static_cast(&t)); case abstract_type::kind::inet: return f(*static_cast(&t)); case abstract_type::kind::int32: return f(*static_cast(&t)); case abstract_type::kind::list: return f(*static_cast(&t)); case abstract_type::kind::long_kind: return f(*static_cast(&t)); case abstract_type::kind::map: return f(*static_cast(&t)); case abstract_type::kind::reversed: return f(*static_cast(&t)); case abstract_type::kind::set: return f(*static_cast(&t)); case abstract_type::kind::short_kind: return f(*static_cast(&t)); case abstract_type::kind::simple_date: return f(*static_cast(&t)); case abstract_type::kind::time: return f(*static_cast(&t)); case abstract_type::kind::timestamp: return f(*static_cast(&t)); case abstract_type::kind::timeuuid: return f(*static_cast(&t)); case abstract_type::kind::tuple: return f(*static_cast(&t)); case abstract_type::kind::user: return f(*static_cast(&t)); case abstract_type::kind::utf8: return f(*static_cast(&t)); case abstract_type::kind::uuid: return f(*static_cast(&t)); case abstract_type::kind::varint: return f(*static_cast(&t)); } __builtin_unreachable(); } template struct data_value_visitor { const void* v; Func& f; auto operator()(const empty_type_impl& t) { return f(t, v); } auto operator()(const counter_type_impl& t) { return f(t, v); } auto operator()(const reversed_type_impl& t) { return f(t, v); } template auto operator()(const T& t) { return f(t, reinterpret_cast(v)); } }; // Given an abstract_type and a void pointer to an object of that // type, call f with the runtime type of t and v casted to the // corresponding native type. // This takes an abstract_type and a void pointer instead of a // data_value to support reversed_type_impl without requiring that // each visitor create a new data_value just to recurse. template inline auto visit(const abstract_type& t, const void* v, Func&& f) { return ::visit(t, data_value_visitor{v, f}); } template inline auto visit(const data_value& v, Func&& f) { return ::visit(*v.type(), v._value, f); }