| 161 | /// \return a new Buffer instance |
| 162 | template <typename T> |
| 163 | static std::shared_ptr<Buffer> FromVector(std::vector<T> vec) { |
| 164 | static_assert(std::is_trivial_v<T>, |
| 165 | "Buffer::FromVector can only wrap vectors of trivial objects"); |
| 166 | |
| 167 | if (vec.empty()) { |
| 168 | return std::shared_ptr<Buffer>{new Buffer()}; |
| 169 | } |
| 170 | |
| 171 | auto* data = reinterpret_cast<uint8_t*>(vec.data()); |
| 172 | auto size_in_bytes = static_cast<int64_t>(vec.size() * sizeof(T)); |
| 173 | return std::shared_ptr<Buffer>{ |
| 174 | new Buffer{data, size_in_bytes}, |
| 175 | // Keep the vector's buffer alive inside the shared_ptr's destructor until after |
| 176 | // we have deleted the Buffer. Note we can't use this trick in FromString since |
| 177 | // std::string's data is inline for short strings so moving invalidates pointers |
| 178 | // into the string's buffer. |
| 179 | [vec = std::move(vec)](Buffer* buffer) { delete buffer; }}; |
| 180 | } |
| 181 | |
| 182 | /// \brief Create buffer referencing typed memory with some length without |
| 183 | /// copying |