diff --git a/native/jni/src/suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h b/native/jni/src/suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h
index f23f1dbc545d0208f3da22e7d83aa80e1c6473f8..ec871ec855e0b3faacc2167cca4a54223c97d9fc 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/utils/buffer_with_extendable_buffer.h
@@ -36,6 +36,10 @@ class BufferWithExtendableBuffer {
             : mOriginalBuffer(originalBuffer), mOriginalBufferSize(originalBufferSize),
               mAdditionalBuffer(INITIAL_ADDITIONAL_BUFFER_SIZE), mUsedAdditionalBufferSize(0) {}
 
+    AK_FORCE_INLINE int getTailPosition() const {
+        return mOriginalBufferSize + mUsedAdditionalBufferSize;
+    }
+
     /**
      * For reading.
      */
@@ -56,6 +60,33 @@ class BufferWithExtendableBuffer {
         return mOriginalBufferSize;
     }
 
+    /**
+     * For writing.
+     *
+     * Writing is allowed for original buffer, already written region of additional buffer and the
+     * tail of additional buffer.
+     */
+    AK_FORCE_INLINE bool writeUintAndAdvancePosition(const uint32_t data, const int size,
+            int *const pos) {
+        if (!(size >= 1 && size <= 4)) {
+            AKLOGI("writeUintAndAdvancePosition() is called with invalid size: %d", size);
+            ASSERT(false);
+            return false;
+        }
+        if (!checkAndPrepareWriting(*pos, size)) {
+            return false;
+        }
+        const bool usesAdditionalBuffer = isInAdditionalBuffer(*pos);
+        uint8_t *const buffer = usesAdditionalBuffer ? &mAdditionalBuffer[0] : mOriginalBuffer;
+        if (usesAdditionalBuffer) {
+            *pos -= mOriginalBufferSize;
+        }
+        ByteArrayUtils::writeUintAndAdvancePosition(buffer, data, size, pos);
+        if (usesAdditionalBuffer) {
+            *pos += mOriginalBufferSize;
+        }
+        return true;
+    }
 
  private:
     DISALLOW_COPY_AND_ASSIGN(BufferWithExtendableBuffer);
@@ -78,6 +109,32 @@ class BufferWithExtendableBuffer {
         mAdditionalBuffer.resize(mAdditionalBuffer.size() + EXTEND_ADDITIONAL_BUFFER_SIZE_STEP);
         return true;
     }
+
+    // Returns if it is possible to write size-bytes from pos. When pos is at the tail position of
+    // the additional buffer, try extending the buffer.
+    AK_FORCE_INLINE bool checkAndPrepareWriting(const int pos, const int size) {
+        if (isInAdditionalBuffer(pos)) {
+            if (pos == mUsedAdditionalBufferSize) {
+                // Append data to the tail.
+                if (pos + size > static_cast<int>(mAdditionalBuffer.size())) {
+                    // Need to extend buffer.
+                    if (!extendBuffer()) {
+                        return false;
+                    }
+                }
+                mUsedAdditionalBufferSize += size;
+            } else if (pos + size >= mUsedAdditionalBufferSize) {
+                // The access will beyond the tail of used region.
+                return false;
+            }
+        } else {
+            if (pos < 0 || mOriginalBufferSize < pos + size) {
+                // Invalid position or violate the boundary.
+                return false;
+            }
+        }
+        return true;
+    }
 };
 }
 #endif /* LATINIME_BUFFER_WITH_EXTENDABLE_BUFFER_H */
diff --git a/native/jni/src/suggest/policyimpl/dictionary/utils/byte_array_utils.h b/native/jni/src/suggest/policyimpl/dictionary/utils/byte_array_utils.h
index 75ccfc766e0c4ed4e29706a39b9f9411d16195c9..1d14929c74fb65023619707a2b4a82d4ed4ee06c 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/utils/byte_array_utils.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/utils/byte_array_utils.h
@@ -29,7 +29,34 @@ namespace latinime {
 class ByteArrayUtils {
  public:
     /**
-     * Integer
+     * Integer writing
+     *
+     * Each method write a corresponding size integer in a big endian manner.
+     */
+    static AK_FORCE_INLINE void writeUintAndAdvancePosition(uint8_t *const buffer,
+            const uint32_t data, const int size, int *const pos) {
+        // size must be in 1 to 4.
+        ASSERT(size >= 1 && size <= 4);
+        switch (size) {
+            case 1:
+                ByteArrayUtils::writeUint8AndAdvancePosition(buffer, data, pos);
+                return;
+            case 2:
+                ByteArrayUtils::writeUint16AndAdvancePosition(buffer, data, pos);
+                return;
+            case 3:
+                ByteArrayUtils::writeUint24AndAdvancePosition(buffer, data, pos);
+                return;
+            case 4:
+                ByteArrayUtils::writeUint32AndAdvancePosition(buffer, data, pos);
+                return;
+            default:
+                break;
+        }
+    }
+
+    /**
+     * Integer reading
      *
      * Each method read a corresponding size integer in a big endian manner.
      */
@@ -187,6 +214,32 @@ class ByteArrayUtils {
 
     static const uint8_t MINIMAL_ONE_BYTE_CHARACTER_VALUE;
     static const uint8_t CHARACTER_ARRAY_TERMINATOR;
+
+    static AK_FORCE_INLINE void writeUint32AndAdvancePosition(uint8_t *const buffer,
+            const uint32_t data, int *const pos) {
+        buffer[(*pos)++] = (data >> 24) & 0xFF;
+        buffer[(*pos)++] = (data >> 16) & 0xFF;
+        buffer[(*pos)++] = (data >> 8) & 0xFF;
+        buffer[(*pos)++] = data & 0xFF;
+    }
+
+    static AK_FORCE_INLINE void writeUint24AndAdvancePosition(uint8_t *const buffer,
+            const uint32_t data, int *const pos) {
+        buffer[(*pos)++] = (data >> 16) & 0xFF;
+        buffer[(*pos)++] = (data >> 8) & 0xFF;
+        buffer[(*pos)++] = data & 0xFF;
+    }
+
+    static AK_FORCE_INLINE void writeUint16AndAdvancePosition(uint8_t *const buffer,
+            const uint16_t data, int *const pos) {
+        buffer[(*pos)++] = (data >> 8) & 0xFF;
+        buffer[(*pos)++] = data & 0xFF;
+    }
+
+    static AK_FORCE_INLINE void writeUint8AndAdvancePosition(uint8_t *const buffer,
+            const uint8_t data, int *const pos) {
+        buffer[(*pos)++] = data & 0xFF;
+    }
 };
 } // namespace latinime
 #endif /* LATINIME_BYTE_ARRAY_UTILS_H */