GGUF (GGML Universal File): C++11/STL parsing library

GGUF is the file format of the ggml tensor library for storing machine learning models, used for example by llama.cpp for inference. It replaced the older GGML, GGMF and GGJT formats.

A GGUF file consists of a header with metadata as key-value pairs (model architecture, hyperparameters, tokenizer, etc.), a description of each tensor (name, dimensions, type and offset), and finally the tensor data.

File extension

gguf

KS implementation details

License: CC0-1.0
Minimal Kaitai Struct required: 0.11

References

This page hosts a formal specification of GGUF (GGML Universal File) using Kaitai Struct. This specification can be automatically translated into a variety of programming languages to get a parsing library.

Usage

Runtime library

All C++11/STL code generated by Kaitai Struct depends on the Kaitai Struct runtime library for C++/STL. You must add this dependency to your project before you can parse or serialize any data.

For C++, the easiest way is to clone the runtime library sources and build them along with your project.

Code

Using Kaitai Struct in C++/STL usually consists of 3 steps.

  1. We need to create an STL input stream (std::istream). One can open local file for that, or use existing std::string or char* buffer.
    #include <fstream>
    
    std::ifstream is("path/to/local/file.gguf", std::ifstream::binary);
    
    #include <sstream>
    
    std::istringstream is(str);
    
    #include <sstream>
    
    const char buf[] = { ... };
    std::string str(buf, sizeof buf);
    std::istringstream is(str);
    
  2. We need to wrap our input stream into Kaitai stream:
    #include "kaitai/kaitaistream.h"
    
    kaitai::kstream ks(&is);
    
  3. And finally, we can invoke the parsing:
    gguf_t data(&ks);
    

After that, one can get various attributes from the structure by invoking getter methods like:

data.magic() // => GGUF file magic
data.len_file() // => Length of the file (computed from the header), including the padding after
the last tensor's data.

This Kaitai Struct implementation stops parsing where the tensor data
starts (which is read lazily, i.e. only on demand). Without reading the
tensor data, you can use this expected file size to check whether the file
has been truncated, to carve the file out of a larger one, etc.

C++11/STL source code to parse GGUF (GGML Universal File)

gguf.h

#pragma once

// This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild

class gguf_t;

#include "kaitai/kaitaistruct.h"
#include <stdint.h>
#include <memory>
#include <set>
#include <vector>

#if KAITAI_STRUCT_VERSION < 11000L
#error "Incompatible Kaitai Struct C++/STL API: version 0.11 or later is required"
#endif

/**
 * GGUF is the file format of the [ggml](https://github.com/ggml-org/ggml)
 * tensor library for storing machine learning models, used for example by
 * [llama.cpp](https://github.com/ggml-org/llama.cpp) for inference. It
 * replaced the older GGML, GGMF and GGJT formats.
 * 
 * A GGUF file consists of a header with metadata as key-value pairs (model
 * architecture, hyperparameters, tokenizer, etc.), a description of each
 * tensor (name, dimensions, type and offset), and finally the tensor data.
 * \sa https://github.com/ggml-org/ggml/blob/a05c9922613c6a2230dbb1d0de679519ecafb4f0/docs/gguf.md Git tag "v0.27.0"
 */

class gguf_t : public kaitai::kstruct {

public:
    class gguf_body_t;

    enum ggml_type_t {
        GGML_TYPE_F32 = 0,
        GGML_TYPE_F16 = 1,
        GGML_TYPE_Q4_0 = 2,
        GGML_TYPE_Q4_1 = 3,
        GGML_TYPE_Q4_2 = 4,
        GGML_TYPE_Q4_3 = 5,
        GGML_TYPE_Q5_0 = 6,
        GGML_TYPE_Q5_1 = 7,
        GGML_TYPE_Q8_0 = 8,
        GGML_TYPE_Q8_1 = 9,
        GGML_TYPE_Q2_K = 10,
        GGML_TYPE_Q3_K = 11,
        GGML_TYPE_Q4_K = 12,
        GGML_TYPE_Q5_K = 13,
        GGML_TYPE_Q6_K = 14,
        GGML_TYPE_Q8_K = 15,
        GGML_TYPE_IQ2_XXS = 16,
        GGML_TYPE_IQ2_XS = 17,
        GGML_TYPE_IQ3_XXS = 18,
        GGML_TYPE_IQ1_S = 19,
        GGML_TYPE_IQ4_NL = 20,
        GGML_TYPE_IQ3_S = 21,
        GGML_TYPE_IQ2_S = 22,
        GGML_TYPE_IQ4_XS = 23,
        GGML_TYPE_I8 = 24,
        GGML_TYPE_I16 = 25,
        GGML_TYPE_I32 = 26,
        GGML_TYPE_I64 = 27,
        GGML_TYPE_F64 = 28,
        GGML_TYPE_IQ1_M = 29,
        GGML_TYPE_BF16 = 30,
        GGML_TYPE_Q4_0_4_4 = 31,
        GGML_TYPE_Q4_0_4_8 = 32,
        GGML_TYPE_Q4_0_8_8 = 33,
        GGML_TYPE_TQ1_0 = 34,
        GGML_TYPE_TQ2_0 = 35,
        GGML_TYPE_IQ4_NL_4_4 = 36,
        GGML_TYPE_IQ4_NL_4_8 = 37,
        GGML_TYPE_IQ4_NL_8_8 = 38,
        GGML_TYPE_MXFP4 = 39,
        GGML_TYPE_NVFP4 = 40,
        GGML_TYPE_Q1_0 = 41,
        GGML_TYPE_Q2_0 = 42
    };
    static bool _is_defined_ggml_type_t(ggml_type_t v);

private:
    static const std::set<ggml_type_t> _values_ggml_type_t;

public:

    enum gguf_type_t {
        GGUF_TYPE_UINT8 = 0,
        GGUF_TYPE_INT8 = 1,
        GGUF_TYPE_UINT16 = 2,
        GGUF_TYPE_INT16 = 3,
        GGUF_TYPE_UINT32 = 4,
        GGUF_TYPE_INT32 = 5,
        GGUF_TYPE_FLOAT32 = 6,
        GGUF_TYPE_BOOL = 7,
        GGUF_TYPE_STRING = 8,
        GGUF_TYPE_ARRAY = 9,
        GGUF_TYPE_UINT64 = 10,
        GGUF_TYPE_INT64 = 11,
        GGUF_TYPE_FLOAT64 = 12
    };
    static bool _is_defined_gguf_type_t(gguf_type_t v);

private:
    static const std::set<gguf_type_t> _values_gguf_type_t;

public:

    gguf_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent = nullptr, gguf_t* p__root = nullptr);

private:
    void _read();
    void _clean_up();

public:
    ~gguf_t();

    class gguf_body_t : public kaitai::kstruct {

    public:
        class gguf_array_t;
        class gguf_bool_t;
        class gguf_float32_t;
        class gguf_float64_t;
        class gguf_int16_t;
        class gguf_int32_t;
        class gguf_int64_t;
        class gguf_int8_t;
        class gguf_kv_t;
        class gguf_str_t;
        class gguf_tensor_info_t;
        class gguf_uint16_t;
        class gguf_uint32_t;
        class gguf_uint64_t;
        class gguf_uint8_t;
        class gguf_value_t;

        gguf_body_t(kaitai::kstream* p__io, gguf_t* p__parent = nullptr, gguf_t* p__root = nullptr);

    private:
        int m__is_le;

    public:

    private:
        void _read();
        void _read_le();
        void _read_be();
        void _clean_up();

    public:
        ~gguf_body_t();

        /**
         * Nested arrays are supported. Although ggml (v0.27.0) doesn't support them,
         * they are explicitly allowed by `gguf.md` - see
         * <https://github.com/ggml-org/ggml/blob/a05c9922613c6a2230dbb1d0de679519ecafb4f0/docs/gguf.md?plain=1#L221>.
         */

        class gguf_array_t : public kaitai::kstruct {

        public:

            gguf_array_t(kaitai::kstream* p__io, gguf_t::gguf_body_t::gguf_value_t* p__parent = nullptr, gguf_t* p__root = nullptr, int p_is_le = -1);

        private:
            int m__is_le;

        public:

        private:
            void _read();
            void _read_le();
            void _read_be();
            void _clean_up();

        public:
            ~gguf_array_t();

        private:
            gguf_type_t m_type;
            uint64_t m_num_elems;
            std::unique_ptr<std::vector<std::unique_ptr<gguf_value_t>>> m_elems;
            gguf_t* m__root;
            gguf_t::gguf_body_t::gguf_value_t* m__parent;

        public:
            gguf_type_t type() const { return m_type; }
            uint64_t num_elems() const { return m_num_elems; }
            std::vector<std::unique_ptr<gguf_value_t>>* elems() const { return m_elems.get(); }
            gguf_t* _root() const { return m__root; }
            gguf_t::gguf_body_t::gguf_value_t* _parent() const { return m__parent; }
        };

        class gguf_bool_t : public kaitai::kstruct {

        public:

            gguf_bool_t(kaitai::kstream* p__io, gguf_t::gguf_body_t::gguf_value_t* p__parent = nullptr, gguf_t* p__root = nullptr, int p_is_le = -1);

        private:
            int m__is_le;

        public:

        private:
            void _read();
            void _read_le();
            void _read_be();
            void _clean_up();

        public:
            ~gguf_bool_t();

        private:
            bool f_value;
            bool m_value;

        public:

            /**
             * \sa https://github.com/ggml-org/ggml/blob/a05c9922613c6a2230dbb1d0de679519ecafb4f0/src/gguf.cpp#L321 Git tag "v0.27.0"
             */
            bool value();

        private:
            uint8_t m_value_raw;
            gguf_t* m__root;
            gguf_t::gguf_body_t::gguf_value_t* m__parent;

        public:
            uint8_t value_raw() const { return m_value_raw; }
            gguf_t* _root() const { return m__root; }
            gguf_t::gguf_body_t::gguf_value_t* _parent() const { return m__parent; }
        };

        class gguf_float32_t : public kaitai::kstruct {

        public:

            gguf_float32_t(kaitai::kstream* p__io, gguf_t::gguf_body_t::gguf_value_t* p__parent = nullptr, gguf_t* p__root = nullptr, int p_is_le = -1);

        private:
            int m__is_le;

        public:

        private:
            void _read();
            void _read_le();
            void _read_be();
            void _clean_up();

        public:
            ~gguf_float32_t();

        private:
            float m_value;
            gguf_t* m__root;
            gguf_t::gguf_body_t::gguf_value_t* m__parent;

        public:
            float value() const { return m_value; }
            gguf_t* _root() const { return m__root; }
            gguf_t::gguf_body_t::gguf_value_t* _parent() const { return m__parent; }
        };

        class gguf_float64_t : public kaitai::kstruct {

        public:

            gguf_float64_t(kaitai::kstream* p__io, gguf_t::gguf_body_t::gguf_value_t* p__parent = nullptr, gguf_t* p__root = nullptr, int p_is_le = -1);

        private:
            int m__is_le;

        public:

        private:
            void _read();
            void _read_le();
            void _read_be();
            void _clean_up();

        public:
            ~gguf_float64_t();

        private:
            double m_value;
            gguf_t* m__root;
            gguf_t::gguf_body_t::gguf_value_t* m__parent;

        public:
            double value() const { return m_value; }
            gguf_t* _root() const { return m__root; }
            gguf_t::gguf_body_t::gguf_value_t* _parent() const { return m__parent; }
        };

        class gguf_int16_t : public kaitai::kstruct {

        public:

            gguf_int16_t(kaitai::kstream* p__io, gguf_t::gguf_body_t::gguf_value_t* p__parent = nullptr, gguf_t* p__root = nullptr, int p_is_le = -1);

        private:
            int m__is_le;

        public:

        private:
            void _read();
            void _read_le();
            void _read_be();
            void _clean_up();

        public:
            ~gguf_int16_t();

        private:
            int16_t m_value;
            gguf_t* m__root;
            gguf_t::gguf_body_t::gguf_value_t* m__parent;

        public:
            int16_t value() const { return m_value; }
            gguf_t* _root() const { return m__root; }
            gguf_t::gguf_body_t::gguf_value_t* _parent() const { return m__parent; }
        };

        class gguf_int32_t : public kaitai::kstruct {

        public:

            gguf_int32_t(kaitai::kstream* p__io, gguf_t::gguf_body_t::gguf_value_t* p__parent = nullptr, gguf_t* p__root = nullptr, int p_is_le = -1);

        private:
            int m__is_le;

        public:

        private:
            void _read();
            void _read_le();
            void _read_be();
            void _clean_up();

        public:
            ~gguf_int32_t();

        private:
            int32_t m_value;
            gguf_t* m__root;
            gguf_t::gguf_body_t::gguf_value_t* m__parent;

        public:
            int32_t value() const { return m_value; }
            gguf_t* _root() const { return m__root; }
            gguf_t::gguf_body_t::gguf_value_t* _parent() const { return m__parent; }
        };

        class gguf_int64_t : public kaitai::kstruct {

        public:

            gguf_int64_t(kaitai::kstream* p__io, gguf_t::gguf_body_t::gguf_value_t* p__parent = nullptr, gguf_t* p__root = nullptr, int p_is_le = -1);

        private:
            int m__is_le;

        public:

        private:
            void _read();
            void _read_le();
            void _read_be();
            void _clean_up();

        public:
            ~gguf_int64_t();

        private:
            int64_t m_value;
            gguf_t* m__root;
            gguf_t::gguf_body_t::gguf_value_t* m__parent;

        public:
            int64_t value() const { return m_value; }
            gguf_t* _root() const { return m__root; }
            gguf_t::gguf_body_t::gguf_value_t* _parent() const { return m__parent; }
        };

        class gguf_int8_t : public kaitai::kstruct {

        public:

            gguf_int8_t(kaitai::kstream* p__io, gguf_t::gguf_body_t::gguf_value_t* p__parent = nullptr, gguf_t* p__root = nullptr, int p_is_le = -1);

        private:
            int m__is_le;

        public:

        private:
            void _read();
            void _read_le();
            void _read_be();
            void _clean_up();

        public:
            ~gguf_int8_t();

        private:
            int8_t m_value;
            gguf_t* m__root;
            gguf_t::gguf_body_t::gguf_value_t* m__parent;

        public:
            int8_t value() const { return m_value; }
            gguf_t* _root() const { return m__root; }
            gguf_t::gguf_body_t::gguf_value_t* _parent() const { return m__parent; }
        };

        /**
         * \sa https://github.com/ggml-org/ggml/blob/a05c9922613c6a2230dbb1d0de679519ecafb4f0/docs/gguf.md?plain=1#L262-L275 Git tag "v0.27.0"
         */

        class gguf_kv_t : public kaitai::kstruct {

        public:

            gguf_kv_t(uint32_t p_prev_alignment, kaitai::kstream* p__io, gguf_t::gguf_body_t* p__parent = nullptr, gguf_t* p__root = nullptr, int p_is_le = -1);

        private:
            int m__is_le;

        public:

        private:
            void _read();
            void _read_le();
            void _read_be();
            void _clean_up();

        public:
            ~gguf_kv_t();

        private:
            bool f_alignment;
            uint32_t m_alignment;

        public:
            uint32_t alignment();

        private:
            std::unique_ptr<gguf_str_t> m_key;
            gguf_type_t m_type;
            std::unique_ptr<gguf_value_t> m_value;
            uint32_t m_prev_alignment;
            gguf_t* m__root;
            gguf_t::gguf_body_t* m__parent;

        public:
            gguf_str_t* key() const { return m_key.get(); }
            gguf_type_t type() const { return m_type; }
            gguf_value_t* value() const { return m_value.get(); }
            uint32_t prev_alignment() const { return m_prev_alignment; }
            gguf_t* _root() const { return m__root; }
            gguf_t::gguf_body_t* _parent() const { return m__parent; }
        };

        /**
         * \sa https://github.com/ggml-org/ggml/blob/a05c9922613c6a2230dbb1d0de679519ecafb4f0/docs/gguf.md?plain=1#L232-L237 Git tag "v0.27.0"
         */

        class gguf_str_t : public kaitai::kstruct {

        public:

            gguf_str_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent = nullptr, gguf_t* p__root = nullptr, int p_is_le = -1);

        private:
            int m__is_le;

        public:

        private:
            void _read();
            void _read_le();
            void _read_be();
            void _clean_up();

        public:
            ~gguf_str_t();

        private:
            uint64_t m_len_value;
            std::string m_value;
            gguf_t* m__root;
            kaitai::kstruct* m__parent;

        public:
            uint64_t len_value() const { return m_len_value; }
            std::string value() const { return m_value; }
            gguf_t* _root() const { return m__root; }
            kaitai::kstruct* _parent() const { return m__parent; }
        };

        /**
         * \sa https://github.com/ggml-org/ggml/blob/a05c9922613c6a2230dbb1d0de679519ecafb4f0/docs/gguf.md?plain=1#L305-L325 Git tag "v0.27.0"
         */

        class gguf_tensor_info_t : public kaitai::kstruct {

        public:

            gguf_tensor_info_t(uint64_t p_expected_offset, kaitai::kstream* p__io, gguf_t::gguf_body_t* p__parent = nullptr, gguf_t* p__root = nullptr, int p_is_le = -1);

        private:
            int m__is_le;

        public:

        private:
            void _read();
            void _read_le();
            void _read_be();
            void _clean_up();

        public:
            ~gguf_tensor_info_t();

        private:
            bool f_data;
            std::string m_data;

        public:
            std::string data();

        private:
            bool f_dump_dims;
            std::string m_dump_dims;

        public:

            /**
             * `dims` joined with the string `" x "`. This is necessary for
             * `-webide-representation`, which cannot format `dims` directly -
             * see <https://github.com/kaitai-io/kaitai_struct_webide/issues/160>.
             */
            std::string dump_dims();

        private:
            bool f_expected_next_offset;
            uint64_t m_expected_next_offset;

        public:

            /**
             * `offset` that the next tensor must have
             */
            uint64_t expected_next_offset();

        private:
            bool f_len_block;
            int32_t m_len_block;

        public:

            /**
             * Size of a block in bytes
             */
            int32_t len_block();

        private:
            bool f_len_data;
            uint64_t m_len_data;

        public:
            uint64_t len_data();

        private:
            bool f_len_padding;
            int32_t m_len_padding;

        public:

            /**
             * Number of padding bytes after the data
             */
            int32_t len_padding();

        private:
            bool f_num_blocks;
            int64_t m_num_blocks;

        public:
            int64_t num_blocks();

        private:
            bool f_num_elements;
            int64_t m_num_elements;

        public:
            int64_t num_elements();

        private:
            bool f_num_elements_per_block;
            int32_t m_num_elements_per_block;

        public:

            /**
             * Number of elements in a block
             */
            int32_t num_elements_per_block();

        private:
            bool f_padding;
            std::string m_padding;

        public:

            /**
             * Padding after the data. ggml requires it even after the last tensor
             * when reading the tensor data.
             * \sa https://github.com/ggml-org/ggml/blob/a05c9922613c6a2230dbb1d0de679519ecafb4f0/src/gguf.cpp#L884-L893 Git tag "v0.27.0"
             */
            std::string padding();

        private:
            std::unique_ptr<gguf_str_t> m_name;
            uint32_t m_num_dims;
            std::unique_ptr<std::vector<int64_t>> m_dims;
            ggml_type_t m_type;
            uint64_t m_offset;
            uint64_t m_expected_offset;
            gguf_t* m__root;
            gguf_t::gguf_body_t* m__parent;

        public:
            gguf_str_t* name() const { return m_name.get(); }
            uint32_t num_dims() const { return m_num_dims; }
            std::vector<int64_t>* dims() const { return m_dims.get(); }
            ggml_type_t type() const { return m_type; }

            /**
             * Offset of the tensor's data, relative to `_parent.ofs_tensor_data`
             */
            uint64_t offset() const { return m_offset; }
            uint64_t expected_offset() const { return m_expected_offset; }
            gguf_t* _root() const { return m__root; }
            gguf_t::gguf_body_t* _parent() const { return m__parent; }
        };

        class gguf_uint16_t : public kaitai::kstruct {

        public:

            gguf_uint16_t(kaitai::kstream* p__io, gguf_t::gguf_body_t::gguf_value_t* p__parent = nullptr, gguf_t* p__root = nullptr, int p_is_le = -1);

        private:
            int m__is_le;

        public:

        private:
            void _read();
            void _read_le();
            void _read_be();
            void _clean_up();

        public:
            ~gguf_uint16_t();

        private:
            uint16_t m_value;
            gguf_t* m__root;
            gguf_t::gguf_body_t::gguf_value_t* m__parent;

        public:
            uint16_t value() const { return m_value; }
            gguf_t* _root() const { return m__root; }
            gguf_t::gguf_body_t::gguf_value_t* _parent() const { return m__parent; }
        };

        class gguf_uint32_t : public kaitai::kstruct {

        public:

            gguf_uint32_t(kaitai::kstream* p__io, gguf_t::gguf_body_t::gguf_value_t* p__parent = nullptr, gguf_t* p__root = nullptr, int p_is_le = -1);

        private:
            int m__is_le;

        public:

        private:
            void _read();
            void _read_le();
            void _read_be();
            void _clean_up();

        public:
            ~gguf_uint32_t();

        private:
            uint32_t m_value;
            gguf_t* m__root;
            gguf_t::gguf_body_t::gguf_value_t* m__parent;

        public:
            uint32_t value() const { return m_value; }
            gguf_t* _root() const { return m__root; }
            gguf_t::gguf_body_t::gguf_value_t* _parent() const { return m__parent; }
        };

        class gguf_uint64_t : public kaitai::kstruct {

        public:

            gguf_uint64_t(kaitai::kstream* p__io, gguf_t::gguf_body_t::gguf_value_t* p__parent = nullptr, gguf_t* p__root = nullptr, int p_is_le = -1);

        private:
            int m__is_le;

        public:

        private:
            void _read();
            void _read_le();
            void _read_be();
            void _clean_up();

        public:
            ~gguf_uint64_t();

        private:
            uint64_t m_value;
            gguf_t* m__root;
            gguf_t::gguf_body_t::gguf_value_t* m__parent;

        public:
            uint64_t value() const { return m_value; }
            gguf_t* _root() const { return m__root; }
            gguf_t::gguf_body_t::gguf_value_t* _parent() const { return m__parent; }
        };

        class gguf_uint8_t : public kaitai::kstruct {

        public:

            gguf_uint8_t(kaitai::kstream* p__io, gguf_t::gguf_body_t::gguf_value_t* p__parent = nullptr, gguf_t* p__root = nullptr, int p_is_le = -1);

        private:
            int m__is_le;

        public:

        private:
            void _read();
            void _read_le();
            void _read_be();
            void _clean_up();

        public:
            ~gguf_uint8_t();

        private:
            uint8_t m_value;
            gguf_t* m__root;
            gguf_t::gguf_body_t::gguf_value_t* m__parent;

        public:
            uint8_t value() const { return m_value; }
            gguf_t* _root() const { return m__root; }
            gguf_t::gguf_body_t::gguf_value_t* _parent() const { return m__parent; }
        };

        /**
         * \sa https://github.com/ggml-org/ggml/blob/a05c9922613c6a2230dbb1d0de679519ecafb4f0/docs/gguf.md?plain=1#L239-L260 Git tag "v0.27.0"
         */

        class gguf_value_t : public kaitai::kstruct {

        public:

            gguf_value_t(gguf_type_t p_type, kaitai::kstream* p__io, kaitai::kstruct* p__parent = nullptr, gguf_t* p__root = nullptr, int p_is_le = -1);

        private:
            int m__is_le;

        public:

        private:
            void _read();
            void _read_le();
            void _read_be();
            void _clean_up();

        public:
            ~gguf_value_t();

        private:
            std::unique_ptr<kaitai::kstruct> m_value;
            bool n_value;

        public:
            bool _is_null_value() { value(); return n_value; };

        private:
            gguf_type_t m_type;
            gguf_t* m__root;
            kaitai::kstruct* m__parent;

        public:
            kaitai::kstruct* value() const { return m_value.get(); }
            gguf_type_t type() const { return m_type; }
            gguf_t* _root() const { return m__root; }
            kaitai::kstruct* _parent() const { return m__parent; }
        };

    private:
        bool f_alignment;
        uint32_t m_alignment;

    public:

        /**
         * Global alignment - from the `general.alignment` key, or 32 if there's no
         * such key.
         * \sa https://github.com/ggml-org/ggml/blob/a05c9922613c6a2230dbb1d0de679519ecafb4f0/src/gguf.cpp#L622-L630 Git tag "v0.27.0"
         */
        uint32_t alignment();

    private:
        bool f_ofs_tensor_data;
        uint64_t m_ofs_tensor_data;

    public:

        /**
         * Offset of the tensor data. Each tensor's `offset` is relative to this
         * position.
         */
        uint64_t ofs_tensor_data();

    private:
        uint32_t m_version;
        uint64_t m_num_tensor_infos;
        uint64_t m_num_kv_pairs;
        std::unique_ptr<std::vector<std::unique_ptr<gguf_kv_t>>> m_kv_pairs;
        std::unique_ptr<std::vector<std::unique_ptr<gguf_tensor_info_t>>> m_tensor_infos;
        std::string m_padding;
        bool n_padding;

    public:
        bool _is_null_padding() { padding(); return n_padding; };

    private:
        std::string m__unnamed6;
        bool n__unnamed6;

    public:
        bool _is_null__unnamed6() { _unnamed6(); return n__unnamed6; };

    private:
        gguf_t* m__root;
        gguf_t* m__parent;

    public:

        /**
         * File format version. Version 1 used 32-bit counts and lengths, which
         * this Kaitai Struct implementation doesn't support, and neither does
         * ggml.
         */
        uint32_t version() const { return m_version; }

        /**
         * The number of tensors in the file
         */
        uint64_t num_tensor_infos() const { return m_num_tensor_infos; }

        /**
         * The number of key-value pairs in the file header
         */
        uint64_t num_kv_pairs() const { return m_num_kv_pairs; }

        /**
         * Key-value pairs. ggml (v0.27.0)
         * [rejects](https://github.com/ggml-org/ggml/blob/a05c9922613c6a2230dbb1d0de679519ecafb4f0/src/gguf.cpp#L575-L578)
         * duplicate keys, but this Kaitai Struct implementation can't detect
         * them. If there are multiple `general.alignment` keys, the last one is
         * used for the `alignment` value instance.
         */
        std::vector<std::unique_ptr<gguf_kv_t>>* kv_pairs() const { return m_kv_pairs.get(); }

        /**
         * Tensor metadata. ggml (v0.27.0)
         * [rejects](https://github.com/ggml-org/ggml/blob/a05c9922613c6a2230dbb1d0de679519ecafb4f0/src/gguf.cpp#L664-L669)
         * duplicate tensor names, but this Kaitai Struct implementation can't
         * detect them.
         */
        std::vector<std::unique_ptr<gguf_tensor_info_t>>* tensor_infos() const { return m_tensor_infos.get(); }

        /**
         * \sa https://github.com/ggml-org/ggml/blob/a05c9922613c6a2230dbb1d0de679519ecafb4f0/src/gguf.cpp#L780-L785 Git tag "v0.27.0"
         */
        std::string padding() const { return m_padding; }
        std::string _unnamed6() const { return m__unnamed6; }
        gguf_t* _root() const { return m__root; }
        gguf_t* _parent() const { return m__parent; }
    };

private:
    bool f_is_big_endian;
    bool m_is_big_endian;

public:
    bool is_big_endian();

private:
    bool f_len_file;
    uint64_t m_len_file;

public:

    /**
     * Length of the file (computed from the header), including the padding after
     * the last tensor's data.
     * 
     * This Kaitai Struct implementation stops parsing where the tensor data
     * starts (which is read lazily, i.e. only on demand). Without reading the
     * tensor data, you can use this expected file size to check whether the file
     * has been truncated, to carve the file out of a larger one, etc.
     */
    uint64_t len_file();

private:
    bool f_version_le;
    uint32_t m_version_le;

public:
    uint32_t version_le();

private:
    std::string m_magic;
    std::unique_ptr<gguf_body_t> m_body;
    gguf_t* m__root;
    kaitai::kstruct* m__parent;

public:

    /**
     * GGUF file magic
     */
    std::string magic() const { return m_magic; }
    gguf_body_t* body() const { return m_body.get(); }
    gguf_t* _root() const { return m__root; }
    kaitai::kstruct* _parent() const { return m__parent; }
};

gguf.cpp

// This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild

#include "gguf.h"
#include "kaitai/exceptions.h"
const std::set<gguf_t::ggml_type_t> gguf_t::_values_ggml_type_t{
    gguf_t::GGML_TYPE_F32,
    gguf_t::GGML_TYPE_F16,
    gguf_t::GGML_TYPE_Q4_0,
    gguf_t::GGML_TYPE_Q4_1,
    gguf_t::GGML_TYPE_Q4_2,
    gguf_t::GGML_TYPE_Q4_3,
    gguf_t::GGML_TYPE_Q5_0,
    gguf_t::GGML_TYPE_Q5_1,
    gguf_t::GGML_TYPE_Q8_0,
    gguf_t::GGML_TYPE_Q8_1,
    gguf_t::GGML_TYPE_Q2_K,
    gguf_t::GGML_TYPE_Q3_K,
    gguf_t::GGML_TYPE_Q4_K,
    gguf_t::GGML_TYPE_Q5_K,
    gguf_t::GGML_TYPE_Q6_K,
    gguf_t::GGML_TYPE_Q8_K,
    gguf_t::GGML_TYPE_IQ2_XXS,
    gguf_t::GGML_TYPE_IQ2_XS,
    gguf_t::GGML_TYPE_IQ3_XXS,
    gguf_t::GGML_TYPE_IQ1_S,
    gguf_t::GGML_TYPE_IQ4_NL,
    gguf_t::GGML_TYPE_IQ3_S,
    gguf_t::GGML_TYPE_IQ2_S,
    gguf_t::GGML_TYPE_IQ4_XS,
    gguf_t::GGML_TYPE_I8,
    gguf_t::GGML_TYPE_I16,
    gguf_t::GGML_TYPE_I32,
    gguf_t::GGML_TYPE_I64,
    gguf_t::GGML_TYPE_F64,
    gguf_t::GGML_TYPE_IQ1_M,
    gguf_t::GGML_TYPE_BF16,
    gguf_t::GGML_TYPE_Q4_0_4_4,
    gguf_t::GGML_TYPE_Q4_0_4_8,
    gguf_t::GGML_TYPE_Q4_0_8_8,
    gguf_t::GGML_TYPE_TQ1_0,
    gguf_t::GGML_TYPE_TQ2_0,
    gguf_t::GGML_TYPE_IQ4_NL_4_4,
    gguf_t::GGML_TYPE_IQ4_NL_4_8,
    gguf_t::GGML_TYPE_IQ4_NL_8_8,
    gguf_t::GGML_TYPE_MXFP4,
    gguf_t::GGML_TYPE_NVFP4,
    gguf_t::GGML_TYPE_Q1_0,
    gguf_t::GGML_TYPE_Q2_0,
};
bool gguf_t::_is_defined_ggml_type_t(gguf_t::ggml_type_t v) {
    return gguf_t::_values_ggml_type_t.find(v) != gguf_t::_values_ggml_type_t.end();
}
const std::set<gguf_t::gguf_type_t> gguf_t::_values_gguf_type_t{
    gguf_t::GGUF_TYPE_UINT8,
    gguf_t::GGUF_TYPE_INT8,
    gguf_t::GGUF_TYPE_UINT16,
    gguf_t::GGUF_TYPE_INT16,
    gguf_t::GGUF_TYPE_UINT32,
    gguf_t::GGUF_TYPE_INT32,
    gguf_t::GGUF_TYPE_FLOAT32,
    gguf_t::GGUF_TYPE_BOOL,
    gguf_t::GGUF_TYPE_STRING,
    gguf_t::GGUF_TYPE_ARRAY,
    gguf_t::GGUF_TYPE_UINT64,
    gguf_t::GGUF_TYPE_INT64,
    gguf_t::GGUF_TYPE_FLOAT64,
};
bool gguf_t::_is_defined_gguf_type_t(gguf_t::gguf_type_t v) {
    return gguf_t::_values_gguf_type_t.find(v) != gguf_t::_values_gguf_type_t.end();
}

gguf_t::gguf_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent, gguf_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root ? p__root : this;
    m_body = nullptr;
    f_is_big_endian = false;
    f_len_file = false;
    f_version_le = false;
    _read();
}

void gguf_t::_read() {
    m_magic = m__io->read_bytes(4);
    if (!(m_magic == std::string("\x47\x47\x55\x46", 4))) {
        throw kaitai::validation_not_equal_error<std::string>(std::string("\x47\x47\x55\x46", 4), m_magic, m__io, std::string("/seq/0"));
    }
    m_body = std::unique_ptr<gguf_body_t>(new gguf_body_t(m__io, this, m__root));
}

gguf_t::~gguf_t() {
    _clean_up();
}

void gguf_t::_clean_up() {
    if (f_version_le) {
    }
}

gguf_t::gguf_body_t::gguf_body_t(kaitai::kstream* p__io, gguf_t* p__parent, gguf_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    m__is_le = -1;
    m_kv_pairs = nullptr;
    m_tensor_infos = nullptr;
    f_alignment = false;
    f_ofs_tensor_data = false;
    _read();
}

void gguf_t::gguf_body_t::_read() {
    {
        bool on = _root()->is_big_endian();
        if (on == true) {
            m__is_le = false;
        }
        else if (on == false) {
            m__is_le = true;
        }
    }

    if (m__is_le == -1) {
        throw kaitai::undecided_endianness_error("/types/gguf_body");
    } else if (m__is_le == 1) {
        _read_le();
    } else {
        _read_be();
    }
}

void gguf_t::gguf_body_t::_read_le() {
    m_version = m__io->read_u4le();
    if (!(m_version >= 2)) {
        throw kaitai::validation_less_than_error<uint32_t>(2, m_version, m__io, std::string("/types/gguf_body/seq/0"));
    }
    if (!(m_version <= 3)) {
        throw kaitai::validation_greater_than_error<uint32_t>(3, m_version, m__io, std::string("/types/gguf_body/seq/0"));
    }
    m_num_tensor_infos = m__io->read_u8le();
    m_num_kv_pairs = m__io->read_u8le();
    m_kv_pairs = std::unique_ptr<std::vector<std::unique_ptr<gguf_kv_t>>>(new std::vector<std::unique_ptr<gguf_kv_t>>());
    const int l_kv_pairs = num_kv_pairs();
    for (int i = 0; i < l_kv_pairs; i++) {
        m_kv_pairs->push_back(std::move(std::unique_ptr<gguf_kv_t>(new gguf_kv_t(((i != 0) ? (kv_pairs()->at(i - 1)->alignment()) : (32)), m__io, this, m__root, m__is_le))));
    }
    m_tensor_infos = std::unique_ptr<std::vector<std::unique_ptr<gguf_tensor_info_t>>>(new std::vector<std::unique_ptr<gguf_tensor_info_t>>());
    const int l_tensor_infos = num_tensor_infos();
    for (int i = 0; i < l_tensor_infos; i++) {
        m_tensor_infos->push_back(std::move(std::unique_ptr<gguf_tensor_info_t>(new gguf_tensor_info_t(((i != 0) ? (tensor_infos()->at(i - 1)->expected_next_offset()) : (0)), m__io, this, m__root, m__is_le))));
    }
    n_padding = true;
    if (num_tensor_infos() != 0) {
        n_padding = false;
        m_padding = m__io->read_bytes(kaitai::kstream::mod(alignment() - kaitai::kstream::mod(_io()->pos(), alignment()), alignment()));
    }
    n__unnamed6 = true;
    if (ofs_tensor_data() < 0) {
        n__unnamed6 = false;
        m__unnamed6 = m__io->read_bytes(0);
    }
}

void gguf_t::gguf_body_t::_read_be() {
    m_version = m__io->read_u4be();
    if (!(m_version >= 2)) {
        throw kaitai::validation_less_than_error<uint32_t>(2, m_version, m__io, std::string("/types/gguf_body/seq/0"));
    }
    if (!(m_version <= 3)) {
        throw kaitai::validation_greater_than_error<uint32_t>(3, m_version, m__io, std::string("/types/gguf_body/seq/0"));
    }
    m_num_tensor_infos = m__io->read_u8be();
    m_num_kv_pairs = m__io->read_u8be();
    m_kv_pairs = std::unique_ptr<std::vector<std::unique_ptr<gguf_kv_t>>>(new std::vector<std::unique_ptr<gguf_kv_t>>());
    const int l_kv_pairs = num_kv_pairs();
    for (int i = 0; i < l_kv_pairs; i++) {
        m_kv_pairs->push_back(std::move(std::unique_ptr<gguf_kv_t>(new gguf_kv_t(((i != 0) ? (kv_pairs()->at(i - 1)->alignment()) : (32)), m__io, this, m__root, m__is_le))));
    }
    m_tensor_infos = std::unique_ptr<std::vector<std::unique_ptr<gguf_tensor_info_t>>>(new std::vector<std::unique_ptr<gguf_tensor_info_t>>());
    const int l_tensor_infos = num_tensor_infos();
    for (int i = 0; i < l_tensor_infos; i++) {
        m_tensor_infos->push_back(std::move(std::unique_ptr<gguf_tensor_info_t>(new gguf_tensor_info_t(((i != 0) ? (tensor_infos()->at(i - 1)->expected_next_offset()) : (0)), m__io, this, m__root, m__is_le))));
    }
    n_padding = true;
    if (num_tensor_infos() != 0) {
        n_padding = false;
        m_padding = m__io->read_bytes(kaitai::kstream::mod(alignment() - kaitai::kstream::mod(_io()->pos(), alignment()), alignment()));
    }
    n__unnamed6 = true;
    if (ofs_tensor_data() < 0) {
        n__unnamed6 = false;
        m__unnamed6 = m__io->read_bytes(0);
    }
}

gguf_t::gguf_body_t::~gguf_body_t() {
    _clean_up();
}

void gguf_t::gguf_body_t::_clean_up() {
    if (!n_padding) {
    }
    if (!n__unnamed6) {
    }
}

gguf_t::gguf_body_t::gguf_array_t::gguf_array_t(kaitai::kstream* p__io, gguf_t::gguf_body_t::gguf_value_t* p__parent, gguf_t* p__root, int p_is_le) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    m__is_le = p_is_le;
    m_elems = nullptr;
    _read();
}

void gguf_t::gguf_body_t::gguf_array_t::_read() {

    if (m__is_le == -1) {
        throw kaitai::undecided_endianness_error("/types/gguf_body/types/gguf_array");
    } else if (m__is_le == 1) {
        _read_le();
    } else {
        _read_be();
    }
}

void gguf_t::gguf_body_t::gguf_array_t::_read_le() {
    m_type = static_cast<gguf_t::gguf_type_t>(m__io->read_u4le());
    if (!gguf_t::_is_defined_gguf_type_t(m_type)) {
        throw kaitai::validation_not_in_enum_error<gguf_t::gguf_type_t>(m_type, m__io, std::string("/types/gguf_body/types/gguf_array/seq/0"));
    }
    m_num_elems = m__io->read_u8le();
    m_elems = std::unique_ptr<std::vector<std::unique_ptr<gguf_value_t>>>(new std::vector<std::unique_ptr<gguf_value_t>>());
    const int l_elems = num_elems();
    for (int i = 0; i < l_elems; i++) {
        m_elems->push_back(std::move(std::unique_ptr<gguf_value_t>(new gguf_value_t(type(), m__io, this, m__root, m__is_le))));
    }
}

void gguf_t::gguf_body_t::gguf_array_t::_read_be() {
    m_type = static_cast<gguf_t::gguf_type_t>(m__io->read_u4be());
    if (!gguf_t::_is_defined_gguf_type_t(m_type)) {
        throw kaitai::validation_not_in_enum_error<gguf_t::gguf_type_t>(m_type, m__io, std::string("/types/gguf_body/types/gguf_array/seq/0"));
    }
    m_num_elems = m__io->read_u8be();
    m_elems = std::unique_ptr<std::vector<std::unique_ptr<gguf_value_t>>>(new std::vector<std::unique_ptr<gguf_value_t>>());
    const int l_elems = num_elems();
    for (int i = 0; i < l_elems; i++) {
        m_elems->push_back(std::move(std::unique_ptr<gguf_value_t>(new gguf_value_t(type(), m__io, this, m__root, m__is_le))));
    }
}

gguf_t::gguf_body_t::gguf_array_t::~gguf_array_t() {
    _clean_up();
}

void gguf_t::gguf_body_t::gguf_array_t::_clean_up() {
}

gguf_t::gguf_body_t::gguf_bool_t::gguf_bool_t(kaitai::kstream* p__io, gguf_t::gguf_body_t::gguf_value_t* p__parent, gguf_t* p__root, int p_is_le) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    m__is_le = p_is_le;
    f_value = false;
    _read();
}

void gguf_t::gguf_body_t::gguf_bool_t::_read() {

    if (m__is_le == -1) {
        throw kaitai::undecided_endianness_error("/types/gguf_body/types/gguf_bool");
    } else if (m__is_le == 1) {
        _read_le();
    } else {
        _read_be();
    }
}

void gguf_t::gguf_body_t::gguf_bool_t::_read_le() {
    m_value_raw = m__io->read_u1();
    if (!(m_value_raw <= 1)) {
        throw kaitai::validation_greater_than_error<uint8_t>(1, m_value_raw, m__io, std::string("/types/gguf_body/types/gguf_bool/seq/0"));
    }
}

void gguf_t::gguf_body_t::gguf_bool_t::_read_be() {
    m_value_raw = m__io->read_u1();
    if (!(m_value_raw <= 1)) {
        throw kaitai::validation_greater_than_error<uint8_t>(1, m_value_raw, m__io, std::string("/types/gguf_body/types/gguf_bool/seq/0"));
    }
}

gguf_t::gguf_body_t::gguf_bool_t::~gguf_bool_t() {
    _clean_up();
}

void gguf_t::gguf_body_t::gguf_bool_t::_clean_up() {
}

bool gguf_t::gguf_body_t::gguf_bool_t::value() {
    if (f_value)
        return m_value;
    f_value = true;
    m_value = value_raw() != 0;
    return m_value;
}

gguf_t::gguf_body_t::gguf_float32_t::gguf_float32_t(kaitai::kstream* p__io, gguf_t::gguf_body_t::gguf_value_t* p__parent, gguf_t* p__root, int p_is_le) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    m__is_le = p_is_le;
    _read();
}

void gguf_t::gguf_body_t::gguf_float32_t::_read() {

    if (m__is_le == -1) {
        throw kaitai::undecided_endianness_error("/types/gguf_body/types/gguf_float32");
    } else if (m__is_le == 1) {
        _read_le();
    } else {
        _read_be();
    }
}

void gguf_t::gguf_body_t::gguf_float32_t::_read_le() {
    m_value = m__io->read_f4le();
}

void gguf_t::gguf_body_t::gguf_float32_t::_read_be() {
    m_value = m__io->read_f4be();
}

gguf_t::gguf_body_t::gguf_float32_t::~gguf_float32_t() {
    _clean_up();
}

void gguf_t::gguf_body_t::gguf_float32_t::_clean_up() {
}

gguf_t::gguf_body_t::gguf_float64_t::gguf_float64_t(kaitai::kstream* p__io, gguf_t::gguf_body_t::gguf_value_t* p__parent, gguf_t* p__root, int p_is_le) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    m__is_le = p_is_le;
    _read();
}

void gguf_t::gguf_body_t::gguf_float64_t::_read() {

    if (m__is_le == -1) {
        throw kaitai::undecided_endianness_error("/types/gguf_body/types/gguf_float64");
    } else if (m__is_le == 1) {
        _read_le();
    } else {
        _read_be();
    }
}

void gguf_t::gguf_body_t::gguf_float64_t::_read_le() {
    m_value = m__io->read_f8le();
}

void gguf_t::gguf_body_t::gguf_float64_t::_read_be() {
    m_value = m__io->read_f8be();
}

gguf_t::gguf_body_t::gguf_float64_t::~gguf_float64_t() {
    _clean_up();
}

void gguf_t::gguf_body_t::gguf_float64_t::_clean_up() {
}

gguf_t::gguf_body_t::gguf_int16_t::gguf_int16_t(kaitai::kstream* p__io, gguf_t::gguf_body_t::gguf_value_t* p__parent, gguf_t* p__root, int p_is_le) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    m__is_le = p_is_le;
    _read();
}

void gguf_t::gguf_body_t::gguf_int16_t::_read() {

    if (m__is_le == -1) {
        throw kaitai::undecided_endianness_error("/types/gguf_body/types/gguf_int16");
    } else if (m__is_le == 1) {
        _read_le();
    } else {
        _read_be();
    }
}

void gguf_t::gguf_body_t::gguf_int16_t::_read_le() {
    m_value = m__io->read_s2le();
}

void gguf_t::gguf_body_t::gguf_int16_t::_read_be() {
    m_value = m__io->read_s2be();
}

gguf_t::gguf_body_t::gguf_int16_t::~gguf_int16_t() {
    _clean_up();
}

void gguf_t::gguf_body_t::gguf_int16_t::_clean_up() {
}

gguf_t::gguf_body_t::gguf_int32_t::gguf_int32_t(kaitai::kstream* p__io, gguf_t::gguf_body_t::gguf_value_t* p__parent, gguf_t* p__root, int p_is_le) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    m__is_le = p_is_le;
    _read();
}

void gguf_t::gguf_body_t::gguf_int32_t::_read() {

    if (m__is_le == -1) {
        throw kaitai::undecided_endianness_error("/types/gguf_body/types/gguf_int32");
    } else if (m__is_le == 1) {
        _read_le();
    } else {
        _read_be();
    }
}

void gguf_t::gguf_body_t::gguf_int32_t::_read_le() {
    m_value = m__io->read_s4le();
}

void gguf_t::gguf_body_t::gguf_int32_t::_read_be() {
    m_value = m__io->read_s4be();
}

gguf_t::gguf_body_t::gguf_int32_t::~gguf_int32_t() {
    _clean_up();
}

void gguf_t::gguf_body_t::gguf_int32_t::_clean_up() {
}

gguf_t::gguf_body_t::gguf_int64_t::gguf_int64_t(kaitai::kstream* p__io, gguf_t::gguf_body_t::gguf_value_t* p__parent, gguf_t* p__root, int p_is_le) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    m__is_le = p_is_le;
    _read();
}

void gguf_t::gguf_body_t::gguf_int64_t::_read() {

    if (m__is_le == -1) {
        throw kaitai::undecided_endianness_error("/types/gguf_body/types/gguf_int64");
    } else if (m__is_le == 1) {
        _read_le();
    } else {
        _read_be();
    }
}

void gguf_t::gguf_body_t::gguf_int64_t::_read_le() {
    m_value = m__io->read_s8le();
}

void gguf_t::gguf_body_t::gguf_int64_t::_read_be() {
    m_value = m__io->read_s8be();
}

gguf_t::gguf_body_t::gguf_int64_t::~gguf_int64_t() {
    _clean_up();
}

void gguf_t::gguf_body_t::gguf_int64_t::_clean_up() {
}

gguf_t::gguf_body_t::gguf_int8_t::gguf_int8_t(kaitai::kstream* p__io, gguf_t::gguf_body_t::gguf_value_t* p__parent, gguf_t* p__root, int p_is_le) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    m__is_le = p_is_le;
    _read();
}

void gguf_t::gguf_body_t::gguf_int8_t::_read() {

    if (m__is_le == -1) {
        throw kaitai::undecided_endianness_error("/types/gguf_body/types/gguf_int8");
    } else if (m__is_le == 1) {
        _read_le();
    } else {
        _read_be();
    }
}

void gguf_t::gguf_body_t::gguf_int8_t::_read_le() {
    m_value = m__io->read_s1();
}

void gguf_t::gguf_body_t::gguf_int8_t::_read_be() {
    m_value = m__io->read_s1();
}

gguf_t::gguf_body_t::gguf_int8_t::~gguf_int8_t() {
    _clean_up();
}

void gguf_t::gguf_body_t::gguf_int8_t::_clean_up() {
}

gguf_t::gguf_body_t::gguf_kv_t::gguf_kv_t(uint32_t p_prev_alignment, kaitai::kstream* p__io, gguf_t::gguf_body_t* p__parent, gguf_t* p__root, int p_is_le) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    m__is_le = p_is_le;
    m_prev_alignment = p_prev_alignment;
    m_key = nullptr;
    m_value = nullptr;
    f_alignment = false;
    _read();
}

void gguf_t::gguf_body_t::gguf_kv_t::_read() {

    if (m__is_le == -1) {
        throw kaitai::undecided_endianness_error("/types/gguf_body/types/gguf_kv");
    } else if (m__is_le == 1) {
        _read_le();
    } else {
        _read_be();
    }
}

void gguf_t::gguf_body_t::gguf_kv_t::_read_le() {
    m_key = std::unique_ptr<gguf_str_t>(new gguf_str_t(m__io, this, m__root, m__is_le));
    {
        std::unique_ptr<gguf_str_t> _ = m_key;
        if (!(_->len_value() != 0)) {
            throw kaitai::validation_expr_error<std::unique_ptr<gguf_t::gguf_body_t::gguf_str_t>>(m_key, m__io, std::string("/types/gguf_body/types/gguf_kv/seq/0"));
        }
    }
    m_type = static_cast<gguf_t::gguf_type_t>(m__io->read_u4le());
    if (!gguf_t::_is_defined_gguf_type_t(m_type)) {
        throw kaitai::validation_not_in_enum_error<gguf_t::gguf_type_t>(m_type, m__io, std::string("/types/gguf_body/types/gguf_kv/seq/1"));
    }
    m_value = std::unique_ptr<gguf_value_t>(new gguf_value_t(type(), m__io, this, m__root, m__is_le));
    {
        std::unique_ptr<gguf_value_t> _ = m_value;
        if (!(((key()->value() == std::string("general.alignment")) ? ( ((type() == gguf_t::GGUF_TYPE_UINT32) && (static_cast<gguf_t::gguf_body_t::gguf_uint32_t*>(_->value())->value() != 0) && ((static_cast<gguf_t::gguf_body_t::gguf_uint32_t*>(_->value())->value() & static_cast<gguf_t::gguf_body_t::gguf_uint32_t*>(_->value())->value() - 1) == 0)) ) : (true)))) {
            throw kaitai::validation_expr_error<std::unique_ptr<gguf_t::gguf_body_t::gguf_value_t>>(m_value, m__io, std::string("/types/gguf_body/types/gguf_kv/seq/2"));
        }
    }
}

void gguf_t::gguf_body_t::gguf_kv_t::_read_be() {
    m_key = std::unique_ptr<gguf_str_t>(new gguf_str_t(m__io, this, m__root, m__is_le));
    {
        std::unique_ptr<gguf_str_t> _ = m_key;
        if (!(_->len_value() != 0)) {
            throw kaitai::validation_expr_error<std::unique_ptr<gguf_t::gguf_body_t::gguf_str_t>>(m_key, m__io, std::string("/types/gguf_body/types/gguf_kv/seq/0"));
        }
    }
    m_type = static_cast<gguf_t::gguf_type_t>(m__io->read_u4be());
    if (!gguf_t::_is_defined_gguf_type_t(m_type)) {
        throw kaitai::validation_not_in_enum_error<gguf_t::gguf_type_t>(m_type, m__io, std::string("/types/gguf_body/types/gguf_kv/seq/1"));
    }
    m_value = std::unique_ptr<gguf_value_t>(new gguf_value_t(type(), m__io, this, m__root, m__is_le));
    {
        std::unique_ptr<gguf_value_t> _ = m_value;
        if (!(((key()->value() == std::string("general.alignment")) ? ( ((type() == gguf_t::GGUF_TYPE_UINT32) && (static_cast<gguf_t::gguf_body_t::gguf_uint32_t*>(_->value())->value() != 0) && ((static_cast<gguf_t::gguf_body_t::gguf_uint32_t*>(_->value())->value() & static_cast<gguf_t::gguf_body_t::gguf_uint32_t*>(_->value())->value() - 1) == 0)) ) : (true)))) {
            throw kaitai::validation_expr_error<std::unique_ptr<gguf_t::gguf_body_t::gguf_value_t>>(m_value, m__io, std::string("/types/gguf_body/types/gguf_kv/seq/2"));
        }
    }
}

gguf_t::gguf_body_t::gguf_kv_t::~gguf_kv_t() {
    _clean_up();
}

void gguf_t::gguf_body_t::gguf_kv_t::_clean_up() {
}

uint32_t gguf_t::gguf_body_t::gguf_kv_t::alignment() {
    if (f_alignment)
        return m_alignment;
    f_alignment = true;
    m_alignment = ((key()->value() == std::string("general.alignment")) ? (static_cast<gguf_t::gguf_body_t::gguf_uint32_t*>(value()->value())->value()) : (prev_alignment()));
    return m_alignment;
}

gguf_t::gguf_body_t::gguf_str_t::gguf_str_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent, gguf_t* p__root, int p_is_le) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    m__is_le = p_is_le;
    _read();
}

void gguf_t::gguf_body_t::gguf_str_t::_read() {

    if (m__is_le == -1) {
        throw kaitai::undecided_endianness_error("/types/gguf_body/types/gguf_str");
    } else if (m__is_le == 1) {
        _read_le();
    } else {
        _read_be();
    }
}

void gguf_t::gguf_body_t::gguf_str_t::_read_le() {
    m_len_value = m__io->read_u8le();
    m_value = kaitai::kstream::bytes_to_str(m__io->read_bytes(len_value()), "UTF-8");
}

void gguf_t::gguf_body_t::gguf_str_t::_read_be() {
    m_len_value = m__io->read_u8be();
    m_value = kaitai::kstream::bytes_to_str(m__io->read_bytes(len_value()), "UTF-8");
}

gguf_t::gguf_body_t::gguf_str_t::~gguf_str_t() {
    _clean_up();
}

void gguf_t::gguf_body_t::gguf_str_t::_clean_up() {
}

gguf_t::gguf_body_t::gguf_tensor_info_t::gguf_tensor_info_t(uint64_t p_expected_offset, kaitai::kstream* p__io, gguf_t::gguf_body_t* p__parent, gguf_t* p__root, int p_is_le) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    m__is_le = p_is_le;
    m_expected_offset = p_expected_offset;
    m_name = nullptr;
    m_dims = nullptr;
    f_data = false;
    f_dump_dims = false;
    f_expected_next_offset = false;
    f_len_block = false;
    f_len_data = false;
    f_len_padding = false;
    f_num_blocks = false;
    f_num_elements = false;
    f_num_elements_per_block = false;
    f_padding = false;
    _read();
}

void gguf_t::gguf_body_t::gguf_tensor_info_t::_read() {

    if (m__is_le == -1) {
        throw kaitai::undecided_endianness_error("/types/gguf_body/types/gguf_tensor_info");
    } else if (m__is_le == 1) {
        _read_le();
    } else {
        _read_be();
    }
}

void gguf_t::gguf_body_t::gguf_tensor_info_t::_read_le() {
    m_name = std::unique_ptr<gguf_str_t>(new gguf_str_t(m__io, this, m__root, m__is_le));
    {
        std::unique_ptr<gguf_str_t> _ = m_name;
        if (!(_->len_value() < 64)) {
            throw kaitai::validation_expr_error<std::unique_ptr<gguf_t::gguf_body_t::gguf_str_t>>(m_name, m__io, std::string("/types/gguf_body/types/gguf_tensor_info/seq/0"));
        }
    }
    m_num_dims = m__io->read_u4le();
    if (!(m_num_dims <= 4)) {
        throw kaitai::validation_greater_than_error<uint32_t>(4, m_num_dims, m__io, std::string("/types/gguf_body/types/gguf_tensor_info/seq/1"));
    }
    m_dims = std::unique_ptr<std::vector<int64_t>>(new std::vector<int64_t>());
    const int l_dims = num_dims();
    for (int i = 0; i < l_dims; i++) {
        m_dims->push_back(std::move(m__io->read_s8le()));
        if (!(m_dims->at(i) >= 0)) {
            throw kaitai::validation_less_than_error<int64_t>(0, m_dims->at(i), m__io, std::string("/types/gguf_body/types/gguf_tensor_info/seq/2"));
        }
    }
    m_type = static_cast<gguf_t::ggml_type_t>(m__io->read_u4le());
    {
        ggml_type_t _ = m_type;
        if (!( ((_ < 43) && (num_elements_per_block() != 0) && (kaitai::kstream::mod(((num_dims() > 0) ? (dims()->at(0)) : (1)), num_elements_per_block()) == 0)) )) {
            throw kaitai::validation_expr_error<gguf_t::ggml_type_t>(m_type, m__io, std::string("/types/gguf_body/types/gguf_tensor_info/seq/3"));
        }
    }
    m_offset = m__io->read_u8le();
    if (!(m_offset == expected_offset())) {
        throw kaitai::validation_not_equal_error<uint64_t>(expected_offset(), m_offset, m__io, std::string("/types/gguf_body/types/gguf_tensor_info/seq/4"));
    }
}

void gguf_t::gguf_body_t::gguf_tensor_info_t::_read_be() {
    m_name = std::unique_ptr<gguf_str_t>(new gguf_str_t(m__io, this, m__root, m__is_le));
    {
        std::unique_ptr<gguf_str_t> _ = m_name;
        if (!(_->len_value() < 64)) {
            throw kaitai::validation_expr_error<std::unique_ptr<gguf_t::gguf_body_t::gguf_str_t>>(m_name, m__io, std::string("/types/gguf_body/types/gguf_tensor_info/seq/0"));
        }
    }
    m_num_dims = m__io->read_u4be();
    if (!(m_num_dims <= 4)) {
        throw kaitai::validation_greater_than_error<uint32_t>(4, m_num_dims, m__io, std::string("/types/gguf_body/types/gguf_tensor_info/seq/1"));
    }
    m_dims = std::unique_ptr<std::vector<int64_t>>(new std::vector<int64_t>());
    const int l_dims = num_dims();
    for (int i = 0; i < l_dims; i++) {
        m_dims->push_back(std::move(m__io->read_s8be()));
        if (!(m_dims->at(i) >= 0)) {
            throw kaitai::validation_less_than_error<int64_t>(0, m_dims->at(i), m__io, std::string("/types/gguf_body/types/gguf_tensor_info/seq/2"));
        }
    }
    m_type = static_cast<gguf_t::ggml_type_t>(m__io->read_u4be());
    {
        ggml_type_t _ = m_type;
        if (!( ((_ < 43) && (num_elements_per_block() != 0) && (kaitai::kstream::mod(((num_dims() > 0) ? (dims()->at(0)) : (1)), num_elements_per_block()) == 0)) )) {
            throw kaitai::validation_expr_error<gguf_t::ggml_type_t>(m_type, m__io, std::string("/types/gguf_body/types/gguf_tensor_info/seq/3"));
        }
    }
    m_offset = m__io->read_u8be();
    if (!(m_offset == expected_offset())) {
        throw kaitai::validation_not_equal_error<uint64_t>(expected_offset(), m_offset, m__io, std::string("/types/gguf_body/types/gguf_tensor_info/seq/4"));
    }
}

gguf_t::gguf_body_t::gguf_tensor_info_t::~gguf_tensor_info_t() {
    _clean_up();
}

void gguf_t::gguf_body_t::gguf_tensor_info_t::_clean_up() {
    if (f_data) {
    }
    if (f_padding) {
    }
}

std::string gguf_t::gguf_body_t::gguf_tensor_info_t::data() {
    if (f_data)
        return m_data;
    f_data = true;
    std::streampos _pos = m__io->pos();
    m__io->seek(_parent()->ofs_tensor_data() + offset());
    if (m__is_le == 1) {
        m_data = m__io->read_bytes(len_data());
    } else {
        m_data = m__io->read_bytes(len_data());
    }
    m__io->seek(_pos);
    return m_data;
}

std::string gguf_t::gguf_body_t::gguf_tensor_info_t::dump_dims() {
    if (f_dump_dims)
        return m_dump_dims;
    f_dump_dims = true;
    m_dump_dims = ((((num_dims() > 0) ? (kaitai::kstream::to_string(dims()->at(0))) : (std::string(""))) + ((num_dims() > 1) ? (std::string(" x ") + kaitai::kstream::to_string(dims()->at(1))) : (std::string("")))) + ((num_dims() > 2) ? (std::string(" x ") + kaitai::kstream::to_string(dims()->at(2))) : (std::string("")))) + ((num_dims() > 3) ? (std::string(" x ") + kaitai::kstream::to_string(dims()->at(3))) : (std::string("")));
    return m_dump_dims;
}

uint64_t gguf_t::gguf_body_t::gguf_tensor_info_t::expected_next_offset() {
    if (f_expected_next_offset)
        return m_expected_next_offset;
    f_expected_next_offset = true;
    m_expected_next_offset = static_cast<uint64_t>((offset() + len_data()) + len_padding());
    return m_expected_next_offset;
}

int32_t gguf_t::gguf_body_t::gguf_tensor_info_t::len_block() {
    if (f_len_block)
        return m_len_block;
    f_len_block = true;
    m_len_block = std::unique_ptr<std::vector<int32_t>>(new std::vector<int32_t>{4, 2, 18, 20, 0, 0, 22, 24, 34, 36, 84, 110, 144, 176, 210, 292, 66, 74, 98, 50, 18, 110, 82, 136, 1, 2, 4, 8, 8, 56, 2, 0, 0, 0, 54, 66, 0, 0, 0, 17, 36, 18, 18})->at(type());
    return m_len_block;
}

uint64_t gguf_t::gguf_body_t::gguf_tensor_info_t::len_data() {
    if (f_len_data)
        return m_len_data;
    f_len_data = true;
    m_len_data = static_cast<uint64_t>(len_block() * num_blocks());
    return m_len_data;
}

int32_t gguf_t::gguf_body_t::gguf_tensor_info_t::len_padding() {
    if (f_len_padding)
        return m_len_padding;
    f_len_padding = true;
    m_len_padding = kaitai::kstream::mod(_parent()->alignment() - kaitai::kstream::mod(len_data(), _parent()->alignment()), _parent()->alignment());
    return m_len_padding;
}

int64_t gguf_t::gguf_body_t::gguf_tensor_info_t::num_blocks() {
    if (f_num_blocks)
        return m_num_blocks;
    f_num_blocks = true;
    m_num_blocks = static_cast<int64_t>(num_elements() / num_elements_per_block());
    return m_num_blocks;
}

int64_t gguf_t::gguf_body_t::gguf_tensor_info_t::num_elements() {
    if (f_num_elements)
        return m_num_elements;
    f_num_elements = true;
    m_num_elements = static_cast<int64_t>(((((num_dims() > 0) ? (dims()->at(0)) : (1)) * ((num_dims() > 1) ? (dims()->at(1)) : (1))) * ((num_dims() > 2) ? (dims()->at(2)) : (1))) * ((num_dims() > 3) ? (dims()->at(3)) : (1)));
    return m_num_elements;
}

int32_t gguf_t::gguf_body_t::gguf_tensor_info_t::num_elements_per_block() {
    if (f_num_elements_per_block)
        return m_num_elements_per_block;
    f_num_elements_per_block = true;
    m_num_elements_per_block = std::unique_ptr<std::vector<int32_t>>(new std::vector<int32_t>{1, 1, 32, 32, 0, 0, 32, 32, 32, 32, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 32, 256, 256, 256, 1, 1, 1, 1, 1, 256, 1, 0, 0, 0, 256, 256, 0, 0, 0, 32, 64, 128, 64})->at(type());
    return m_num_elements_per_block;
}

std::string gguf_t::gguf_body_t::gguf_tensor_info_t::padding() {
    if (f_padding)
        return m_padding;
    f_padding = true;
    std::streampos _pos = m__io->pos();
    m__io->seek((_parent()->ofs_tensor_data() + offset()) + len_data());
    if (m__is_le == 1) {
        m_padding = m__io->read_bytes(len_padding());
    } else {
        m_padding = m__io->read_bytes(len_padding());
    }
    m__io->seek(_pos);
    return m_padding;
}

gguf_t::gguf_body_t::gguf_uint16_t::gguf_uint16_t(kaitai::kstream* p__io, gguf_t::gguf_body_t::gguf_value_t* p__parent, gguf_t* p__root, int p_is_le) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    m__is_le = p_is_le;
    _read();
}

void gguf_t::gguf_body_t::gguf_uint16_t::_read() {

    if (m__is_le == -1) {
        throw kaitai::undecided_endianness_error("/types/gguf_body/types/gguf_uint16");
    } else if (m__is_le == 1) {
        _read_le();
    } else {
        _read_be();
    }
}

void gguf_t::gguf_body_t::gguf_uint16_t::_read_le() {
    m_value = m__io->read_u2le();
}

void gguf_t::gguf_body_t::gguf_uint16_t::_read_be() {
    m_value = m__io->read_u2be();
}

gguf_t::gguf_body_t::gguf_uint16_t::~gguf_uint16_t() {
    _clean_up();
}

void gguf_t::gguf_body_t::gguf_uint16_t::_clean_up() {
}

gguf_t::gguf_body_t::gguf_uint32_t::gguf_uint32_t(kaitai::kstream* p__io, gguf_t::gguf_body_t::gguf_value_t* p__parent, gguf_t* p__root, int p_is_le) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    m__is_le = p_is_le;
    _read();
}

void gguf_t::gguf_body_t::gguf_uint32_t::_read() {

    if (m__is_le == -1) {
        throw kaitai::undecided_endianness_error("/types/gguf_body/types/gguf_uint32");
    } else if (m__is_le == 1) {
        _read_le();
    } else {
        _read_be();
    }
}

void gguf_t::gguf_body_t::gguf_uint32_t::_read_le() {
    m_value = m__io->read_u4le();
}

void gguf_t::gguf_body_t::gguf_uint32_t::_read_be() {
    m_value = m__io->read_u4be();
}

gguf_t::gguf_body_t::gguf_uint32_t::~gguf_uint32_t() {
    _clean_up();
}

void gguf_t::gguf_body_t::gguf_uint32_t::_clean_up() {
}

gguf_t::gguf_body_t::gguf_uint64_t::gguf_uint64_t(kaitai::kstream* p__io, gguf_t::gguf_body_t::gguf_value_t* p__parent, gguf_t* p__root, int p_is_le) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    m__is_le = p_is_le;
    _read();
}

void gguf_t::gguf_body_t::gguf_uint64_t::_read() {

    if (m__is_le == -1) {
        throw kaitai::undecided_endianness_error("/types/gguf_body/types/gguf_uint64");
    } else if (m__is_le == 1) {
        _read_le();
    } else {
        _read_be();
    }
}

void gguf_t::gguf_body_t::gguf_uint64_t::_read_le() {
    m_value = m__io->read_u8le();
}

void gguf_t::gguf_body_t::gguf_uint64_t::_read_be() {
    m_value = m__io->read_u8be();
}

gguf_t::gguf_body_t::gguf_uint64_t::~gguf_uint64_t() {
    _clean_up();
}

void gguf_t::gguf_body_t::gguf_uint64_t::_clean_up() {
}

gguf_t::gguf_body_t::gguf_uint8_t::gguf_uint8_t(kaitai::kstream* p__io, gguf_t::gguf_body_t::gguf_value_t* p__parent, gguf_t* p__root, int p_is_le) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    m__is_le = p_is_le;
    _read();
}

void gguf_t::gguf_body_t::gguf_uint8_t::_read() {

    if (m__is_le == -1) {
        throw kaitai::undecided_endianness_error("/types/gguf_body/types/gguf_uint8");
    } else if (m__is_le == 1) {
        _read_le();
    } else {
        _read_be();
    }
}

void gguf_t::gguf_body_t::gguf_uint8_t::_read_le() {
    m_value = m__io->read_u1();
}

void gguf_t::gguf_body_t::gguf_uint8_t::_read_be() {
    m_value = m__io->read_u1();
}

gguf_t::gguf_body_t::gguf_uint8_t::~gguf_uint8_t() {
    _clean_up();
}

void gguf_t::gguf_body_t::gguf_uint8_t::_clean_up() {
}

gguf_t::gguf_body_t::gguf_value_t::gguf_value_t(gguf_type_t p_type, kaitai::kstream* p__io, kaitai::kstruct* p__parent, gguf_t* p__root, int p_is_le) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    m__is_le = p_is_le;
    m_type = p_type;
    _read();
}

void gguf_t::gguf_body_t::gguf_value_t::_read() {

    if (m__is_le == -1) {
        throw kaitai::undecided_endianness_error("/types/gguf_body/types/gguf_value");
    } else if (m__is_le == 1) {
        _read_le();
    } else {
        _read_be();
    }
}

void gguf_t::gguf_body_t::gguf_value_t::_read_le() {
    n_value = true;
    switch (type()) {
    case gguf_t::GGUF_TYPE_ARRAY: {
        n_value = false;
        m_value = std::unique_ptr<gguf_array_t>(new gguf_array_t(m__io, this, m__root, m__is_le));
        break;
    }
    case gguf_t::GGUF_TYPE_BOOL: {
        n_value = false;
        m_value = std::unique_ptr<gguf_bool_t>(new gguf_bool_t(m__io, this, m__root, m__is_le));
        break;
    }
    case gguf_t::GGUF_TYPE_FLOAT32: {
        n_value = false;
        m_value = std::unique_ptr<gguf_float32_t>(new gguf_float32_t(m__io, this, m__root, m__is_le));
        break;
    }
    case gguf_t::GGUF_TYPE_FLOAT64: {
        n_value = false;
        m_value = std::unique_ptr<gguf_float64_t>(new gguf_float64_t(m__io, this, m__root, m__is_le));
        break;
    }
    case gguf_t::GGUF_TYPE_INT16: {
        n_value = false;
        m_value = std::unique_ptr<gguf_int16_t>(new gguf_int16_t(m__io, this, m__root, m__is_le));
        break;
    }
    case gguf_t::GGUF_TYPE_INT32: {
        n_value = false;
        m_value = std::unique_ptr<gguf_int32_t>(new gguf_int32_t(m__io, this, m__root, m__is_le));
        break;
    }
    case gguf_t::GGUF_TYPE_INT64: {
        n_value = false;
        m_value = std::unique_ptr<gguf_int64_t>(new gguf_int64_t(m__io, this, m__root, m__is_le));
        break;
    }
    case gguf_t::GGUF_TYPE_INT8: {
        n_value = false;
        m_value = std::unique_ptr<gguf_int8_t>(new gguf_int8_t(m__io, this, m__root, m__is_le));
        break;
    }
    case gguf_t::GGUF_TYPE_STRING: {
        n_value = false;
        m_value = std::unique_ptr<gguf_str_t>(new gguf_str_t(m__io, this, m__root, m__is_le));
        break;
    }
    case gguf_t::GGUF_TYPE_UINT16: {
        n_value = false;
        m_value = std::unique_ptr<gguf_uint16_t>(new gguf_uint16_t(m__io, this, m__root, m__is_le));
        break;
    }
    case gguf_t::GGUF_TYPE_UINT32: {
        n_value = false;
        m_value = std::unique_ptr<gguf_uint32_t>(new gguf_uint32_t(m__io, this, m__root, m__is_le));
        break;
    }
    case gguf_t::GGUF_TYPE_UINT64: {
        n_value = false;
        m_value = std::unique_ptr<gguf_uint64_t>(new gguf_uint64_t(m__io, this, m__root, m__is_le));
        break;
    }
    case gguf_t::GGUF_TYPE_UINT8: {
        n_value = false;
        m_value = std::unique_ptr<gguf_uint8_t>(new gguf_uint8_t(m__io, this, m__root, m__is_le));
        break;
    }
    }
}

void gguf_t::gguf_body_t::gguf_value_t::_read_be() {
    n_value = true;
    switch (type()) {
    case gguf_t::GGUF_TYPE_ARRAY: {
        n_value = false;
        m_value = std::unique_ptr<gguf_array_t>(new gguf_array_t(m__io, this, m__root, m__is_le));
        break;
    }
    case gguf_t::GGUF_TYPE_BOOL: {
        n_value = false;
        m_value = std::unique_ptr<gguf_bool_t>(new gguf_bool_t(m__io, this, m__root, m__is_le));
        break;
    }
    case gguf_t::GGUF_TYPE_FLOAT32: {
        n_value = false;
        m_value = std::unique_ptr<gguf_float32_t>(new gguf_float32_t(m__io, this, m__root, m__is_le));
        break;
    }
    case gguf_t::GGUF_TYPE_FLOAT64: {
        n_value = false;
        m_value = std::unique_ptr<gguf_float64_t>(new gguf_float64_t(m__io, this, m__root, m__is_le));
        break;
    }
    case gguf_t::GGUF_TYPE_INT16: {
        n_value = false;
        m_value = std::unique_ptr<gguf_int16_t>(new gguf_int16_t(m__io, this, m__root, m__is_le));
        break;
    }
    case gguf_t::GGUF_TYPE_INT32: {
        n_value = false;
        m_value = std::unique_ptr<gguf_int32_t>(new gguf_int32_t(m__io, this, m__root, m__is_le));
        break;
    }
    case gguf_t::GGUF_TYPE_INT64: {
        n_value = false;
        m_value = std::unique_ptr<gguf_int64_t>(new gguf_int64_t(m__io, this, m__root, m__is_le));
        break;
    }
    case gguf_t::GGUF_TYPE_INT8: {
        n_value = false;
        m_value = std::unique_ptr<gguf_int8_t>(new gguf_int8_t(m__io, this, m__root, m__is_le));
        break;
    }
    case gguf_t::GGUF_TYPE_STRING: {
        n_value = false;
        m_value = std::unique_ptr<gguf_str_t>(new gguf_str_t(m__io, this, m__root, m__is_le));
        break;
    }
    case gguf_t::GGUF_TYPE_UINT16: {
        n_value = false;
        m_value = std::unique_ptr<gguf_uint16_t>(new gguf_uint16_t(m__io, this, m__root, m__is_le));
        break;
    }
    case gguf_t::GGUF_TYPE_UINT32: {
        n_value = false;
        m_value = std::unique_ptr<gguf_uint32_t>(new gguf_uint32_t(m__io, this, m__root, m__is_le));
        break;
    }
    case gguf_t::GGUF_TYPE_UINT64: {
        n_value = false;
        m_value = std::unique_ptr<gguf_uint64_t>(new gguf_uint64_t(m__io, this, m__root, m__is_le));
        break;
    }
    case gguf_t::GGUF_TYPE_UINT8: {
        n_value = false;
        m_value = std::unique_ptr<gguf_uint8_t>(new gguf_uint8_t(m__io, this, m__root, m__is_le));
        break;
    }
    }
}

gguf_t::gguf_body_t::gguf_value_t::~gguf_value_t() {
    _clean_up();
}

void gguf_t::gguf_body_t::gguf_value_t::_clean_up() {
    if (!n_value) {
    }
}

uint32_t gguf_t::gguf_body_t::alignment() {
    if (f_alignment)
        return m_alignment;
    f_alignment = true;
    m_alignment = ((kv_pairs()->size() != 0) ? (kv_pairs()->back()->alignment()) : (32));
    return m_alignment;
}

uint64_t gguf_t::gguf_body_t::ofs_tensor_data() {
    if (f_ofs_tensor_data)
        return m_ofs_tensor_data;
    f_ofs_tensor_data = true;
    m_ofs_tensor_data = static_cast<uint64_t>(_io()->pos());
    return m_ofs_tensor_data;
}

bool gguf_t::is_big_endian() {
    if (f_is_big_endian)
        return m_is_big_endian;
    f_is_big_endian = true;
    m_is_big_endian = (version_le() & 65535) == 0;
    return m_is_big_endian;
}

uint64_t gguf_t::len_file() {
    if (f_len_file)
        return m_len_file;
    f_len_file = true;
    m_len_file = static_cast<uint64_t>(body()->ofs_tensor_data() + ((body()->num_tensor_infos() != 0) ? (body()->tensor_infos()->back()->expected_next_offset()) : (0)));
    return m_len_file;
}

uint32_t gguf_t::version_le() {
    if (f_version_le)
        return m_version_le;
    f_version_le = true;
    std::streampos _pos = m__io->pos();
    m__io->seek(4);
    m_version_le = m__io->read_u4le();
    m__io->seek(_pos);
    return m_version_le;
}