// File: cristian-bicheru[P]arith/./huffman.h
// Function: void huffman::CompressBuffer<unsigned char, unsigned long>(std::vector<unsigned char, std::allocator<unsigned char>>&, buffer::CodecByteStream&)
void CompressBuffer(std::vector<SymbolType>& UncompressedBuffer, buffer::CodecByteStream& CompressedBuffer) {
        std::map<SymbolType, ValueType> SortedFrequencyTable;
        PopulateFrequencyTable(SortedFrequencyTable, UncompressedBuffer);
        HuffmanTree<SymbolType, ValueType> HuffTree(SortedFrequencyTable);
        HuffTree.ConstructSymbolTable();
        auto SymTable = HuffTree.GetSymbolTable();
        uint64_t index = sizeof(uint16_t)+sizeof(uint64_t);
        for (auto keyval : SortedFrequencyTable) {
            buffer::EncodeTypeToBuffer<SymbolType>(CompressedBuffer.GetBuffer(), index, &keyval.first);
            index += sizeof(SymbolType);
            buffer::EncodeTypeToBuffer<ValueType>(CompressedBuffer.GetBuffer(), index, &keyval.second);
            index += sizeof(ValueType);
        }
        auto ushrt = uint16_t(index);
        buffer::EncodeTypeToBuffer<uint16_t>(CompressedBuffer.GetBuffer(), 0, &ushrt);
        auto ull = uint64_t(UncompressedBuffer.size());
        buffer::EncodeTypeToBuffer<uint64_t>(CompressedBuffer.GetBuffer(), sizeof(uint16_t), &ull);

        std::vector<bool> code;
        for (SymbolType symbol : UncompressedBuffer) {
            code = SymTable[symbol];
            for (bool bit : code) {
                CompressedBuffer.WriteBit(bit);
            }
        }
    }

// Assembly:
subq $0x1e8, %rsp            # imm = 0x1E8
movq %rdi, 0x1e0(%rsp)
movq %rsi, 0x1d8(%rsp)
leaq 0x1a8(%rsp), %rdi
movq %rdi, 0x20(%rsp)
callq 0xa0a0
movq 0x20(%rsp), %rdi
movq 0x1e0(%rsp), %rsi
callq 0xa0b0
jmp 0x588d
leaq 0x148(%rsp), %rdi
leaq 0x1a8(%rsp), %rsi
callq 0xa140
jmp 0x58a4
leaq 0x148(%rsp), %rdi
callq 0xa4b0
jmp 0x58b3
leaq 0x118(%rsp), %rdi
leaq 0x148(%rsp), %rsi
callq 0xa5e0
jmp 0x58ca
movq $0xa, 0x110(%rsp)
leaq 0x1a8(%rsp), %rax
movq %rax, 0x108(%rsp)
movq 0x108(%rsp), %rdi
callq 0xa610
movq %rax, 0x100(%rsp)
movq 0x108(%rsp), %rdi
callq 0xa640
movq %rax, 0xf8(%rsp)
leaq 0x100(%rsp), %rdi
leaq 0xf8(%rsp), %rsi
callq 0xa670
testb $0x1, %al
jne 0x592e
jmp 0x5a1b
leaq 0x100(%rsp), %rdi
callq 0xa690
movups (%rax), %xmm0
movaps %xmm0, 0xe0(%rsp)
movq 0x1d8(%rsp), %rdi
callq 0x55f0
movq %rax, %rdi
movq 0x110(%rsp), %rsi
leaq 0xe0(%rsp), %rdx
callq 0xa6b0
jmp 0x596d
movq 0x110(%rsp), %rax
addq $0x1, %rax
movq %rax, 0x110(%rsp)
movq 0x1d8(%rsp), %rdi
callq 0x55f0
movq %rax, %rdi
movq 0x110(%rsp), %rsi
leaq 0xe0(%rsp), %rdx
addq $0x8, %rdx
callq 0x5580
movq 0x110(%rsp), %rax
addq $0x8, %rax
movq %rax, 0x110(%rsp)
leaq 0x100(%rsp), %rdi
callq 0xa720
jmp 0x5910
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1a0(%rsp)
movl %eax, 0x19c(%rsp)
jmp 0x5c9c
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1a0(%rsp)
movl %eax, 0x19c(%rsp)
jmp 0x5c8f
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1a0(%rsp)
movl %eax, 0x19c(%rsp)
jmp 0x5c82
movw 0x110(%rsp), %ax
movw %ax, 0xde(%rsp)
movq 0x1d8(%rsp), %rdi
callq 0x55f0
movq %rax, %rdi
xorl %eax, %eax
movl %eax, %esi
leaq 0xde(%rsp), %rdx
callq 0xa750
jmp 0x5a4e
movq 0x1e0(%rsp), %rdi
callq 0x4b20
movq %rax, 0xd0(%rsp)
movq 0x1d8(%rsp), %rdi
callq 0x55f0
movq %rax, %rdi
movl $0x2, %esi
leaq 0xd0(%rsp), %rdx
callq 0x5580
leaq 0xa8(%rsp), %rdi
callq 0xa7c0
movq 0x1e0(%rsp), %rax
movq %rax, 0xa0(%rsp)
movq 0xa0(%rsp), %rdi
callq 0x65b0
movq %rax, 0x98(%rsp)
movq 0xa0(%rsp), %rdi
callq 0x65e0
movq %rax, 0x90(%rsp)
leaq 0x98(%rsp), %rdi
leaq 0x90(%rsp), %rsi
callq 0xa7d0
testb $0x1, %al
jne 0x5aea
jmp 0x5c46
leaq 0x98(%rsp), %rdi
callq 0xa810
movb (%rax), %al
movb %al, 0x8f(%rsp)
leaq 0x118(%rsp), %rdi
leaq 0x8f(%rsp), %rsi
callq 0xa820
movq %rax, 0x18(%rsp)
jmp 0x5b1c
movq 0x18(%rsp), %rsi
leaq 0xa8(%rsp), %rdi
callq 0xa910
jmp 0x5b30
leaq 0xa8(%rsp), %rax
movq %rax, 0x80(%rsp)
movq 0x80(%rsp), %rdi
callq 0xaaa0
movl %edx, 0x68(%rsp)
movq %rax, 0x60(%rsp)
movl 0x68(%rsp), %eax
movl %eax, 0x78(%rsp)
movq 0x60(%rsp), %rax
movq %rax, 0x70(%rsp)
movq 0x80(%rsp), %rdi
callq 0xaae0
movl %edx, 0x48(%rsp)
movq %rax, 0x40(%rsp)
movq 0x40(%rsp), %rax
movq %rax, 0x50(%rsp)
movl 0x48(%rsp), %eax
movl %eax, 0x58(%rsp)
leaq 0x70(%rsp), %rdi
leaq 0x50(%rsp), %rsi
callq 0xab00
movb %al, 0x17(%rsp)
jmp 0x5ba5
movb 0x17(%rsp), %al
testb $0x1, %al
jne 0x5bb2
jmp 0x5c32
leaq 0x70(%rsp), %rdi
callq 0xab30
movq %rdx, (%rsp)
movq %rax, 0x8(%rsp)
jmp 0x5bc7
movq (%rsp), %rax
movq 0x8(%rsp), %rcx
movq %rcx, 0x28(%rsp)
movq %rax, 0x30(%rsp)
leaq 0x28(%rsp), %rdi
callq 0xab70
movb %al, 0x3f(%rsp)
movq 0x1d8(%rsp), %rdi
movzbl 0x3f(%rsp), %esi
andl $0x1, %esi
callq 0x50d0
jmp 0x5bff
jmp 0x5c01
leaq 0x70(%rsp), %rdi
callq 0xaba0
jmp 0x5c0d
jmp 0x5b90
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1a0(%rsp)
movl %eax, 0x19c(%rsp)
leaq 0xa8(%rsp), %rdi
callq 0xabf0
jmp 0x5c82
jmp 0x5c34
leaq 0x98(%rsp), %rdi
callq 0xabd0
jmp 0x5acc
leaq 0xa8(%rsp), %rdi
callq 0xabf0
leaq 0x118(%rsp), %rdi
callq 0xac00
leaq 0x148(%rsp), %rdi
callq 0xac10
leaq 0x1a8(%rsp), %rdi
callq 0xacc0
addq $0x1e8, %rsp            # imm = 0x1E8
retq
leaq 0x118(%rsp), %rdi
callq 0xac00
leaq 0x148(%rsp), %rdi
callq 0xac10
leaq 0x1a8(%rsp), %rdi
callq 0xacc0
movq 0x1a0(%rsp), %rdi
callq 0x2310
nopw %cs:(%rax,%rax)