123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118(*
* Copyright (c) 2014 Leo White <leo@lpw25.net>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*)openOdoc_utilsopenResultMonadopenOdoc_modeltypeunit_content=Lang.Compilation_unit.ttypecontent=|Page_contentofLang.Page.t|Impl_contentofLang.Implementation.t|Unit_contentofunit_content|Asset_contentofLang.Asset.ttypet={content:content;warnings:Odoc_model.Error.tlist}(** Written at the top of the files. Checked when loading. *)letmagic="odoc-3.2.1"(** Exceptions while saving are allowed to leak. *)letsave_filef=Fs.Directory.mkdir_p(Fs.File.dirnamefile);Io_utils.with_open_out_bin(Fs.File.to_stringfile)(funoc->output_stringocmagic;foc)letsave_unitfile(root:Root.t)(t:t)=save_file(funoc->Marshal.to_channelocroot[];Marshal.to_channeloct[])letsave_pagefile~warningspage=letdir=Fs.File.dirnamefileinletbase=Fs.File.(to_string@@basenamefile)inletfile=ifAstring.String.is_prefix~affix:"page-"basethenfileelseFs.File.create~directory:dir~name:("page-"^base)insave_unitfilepage.Lang.Page.root{content=Page_contentpage;warnings}letsave_implfile~warningsimpl=letdir=Fs.File.dirnamefileinletbase=Fs.File.(to_string@@basenamefile)inletfile=ifAstring.String.is_prefix~affix:"impl-"basethenfileelseFs.File.create~directory:dir~name:("impl-"^base)insave_unitfileimpl.Lang.Implementation.root{content=Impl_contentimpl;warnings}letsave_assetfile~warningsasset=letdir=Fs.File.dirnamefileinletbase=Fs.File.(to_string@@basenamefile)inletfile=ifAstring.String.is_prefix~affix:"asset-"basethenfileelseFs.File.create~directory:dir~name:("asset-"^base)inlett={content=Asset_contentasset;warnings}insave_unitfileasset.roottletsave_unitfile~warningsm=save_unitfilem.Lang.Compilation_unit.root{content=Unit_contentm;warnings}letload_filef=letfile=Fs.File.to_stringfilein(ifSys.file_existsfilethenOkfileelseError(`Msg(Printf.sprintf"File does not exist")))>>=funfile->Io_utils.with_open_in_binfile@@funic->tryletactual_magic=really_input_stringic(String.lengthmagic)inifactual_magic=magicthenficelseletmsg=Printf.sprintf"%s: invalid magic number %S, expected %S\n%!"fileactual_magicmagicinError(`Msgmsg)withexn->letmsg=Printf.sprintf"Error while unmarshalling %S: %s\n%!"file(matchexnwithFailures->s|_->Printexc.to_stringexn)inError(`Msgmsg)letloadfile=load_file(funic->let_root=Marshal.from_channelicinOk(Marshal.from_channelic))(** The root is saved separately in the files to support this function. *)letload_rootfile=load_file(funic->letroot=Marshal.from_channelicinOkroot)letsave_indexdstidx=save_dst(funoc->Marshal.to_channelocidx[])letload_indexfile=load_file(funic->Ok(Marshal.from_channelic))letsave_sidebardstidx=save_dst(funoc->Marshal.to_channelocidx[])letload_sidebarfile=load_file(funic->Ok(Marshal.from_channelic))