1 import Base 2 import ./restore_data.bend as R 3 import ./snapshot_data.bend as Snapshot 4 import ./decode_data.bend as D 5 import ./entity_key.bend as Key 6 import ./decode_construction.bend as Constructor 7 8 type Walk is Type: 9 Working{state:State} 10 Stopped{state:State,error:R.Error} 11 def unknown(~Custom:Data,position:R.Position,name:String) -> R.Error: 12 match position: 13 case R.Component{key}:R.UnknownComponent{key,name} 14 case R.Resource{}:R.UnknownResource{name} 15 def invalid(~Custom:Data,position:R.Position,name:String,error:Constructor.Error) -> R.Error: 16 match position: 17 case R.Component{key}:R.InvalidComponent{key,name,error} 18 case R.Resource{}:R.InvalidResource{name,error} 19 def dispatched(~State:Type,~Custom:Data,+position:R.Position,+name:String,next:State -> Walk,observed:State & R.Dispatch) -> Walk: 20 match observed: 21 case (state,R.Unhandled{}):Stopped{state,unknown(~Custom,position,name)} 22 case (state,R.Rejected{error}):Stopped{state,invalid(~Custom,position,name,error)} 23 case (state,R.Staged{}):next(state) 24 def fields(~State:Type,~Custom:Data,~stage:State -> R.Position -> D.Field -> State & R.Dispatch,+position:R.Position,values:List<&2,D.Field>,state:State) -> Walk: 25 match values: 26 case []:Working{state} 27 case D.Field{+name,value} <> rest:dispatched(~State,~Custom,position,name,next => fields(~State,~Custom,~stage,position,rest,next),stage(state,position,D.Field{name,value})) 28 def seen(+key:Key.Key,keys:List<&2,Key.Key>) -> Bool: 29 match keys: 30 case []:False{} 31 case other <> rest:Bool.or(Key.equal(key,other),seen(key,rest)) 32 def continued(~State:Type,~Custom:Data,next:State -> Walk,result:Walk) -> Walk: 33 match result: 34 case Working{state}:next(state) 35 case Stopped{state,error}:Stopped{state,error} 36 def entity_checked(~State:Type,~Custom:Data,duplicate:Bool,+key:Key.Key,fields:List<&2,D.Field>,state:State,next:State -> Walk,stage:State -> List<&2,D.Field> -> Walk) -> Walk: 37 match duplicate: 38 case True{}:Stopped{state,R.DuplicateEntity{key}} 39 case False{}:continued(~State,~Custom,next,stage(state,fields)) 40 def entities(~State:Type,~Custom:Data,~stage:State -> R.Position -> D.Field -> State & R.Dispatch,values:List<&2,Snapshot.Entity>,+previous:List<&2,Key.Key>,state:State) -> Walk: 41 match values: 42 case []:Working{state} 43 case Snapshot.Entity{+key,components} <> rest:entity_checked(~State,~Custom,seen(key,previous),key,components,state,next => entities(~State,~Custom,~stage,rest,key <> previous,next),(next => values => fields(~State,~Custom,~stage,R.Component{key},values,next))) 44 def finished(~State:Type,~Custom:Data,~release:State -> State,+input:Snapshot.Snapshot,result:Walk) -> R.Prepared: 45 match result: 46 case Working{state}:R.Ready{state,input} 47 case Stopped{state,error}:R.Refused{release(state),input,error} 48 def header(~State:Type,~Custom:Data,~stage:State -> R.Position -> D.Field -> State & R.Dispatch,~release:State -> State,version:Bool,progress:Bool,state:State,+input:Snapshot.Snapshot) -> R.Prepared: 49 match version progress input: 50 case False{} _ Snapshot.Snapshot{value,next,entities,resources}:R.Refused{state,Snapshot.Snapshot{value,next,entities,resources},R.UnsupportedVersion{D.Number{value}}} 51 case True{} False{} Snapshot.Snapshot{version,next,entities,resources}:R.Refused{state,Snapshot.Snapshot{version,next,entities,resources},R.InvalidSnapshot{"$.nextEntity"}} 52 case True{} True{} Snapshot.Snapshot{version,next,+values,+resources}:finished(~State,~Custom,~release,Snapshot.Snapshot{version,next,values,resources},continued(~State,~Custom,state => fields(~State,~Custom,~stage,R.Resource{},resources,state),entities(~State,~Custom,~stage,values,[],state))) 53 def prepare(~State:Type,~Custom:Data,~stage:State -> R.Position -> D.Field -> State & R.Dispatch,~release:State -> State,state:State,+input:Snapshot.Snapshot) -> R.Prepared: 54 match input: 55 case Snapshot.Snapshot{+version,+next,+entities,+resources}:header(~State,~Custom,~stage,~release,U32.is_eq(version,1),Bool.and(U32.is_lt(0,next),U32.is_le(next,131073)),state,Snapshot.Snapshot{version,next,entities,resources})