"""Owned UTF-8 word-mark offsets, version hash and Unicode/UTF16 mapping. No audio generated."""
import hashlib,json
TEXT='سلام 🙂 سلام.'
def validate(text,source_hash,marks,input_type='plain'):
    if input_type!='plain':raise ValueError('plain text only; SSML mappings are a separate contract')
    raw=text.encode('utf-8');actual=hashlib.sha256(raw).hexdigest()
    if actual!=source_hash:raise ValueError('text version hash mismatch')
    rows=[];last_time=-1
    for mark in marks:
        if mark.get('type')!='word':raise ValueError('word marks only')
        a,b,ms=mark['start'],mark['end'],mark['time']
        if any(type(x)is not int for x in [a,b,ms])or not 0<=a<b<=len(raw)or ms<0 or ms<last_time:raise ValueError('bounded byte span and ordered nonnegative integer milliseconds')
        try:prefix=raw[:a].decode('utf-8','strict');span=raw[a:b].decode('utf-8','strict');end=raw[:b].decode('utf-8','strict')
        except UnicodeDecodeError as e:raise ValueError('offset splits UTF-8 sequence')from e
        if span!=mark['value']:raise ValueError('byte span does not equal stated occurrence value')
        rows.append({**mark,'start_codepoint':len(prefix),'end_codepoint_exclusive':len(end),'start_utf16_unit':len(prefix.encode('utf-16-le'))//2,'end_utf16_unit_exclusive':len(end.encode('utf-16-le'))//2,'validated_substring':span});last_time=ms
    return {'text_sha256':actual,'byte_end_contract':'exclusive in this plain-text fixture','validated_marks':rows,'audio_alignment_validated':False}
def demo():
    h=hashlib.sha256(TEXT.encode('utf-8')).hexdigest();marks=[{'time':0,'type':'word','start':0,'end':8,'value':'سلام'},{'time':700,'type':'word','start':14,'end':22,'value':'سلام'}];r=validate(TEXT,h,marks)
    assert [(x['start_codepoint'],x['end_codepoint_exclusive'])for x in r['validated_marks']]==[(0,4),(7,11)]
    assert r['validated_marks'][1]['start_utf16_unit']==8 and r['validated_marks'][1]['end_utf16_unit_exclusive']==12
    assert TEXT[14:22]!='سلام'and TEXT.find('سلام')==0 # Byte offsets and first occurrence lookup cannot locate the second word.
    bad=[('inside_utf8',TEXT,h,[{**marks[1],'start':15}],'plain'),('changed_text_version',' '+TEXT,h,marks,'plain'),('wrong_occurrence_value',TEXT,h,[{**marks[1],'value':'دیگر'}],'plain'),('out_of_bounds',TEXT,h,[{**marks[1],'end':999}],'plain'),('SSML_not_this_contract',TEXT,h,marks,'ssml')];rejected=[]
    for name,text,sha,rows,kind in bad:
        try:validate(text,sha,rows,kind)
        except ValueError:rejected.append(name)
        else:raise AssertionError('invalid mark accepted')
    return {'authored_text':TEXT,'all_marks_and_time_values_manually_authored_not_engine_output':True,'input_marks':marks,'actual_validation':r,'line_delimited_json':''.join(json.dumps(m,ensure_ascii=False)+'\n'for m in marks),'five_invalid_cases_rejected':rejected,'voice_id':'authored-no-synthesis','audio_file_or_service_request_made':False}
if __name__=='__main__':print(json.dumps(demo(),ensure_ascii=False,indent=2))
