package contract import ( "errors" "strings" "sync" policycontract "git.frostfs.info/TrueCloudLab/frostfs-contract/policy" "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/frostfs/policy" "github.com/nspcc-dev/neo-go/pkg/util" ) type InMemoryContract struct { iamChains *syncedMap containerChains *syncedMap namespaceChains *syncedMap } type syncedMap struct { mu sync.RWMutex data map[string][]byte } var _ policy.Contract = (*InMemoryContract)(nil) var ErrChainNotFound = errors.New("chain not found") // NewInMemoryContract creates new inmemory Policy contract wrapper. func NewInMemoryContract() *InMemoryContract { return &InMemoryContract{ iamChains: &syncedMap{data: map[string][]byte{}}, containerChains: &syncedMap{data: map[string][]byte{}}, namespaceChains: &syncedMap{data: map[string][]byte{}}, } } func (c *InMemoryContract) AddChain(kind policycontract.Kind, entity string, name []byte, chain []byte) (util.Uint256, uint32, error) { syncMap := c.getMap(kind) syncMap.mu.Lock() syncMap.data[entity+string(name)] = chain syncMap.mu.Unlock() return util.Uint256{}, 0, nil } func (c *InMemoryContract) GetChain(kind policycontract.Kind, entity string, name []byte) ([]byte, error) { syncMap := c.getMap(kind) syncMap.mu.RLock() defer syncMap.mu.RUnlock() val, ok := syncMap.data[entity+string(name)] if !ok { return nil, ErrChainNotFound } return val, nil } func (c *InMemoryContract) RemoveChain(kind policycontract.Kind, entity string, name []byte) (util.Uint256, uint32, error) { syncMap := c.getMap(kind) syncMap.mu.Lock() delete(syncMap.data, entity+string(name)) syncMap.mu.Unlock() return util.Uint256{}, 0, nil } func (c *InMemoryContract) ListChains(kind policycontract.Kind, entity string, name []byte) ([][]byte, error) { syncMap := c.getMap(kind) syncMap.mu.RLock() defer syncMap.mu.RUnlock() var res [][]byte for key, val := range syncMap.data { if strings.HasPrefix(key, entity+string(name)) { res = append(res, val) } } return res, nil } func (c *InMemoryContract) Wait(_ util.Uint256, _ uint32, err error) error { return err } func (c *InMemoryContract) getMap(kind policycontract.Kind) *syncedMap { switch kind { case policycontract.IAM: return c.iamChains case policycontract.Container: return c.containerChains case policycontract.Namespace: return c.namespaceChains default: return &syncedMap{data: map[string][]byte{}} } }