def parse_sgtin_96(sgtin_96):
    '''Given a SGTIN-96 hex string, parse each segment.
    Returns a dictionary of the segments.'''

    if not sgtin_96:
        raise Exception('Pass in a value.')

    if not sgtin_96.startswith("30"):
        # not a sgtin, not handled
        raise Exception('Not SGTIN-96.')

    binary = "{0:020b}".format(int(sgtin_96, 16)).zfill(96)

    header = int(binary[:8], 2)
    tag_filter = int(binary[8:11], 2)

    partition = binary[11:14]
    partition_value = int(partition, 2)

    m, l, n, k = SGTIN_96_PARTITION_MAP[partition_value]

    company_start = 8 + 3 + 3
    company_end = company_start + m
    company_data = int(binary[company_start:company_end], 2)
    if company_data > pow(10, l):
        # can't be too large
        raise Exception('Company value is too large')
    company_prefix = str(company_data).zfill(l)

    item_start = company_end
    item_end = item_start + n
    item_data = binary[item_start:item_end]
    item_number = int(item_data, 2)
    item_reference = str(item_number).zfill(k)

    serial = int(binary[-38:], 2)

    return {
        "header": header,
        "filter": tag_filter,
        "partition": partition,
        "company_prefix": company_prefix,
        "item_reference": item_reference,
        "serial": serial
    }