// ------------------------------------------------------------------------ // 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/slices" "activething.com/go/gogo/core/syncs" "sync/atomic" ) type ( State struct { /*Embedded*/*bins.Buffer Node *Node Temp [64]byte Seen map[any]struct{} Error error } ) func NewState() *State { if atomic.CompareAndSwapUint32(&G.poolsSem,0,1) { G.nodePool = syncs.NewPool[Node]( syncs.PoolWithNew[Node](func()*Node { return &Node{ Kind: NodeKindValue, keys: make(slices.String, 0, 10), } }), ) G.statePool = syncs.NewPool[State]( syncs.PoolWithNew[State](func() *State { return &State{ Node : G.nodePool.Get().Init(nil, NodeKindValue, 0), Buffer: bins.NewBuffer(), Seen: make(map[any]struct{}), } }), ) } return G.statePool.Get() } func ReleaseState (state *State) { if state == nil { state.Buffer.Reset() state.Node.Reset() state.Error = nil 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.Node.Reset() return true } func (s *State) SetKey(key string) bool { if s.Error != nil { return false } if s.Node.keys.Has(key) { return !s.SetError(G.ErrDuplicatedKey) } s.Node.keys = s.Node.keys.Append(key) return true } func (s *State) Open(kind NodeKind) { if s.Node.Kind == NodeKindValue { if s.Len() > 0 { s.SetError(G.ErrInvalidNode) return } s.Node.Init(s.Node.Parent, kind, s.Len()) return } s.Node = G.nodePool.Get().Init(s.Node, kind, s.Len()) } func (s *State) Close() { if s.Node.Kind == NodeKindValue { s.SetError(G.ErrInvalidNode) return } if s.Node.Parent != nil { p := s.Node s.Node = s.Node.Parent G.nodePool.Put(p.Reset()) } s.Node.Count++ }