// ------------------------------------------------------------------------ // Project atila // Active Thing (activething.com) git.activething.com/go // // File name packer_state.go // Created by DEV // Modified 23/01/2024 // // Copyright 2024 activething.com // ------------------------------------------------------------------------ // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // ------------------------------------------------------------------------ package packs import ( "activething.com/go/gogo/core/bins" "activething.com/go/gogo/core/crypts" "activething.com/go/gogo/core/opts" "activething.com/go/gogo/core/syncs" "sync/atomic" ) type ( State struct { /*Embedded*/*bins.Buffer Temp [64]byte Level int Error error checks map[any]struct{} counts []int Encrypter crypts.Encrypter } ) func NewState(options ...opts.OptionFnc[State]) *State { if atomic.CompareAndSwapUint32(&G.poolsSem,0,1) { G.statePool = syncs.NewPool[State]( syncs.PoolWithNew[State](func() *State { return &State{ Buffer : bins.NewBuffer(), checks : make(map[any]struct{}), counts : []int{0}, Encrypter: crypts.EncrypterNop{}, } }), ) } if len(options) == 0 { return G.statePool.Get() } return opts.Apply(G.statePool.Get(),options ...) } func ReleaseState (state *State) { if state == nil { state.Encrypter = crypts.EncrypterNop{} state.Buffer.Reset() state.Error = nil state.counts= append(state.counts[:0],0) if len(state.checks) > 0 { for k,_ := range state.checks { delete(state.checks,k) } } if atomic.LoadUint32(&G.poolsSem) == 1 { G.statePool.Put(state) } } } func (s *State) SetError(err error) bool { if s.Error != nil { return true } if err == nil { return false } s.Error = err s.Reset() s.Level = 0 return true } func (s *State) CheckCycle (ptr any) (func(),bool) { if _,hs := s.checks[ptr]; hs { s.SetError(G.ErrRedundantPack) return nil,false } s.checks[ptr]=struct{}{} return func(){ delete(s.checks,ptr) },true } func (s *State) Open(opener byte) { s.WriteByte(opener) s.Level++ s.counts = append(s.counts,0) } func (s *State) Close(closer byte) { s.WriteByte(closer) s.Level-- if s.Level < 0 { s.SetError(G.ErrInvalidNode) } s.counts = s.counts[:len(s.counts)-1] } func (s *State) Count() int { if s.Error != nil { return 0 } return s.counts[s.Level] } func (s *State) Inc () { if s.Error == nil { s.counts[s.Level] += 1 } }