package state import ( "encoding/gob" "os" "ripple/config" "ripple/helpers" "ripple/types" ) type State struct { Storage Storage Memory Memory } func newState() *State { return &State{ Memory: Memory{ Commit: make(map[types.UserIdentifier]map[[32]byte]struct{}), Pathfinding: make(map[[32]byte]Pathfinding), }, } } func (s *State) Save() error { filePath, err := helpers.GetFilePath(config.StorageFile) if err != nil { return err } f, err := os.Create(filePath) if err != nil { return err } defer f.Close() enc := gob.NewEncoder(f) return enc.Encode(s.Storage) } func Load() (*State, error) { filePath, err := helpers.GetFilePath(config.StorageFile) if err != nil { return nil, err } f, err := os.Open(filePath) if err != nil { return nil, err } defer f.Close() dec := gob.NewDecoder(f) st := newState() if err := dec.Decode(&st.Storage); err != nil { return nil, err } return st, nil } func (s *State) Clone() State { newStorage := Storage{ User: s.Storage.User, Accounts: make(map[types.UserIdentifier]Account, len(s.Storage.Accounts)), Payments: make(map[[32]byte]Payment, len(s.Storage.Payments)), Receipts: s.Storage.Receipts, } for accID, acc := range s.Storage.Accounts { newAcc := acc newAcc.Pending = make(map[[32]byte]struct{}, len(acc.Pending)) for pid := range acc.Pending { newAcc.Pending[pid] = struct{}{} } newStorage.Accounts[accID] = newAcc } for payID, pay := range s.Storage.Payments { newStorage.Payments[payID] = pay } newMemory := Memory{ Commit: make(map[types.UserIdentifier]map[[32]byte]struct{}, len(s.Memory.Commit)), Pathfinding: make(map[[32]byte]Pathfinding, len(s.Memory.Pathfinding)), Payment: s.Memory.Payment, } for acctID, paymentMap := range s.Memory.Commit { newPaymentMap := make(map[[32]byte]struct{}, len(paymentMap)) for pid := range paymentMap { newPaymentMap[pid] = struct{}{} } newMemory.Commit[acctID] = newPaymentMap } for pfID, pf := range s.Memory.Pathfinding { newMemory.Pathfinding[pfID] = pf } return State{ Storage: newStorage, Memory: newMemory, } } func (s *State) Apply(newState State) { *s = newState } func (s *State) AddAccount(id types.UserIdentifier, turnBit byte) error { if err := s.Storage.AddAccount(id, turnBit); err != nil { return err } s.Memory.AddAccount(id) return s.Save() } func (s *State) RemoveAccount(id types.UserIdentifier) error { s.Memory.RemoveAccount(id) s.Storage.RemoveAccount(id) return s.Save() }