| // Copyright 2017 The Chromium Authors. All rights reserved. | 
 | // Use of this source code is governed by a BSD-style license that can be | 
 | // found in the LICENSE file. | 
 |  | 
 | #ifndef COMPONENTS_ZUCCHINI_BUFFER_SINK_H_ | 
 | #define COMPONENTS_ZUCCHINI_BUFFER_SINK_H_ | 
 |  | 
 | #include <stdint.h> | 
 |  | 
 | #include <algorithm> | 
 | #include <iterator> | 
 |  | 
 | #include "base/logging.h" | 
 | #include "components/zucchini/buffer_view.h" | 
 |  | 
 | namespace zucchini { | 
 |  | 
 | // BufferSink acts like an output stream with convenience methods to serialize | 
 | // data into a contiguous sequence of raw data. The underlying MutableBufferView | 
 | // emulates a cursor to track current write position, and guards against buffer | 
 | // overrun. Where applicable, BufferSink should be passed by pointer to maintain | 
 | // cursor progress across writes. | 
 | class BufferSink : public MutableBufferView { | 
 |  public: | 
 |   using iterator = MutableBufferView::iterator; | 
 |  | 
 |   using MutableBufferView::MutableBufferView; | 
 |   BufferSink() = default; | 
 |   explicit BufferSink(MutableBufferView buffer); | 
 |   BufferSink(const BufferSink&) = default; | 
 |   BufferSink& operator=(BufferSink&&) = default; | 
 |  | 
 |   // If sufficient space is available, writes the binary representation of | 
 |   // |value| starting at the cursor, while advancing the cursor beyond the | 
 |   // written region, and returns true. Otherwise returns false. | 
 |   template <class T> | 
 |   bool PutValue(const T& value) { | 
 |     DCHECK_NE(begin(), nullptr); | 
 |     if (Remaining() < sizeof(T)) | 
 |       return false; | 
 |     *reinterpret_cast<T*>(begin()) = value; | 
 |     remove_prefix(sizeof(T)); | 
 |     return true; | 
 |   } | 
 |  | 
 |   // If sufficient space is available, writes the raw bytes [|first|, |last|) | 
 |   // starting at the cursor, while advancing the cursor beyond the written | 
 |   // region, and returns true. Otherwise returns false. | 
 |   template <class It> | 
 |   bool PutRange(It first, It last) { | 
 |     static_assert(sizeof(typename std::iterator_traits<It>::value_type) == | 
 |                       sizeof(uint8_t), | 
 |                   "value_type should fit in uint8_t"); | 
 |     DCHECK_NE(begin(), nullptr); | 
 |     DCHECK(last >= first); | 
 |     if (Remaining() < size_type(last - first)) | 
 |       return false; | 
 |     std::copy(first, last, begin()); | 
 |     remove_prefix(last - first); | 
 |     return true; | 
 |   } | 
 |  | 
 |   size_type Remaining() const { return size(); } | 
 | }; | 
 |  | 
 | }  // namespace zucchini | 
 |  | 
 | #endif  // COMPONENTS_ZUCCHINI_BUFFER_SINK_H_ |