sql_utils/public/value_content.h (60 lines of code) (raw):

/* * Copyright 2023 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef THIRD_PARTY_PY_BIGQUERY_ML_UTILS_SQL_UTILS_PUBLIC_VALUE_CONTENT_H_ #define THIRD_PARTY_PY_BIGQUERY_ML_UTILS_SQL_UTILS_PUBLIC_VALUE_CONTENT_H_ #include <cstdint> #include <type_traits> #include <cstdint> namespace bigquery_ml_utils { class SimpleType; // ValueContent class is a typeless represention of bigquery_ml_utils::Value content // (Value, in comparison, also stores a reference to bigquery_ml_utils::Type instance): // 1) ValueContent is not stored in Value directly, but serves as a value's // content exchange container in a contract between Value and Type for // conveying value content from Type to Value class. This helps to decouple // Type and Value: ValueContent doesn't depend on either of them and thus // allows avoiding circular-dependency between Value (which references Type) // and Type (which defines Value content). // 2) Value class stores value's content within its space together with other // Value's fields (like, type identifier) using different layouts depending on // whether Value belongs to simple type or not. Simple types are those builtin // types that can be represented with just a TypeKind, with no parameters (in // SQL type's classes hierarchy, simple types are represented by // SimpleType class). // 3) This class should only be used inside Value and inside Type subclasses. // 4) ValueContent provides 8 bytes of value's content. // 5) For builtin simple types, an extra four bytes of storage is available in // Value because the type is stored as an TypeKind enum rather than a Type* // pointer. This extra storage (in simple_type_extended_content_) is usable // only in SimpleType. class ValueContent { private: template <typename T> struct Storage { union { int64_t base_value; T value; }; }; public: // Explicitly copyable and assignable. constexpr ValueContent(const ValueContent& other) = default; constexpr ValueContent& operator=(const ValueContent& other) = default; template <class T> static constexpr bool IsTypeSupported() { return std::is_trivially_copyable<T>::value && sizeof(Storage<T>) == sizeof(content_); } template <class T> constexpr std::enable_if_t<IsTypeSupported<T>(), void> set(T value) { content<T>()->value = value; } template <class T> constexpr std::enable_if_t<IsTypeSupported<T>(), T> GetAs() const { return content<T>()->value; } // Creates a content that stores the given value. template <class T> constexpr static std::enable_if_t<IsTypeSupported<T>(), ValueContent> Create( T value) { ValueContent result(/*value=*/0, /*extended_value=*/0); result.set(value); return result; } private: friend class SimpleType; friend class Value; template <typename T> constexpr Storage<T>* content() { static_assert(IsTypeSupported<T>()); return reinterpret_cast<Storage<T>*>(&content_); } template <typename T> constexpr const Storage<T>* content() const { static_assert(IsTypeSupported<T>()); return reinterpret_cast<const Storage<T>*>(&content_); } constexpr explicit ValueContent(int64_t value = 0, int32_t extended_value = 0) : content_(value), simple_type_extended_content_(extended_value) {} // Main content of the value that all types use int64_t content_; // Field below can be used only by simple types (SimpleType). int32_t simple_type_extended_content_; }; static_assert(sizeof(ValueContent) <= 16); } // namespace bigquery_ml_utils #endif // THIRD_PARTY_PY_BIGQUERY_ML_UTILS_SQL_UTILS_PUBLIC_VALUE_CONTENT_H_