123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105moduleOrdered=Map.Make(Number)typefield=Rfc5322.fieldtypet=(Field.field*Location.t)Ordered.tletreduce:(Number.t*([>field]as'a)*Location.t)list->t->(t*(Number.t*'a*Location.t)list)=funfieldsheader->List.fold_left(fun(header,rest)(n,field,loc)->matchfieldwith|#fieldasfield->Ordered.addn(Field.of_rfc5322_fieldfield,loc)header,rest|field->header,(n,field,loc)::rest)(header,[])fields|>fun(header,rest)->(header,List.revrest)typevalue=Value:'aField.v*'a->valueletfield_to_value:Field.field->value=fun(Field(field_name,v))->Value(Field.field_valuefield_name,v)letgetfield_nameheader=letfi(field,loc)a=ifField_name.equalfield_name(Field.field_namefield)then(i,field_to_valuefield,loc)::aelseainOrdered.fold(funi(field,loc)a->matchfieldwith(* TODO: folded fields. *)|Field.Field(Field.Content,_)->a|Field.Field(Field.Resent,_)->a|Field.Field(Field.Trace,_)->a|field->fi(field,loc)a)header[]letcardinalt=letfolder:Number.t->(Field.field*Location.t)->(Number.t,[`Msgofstring])result->(Number.t,[`Msgofstring])result=fun_(field,_)a->letopenRresult.Rinmatchfieldwith|Field.Field(Content,v)->binda(Number.add_int(Content.lengthv))|Field.Field(Resent,v)->binda(Number.add_int(Resent.lengthv))|Field.Field(Trace,v)->binda(Number.add_int(Trace.lengthv))|_->mapNumber.succainletres=Ordered.foldfoldert(OkNumber.zero)inmatchreswith|Oklength->length|Error(`Msgerr)->invalid_argerr(* XXX(dinosaure): should never occur. *)letaddfieldt=Ordered.add(cardinalt)(field,Location.none)tletadd_or_replace(Field.Field(field_name,v)asfield)t=letexceptionExistsofNumber.tintryOrdered.iter(funnField.(Field(field_name',v'),_)->matchField.equalfield_namefield_name'with|SomeRefl.Refl->raise_notrace(Existsn)|None->())t;addfieldtwithExistsn->Ordered.addn(field,Location.none)tlet(&)=addletpp:tFmt.t=funppft->Fmt.Dump.iter_bindingsOrdered.iterFmt.(always"header")Fmt.nopFmt.(funppf(Field.Field(k,v))->matchkwith|Resent->Resent.ppppfv|Trace->Trace.ppppfv|Content->Content.ppppfv|k->Dump.pair(usingField.to_field_nameField_name.pp)(Field.pp_of_field_namek)ppf(k,v))ppf(Ordered.mapfstt)letpp_valueppf=fun(Value(k,v))->Field.pp_of_field_valuekppfvletempty=Ordered.emptyletcontentheader=letcontent:Content.toptionref=refNoneinOrdered.iter(fun_->function|Field.Field(Field.Content,v),_->content:=Somev|_->())header;match!contentwith|Somecontent->content|None->Content.defaultmoduleEncoder=structincludeEncoderletepsilon=(funt()->t),()letfieldppf(_,(x,_))=Field.Encoder.fieldppfxletheaderppfx=(list~sep:epsilonfield)ppf(Ordered.bindingsx)endletto_stringx=Encoder.to_stringEncoder.headerxletto_streamx=Encoder.to_streamEncoder.headerx