| /* | |
| * Licensed to the Apache Software Foundation (ASF) under one | |
| * or more contributor license agreements. See the NOTICE file | |
| * distributed with this work for additional information | |
| * regarding copyright ownership. The ASF licenses this file | |
| * to you 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. | |
| */ | |
| #pragma once | |
| #include <memory> | |
| #include <vector> | |
| #include "paimon/common/data/binary_array.h" | |
| #include "paimon/common/data/binary_map.h" | |
| #include "paimon/common/data/binary_row.h" | |
| #include "paimon/common/data/binary_string.h" | |
| #include "paimon/common/data/internal_map.h" | |
| #include "paimon/data/decimal.h" | |
| #include "paimon/data/timestamp.h" | |
| #include "paimon/type_fwd.h" | |
| namespace paimon { | |
| /// Utils for `MemorySegment`. | |
| class BinaryDataReadUtils { | |
| public: | |
| BinaryDataReadUtils() = delete; | |
| ~BinaryDataReadUtils() = delete; | |
| /// Gets an instance of `Timestamp` from underlying `MemorySegment`. | |
| /// @param segment the underlying `MemorySegment`s | |
| /// @param base_offset the base offset of current instance of TimestampData | |
| /// @param offset_and_nanos the offset of milli-seconds part and nanoseconds | |
| /// @return an instance of `Timestamp` | |
| static Timestamp ReadTimestampData(const MemorySegment& segment, int32_t base_offset, | |
| int64_t offset_and_nanos) { | |
| auto nano_of_millisecond = static_cast<int32_t>(offset_and_nanos & LOW_BYTES_MASK); | |
| auto sub_offset = static_cast<int32_t>(offset_and_nanos >> 32); | |
| auto millisecond = | |
| MemorySegmentUtils::GetValue<int64_t>({segment}, base_offset + sub_offset); | |
| return Timestamp::FromEpochMillis(millisecond, nano_of_millisecond); | |
| } | |
| /// Gets an instance of `Decimal` from underlying `MemorySegment`. | |
| static Decimal ReadDecimal(const MemorySegment& segment, int32_t base_offset, | |
| int64_t offset_and_size, int32_t precision, int32_t scale) { | |
| auto size = static_cast<int32_t>(offset_and_size & LOW_BYTES_MASK); | |
| auto sub_offset = static_cast<int32_t>(offset_and_size >> 32); | |
| auto bytes = Bytes::AllocateBytes(size, GetDefaultPool().get()); | |
| std::memset(bytes->data(), 0, bytes->size()); | |
| MemorySegmentUtils::CopyToBytes<Bytes>({segment}, base_offset + sub_offset, bytes.get(), 0, | |
| size); | |
| return Decimal::FromUnscaledBytes(precision, scale, bytes.get()); | |
| } | |
| /// Get binary string, if len less than 8, will be include in variable_part_offset_and_len. | |
| /// @note Need to consider the ByteOrder. | |
| /// @param base_offset base offset of composite binary format. | |
| /// @param field_offset absolute start offset of variable_part_offset_and_len. | |
| /// @param variable_part_offset_and_len a long value, real data or offset and len. | |
| static BinaryString ReadBinaryString(const MemorySegment& segment, int32_t base_offset, | |
| int64_t field_offset, | |
| int64_t variable_part_offset_and_len) { | |
| int64_t mark = variable_part_offset_and_len & BinaryString::HIGHEST_FIRST_BIT; | |
| if (mark == 0) { | |
| const auto sub_offset = static_cast<int32_t>(variable_part_offset_and_len >> 32); | |
| const auto len = static_cast<int32_t>(variable_part_offset_and_len & LOW_BYTES_MASK); | |
| return BinaryString::FromAddress(segment, base_offset + sub_offset, len); | |
| } else { | |
| auto len = static_cast<int32_t>( | |
| (static_cast<uint64_t>(variable_part_offset_and_len & | |
| BinaryString::HIGHEST_SECOND_TO_EIGHTH_BIT)) >> | |
| 56); | |
| if (SystemByteOrder() == ByteOrder::PAIMON_LITTLE_ENDIAN) { | |
| return BinaryString::FromAddress(segment, field_offset, len); | |
| } else { | |
| // field_offset + 1 to skip header. | |
| return BinaryString::FromAddress(segment, field_offset + 1, len); | |
| } | |
| } | |
| } | |
| static std::shared_ptr<InternalArray> ReadArrayData(const MemorySegment& segment, | |
| int32_t base_offset, | |
| int64_t offset_and_size) { | |
| auto size = static_cast<int32_t>(offset_and_size & LOW_BYTES_MASK); | |
| auto offset = static_cast<int32_t>(offset_and_size >> 32); | |
| auto binary_array = std::make_shared<BinaryArray>(); | |
| binary_array->PointTo(segment, offset + base_offset, size); | |
| return binary_array; | |
| } | |
| /// Gets an instance of `InternalRow` from underlying `MemorySegment`. | |
| static std::shared_ptr<InternalRow> ReadRowData(const MemorySegment& segment, | |
| int32_t num_fields, int32_t base_offset, | |
| int64_t offset_and_size) { | |
| auto size = static_cast<int32_t>(offset_and_size & LOW_BYTES_MASK); | |
| auto offset = static_cast<int32_t>(offset_and_size >> 32); | |
| auto row = std::make_shared<BinaryRow>(num_fields); | |
| row->PointTo(segment, offset + base_offset, size); | |
| return row; | |
| } | |
| static std::shared_ptr<InternalMap> ReadMapData(const MemorySegment& segment, | |
| int32_t base_offset, int64_t offset_and_size) { | |
| auto size = static_cast<int32_t>(offset_and_size & LOW_BYTES_MASK); | |
| auto offset = static_cast<int32_t>(offset_and_size >> 32); | |
| auto binary_map = std::make_shared<BinaryMap>(); | |
| binary_map->PointTo(segment, offset + base_offset, size); | |
| return binary_map; | |
| } | |
| private: | |
| static constexpr uint64_t LOW_BYTES_MASK = 0xFFFFFFFF; | |
| }; | |
| } // namespace paimon |