123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869moduleCharEncoding=MetadataCharEncodingmoduleMake(E:CharEncoding.T)=structincludeMetadataBasemoduleID3v1=MetadataID3v1moduleID3v2=MetadataID3v2moduleOGG=MetadataOGGmoduleFLAC=MetadataFLACmoduleJPEG=MetadataJPEGmodulePNG=MetadataPNGmoduleAVI=MetadataAVImoduleMP4=MetadataMP4letrecode=E.convertmoduleID3=structletparsef=letfailure,v2=try(false,ID3v2.parse~recodef)with_->(true,[])inletv1=tryReader.resetf;ID3v1.parse~recodefwith_->iffailurethenraiseInvalidelse[]inv2@v1letparse_file=Reader.with_fileparseend(** Return the first application which does not raise invalid. *)letrecfirst_validlfile=matchlwith|f::l->(tryffilewithInvalid->Reader.resetfile;first_validlfile)|[]->raiseInvalidmoduleAudio=structletparsers=[ID3.parse;OGG.parse;FLAC.parse]letparse=first_validparsersletparse_file=Reader.with_fileparseendmoduleImage=structletparsers=[JPEG.parse;PNG.parse]letparse=first_validparsersletparse_file=Reader.with_fileparseendmoduleVideo=structletparsers=[AVI.parse;MP4.parse]letparse=first_validparsersletparse_file=Reader.with_fileparseendmoduleAny=structletparsers=Audio.parsers@Image.parsers@Video.parsersletparse=first_validparsersletparse_file=Reader.with_fileparseendincludeAnyendincludeMake(CharEncoding.Naive)