## Coverage Report

#### Created: 2026-01-25 15:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)

    /home/noah/src/realizar/src/gguf/types.rs

    Line
    Count
    Source
    1
    //! GGUF type definitions and constants
    2
    //!
    3
    //! Core types used throughout the GGUF parser and model loading.
    4
    //!
    5
    //! This module defines the foundational types for GGUF file parsing:
    6
    //! - Magic numbers and version constants
    7
    //! - Quantization type constants (Q4_0, Q4_K, Q6_K, etc.)
    8
    //! - Buffer types with small buffer optimization
    9
    //! - Core structs: GGUFValue, GGUFHeader, TensorInfo, GGUFModel
    10
    11
    use std::collections::HashMap;
    12
    13
    // ============================================================================
    14
    // GGUF Magic and Version Constants
    15
    // ============================================================================
    16
    17
    /// GGUF magic number: "GGUF" in little-endian
    18
    pub const GGUF_MAGIC: u32 = 0x4655_4747;
    19
    20
    /// Supported GGUF versions
    21
    pub const GGUF_VERSION_V3: u32 = 3;
    22
    23
    // ============================================================================
    24
    // Quantization Type Constants
    25
    // ============================================================================
    26
    27
    /// GGUF quantization type: F32 (unquantized float32)
    28
    pub const GGUF_TYPE_F32: u32 = 0;
    29
    30
    /// GGUF quantization type: F16 (half precision float16)
    31
    pub const GGUF_TYPE_F16: u32 = 1;
    32
    33
    /// GGUF quantization type: `Q4_0` (4-bit quantization, block size 32)
    34
    pub const GGUF_TYPE_Q4_0: u32 = 2;
    35
    36
    /// GGUF quantization type: `Q4_1` (4-bit quantization with min, block size 32)
    37
    pub const GGUF_TYPE_Q4_1: u32 = 3;
    38
    39
    /// GGUF quantization type: `Q5_0` (5-bit quantization, block size 32)
    40
    pub const GGUF_TYPE_Q5_0: u32 = 6;
    41
    42
    /// GGUF quantization type: `Q5_1` (5-bit quantization with min, block size 32)
    43
    pub const GGUF_TYPE_Q5_1: u32 = 7;
    44
    45
    /// GGUF quantization type: `Q8_0` (8-bit quantization, block size 32)
    46
    pub const GGUF_TYPE_Q8_0: u32 = 8;
    47
    48
    /// GGUF quantization type: `Q2_K` (2-bit K-quantization, super-block size 256)
    49
    pub const GGUF_TYPE_Q2_K: u32 = 10;
    50
    51
    /// GGUF quantization type: `Q3_K` (3-bit K-quantization, super-block size 256)
    52
    pub const GGUF_TYPE_Q3_K: u32 = 11;
    53
    54
    /// GGUF quantization type: `Q4_K` (4-bit K-quantization, super-block size 256)
    55
    pub const GGUF_TYPE_Q4_K: u32 = 12;
    56
    57
    /// GGUF quantization type: `Q5_K` (5-bit K-quantization, super-block size 256)
    58
    pub const GGUF_TYPE_Q5_K: u32 = 13;
    59
    60
    /// GGUF quantization type: `Q6_K` (6-bit K-quantization, super-block size 256)
    61
    pub const GGUF_TYPE_Q6_K: u32 = 14;
    62
    63
    // ============================================================================
    64
    // IMP-117: Small Buffer Optimization Constants (per spec Section 4.1-4.2)
    65
    // ============================================================================
    66
    67
    /// Small buffer inline capacity for token IDs (IMP-117)
    68
    /// Most prompts are < 32 tokens, avoiding heap allocation
    69
    pub const TOKEN_BUFFER_INLINE_CAP: usize = 32;
    70
    71
    /// Small buffer inline capacity for attention scores (IMP-117)
    72
    /// Stack-allocated for short sequences (per-head, small context)
    73
    pub const ATTENTION_BUFFER_INLINE_CAP: usize = 64;
    74
    75
    /// Small buffer inline capacity for hidden states (IMP-117)
    76
    /// Inline storage for small models (hidden_dim <= 128)
    77
    pub const HIDDEN_BUFFER_INLINE_CAP: usize = 128;
    78
    79
    /// Buffer watermark: Low mark for inline/stack allocation
    80
    pub const BUFFER_LW_SIZE: usize = 1024;
    81
    82
    /// Buffer watermark: High mark for pooled allocations
    83
    pub const BUFFER_HW_SIZE: usize = 8 * 1024;
    84
    85
    /// Buffer watermark: Maximum before chunking
    86
    pub const BUFFER_MAX_SIZE: usize = 32 * 1024;
    87
    88
    // ============================================================================
    89
    // Buffer Type Aliases with Small Buffer Optimization
    90
    // ============================================================================
    91
    92
    /// Token buffer with inline storage (IMP-117)
    93
    /// Uses SmallVec for stack allocation when size <= TOKEN_BUFFER_INLINE_CAP
    94
    pub type TokenBuffer = smallvec::SmallVec<[u32; TOKEN_BUFFER_INLINE_CAP]>;
    95
    96
    /// Attention score buffer with inline storage (IMP-117)
    97
    /// Uses SmallVec for stack allocation when size <= ATTENTION_BUFFER_INLINE_CAP
    98
    pub type AttentionBuffer = smallvec::SmallVec<[f32; ATTENTION_BUFFER_INLINE_CAP]>;
    99
    100
    /// Hidden state buffer with inline storage (IMP-117)
    101
    /// Uses SmallVec for stack allocation when size <= HIDDEN_BUFFER_INLINE_CAP
    102
    pub type HiddenBuffer = smallvec::SmallVec<[f32; HIDDEN_BUFFER_INLINE_CAP]>;
    103
    104
    // ============================================================================
    105
    // Core GGUF Types
    106
    // ============================================================================
    107
    108
    /// GGUF alignment requirement (32 bytes)
    109
    pub const GGUF_ALIGNMENT: usize = 32;
    110
    111
    /// GGUF metadata value types
    112
    #[derive(Debug, Clone, PartialEq)]
    113
    pub enum GGUFValue {
    114
        /// Unsigned 8-bit integer
    115
        UInt8(u8),
    116
        /// Signed 8-bit integer
    117
        Int8(i8),
    118
        /// Unsigned 16-bit integer
    119
        UInt16(u16),
    120
        /// Signed 16-bit integer
    121
        Int16(i16),
    122
        /// Unsigned 32-bit integer
    123
        UInt32(u32),
    124
        /// Signed 32-bit integer
    125
        Int32(i32),
    126
        /// 32-bit floating point
    127
        Float32(f32),
    128
        /// Boolean
    129
        Bool(bool),
    130
        /// UTF-8 string
    131
        String(String),
    132
        /// Array of values
    133
        Array(Vec<GGUFValue>),
    134
        /// Unsigned 64-bit integer
    135
        UInt64(u64),
    136
        /// Signed 64-bit integer
    137
        Int64(i64),
    138
        /// 64-bit floating point
    139
        Float64(f64),
    140
    }
    141
    142
    /// GGUF file header
    143
    #[derive(Debug, Clone, PartialEq)]
    144
    pub struct GGUFHeader {
    145
        /// Magic number (must be `GGUF_MAGIC`)
    146
        pub magic: u32,
    147
        /// Format version
    148
        pub version: u32,
    149
        /// Number of tensors in the file
    150
        pub tensor_count: u64,
    151
        /// Number of metadata key-value pairs
    152
        pub metadata_count: u64,
    153
    }
    154
    155
    /// Tensor information
    156
    #[derive(Debug, Clone, PartialEq)]
    157
    pub struct TensorInfo {
    158
        /// Tensor name
    159
        pub name: String,
    160
        /// Number of dimensions
    161
        pub n_dims: u32,
    162
        /// Dimensions (shape)
    163
        pub dims: Vec<u64>,
    164
        /// Quantization type
    165
        pub qtype: u32,
    166
        /// Offset in the file where tensor data starts
    167
        pub offset: u64,
    168
    }
    169
    170
    /// GGUF model container
    171
    #[derive(Debug, Clone)]
    172
    pub struct GGUFModel {
    173
        /// File header
    174
        pub header: GGUFHeader,
    175
        /// Metadata key-value pairs
    176
        pub metadata: HashMap<String, GGUFValue>,
    177
        /// Tensor information
    178
        pub tensors: Vec<TensorInfo>,
    179
        /// Offset where tensor data starts (after header/metadata/tensor_info + alignment)
    180
        pub tensor_data_start: usize,
    181
    }
    182
    183
    #[cfg(test)]
    184
    mod tests {
    185
        use super::*;
    186
    187
        #[test]
    188
    1
        fn test_magic_constant() {
    189
    1
            assert_eq!(GGUF_MAGIC, 0x4655_4747);
    190
    1
        }
    191
    192
        #[test]
    193
    1
        fn test_quantization_constants() {
    194
    1
            assert_eq!(GGUF_TYPE_F32, 0);
    195
    1
            assert_eq!(GGUF_TYPE_F16, 1);
    196
    1
            assert_eq!(GGUF_TYPE_Q4_0, 2);
    197
    1
            assert_eq!(GGUF_TYPE_Q8_0, 8);
    198
    1
            assert_eq!(GGUF_TYPE_Q4_K, 12);
    199
    1
            assert_eq!(GGUF_TYPE_Q6_K, 14);
    200
    1
        }
    201
    202
        #[test]
    203
    1
        fn test_buffer_constants() {
    204
    1
            assert_eq!(TOKEN_BUFFER_INLINE_CAP, 32);
    205
    1
            assert_eq!(ATTENTION_BUFFER_INLINE_CAP, 64);
    206
    1
            assert_eq!(HIDDEN_BUFFER_INLINE_CAP, 128);
    207
    1
        }
    208
    209
        #[test]
    210
    1
        fn test_buffer_watermarks() {
    211
    1
            assert_eq!(BUFFER_LW_SIZE, 1024);
    212
    1
            assert_eq!(BUFFER_HW_SIZE, 8 * 1024);
    213
    1
            assert_eq!(BUFFER_MAX_SIZE, 32 * 1024);
    214
    1
        }
    215
    216
        #[test]
    217
    1
        fn test_version_constant() {
    218
    1
            assert_eq!(GGUF_VERSION_V3, 3);
    219
    1
        }
    220
    221
        #[test]
    222
    1
        fn test_gguf_value_variants() {
    223
    1
            let uint8 = GGUFValue::UInt8(255);
    224
    1
            let string = GGUFValue::String("test".to_string());
    225
    1
            let array = GGUFValue::Array(vec![GGUFValue::UInt32(1), GGUFValue::UInt32(2)]);
    226
    227
    1
            assert_eq!(uint8, GGUFValue::UInt8(255));
    228
    1
            assert_eq!(string, GGUFValue::String("test".to_string()));
    229
    1
            assert!(matches!0(array, GGUFValue::Array(_)));
    230
    1
        }
    231
    232
        #[test]
    233
    1
        fn test_gguf_header() {
    234
    1
            let header = GGUFHeader {
    235
    1
                magic: GGUF_MAGIC,
    236
    1
                version: GGUF_VERSION_V3,
    237
    1
                tensor_count: 100,
    238
    1
                metadata_count: 50,
    239
    1
            };
    240
    241
    1
            assert_eq!(header.magic, 0x4655_4747);
    242
    1
            assert_eq!(header.version, 3);
    243
    1
            assert_eq!(header.tensor_count, 100);
    244
    1
            assert_eq!(header.metadata_count, 50);
    245
    1
        }
    246
    247
        #[test]
    248
    1
        fn test_tensor_info() {
    249
    1
            let info = TensorInfo {
    250
    1
                name: "model.layers.0.attn.wq".to_string(),
    251
    1
                n_dims: 2,
    252
    1
                dims: vec![4096, 4096],
    253
    1
                qtype: GGUF_TYPE_Q4_K,
    254
    1
                offset: 1024,
    255
    1
            };
    256
    257
    1
            assert_eq!(info.name, "model.layers.0.attn.wq");
    258
    1
            assert_eq!(info.n_dims, 2);
    259
    1
            assert_eq!(info.dims, vec![4096, 4096]);
    260
    1
            assert_eq!(info.qtype, GGUF_TYPE_Q4_K);
    261
    1
            assert_eq!(info.offset, 1024);
    262
    1
        }
    263
    264
        #[test]
    265
    1
        fn test_gguf_model() {
    266
    1
            let model = GGUFModel {
    267
    1
                header: GGUFHeader {
    268
    1
                    magic: GGUF_MAGIC,
    269
    1
                    version: GGUF_VERSION_V3,
    270
    1
                    tensor_count: 1,
    271
    1
                    metadata_count: 0,
    272
    1
                },
    273
    1
                metadata: HashMap::new(),
    274
    1
                tensors: vec![],
    275
    1
                tensor_data_start: 128,
    276
    1
            };
    277
    278
    1
            assert_eq!(model.header.magic, GGUF_MAGIC);
    279
    1
            assert!(model.tensors.is_empty());
    280
    1
            assert_eq!(model.tensor_data_start, 128);
    281
    1
        }
    282
    283
        #[test]
    284
    1
        fn test_alignment_constant() {
    285
    1
            assert_eq!(GGUF_ALIGNMENT, 32);
    286
            // Verify it's a power of 2
    287
    1
            assert_eq!(GGUF_ALIGNMENT & (GGUF_ALIGNMENT - 1), 0);
    288
    1
        }
    289
    }